Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
authorLinus Torvalds <torvalds@g5.osdl.org>
Sun, 2 Apr 2006 19:51:22 +0000 (12:51 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 2 Apr 2006 19:51:22 +0000 (12:51 -0700)
* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband:
  IB/ipath: kbuild infrastructure
  IB/ipath: infiniband verbs support
  IB/ipath: misc infiniband code, part 2
  IB/ipath: misc infiniband code, part 1
  IB/ipath: infiniband RC protocol support
  IB/ipath: infiniband UC and UD protocol support
  IB/ipath: infiniband header files
  IB/ipath: layering interfaces used by higher-level driver code
  IB/ipath: support for userspace apps using core driver
  IB/ipath: sysfs and ipathfs support for core driver
  IB/ipath: misc driver support code
  IB/ipath: chip initialisation code, and diag support
  IB/ipath: support for PCI Express devices
  IB/ipath: support for HyperTransport devices
  IB/ipath: core driver header files
  IB/ipath: core device driver

575 files changed:
Documentation/feature-removal-schedule.txt
Documentation/input/joystick-parport.txt
Documentation/leds-class.txt [new file with mode: 0644]
Documentation/memory-barriers.txt [new file with mode: 0644]
Documentation/pcmcia/driver-changes.txt
arch/alpha/kernel/alpha_ksyms.c
arch/alpha/kernel/core_marvel.c
arch/alpha/kernel/setup.c
arch/arm/Kconfig
arch/arm/Kconfig-nommu [new file with mode: 0644]
arch/arm/Makefile
arch/arm/boot/compressed/head.S
arch/arm/common/sharpsl_pm.c
arch/arm/kernel/entry-armv.S
arch/arm/kernel/head-common.S [new file with mode: 0644]
arch/arm/kernel/head-nommu.S [new file with mode: 0644]
arch/arm/kernel/head.S
arch/arm/kernel/process.c
arch/arm/kernel/signal.h
arch/arm/kernel/traps.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/tosa.c
arch/arm/mm/proc-xsc3.S
arch/arm26/kernel/armksyms.c
arch/frv/kernel/frv_ksyms.c
arch/h8300/kernel/h8300_ksyms.c
arch/i386/kernel/apic.c
arch/i386/kernel/cpu/mcheck/mce.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/process.c
arch/i386/kernel/setup.c
arch/i386/kernel/syscall_table.S
arch/i386/kernel/traps.c
arch/i386/kernel/vsyscall-sigreturn.S
arch/ia64/kernel/palinfo.c
arch/ia64/kernel/time.c
arch/ia64/kernel/topology.c
arch/m68k/kernel/m68k_ksyms.c
arch/m68knommu/kernel/m68k_ksyms.c
arch/mips/Kconfig
arch/mips/kernel/Makefile
arch/mips/kernel/i8253.c [new file with mode: 0644]
arch/mips/kernel/process.c
arch/parisc/Kconfig
arch/parisc/configs/712_defconfig
arch/parisc/configs/a500_defconfig
arch/parisc/configs/b180_defconfig
arch/parisc/configs/c3000_defconfig
arch/parisc/defconfig
arch/parisc/kernel/cache.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/pacache.S
arch/parisc/kernel/parisc_ksyms.c
arch/parisc/kernel/pdc_chassis.c
arch/parisc/kernel/perf.c
arch/parisc/kernel/syscall_table.S
arch/parisc/lib/iomap.c
arch/parisc/mm/init.c
arch/parisc/mm/ioremap.c
arch/powerpc/kernel/crash_dump.c
arch/powerpc/kernel/lparcfg.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/systbl.S
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/vdso32/sigtramp.S
arch/powerpc/kernel/vdso64/sigtramp.S
arch/powerpc/mm/fault.c
arch/powerpc/platforms/83xx/mpc834x_sys.c
arch/powerpc/platforms/85xx/mpc85xx_ads.c
arch/powerpc/platforms/cell/spu_callbacks.c
arch/powerpc/platforms/cell/spufs/run.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_driver.c
arch/powerpc/platforms/pseries/eeh_event.c
arch/powerpc/platforms/pseries/hvCall.S
arch/powerpc/platforms/pseries/hvconsole.c
arch/powerpc/platforms/pseries/hvcserver.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/vio.c
arch/powerpc/platforms/pseries/xics.c
arch/s390/kernel/smp.c
arch/sh/kernel/cpu/init.c
arch/sh/kernel/setup.c
arch/sparc/kernel/systbls.S
arch/sparc64/defconfig
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sys32.S
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/systbls.S
arch/sparc64/mm/fault.c
arch/sparc64/mm/hugetlbpage.c
arch/um/Kconfig
arch/um/Makefile
arch/um/Makefile-x86_64
arch/um/drivers/daemon_kern.c
arch/um/drivers/harddog_kern.c
arch/um/drivers/hostaudio_kern.c
arch/um/drivers/mcast_kern.c
arch/um/drivers/mconsole_kern.c
arch/um/drivers/pcap_kern.c
arch/um/drivers/slip_kern.c
arch/um/drivers/slirp_kern.c
arch/um/drivers/ubd_kern.c
arch/um/include/kern_util.h
arch/um/include/line.h
arch/um/include/mem_user.h
arch/um/include/os.h
arch/um/include/sysdep-i386/checksum.h
arch/um/include/sysdep-i386/ptrace.h
arch/um/include/sysdep-i386/tls.h [new file with mode: 0644]
arch/um/include/sysdep-x86_64/tls.h [new file with mode: 0644]
arch/um/include/user_util.h
arch/um/kernel/exec_kern.c
arch/um/kernel/mem.c
arch/um/kernel/process_kern.c
arch/um/kernel/ptrace.c
arch/um/kernel/skas/process_kern.c
arch/um/kernel/syscall_kern.c
arch/um/kernel/trap_kern.c
arch/um/kernel/tt/process_kern.c
arch/um/os-Linux/Makefile
arch/um/os-Linux/drivers/ethertap_kern.c
arch/um/os-Linux/drivers/tuntap_kern.c
arch/um/os-Linux/mem.c
arch/um/os-Linux/process.c
arch/um/os-Linux/start_up.c
arch/um/os-Linux/sys-i386/Makefile
arch/um/os-Linux/sys-i386/tls.c [new file with mode: 0644]
arch/um/os-Linux/tls.c [new file with mode: 0644]
arch/um/scripts/Makefile.rules
arch/um/scripts/Makefile.unmap [deleted file]
arch/um/sys-i386/Makefile
arch/um/sys-i386/ptrace.c
arch/um/sys-i386/ptrace_user.c
arch/um/sys-i386/signal.c
arch/um/sys-i386/sys_call_table.S
arch/um/sys-i386/syscalls.c
arch/um/sys-i386/tls.c [new file with mode: 0644]
arch/um/sys-x86_64/Makefile
arch/um/sys-x86_64/tls.c [new file with mode: 0644]
arch/x86_64/ia32/vsyscall-sigreturn.S
arch/x86_64/kernel/apic.c
arch/x86_64/kernel/early_printk.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/pmtimer.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/setup64.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/traps.c
arch/x86_64/kernel/x8664_ksyms.c
arch/x86_64/mm/fault.c
arch/xtensa/kernel/xtensa_ksyms.c
block/Kconfig
block/elevator.c
block/genhd.c
drivers/Kconfig
drivers/Makefile
drivers/acpi/ec.c
drivers/block/amiflop.c
drivers/bluetooth/bluecard_cs.c
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/btuart_cs.c
drivers/bluetooth/dtl1_cs.c
drivers/char/hvcs.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_kcs_sm.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_poweroff.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/istallion.c
drivers/char/keyboard.c
drivers/char/pcmcia/cm4000_cs.c
drivers/char/pcmcia/cm4040_cs.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/stallion.c
drivers/char/tty_io.c
drivers/char/vt.c
drivers/edac/Kconfig
drivers/ide/ide-disk.c
drivers/ide/ide-taskfile.c
drivers/ide/legacy/ide-cs.c
drivers/input/evbug.c
drivers/input/evdev.c
drivers/input/gameport/gameport.c
drivers/input/gameport/ns558.c
drivers/input/input.c
drivers/input/joydev.c
drivers/input/joystick/amijoy.c
drivers/input/joystick/db9.c
drivers/input/joystick/gamecon.c
drivers/input/joystick/iforce/iforce-ff.c
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce.h
drivers/input/joystick/turbografx.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/corgikbd.c
drivers/input/keyboard/hil_kbd.c
drivers/input/keyboard/hilkbd.c
drivers/input/keyboard/spitzkbd.c
drivers/input/misc/pcspkr.c
drivers/input/misc/uinput.c
drivers/input/mouse/hil_ptr.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/synaptics.c
drivers/input/mousedev.c
drivers/input/power.c
drivers/input/serio/gscps2.c
drivers/input/serio/hil_mlc.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/libps2.c
drivers/input/serio/parkbd.c
drivers/input/serio/rpckbd.c
drivers/input/serio/serio.c
drivers/input/serio/serio_raw.c
drivers/input/tsdev.c
drivers/isdn/hardware/avm/avm_cs.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/teles_cs.c
drivers/isdn/sc/ioctl.c
drivers/leds/Kconfig [new file with mode: 0644]
drivers/leds/Makefile [new file with mode: 0644]
drivers/leds/led-class.c [new file with mode: 0644]
drivers/leds/led-core.c [new file with mode: 0644]
drivers/leds/led-triggers.c [new file with mode: 0644]
drivers/leds/leds-corgi.c [new file with mode: 0644]
drivers/leds/leds-ixp4xx-gpio.c [new file with mode: 0644]
drivers/leds/leds-locomo.c [new file with mode: 0644]
drivers/leds/leds-spitz.c [new file with mode: 0644]
drivers/leds/leds-tosa.c [new file with mode: 0644]
drivers/leds/leds.h [new file with mode: 0644]
drivers/leds/ledtrig-ide-disk.c [new file with mode: 0644]
drivers/leds/ledtrig-timer.c [new file with mode: 0644]
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid6main.c
drivers/media/video/cpia_pp.c
drivers/mmc/Kconfig
drivers/mmc/Makefile
drivers/mmc/au1xmmc.c
drivers/mmc/mmc.c
drivers/mmc/mmci.c
drivers/mmc/omap.c [new file with mode: 0644]
drivers/mmc/omap.h [new file with mode: 0644]
drivers/mmc/pxamci.c
drivers/mmc/sdhci.c
drivers/mmc/wbsd.c
drivers/mtd/chips/amd_flash.c
drivers/mtd/chips/jedec_probe.c
drivers/mtd/chips/sharp.c
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/blkmtd.c
drivers/mtd/devices/block2mtd.c
drivers/mtd/devices/doc2000.c
drivers/mtd/devices/lart.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/ms02-nv.c
drivers/mtd/inftlcore.c
drivers/mtd/maps/alchemy-flash.c
drivers/mtd/maps/cfi_flagadm.c
drivers/mtd/maps/dbox2-flash.c
drivers/mtd/maps/dilnetpc.c
drivers/mtd/maps/dmv182.c
drivers/mtd/maps/h720x-flash.c
drivers/mtd/maps/netsc520.c
drivers/mtd/maps/nettel.c
drivers/mtd/maps/ocotea.c
drivers/mtd/maps/pci.c
drivers/mtd/maps/pcmciamtd.c
drivers/mtd/maps/redwood.c
drivers/mtd/maps/sbc8240.c
drivers/mtd/maps/sc520cdp.c
drivers/mtd/maps/scx200_docflash.c
drivers/mtd/maps/sharpsl-flash.c
drivers/mtd/maps/ts5500_flash.c
drivers/mtd/maps/uclinux.c
drivers/mtd/maps/vmax301.c
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdblock.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/au1550nd.c
drivers/mtd/nand/nand_base.c
drivers/mtd/redboot.c
drivers/net/3c59x.c
drivers/net/Kconfig
drivers/net/arcnet/com90xx.c
drivers/net/ibmveth.c
drivers/net/netconsole.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/com20020_cs.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/ibmtr_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/tg3.c
drivers/net/tokenring/Kconfig
drivers/net/wireless/Kconfig
drivers/net/wireless/airo_cs.c
drivers/net/wireless/atmel_cs.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/netwave_cs.c
drivers/net/wireless/orinoco_cs.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/ray_cs.h
drivers/net/wireless/spectrum_cs.c
drivers/net/wireless/wavelan_cs.c
drivers/net/wireless/wavelan_cs.p.h
drivers/net/wireless/wl3501.h
drivers/net/wireless/wl3501_cs.c
drivers/parisc/ccio-dma.c
drivers/parisc/dino.c
drivers/parisc/eisa.c
drivers/parisc/iosapic.c
drivers/parisc/lba_pci.c
drivers/parisc/pdc_stable.c
drivers/parisc/sba_iommu.c
drivers/parisc/superio.c
drivers/parport/parport_cs.c
drivers/pcmcia/Kconfig
drivers/pcmcia/Makefile
drivers/pcmcia/at91_cf.c [new file with mode: 0644]
drivers/pcmcia/cistpl.c
drivers/pcmcia/cs.c
drivers/pcmcia/cs_internal.h
drivers/pcmcia/ds.c
drivers/pcmcia/ds_internal.h
drivers/pcmcia/i82092.c
drivers/pcmcia/i82365.c
drivers/pcmcia/pcmcia_compat.c [deleted file]
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/pd6729.c
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/rsrc_nonstatic.c
drivers/pcmcia/sa1100_cerf.c
drivers/pcmcia/socket_sysfs.c
drivers/pcmcia/ti113x.h
drivers/pcmcia/vrc4171_card.c
drivers/pcmcia/vrc4173_cardu.c
drivers/scsi/ahci.c
drivers/scsi/ata_piix.c
drivers/scsi/ibmmca.c
drivers/scsi/ibmvscsi/rpa_vscsi.c
drivers/scsi/lasi700.c
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
drivers/scsi/libata.h
drivers/scsi/pcmcia/aha152x_stub.c
drivers/scsi/pcmcia/fdomain_stub.c
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/pcmcia/nsp_cs.h
drivers/scsi/pcmcia/qlogic_stub.c
drivers/scsi/pcmcia/sym53c500_cs.c
drivers/scsi/zalon.c
drivers/serial/8250_gsc.c
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/jsm/jsm_tty.c
drivers/serial/mux.c
drivers/serial/serial_cs.c
drivers/telephony/ixj_pcmcia.c
drivers/usb/host/sl811_cs.c
drivers/usb/input/hid-input.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/backlight/Kconfig
drivers/video/backlight/backlight.c
drivers/video/backlight/corgi_bl.c
drivers/video/backlight/hp680_bl.c
drivers/video/cfbimgblt.c
drivers/video/console/fbcon.c
drivers/video/console/sticore.c
drivers/video/fbmem.c
drivers/video/pxafb.c
drivers/video/radeonfb.c [deleted file]
drivers/video/sticore.h
drivers/video/stifb.c
drivers/video/w100fb.c
drivers/video/w100fb.h
fs/Makefile
fs/char_dev.c
fs/cifs/CHANGES
fs/cifs/Makefile
fs/cifs/README
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/link.c
fs/cifs/misc.c
fs/cifs/ntlmssp.c [new file with mode: 0644]
fs/cifs/ntlmssp.h
fs/cifs/readdir.c
fs/cifs/transport.c
fs/dcache.c
fs/hppfs/hppfs_kern.c
fs/locks.c
fs/msdos/namei.c
fs/namei.c
fs/proc/base.c
fs/proc/proc_misc.c
fs/select.c
fs/splice.c
fs/sync.c [new file with mode: 0644]
fs/vfat/namei.c
include/asm-arm/arch-at91rm9200/hardware.h
include/asm-arm/arch-ixp23xx/uncompress.h
include/asm-arm/arch-pxa/pxa-regs.h
include/asm-arm/arch-pxa/sharpsl.h
include/asm-arm/unistd.h
include/asm-generic/local.h
include/asm-generic/mutex-dec.h
include/asm-generic/mutex-xchg.h
include/asm-i386/apicdef.h
include/asm-i386/floppy.h
include/asm-i386/local.h
include/asm-i386/unistd.h
include/asm-ia64/pal.h
include/asm-parisc/atomic.h
include/asm-parisc/cache.h
include/asm-parisc/cacheflush.h
include/asm-parisc/io.h
include/asm-parisc/local.h
include/asm-parisc/page.h
include/asm-parisc/pci.h
include/asm-parisc/pdc_chassis.h
include/asm-parisc/spinlock.h
include/asm-parisc/thread_info.h
include/asm-powerpc/eeh.h
include/asm-powerpc/hvcall.h
include/asm-powerpc/system.h
include/asm-s390/percpu.h
include/asm-sparc/unistd.h
include/asm-sparc64/unistd.h
include/asm-um/desc.h
include/asm-um/host_ldt-i386.h [new file with mode: 0644]
include/asm-um/host_ldt-x86_64.h [new file with mode: 0644]
include/asm-um/ldt-i386.h [deleted file]
include/asm-um/ldt-x86_64.h [deleted file]
include/asm-um/ldt.h [new file with mode: 0644]
include/asm-um/processor-i386.h
include/asm-um/processor-x86_64.h
include/asm-um/ptrace-generic.h
include/asm-um/ptrace-i386.h
include/asm-um/ptrace-x86_64.h
include/asm-um/segment.h
include/asm-um/thread_info.h
include/asm-um/uaccess.h
include/asm-x86_64/local.h
include/linux/backlight.h
include/linux/dcache.h
include/linux/fadvise.h
include/linux/fb.h
include/linux/fs.h
include/linux/gameport.h
include/linux/hrtimer.h
include/linux/input.h
include/linux/ipmi_smi.h
include/linux/kbd_kern.h
include/linux/keyboard.h
include/linux/leds.h [new file with mode: 0644]
include/linux/libps2.h
include/linux/migrate.h
include/linux/mtd/blktrans.h
include/linux/mtd/doc2000.h
include/linux/mtd/inftl.h
include/linux/namei.h
include/linux/netdevice.h
include/linux/netfilter/x_tables.h
include/linux/netfilter/xt_esp.h [new file with mode: 0644]
include/linux/netfilter/xt_multiport.h [new file with mode: 0644]
include/linux/netfilter_ipv4/ip_tables.h
include/linux/netfilter_ipv4/ipt_esp.h
include/linux/netfilter_ipv4/ipt_multiport.h
include/linux/netfilter_ipv6/ip6t_esp.h
include/linux/netfilter_ipv6/ip6t_multiport.h
include/linux/pagemap.h
include/linux/pid.h
include/linux/pipe_fs_i.h
include/linux/sched.h
include/linux/serio.h
include/linux/skbuff.h
include/linux/syscalls.h
include/linux/timer.h
include/linux/tiocl.h
include/linux/uinput.h
include/net/tcp.h
include/net/xfrm.h
include/pcmcia/bulkmem.h
include/pcmcia/ciscode.h
include/pcmcia/cistpl.h
include/pcmcia/cs.h
include/pcmcia/ds.h
include/pcmcia/ss.h
kernel/acct.c
kernel/audit.c
kernel/cpuset.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/futex_compat.c
kernel/hrtimer.c
kernel/module.c
kernel/pid.c
kernel/power/process.c
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/timer.c
lib/Kconfig.debug
mm/fadvise.c
mm/hugetlb.c
mm/memory.c
mm/swapfile.c
net/compat.c
net/core/dev.c
net/core/sock.c
net/dccp/feat.c
net/decnet/dn_dev.c
net/ipv4/ah4.c
net/ipv4/esp4.c
net/ipv4/ipcomp.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Makefile
net/ipv4/netfilter/ip_conntrack_netlink.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipt_esp.c [deleted file]
net/ipv4/netfilter/ipt_multiport.c [deleted file]
net/ipv4/xfrm4_input.c
net/ipv4/xfrm4_tunnel.c
net/ipv6/ah6.c
net/ipv6/esp6.c
net/ipv6/ipcomp6.c
net/ipv6/netfilter/Kconfig
net/ipv6/netfilter/Makefile
net/ipv6/netfilter/ip6t_esp.c [deleted file]
net/ipv6/netfilter/ip6t_multiport.c [deleted file]
net/ipv6/xfrm6_input.c
net/ipv6/xfrm6_tunnel.c
net/netfilter/Kconfig
net/netfilter/Makefile
net/netfilter/nf_conntrack_netlink.c
net/netfilter/x_tables.c
net/netfilter/xt_esp.c [new file with mode: 0644]
net/netfilter/xt_multiport.c [new file with mode: 0644]
net/netfilter/xt_policy.c
net/socket.c
net/xfrm/xfrm_input.c
net/xfrm/xfrm_policy.c
sound/pcmcia/pdaudiocf/pdaudiocf.c
sound/pcmcia/pdaudiocf/pdaudiocf.h
sound/pcmcia/vx/vxpocket.c
sound/pcmcia/vx/vxpocket.h

index 495858b..59d0c74 100644 (file)
@@ -127,13 +127,6 @@ Who:       Christoph Hellwig <hch@lst.de>
 
 ---------------------------
 
-What:  EXPORT_SYMBOL(lookup_hash)
-When:  January 2006
-Why:   Too low-level interface.  Use lookup_one_len or lookup_create instead.
-Who:   Christoph Hellwig <hch@lst.de>
-
----------------------------
-
 What:  CONFIG_FORCED_INLINING
 When:  June 2006
 Why:   Config option is there to see if gcc is good enough. (in january
@@ -241,3 +234,15 @@ Why:       The USB subsystem has changed a lot over time, and it has been
 Who:   Greg Kroah-Hartman <gregkh@suse.de>
 
 ---------------------------
+
+What:  find_trylock_page
+When:  January 2007
+Why:   The interface no longer has any callers left in the kernel. It
+       is an odd interface (compared with other find_*_page functions), in
+       that it does not take a refcount to the page, only the page lock.
+       It should be replaced with find_get_page or find_lock_page if possible.
+       This feature removal can be reevaluated if users of the interface
+       cannot cleanly use something else.
+Who:   Nick Piggin <npiggin@suse.de>
+
+---------------------------
index 88a011c..d537c48 100644 (file)
@@ -36,12 +36,12 @@ with them.
 
   All NES and SNES use the same synchronous serial protocol, clocked from
 the computer's side (and thus timing insensitive). To allow up to 5 NES
-and/or SNES gamepads connected to the parallel port at once, the output
-lines of the parallel port are shared, while one of 5 available input lines
-is assigned to each gamepad.
+and/or SNES gamepads and/or SNES mice connected to the parallel port at once,
+the output lines of the parallel port are shared, while one of 5 available
+input lines is assigned to each gamepad.
 
   This protocol is handled by the gamecon.c driver, so that's the one
-you'll use for NES and SNES gamepads.
+you'll use for NES, SNES gamepads and SNES mice.
 
   The main problem with PC parallel ports is that they don't have +5V power
 source on any of their pins. So, if you want a reliable source of power
@@ -106,7 +106,7 @@ A, Turbo B, Select and Start, and is connected through 5 wires, then it is
 either a NES or NES clone and will work with this connection. SNES gamepads
 also use 5 wires, but have more buttons. They will work as well, of course.
 
-Pinout for NES gamepads                 Pinout for SNES gamepads
+Pinout for NES gamepads                 Pinout for SNES gamepads and mice
 
           +----> Power                   +-----------------------\
           |                            7 | o  o  o  o |  x  x  o  | 1
@@ -454,6 +454,7 @@ uses the following kernel/module command line:
          6  | N64 pad
          7  | Sony PSX controller
          8  | Sony PSX DDR controller
+         9  | SNES mouse
 
   The exact type of the PSX controller type is autoprobed when used so
 hot swapping should work (but is not recomended).
diff --git a/Documentation/leds-class.txt b/Documentation/leds-class.txt
new file mode 100644 (file)
index 0000000..8c35c04
--- /dev/null
@@ -0,0 +1,71 @@
+LED handling under Linux
+========================
+
+If you're reading this and thinking about keyboard leds, these are
+handled by the input subsystem and the led class is *not* needed.
+
+In its simplest form, the LED class just allows control of LEDs from
+userspace. LEDs appear in /sys/class/leds/. The brightness file will
+set the brightness of the LED (taking a value 0-255). Most LEDs don't
+have hardware brightness support so will just be turned on for non-zero
+brightness settings.
+
+The class also introduces the optional concept of an LED trigger. A trigger
+is a kernel based source of led events. Triggers can either be simple or
+complex. A simple trigger isn't configurable and is designed to slot into
+existing subsystems with minimal additional code. Examples are the ide-disk,
+nand-disk and sharpsl-charge triggers. With led triggers disabled, the code
+optimises away.
+
+Complex triggers whilst available to all LEDs have LED specific
+parameters and work on a per LED basis. The timer trigger is an example.
+
+You can change triggers in a similar manner to the way an IO scheduler
+is chosen (via /sys/class/leds/<device>/trigger). Trigger specific
+parameters can appear in /sys/class/leds/<device> once a given trigger is
+selected.
+
+
+Design Philosophy
+=================
+
+The underlying design philosophy is simplicity. LEDs are simple devices
+and the aim is to keep a small amount of code giving as much functionality
+as possible.  Please keep this in mind when suggesting enhancements.
+
+
+LED Device Naming
+=================
+
+Is currently of the form:
+
+"devicename:colour"
+
+There have been calls for LED properties such as colour to be exported as
+individual led class attributes. As a solution which doesn't incur as much
+overhead, I suggest these become part of the device name. The naming scheme
+above leaves scope for further attributes should they be needed.
+
+
+Known Issues
+============
+
+The LED Trigger core cannot be a module as the simple trigger functions
+would cause nightmare dependency issues. I see this as a minor issue
+compared to the benefits the simple trigger functionality brings. The
+rest of the LED subsystem can be modular.
+
+Some leds can be programmed to flash in hardware. As this isn't a generic
+LED device property, this should be exported as a device specific sysfs
+attribute rather than part of the class if this functionality is required.
+
+
+Future Development
+==================
+
+At the moment, a trigger can't be created specifically for a single LED.
+There are a number of cases where a trigger might only be mappable to a
+particular LED (ACPI?). The addition of triggers provided by the LED driver
+should cover this option and be possible to add without breaking the
+current interface.
+
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
new file mode 100644 (file)
index 0000000..f855031
--- /dev/null
@@ -0,0 +1,1913 @@
+                        ============================
+                        LINUX KERNEL MEMORY BARRIERS
+                        ============================
+
+By: David Howells <dhowells@redhat.com>
+
+Contents:
+
+ (*) Abstract memory access model.
+
+     - Device operations.
+     - Guarantees.
+
+ (*) What are memory barriers?
+
+     - Varieties of memory barrier.
+     - What may not be assumed about memory barriers?
+     - Data dependency barriers.
+     - Control dependencies.
+     - SMP barrier pairing.
+     - Examples of memory barrier sequences.
+
+ (*) Explicit kernel barriers.
+
+     - Compiler barrier.
+     - The CPU memory barriers.
+     - MMIO write barrier.
+
+ (*) Implicit kernel memory barriers.
+
+     - Locking functions.
+     - Interrupt disabling functions.
+     - Miscellaneous functions.
+
+ (*) Inter-CPU locking barrier effects.
+
+     - Locks vs memory accesses.
+     - Locks vs I/O accesses.
+
+ (*) Where are memory barriers needed?
+
+     - Interprocessor interaction.
+     - Atomic operations.
+     - Accessing devices.
+     - Interrupts.
+
+ (*) Kernel I/O barrier effects.
+
+ (*) Assumed minimum execution ordering model.
+
+ (*) The effects of the cpu cache.
+
+     - Cache coherency.
+     - Cache coherency vs DMA.
+     - Cache coherency vs MMIO.
+
+ (*) The things CPUs get up to.
+
+     - And then there's the Alpha.
+
+ (*) References.
+
+
+============================
+ABSTRACT MEMORY ACCESS MODEL
+============================
+
+Consider the following abstract model of the system:
+
+                           :                :
+                           :                :
+                           :                :
+               +-------+   :   +--------+   :   +-------+
+               |       |   :   |        |   :   |       |
+               |       |   :   |        |   :   |       |
+               | CPU 1 |<----->| Memory |<----->| CPU 2 |
+               |       |   :   |        |   :   |       |
+               |       |   :   |        |   :   |       |
+               +-------+   :   +--------+   :   +-------+
+                   ^       :       ^        :       ^
+                   |       :       |        :       |
+                   |       :       |        :       |
+                   |       :       v        :       |
+                   |       :   +--------+   :       |
+                   |       :   |        |   :       |
+                   |       :   |        |   :       |
+                   +---------->| Device |<----------+
+                           :   |        |   :
+                           :   |        |   :
+                           :   +--------+   :
+                           :                :
+
+Each CPU executes a program that generates memory access operations.  In the
+abstract CPU, memory operation ordering is very relaxed, and a CPU may actually
+perform the memory operations in any order it likes, provided program causality
+appears to be maintained.  Similarly, the compiler may also arrange the
+instructions it emits in any order it likes, provided it doesn't affect the
+apparent operation of the program.
+
+So in the above diagram, the effects of the memory operations performed by a
+CPU are perceived by the rest of the system as the operations cross the
+interface between the CPU and rest of the system (the dotted lines).
+
+
+For example, consider the following sequence of events:
+
+       CPU 1           CPU 2
+       =============== ===============
+       { A == 1; B == 2 }
+       A = 3;          x = A;
+       B = 4;          y = B;
+
+The set of accesses as seen by the memory system in the middle can be arranged
+in 24 different combinations:
+
+       STORE A=3,      STORE B=4,      x=LOAD A->3,    y=LOAD B->4
+       STORE A=3,      STORE B=4,      y=LOAD B->4,    x=LOAD A->3
+       STORE A=3,      x=LOAD A->3,    STORE B=4,      y=LOAD B->4
+       STORE A=3,      x=LOAD A->3,    y=LOAD B->2,    STORE B=4
+       STORE A=3,      y=LOAD B->2,    STORE B=4,      x=LOAD A->3
+       STORE A=3,      y=LOAD B->2,    x=LOAD A->3,    STORE B=4
+       STORE B=4,      STORE A=3,      x=LOAD A->3,    y=LOAD B->4
+       STORE B=4, ...
+       ...
+
+and can thus result in four different combinations of values:
+
+       x == 1, y == 2
+       x == 1, y == 4
+       x == 3, y == 2
+       x == 3, y == 4
+
+
+Furthermore, the stores committed by a CPU to the memory system may not be
+perceived by the loads made by another CPU in the same order as the stores were
+committed.
+
+
+As a further example, consider this sequence of events:
+
+       CPU 1           CPU 2
+       =============== ===============
+       { A == 1, B == 2, C = 3, P == &A, Q == &C }
+       B = 4;          Q = P;
+       P = &B          D = *Q;
+
+There is an obvious data dependency here, as the value loaded into D depends on
+the address retrieved from P by CPU 2.  At the end of the sequence, any of the
+following results are possible:
+
+       (Q == &A) and (D == 1)
+       (Q == &B) and (D == 2)
+       (Q == &B) and (D == 4)
+
+Note that CPU 2 will never try and load C into D because the CPU will load P
+into Q before issuing the load of *Q.
+
+
+DEVICE OPERATIONS
+-----------------
+
+Some devices present their control interfaces as collections of memory
+locations, but the order in which the control registers are accessed is very
+important.  For instance, imagine an ethernet card with a set of internal
+registers that are accessed through an address port register (A) and a data
+port register (D).  To read internal register 5, the following code might then
+be used:
+
+       *A = 5;
+       x = *D;
+
+but this might show up as either of the following two sequences:
+
+       STORE *A = 5, x = LOAD *D
+       x = LOAD *D, STORE *A = 5
+
+the second of which will almost certainly result in a malfunction, since it set
+the address _after_ attempting to read the register.
+
+
+GUARANTEES
+----------
+
+There are some minimal guarantees that may be expected of a CPU:
+
+ (*) On any given CPU, dependent memory accesses will be issued in order, with
+     respect to itself.  This means that for:
+
+       Q = P; D = *Q;
+
+     the CPU will issue the following memory operations:
+
+       Q = LOAD P, D = LOAD *Q
+
+     and always in that order.
+
+ (*) Overlapping loads and stores within a particular CPU will appear to be
+     ordered within that CPU.  This means that for:
+
+       a = *X; *X = b;
+
+     the CPU will only issue the following sequence of memory operations:
+
+       a = LOAD *X, STORE *X = b
+
+     And for:
+
+       *X = c; d = *X;
+
+     the CPU will only issue:
+
+       STORE *X = c, d = LOAD *X
+
+     (Loads and stores overlap if they are targetted at overlapping pieces of
+     memory).
+
+And there are a number of things that _must_ or _must_not_ be assumed:
+
+ (*) It _must_not_ be assumed that independent loads and stores will be issued
+     in the order given.  This means that for:
+
+       X = *A; Y = *B; *D = Z;
+
+     we may get any of the following sequences:
+
+       X = LOAD *A,  Y = LOAD *B,  STORE *D = Z
+       X = LOAD *A,  STORE *D = Z, Y = LOAD *B
+       Y = LOAD *B,  X = LOAD *A,  STORE *D = Z
+       Y = LOAD *B,  STORE *D = Z, X = LOAD *A
+       STORE *D = Z, X = LOAD *A,  Y = LOAD *B
+       STORE *D = Z, Y = LOAD *B,  X = LOAD *A
+
+ (*) It _must_ be assumed that overlapping memory accesses may be merged or
+     discarded.  This means that for:
+
+       X = *A; Y = *(A + 4);
+
+     we may get any one of the following sequences:
+
+       X = LOAD *A; Y = LOAD *(A + 4);
+       Y = LOAD *(A + 4); X = LOAD *A;
+       {X, Y} = LOAD {*A, *(A + 4) };
+
+     And for:
+
+       *A = X; Y = *A;
+
+     we may get either of:
+
+       STORE *A = X; Y = LOAD *A;
+       STORE *A = Y;
+
+
+=========================
+WHAT ARE MEMORY BARRIERS?
+=========================
+
+As can be seen above, independent memory operations are effectively performed
+in random order, but this can be a problem for CPU-CPU interaction and for I/O.
+What is required is some way of intervening to instruct the compiler and the
+CPU to restrict the order.
+
+Memory barriers are such interventions.  They impose a perceived partial
+ordering between the memory operations specified on either side of the barrier.
+They request that the sequence of memory events generated appears to other
+parts of the system as if the barrier is effective on that CPU.
+
+
+VARIETIES OF MEMORY BARRIER
+---------------------------
+
+Memory barriers come in four basic varieties:
+
+ (1) Write (or store) memory barriers.
+
+     A write memory barrier gives a guarantee that all the STORE operations
+     specified before the barrier will appear to happen before all the STORE
+     operations specified after the barrier with respect to the other
+     components of the system.
+
+     A write barrier is a partial ordering on stores only; it is not required
+     to have any effect on loads.
+
+     A CPU can be viewed as as commiting a sequence of store operations to the
+     memory system as time progresses.  All stores before a write barrier will
+     occur in the sequence _before_ all the stores after the write barrier.
+
+     [!] Note that write barriers should normally be paired with read or data
+     dependency barriers; see the "SMP barrier pairing" subsection.
+
+
+ (2) Data dependency barriers.
+
+     A data dependency barrier is a weaker form of read barrier.  In the case
+     where two loads are performed such that the second depends on the result
+     of the first (eg: the first load retrieves the address to which the second
+     load will be directed), a data dependency barrier would be required to
+     make sure that the target of the second load is updated before the address
+     obtained by the first load is accessed.
+
+     A data dependency barrier is a partial ordering on interdependent loads
+     only; it is not required to have any effect on stores, independent loads
+     or overlapping loads.
+
+     As mentioned in (1), the other CPUs in the system can be viewed as
+     committing sequences of stores to the memory system that the CPU being
+     considered can then perceive.  A data dependency barrier issued by the CPU
+     under consideration guarantees that for any load preceding it, if that
+     load touches one of a sequence of stores from another CPU, then by the
+     time the barrier completes, the effects of all the stores prior to that
+     touched by the load will be perceptible to any loads issued after the data
+     dependency barrier.
+
+     See the "Examples of memory barrier sequences" subsection for diagrams
+     showing the ordering constraints.
+
+     [!] Note that the first load really has to have a _data_ dependency and
+     not a control dependency.  If the address for the second load is dependent
+     on the first load, but the dependency is through a conditional rather than
+     actually loading the address itself, then it's a _control_ dependency and
+     a full read barrier or better is required.  See the "Control dependencies"
+     subsection for more information.
+
+     [!] Note that data dependency barriers should normally be paired with
+     write barriers; see the "SMP barrier pairing" subsection.
+
+
+ (3) Read (or load) memory barriers.
+
+     A read barrier is a data dependency barrier plus a guarantee that all the
+     LOAD operations specified before the barrier will appear to happen before
+     all the LOAD operations specified after the barrier with respect to the
+     other components of the system.
+
+     A read barrier is a partial ordering on loads only; it is not required to
+     have any effect on stores.
+
+     Read memory barriers imply data dependency barriers, and so can substitute
+     for them.
+
+     [!] Note that read barriers should normally be paired with write barriers;
+     see the "SMP barrier pairing" subsection.
+
+
+ (4) General memory barriers.
+
+     A general memory barrier is a combination of both a read memory barrier
+     and a write memory barrier.  It is a partial ordering over both loads and
+     stores.
+
+     General memory barriers imply both read and write memory barriers, and so
+     can substitute for either.
+
+
+And a couple of implicit varieties:
+
+ (5) LOCK operations.
+
+     This acts as a one-way permeable barrier.  It guarantees that all memory
+     operations after the LOCK operation will appear to happen after the LOCK
+     operation with respect to the other components of the system.
+
+     Memory operations that occur before a LOCK operation may appear to happen
+     after it completes.
+
+     A LOCK operation should almost always be paired with an UNLOCK operation.
+
+
+ (6) UNLOCK operations.
+
+     This also acts as a one-way permeable barrier.  It guarantees that all
+     memory operations before the UNLOCK operation will appear to happen before
+     the UNLOCK operation with respect to the other components of the system.
+
+     Memory operations that occur after an UNLOCK operation may appear to
+     happen before it completes.
+
+     LOCK and UNLOCK operations are guaranteed to appear with respect to each
+     other strictly in the order specified.
+
+     The use of LOCK and UNLOCK operations generally precludes the need for
+     other sorts of memory barrier (but note the exceptions mentioned in the
+     subsection "MMIO write barrier").
+
+
+Memory barriers are only required where there's a possibility of interaction
+between two CPUs or between a CPU and a device.  If it can be guaranteed that
+there won't be any such interaction in any particular piece of code, then
+memory barriers are unnecessary in that piece of code.
+
+
+Note that these are the _minimum_ guarantees.  Different architectures may give
+more substantial guarantees, but they may _not_ be relied upon outside of arch
+specific code.
+
+
+WHAT MAY NOT BE ASSUMED ABOUT MEMORY BARRIERS?
+----------------------------------------------
+
+There are certain things that the Linux kernel memory barriers do not guarantee:
+
+ (*) There is no guarantee that any of the memory accesses specified before a
+     memory barrier will be _complete_ by the completion of a memory barrier
+     instruction; the barrier can be considered to draw a line in that CPU's
+     access queue that accesses of the appropriate type may not cross.
+
+ (*) There is no guarantee that issuing a memory barrier on one CPU will have
+     any direct effect on another CPU or any other hardware in the system.  The
+     indirect effect will be the order in which the second CPU sees the effects
+     of the first CPU's accesses occur, but see the next point:
+
+ (*) There is no guarantee that the a CPU will see the correct order of effects
+     from a second CPU's accesses, even _if_ the second CPU uses a memory
+     barrier, unless the first CPU _also_ uses a matching memory barrier (see
+     the subsection on "SMP Barrier Pairing").
+
+ (*) There is no guarantee that some intervening piece of off-the-CPU
+     hardware[*] will not reorder the memory accesses.  CPU cache coherency
+     mechanisms should propagate the indirect effects of a memory barrier
+     between CPUs, but might not do so in order.
+
+       [*] For information on bus mastering DMA and coherency please read:
+
+           Documentation/pci.txt
+           Documentation/DMA-mapping.txt
+           Documentation/DMA-API.txt
+
+
+DATA DEPENDENCY BARRIERS
+------------------------
+
+The usage requirements of data dependency barriers are a little subtle, and
+it's not always obvious that they're needed.  To illustrate, consider the
+following sequence of events:
+
+       CPU 1           CPU 2
+       =============== ===============
+       { A == 1, B == 2, C = 3, P == &A, Q == &C }
+       B = 4;
+       <write barrier>
+       P = &B
+                       Q = P;
+                       D = *Q;
+
+There's a clear data dependency here, and it would seem that by the end of the
+sequence, Q must be either &A or &B, and that:
+
+       (Q == &A) implies (D == 1)
+       (Q == &B) implies (D == 4)
+
+But! CPU 2's perception of P may be updated _before_ its perception of B, thus
+leading to the following situation:
+
+       (Q == &B) and (D == 2) ????
+
+Whilst this may seem like a failure of coherency or causality maintenance, it
+isn't, and this behaviour can be observed on certain real CPUs (such as the DEC
+Alpha).
+
+To deal with this, a data dependency barrier must be inserted between the
+address load and the data load:
+
+       CPU 1           CPU 2
+       =============== ===============
+       { A == 1, B == 2, C = 3, P == &A, Q == &C }
+       B = 4;
+       <write barrier>
+       P = &B
+                       Q = P;
+                       <data dependency barrier>
+                       D = *Q;
+
+This enforces the occurrence of one of the two implications, and prevents the
+third possibility from arising.
+
+[!] Note that this extremely counterintuitive situation arises most easily on
+machines with split caches, so that, for example, one cache bank processes
+even-numbered cache lines and the other bank processes odd-numbered cache
+lines.  The pointer P might be stored in an odd-numbered cache line, and the
+variable B might be stored in an even-numbered cache line.  Then, if the
+even-numbered bank of the reading CPU's cache is extremely busy while the
+odd-numbered bank is idle, one can see the new value of the pointer P (&B),
+but the old value of the variable B (1).
+
+
+Another example of where data dependency barriers might by required is where a
+number is read from memory and then used to calculate the index for an array
+access:
+
+       CPU 1           CPU 2
+       =============== ===============
+       { M[0] == 1, M[1] == 2, M[3] = 3, P == 0, Q == 3 }
+       M[1] = 4;
+       <write barrier>
+       P = 1
+                       Q = P;
+                       <data dependency barrier>
+                       D = M[Q];
+
+
+The data dependency barrier is very important to the RCU system, for example.
+See rcu_dereference() in include/linux/rcupdate.h.  This permits the current
+target of an RCU'd pointer to be replaced with a new modified target, without
+the replacement target appearing to be incompletely initialised.
+
+See also the subsection on "Cache Coherency" for a more thorough example.
+
+
+CONTROL DEPENDENCIES
+--------------------
+
+A control dependency requires a full read memory barrier, not simply a data
+dependency barrier to make it work correctly.  Consider the following bit of
+code:
+
+       q = &a;
+       if (p)
+               q = &b;
+       <data dependency barrier>
+       x = *q;
+
+This will not have the desired effect because there is no actual data
+dependency, but rather a control dependency that the CPU may short-circuit by
+attempting to predict the outcome in advance.  In such a case what's actually
+required is:
+
+       q = &a;
+       if (p)
+               q = &b;
+       <read barrier>
+       x = *q;
+
+
+SMP BARRIER PAIRING
+-------------------
+
+When dealing with CPU-CPU interactions, certain types of memory barrier should
+always be paired.  A lack of appropriate pairing is almost certainly an error.
+
+A write barrier should always be paired with a data dependency barrier or read
+barrier, though a general barrier would also be viable.  Similarly a read
+barrier or a data dependency barrier should always be paired with at least an
+write barrier, though, again, a general barrier is viable:
+
+       CPU 1           CPU 2
+       =============== ===============
+       a = 1;
+       <write barrier>
+       b = 2;          x = a;
+                       <read barrier>
+                       y = b;
+
+Or:
+
+       CPU 1           CPU 2
+       =============== ===============================
+       a = 1;
+       <write barrier>
+       b = &a;         x = b;
+                       <data dependency barrier>
+                       y = *x;
+
+Basically, the read barrier always has to be there, even though it can be of
+the "weaker" type.
+
+
+EXAMPLES OF MEMORY BARRIER SEQUENCES
+------------------------------------
+
+Firstly, write barriers act as a partial orderings on store operations.
+Consider the following sequence of events:
+
+       CPU 1
+       =======================
+       STORE A = 1
+       STORE B = 2
+       STORE C = 3
+       <write barrier>
+       STORE D = 4
+       STORE E = 5
+
+This sequence of events is committed to the memory coherence system in an order
+that the rest of the system might perceive as the unordered set of { STORE A,
+STORE B, STORE C } all occuring before the unordered set of { STORE D, STORE E
+}:
+
+       +-------+       :      :
+       |       |       +------+
+       |       |------>| C=3  |     }     /\
+       |       |  :    +------+     }-----  \  -----> Events perceptible
+       |       |  :    | A=1  |     }        \/       to rest of system
+       |       |  :    +------+     }
+       | CPU 1 |  :    | B=2  |     }
+       |       |       +------+     }
+       |       |   wwwwwwwwwwwwwwww }   <--- At this point the write barrier
+       |       |       +------+     }        requires all stores prior to the
+       |       |  :    | E=5  |     }        barrier to be committed before
+       |       |  :    +------+     }        further stores may be take place.
+       |       |------>| D=4  |     }
+       |       |       +------+
+       +-------+       :      :
+                          |
+                          | Sequence in which stores committed to memory system
+                          | by CPU 1
+                          V
+
+
+Secondly, data dependency barriers act as a partial orderings on data-dependent
+loads.  Consider the following sequence of events:
+
+       CPU 1                   CPU 2
+       ======================= =======================
+       STORE A = 1
+       STORE B = 2
+       <write barrier>
+       STORE C = &B            LOAD X
+       STORE D = 4             LOAD C (gets &B)
+                               LOAD *C (reads B)
+
+Without intervention, CPU 2 may perceive the events on CPU 1 in some
+effectively random order, despite the write barrier issued by CPU 1:
+
+       +-------+       :      :                :       :
+       |       |       +------+                +-------+  | Sequence of update
+       |       |------>| B=2  |-----       --->| Y->8  |  | of perception on
+       |       |  :    +------+     \          +-------+  | CPU 2
+       | CPU 1 |  :    | A=1  |      \     --->| C->&Y |  V
+       |       |       +------+       |        +-------+
+       |       |   wwwwwwwwwwwwwwww   |        :       :
+       |       |       +------+       |        :       :
+       |       |  :    | C=&B |---    |        :       :       +-------+
+       |       |  :    +------+   \   |        +-------+       |       |
+       |       |------>| D=4  |    ----------->| C->&B |------>|       |
+       |       |       +------+       |        +-------+       |       |
+       +-------+       :      :       |        :       :       |       |
+                                      |        :       :       |       |
+                                      |        :       :       | CPU 2 |
+                                      |        +-------+       |       |
+           Apparently incorrect --->  |        | B->7  |------>|       |
+           perception of B (!)        |        +-------+       |       |
+                                      |        :       :       |       |
+                                      |        +-------+       |       |
+           The load of X holds --->    \       | X->9  |------>|       |
+           up the maintenance           \      +-------+       |       |
+           of coherence of B             ----->| B->2  |       +-------+
+                                               +-------+
+                                               :       :
+
+
+In the above example, CPU 2 perceives that B is 7, despite the load of *C
+(which would be B) coming after the the LOAD of C.
+
+If, however, a data dependency barrier were to be placed between the load of C
+and the load of *C (ie: B) on CPU 2, then the following will occur:
+
+       +-------+       :      :                :       :
+       |       |       +------+                +-------+
+       |       |------>| B=2  |-----       --->| Y->8  |
+       |       |  :    +------+     \          +-------+
+       | CPU 1 |  :    | A=1  |      \     --->| C->&Y |
+       |       |       +------+       |        +-------+
+       |       |   wwwwwwwwwwwwwwww   |        :       :
+       |       |       +------+       |        :       :
+       |       |  :    | C=&B |---    |        :       :       +-------+
+       |       |  :    +------+   \   |        +-------+       |       |
+       |       |------>| D=4  |    ----------->| C->&B |------>|       |
+       |       |       +------+       |        +-------+       |       |
+       +-------+       :      :       |        :       :       |       |
+                                      |        :       :       |       |
+                                      |        :       :       | CPU 2 |
+                                      |        +-------+       |       |
+                                       \       | X->9  |------>|       |
+                                        \      +-------+       |       |
+                                         ----->| B->2  |       |       |
+                                               +-------+       |       |
+            Makes sure all effects --->    ddddddddddddddddd   |       |
+            prior to the store of C            +-------+       |       |
+            are perceptible to                 | B->2  |------>|       |
+            successive loads                   +-------+       |       |
+                                               :       :       +-------+
+
+
+And thirdly, a read barrier acts as a partial order on loads.  Consider the
+following sequence of events:
+
+       CPU 1                   CPU 2
+       ======================= =======================
+       STORE A=1
+       STORE B=2
+       STORE C=3
+       <write barrier>
+       STORE D=4
+       STORE E=5
+                               LOAD A
+                               LOAD B
+                               LOAD C
+                               LOAD D
+                               LOAD E
+
+Without intervention, CPU 2 may then choose to perceive the events on CPU 1 in
+some effectively random order, despite the write barrier issued by CPU 1:
+
+       +-------+       :      :
+       |       |       +------+
+       |       |------>| C=3  | }
+       |       |  :    +------+ }
+       |       |  :    | A=1  | }
+       |       |  :    +------+ }
+       | CPU 1 |  :    | B=2  | }---
+       |       |       +------+ }   \
+       |       |   wwwwwwwwwwwww}    \
+       |       |       +------+ }     \          :       :       +-------+
+       |       |  :    | E=5  | }      \         +-------+       |       |
+       |       |  :    +------+ }       \      { | C->3  |------>|       |
+       |       |------>| D=4  | }        \     { +-------+    :  |       |
+       |       |       +------+           \    { | E->5  |    :  |       |
+       +-------+       :      :            \   { +-------+    :  |       |
+                                  Transfer  -->{ | A->1  |    :  | CPU 2 |
+                                 from CPU 1    { +-------+    :  |       |
+                                  to CPU 2     { | D->4  |    :  |       |
+                                               { +-------+    :  |       |
+                                               { | B->2  |------>|       |
+                                                 +-------+       |       |
+                                                 :       :       +-------+
+
+
+If, however, a read barrier were to be placed between the load of C and the
+load of D on CPU 2, then the partial ordering imposed by CPU 1 will be
+perceived correctly by CPU 2.
+
+       +-------+       :      :
+       |       |       +------+
+       |       |------>| C=3  | }
+       |       |  :    +------+ }
+       |       |  :    | A=1  | }---
+       |       |  :    +------+ }   \
+       | CPU 1 |  :    | B=2  | }    \
+       |       |       +------+       \
+       |       |   wwwwwwwwwwwwwwww    \
+       |       |       +------+         \        :       :       +-------+
+       |       |  :    | E=5  | }        \       +-------+       |       |
+       |       |  :    +------+ }---      \    { | C->3  |------>|       |
+       |       |------>| D=4  | }   \      \   { +-------+    :  |       |
+       |       |       +------+      \      -->{ | B->2  |    :  |       |
+       +-------+       :      :       \        { +-------+    :  |       |
+                                       \       { | A->1  |    :  | CPU 2 |
+                                        \        +-------+       |       |
+          At this point the read ---->   \   rrrrrrrrrrrrrrrrr   |       |
+          barrier causes all effects      \      +-------+       |       |
+          prior to the storage of C        \   { | E->5  |    :  |       |
+          to be perceptible to CPU 2        -->{ +-------+    :  |       |
+                                               { | D->4  |------>|       |
+                                                 +-------+       |       |
+                                                 :       :       +-------+
+
+
+========================
+EXPLICIT KERNEL BARRIERS
+========================
+
+The Linux kernel has a variety of different barriers that act at different
+levels:
+
+  (*) Compiler barrier.
+
+  (*) CPU memory barriers.
+
+  (*) MMIO write barrier.
+
+
+COMPILER BARRIER
+----------------
+
+The Linux kernel has an explicit compiler barrier function that prevents the
+compiler from moving the memory accesses either side of it to the other side:
+
+       barrier();
+
+This a general barrier - lesser varieties of compiler barrier do not exist.
+
+The compiler barrier has no direct effect on the CPU, which may then reorder
+things however it wishes.
+
+
+CPU MEMORY BARRIERS
+-------------------
+
+The Linux kernel has eight basic CPU memory barriers:
+
+       TYPE            MANDATORY               SMP CONDITIONAL
+       =============== ======================= ===========================
+       GENERAL         mb()                    smp_mb()
+       WRITE           wmb()                   smp_wmb()
+       READ            rmb()                   smp_rmb()
+       DATA DEPENDENCY read_barrier_depends()  smp_read_barrier_depends()
+
+
+All CPU memory barriers unconditionally imply compiler barriers.
+
+SMP memory barriers are reduced to compiler barriers on uniprocessor compiled
+systems because it is assumed that a CPU will be appear to be self-consistent,
+and will order overlapping accesses correctly with respect to itself.
+
+[!] Note that SMP memory barriers _must_ be used to control the ordering of
+references to shared memory on SMP systems, though the use of locking instead
+is sufficient.
+
+Mandatory barriers should not be used to control SMP effects, since mandatory
+barriers unnecessarily impose overhead on UP systems. They may, however, be
+used to control MMIO effects on accesses through relaxed memory I/O windows.
+These are required even on non-SMP systems as they affect the order in which
+memory operations appear to a device by prohibiting both the compiler and the
+CPU from reordering them.
+
+
+There are some more advanced barrier functions:
+
+ (*) set_mb(var, value)
+ (*) set_wmb(var, value)
+
+     These assign the value to the variable and then insert at least a write
+     barrier after it, depending on the function.  They aren't guaranteed to
+     insert anything more than a compiler barrier in a UP compilation.
+
+
+ (*) smp_mb__before_atomic_dec();
+ (*) smp_mb__after_atomic_dec();
+ (*) smp_mb__before_atomic_inc();
+ (*) smp_mb__after_atomic_inc();
+
+     These are for use with atomic add, subtract, increment and decrement
+     functions, especially when used for reference counting.  These functions
+     do not imply memory barriers.
+
+     As an example, consider a piece of code that marks an object as being dead
+     and then decrements the object's reference count:
+
+       obj->dead = 1;
+       smp_mb__before_atomic_dec();
+       atomic_dec(&obj->ref_count);
+
+     This makes sure that the death mark on the object is perceived to be set
+     *before* the reference counter is decremented.
+
+     See Documentation/atomic_ops.txt for more information.  See the "Atomic
+     operations" subsection for information on where to use these.
+
+
+ (*) smp_mb__before_clear_bit(void);
+ (*) smp_mb__after_clear_bit(void);
+
+     These are for use similar to the atomic inc/dec barriers.  These are
+     typically used for bitwise unlocking operations, so care must be taken as
+     there are no implicit memory barriers here either.
+
+     Consider implementing an unlock operation of some nature by clearing a
+     locking bit.  The clear_bit() would then need to be barriered like this:
+
+       smp_mb__before_clear_bit();
+       clear_bit( ... );
+
+     This prevents memory operations before the clear leaking to after it.  See
+     the subsection on "Locking Functions" with reference to UNLOCK operation
+     implications.
+
+     See Documentation/atomic_ops.txt for more information.  See the "Atomic
+     operations" subsection for information on where to use these.
+
+
+MMIO WRITE BARRIER
+------------------
+
+The Linux kernel also has a special barrier for use with memory-mapped I/O
+writes:
+
+       mmiowb();
+
+This is a variation on the mandatory write barrier that causes writes to weakly
+ordered I/O regions to be partially ordered.  Its effects may go beyond the
+CPU->Hardware interface and actually affect the hardware at some level.
+
+See the subsection "Locks vs I/O accesses" for more information.
+
+
+===============================
+IMPLICIT KERNEL MEMORY BARRIERS
+===============================
+
+Some of the other functions in the linux kernel imply memory barriers, amongst
+which are locking, scheduling and memory allocation functions.
+
+This specification is a _minimum_ guarantee; any particular architecture may
+provide more substantial guarantees, but these may not be relied upon outside
+of arch specific code.
+
+
+LOCKING FUNCTIONS
+-----------------
+
+The Linux kernel has a number of locking constructs:
+
+ (*) spin locks
+ (*) R/W spin locks
+ (*) mutexes
+ (*) semaphores
+ (*) R/W semaphores
+ (*) RCU
+
+In all cases there are variants on "LOCK" operations and "UNLOCK" operations
+for each construct.  These operations all imply certain barriers:
+
+ (1) LOCK operation implication:
+
+     Memory operations issued after the LOCK will be completed after the LOCK
+     operation has completed.
+
+     Memory operations issued before the LOCK may be completed after the LOCK
+     operation has completed.
+
+ (2) UNLOCK operation implication:
+
+     Memory operations issued before the UNLOCK will be completed before the
+     UNLOCK operation has completed.
+
+     Memory operations issued after the UNLOCK may be completed before the
+     UNLOCK operation has completed.
+
+ (3) LOCK vs LOCK implication:
+
+     All LOCK operations issued before another LOCK operation will be completed
+     before that LOCK operation.
+
+ (4) LOCK vs UNLOCK implication:
+
+     All LOCK operations issued before an UNLOCK operation will be completed
+     before the UNLOCK operation.
+
+     All UNLOCK operations issued before a LOCK operation will be completed
+     before the LOCK operation.
+
+ (5) Failed conditional LOCK implication:
+
+     Certain variants of the LOCK operation may fail, either due to being
+     unable to get the lock immediately, or due to receiving an unblocked
+     signal whilst asleep waiting for the lock to become available.  Failed
+     locks do not imply any sort of barrier.
+
+Therefore, from (1), (2) and (4) an UNLOCK followed by an unconditional LOCK is
+equivalent to a full barrier, but a LOCK followed by an UNLOCK is not.
+
+[!] Note: one of the consequence of LOCKs and UNLOCKs being only one-way
+    barriers is that the effects instructions outside of a critical section may
+    seep into the inside of the critical section.
+
+Locks and semaphores may not provide any guarantee of ordering on UP compiled
+systems, and so cannot be counted on in such a situation to actually achieve
+anything at all - especially with respect to I/O accesses - unless combined
+with interrupt disabling operations.
+
+See also the section on "Inter-CPU locking barrier effects".
+
+
+As an example, consider the following:
+
+       *A = a;
+       *B = b;
+       LOCK
+       *C = c;
+       *D = d;
+       UNLOCK
+       *E = e;
+       *F = f;
+
+The following sequence of events is acceptable:
+
+       LOCK, {*F,*A}, *E, {*C,*D}, *B, UNLOCK
+
+       [+] Note that {*F,*A} indicates a combined access.
+
+But none of the following are:
+
+       {*F,*A}, *B,    LOCK, *C, *D,   UNLOCK, *E
+       *A, *B, *C,     LOCK, *D,       UNLOCK, *E, *F
+       *A, *B,         LOCK, *C,       UNLOCK, *D, *E, *F
+       *B,             LOCK, *C, *D,   UNLOCK, {*F,*A}, *E
+
+
+
+INTERRUPT DISABLING FUNCTIONS
+-----------------------------
+
+Functions that disable interrupts (LOCK equivalent) and enable interrupts
+(UNLOCK equivalent) will act as compiler barriers only.  So if memory or I/O
+barriers are required in such a situation, they must be provided from some
+other means.
+
+
+MISCELLANEOUS FUNCTIONS
+-----------------------
+
+Other functions that imply barriers:
+
+ (*) schedule() and similar imply full memory barriers.
+
+ (*) Memory allocation and release functions imply full memory barriers.
+
+
+=================================
+INTER-CPU LOCKING BARRIER EFFECTS
+=================================
+
+On SMP systems locking primitives give a more substantial form of barrier: one
+that does affect memory access ordering on other CPUs, within the context of
+conflict on any particular lock.
+
+
+LOCKS VS MEMORY ACCESSES
+------------------------
+
+Consider the following: the system has a pair of spinlocks (N) and (Q), and
+three CPUs; then should the following sequence of events occur:
+
+       CPU 1                           CPU 2
+       =============================== ===============================
+       *A = a;                         *E = e;
+       LOCK M                          LOCK Q
+       *B = b;                         *F = f;
+       *C = c;                         *G = g;
+       UNLOCK M                        UNLOCK Q
+       *D = d;                         *H = h;
+
+Then there is no guarantee as to what order CPU #3 will see the accesses to *A
+through *H occur in, other than the constraints imposed by the separate locks
+on the separate CPUs. It might, for example, see:
+
+       *E, LOCK M, LOCK Q, *G, *C, *F, *A, *B, UNLOCK Q, *D, *H, UNLOCK M
+
+But it won't see any of:
+
+       *B, *C or *D preceding LOCK M
+       *A, *B or *C following UNLOCK M
+       *F, *G or *H preceding LOCK Q
+       *E, *F or *G following UNLOCK Q
+
+
+However, if the following occurs:
+
+       CPU 1                           CPU 2
+       =============================== ===============================
+       *A = a;
+       LOCK M          [1]
+       *B = b;
+       *C = c;
+       UNLOCK M        [1]
+       *D = d;                         *E = e;
+                                       LOCK M          [2]
+                                       *F = f;
+                                       *G = g;
+                                       UNLOCK M        [2]
+                                       *H = h;
+
+CPU #3 might see:
+
+       *E, LOCK M [1], *C, *B, *A, UNLOCK M [1],
+               LOCK M [2], *H, *F, *G, UNLOCK M [2], *D
+
+But assuming CPU #1 gets the lock first, it won't see any of:
+
+       *B, *C, *D, *F, *G or *H preceding LOCK M [1]
+       *A, *B or *C following UNLOCK M [1]
+       *F, *G or *H preceding LOCK M [2]
+       *A, *B, *C, *E, *F or *G following UNLOCK M [2]
+
+
+LOCKS VS I/O ACCESSES
+---------------------
+
+Under certain circumstances (especially involving NUMA), I/O accesses within
+two spinlocked sections on two different CPUs may be seen as interleaved by the
+PCI bridge, because the PCI bridge does not necessarily participate in the
+cache-coherence protocol, and is therefore incapable of issuing the required
+read memory barriers.
+
+For example:
+
+       CPU 1                           CPU 2
+       =============================== ===============================
+       spin_lock(Q)
+       writel(0, ADDR)
+       writel(1, DATA);
+       spin_unlock(Q);
+                                       spin_lock(Q);
+                                       writel(4, ADDR);
+                                       writel(5, DATA);
+                                       spin_unlock(Q);
+
+may be seen by the PCI bridge as follows:
+
+       STORE *ADDR = 0, STORE *ADDR = 4, STORE *DATA = 1, STORE *DATA = 5
+
+which would probably cause the hardware to malfunction.
+
+
+What is necessary here is to intervene with an mmiowb() before dropping the
+spinlock, for example:
+
+       CPU 1                           CPU 2
+       =============================== ===============================
+       spin_lock(Q)
+       writel(0, ADDR)
+       writel(1, DATA);
+       mmiowb();
+       spin_unlock(Q);
+                                       spin_lock(Q);
+                                       writel(4, ADDR);
+                                       writel(5, DATA);
+                                       mmiowb();
+                                       spin_unlock(Q);
+
+this will ensure that the two stores issued on CPU #1 appear at the PCI bridge
+before either of the stores issued on CPU #2.
+
+
+Furthermore, following a store by a load to the same device obviates the need
+for an mmiowb(), because the load forces the store to complete before the load
+is performed:
+
+       CPU 1                           CPU 2
+       =============================== ===============================
+       spin_lock(Q)
+       writel(0, ADDR)
+       a = readl(DATA);
+       spin_unlock(Q);
+                                       spin_lock(Q);
+                                       writel(4, ADDR);
+                                       b = readl(DATA);
+                                       spin_unlock(Q);
+
+
+See Documentation/DocBook/deviceiobook.tmpl for more information.
+
+
+=================================
+WHERE ARE MEMORY BARRIERS NEEDED?
+=================================
+
+Under normal operation, memory operation reordering is generally not going to
+be a problem as a single-threaded linear piece of code will still appear to
+work correctly, even if it's in an SMP kernel.  There are, however, three
+circumstances in which reordering definitely _could_ be a problem:
+
+ (*) Interprocessor interaction.
+
+ (*) Atomic operations.
+
+ (*) Accessing devices (I/O).
+
+ (*) Interrupts.
+
+
+INTERPROCESSOR INTERACTION
+--------------------------
+
+When there's a system with more than one processor, more than one CPU in the
+system may be working on the same data set at the same time.  This can cause
+synchronisation problems, and the usual way of dealing with them is to use
+locks.  Locks, however, are quite expensive, and so it may be preferable to
+operate without the use of a lock if at all possible.  In such a case
+operations that affect both CPUs may have to be carefully ordered to prevent
+a malfunction.
+
+Consider, for example, the R/W semaphore slow path.  Here a waiting process is
+queued on the semaphore, by virtue of it having a piece of its stack linked to
+the semaphore's list of waiting processes:
+
+       struct rw_semaphore {
+               ...
+               spinlock_t lock;
+               struct list_head waiters;
+       };
+
+       struct rwsem_waiter {
+               struct list_head list;
+               struct task_struct *task;
+       };
+
+To wake up a particular waiter, the up_read() or up_write() functions have to:
+
+ (1) read the next pointer from this waiter's record to know as to where the
+     next waiter record is;
+
+ (4) read the pointer to the waiter's task structure;
+
+ (3) clear the task pointer to tell the waiter it has been given the semaphore;
+
+ (4) call wake_up_process() on the task; and
+
+ (5) release the reference held on the waiter's task struct.
+
+In otherwords, it has to perform this sequence of events:
+
+       LOAD waiter->list.next;
+       LOAD waiter->task;
+       STORE waiter->task;
+       CALL wakeup
+       RELEASE task
+
+and if any of these steps occur out of order, then the whole thing may
+malfunction.
+
+Once it has queued itself and dropped the semaphore lock, the waiter does not
+get the lock again; it instead just waits for its task pointer to be cleared
+before proceeding.  Since the record is on the waiter's stack, this means that
+if the task pointer is cleared _before_ the next pointer in the list is read,
+another CPU might start processing the waiter and might clobber the waiter's
+stack before the up*() function has a chance to read the next pointer.
+
+Consider then what might happen to the above sequence of events:
+
+       CPU 1                           CPU 2
+       =============================== ===============================
+                                       down_xxx()
+                                       Queue waiter
+                                       Sleep
+       up_yyy()
+       LOAD waiter->task;
+       STORE waiter->task;
+                                       Woken up by other event
+       <preempt>
+                                       Resume processing
+                                       down_xxx() returns
+                                       call foo()
+                                       foo() clobbers *waiter
+       </preempt>
+       LOAD waiter->list.next;
+       --- OOPS ---
+
+This could be dealt with using the semaphore lock, but then the down_xxx()
+function has to needlessly get the spinlock again after being woken up.
+
+The way to deal with this is to insert a general SMP memory barrier:
+
+       LOAD waiter->list.next;
+       LOAD waiter->task;
+       smp_mb();
+       STORE waiter->task;
+       CALL wakeup
+       RELEASE task
+
+In this case, the barrier makes a guarantee that all memory accesses before the
+barrier will appear to happen before all the memory accesses after the barrier
+with respect to the other CPUs on the system.  It does _not_ guarantee that all
+the memory accesses before the barrier will be complete by the time the barrier
+instruction itself is complete.
+
+On a UP system - where this wouldn't be a problem - the smp_mb() is just a
+compiler barrier, thus making sure the compiler emits the instructions in the
+right order without actually intervening in the CPU.  Since there there's only
+one CPU, that CPU's dependency ordering logic will take care of everything
+else.
+
+
+ATOMIC OPERATIONS
+-----------------
+
+Though they are technically interprocessor interaction considerations, atomic
+operations are noted specially as they do _not_ generally imply memory
+barriers.  The possible offenders include:
+
+       xchg();
+       cmpxchg();
+       test_and_set_bit();
+       test_and_clear_bit();
+       test_and_change_bit();
+       atomic_cmpxchg();
+       atomic_inc_return();
+       atomic_dec_return();
+       atomic_add_return();
+       atomic_sub_return();
+       atomic_inc_and_test();
+       atomic_dec_and_test();
+       atomic_sub_and_test();
+       atomic_add_negative();
+       atomic_add_unless();
+
+These may be used for such things as implementing LOCK operations or controlling
+the lifetime of objects by decreasing their reference counts.  In such cases
+they need preceding memory barriers.
+
+The following may also be possible offenders as they may be used as UNLOCK
+operations.
+
+       set_bit();
+       clear_bit();
+       change_bit();
+       atomic_set();
+
+
+The following are a little tricky:
+
+       atomic_add();
+       atomic_sub();
+       atomic_inc();
+       atomic_dec();
+
+If they're used for statistics generation, then they probably don't need memory
+barriers, unless there's a coupling between statistical data.
+
+If they're used for reference counting on an object to control its lifetime,
+they probably don't need memory barriers because either the reference count
+will be adjusted inside a locked section, or the caller will already hold
+sufficient references to make the lock, and thus a memory barrier unnecessary.
+
+If they're used for constructing a lock of some description, then they probably
+do need memory barriers as a lock primitive generally has to do things in a
+specific order.
+
+
+Basically, each usage case has to be carefully considered as to whether memory
+barriers are needed or not.  The simplest rule is probably: if the atomic
+operation is protected by a lock, then it does not require a barrier unless
+there's another operation within the critical section with respect to which an
+ordering must be maintained.
+
+See Documentation/atomic_ops.txt for more information.
+
+
+ACCESSING DEVICES
+-----------------
+
+Many devices can be memory mapped, and so appear to the CPU as if they're just
+a set of memory locations.  To control such a device, the driver usually has to
+make the right memory accesses in exactly the right order.
+
+However, having a clever CPU or a clever compiler creates a potential problem
+in that the carefully sequenced accesses in the driver code won't reach the
+device in the requisite order if the CPU or the compiler thinks it is more
+efficient to reorder, combine or merge accesses - something that would cause
+the device to malfunction.
+
+Inside of the Linux kernel, I/O should be done through the appropriate accessor
+routines - such as inb() or writel() - which know how to make such accesses
+appropriately sequential.  Whilst this, for the most part, renders the explicit
+use of memory barriers unnecessary, there are a couple of situations where they
+might be needed:
+
+ (1) On some systems, I/O stores are not strongly ordered across all CPUs, and
+     so for _all_ general drivers locks should be used and mmiowb() must be
+     issued prior to unlocking the critical section.
+
+ (2) If the accessor functions are used to refer to an I/O memory window with
+     relaxed memory access properties, then _mandatory_ memory barriers are
+     required to enforce ordering.
+
+See Documentation/DocBook/deviceiobook.tmpl for more information.
+
+
+INTERRUPTS
+----------
+
+A driver may be interrupted by its own interrupt service routine, and thus the
+two parts of the driver may interfere with each other's attempts to control or
+access the device.
+
+This may be alleviated - at least in part - by disabling local interrupts (a
+form of locking), such that the critical operations are all contained within
+the interrupt-disabled section in the driver.  Whilst the driver's interrupt
+routine is executing, the driver's core may not run on the same CPU, and its
+interrupt is not permitted to happen again until the current interrupt has been
+handled, thus the interrupt handler does not need to lock against that.
+
+However, consider a driver that was talking to an ethernet card that sports an
+address register and a data register.  If that driver's core talks to the card
+under interrupt-disablement and then the driver's interrupt handler is invoked:
+
+       LOCAL IRQ DISABLE
+       writew(ADDR, 3);
+       writew(DATA, y);
+       LOCAL IRQ ENABLE
+       <interrupt>
+       writew(ADDR, 4);
+       q = readw(DATA);
+       </interrupt>
+
+The store to the data register might happen after the second store to the
+address register if ordering rules are sufficiently relaxed:
+
+       STORE *ADDR = 3, STORE *ADDR = 4, STORE *DATA = y, q = LOAD *DATA
+
+
+If ordering rules are relaxed, it must be assumed that accesses done inside an
+interrupt disabled section may leak outside of it and may interleave with
+accesses performed in an interrupt - and vice versa - unless implicit or
+explicit barriers are used.
+
+Normally this won't be a problem because the I/O accesses done inside such
+sections will include synchronous load operations on strictly ordered I/O
+registers that form implicit I/O barriers. If this isn't sufficient then an
+mmiowb() may need to be used explicitly.
+
+
+A similar situation may occur between an interrupt routine and two routines
+running on separate CPUs that communicate with each other. If such a case is
+likely, then interrupt-disabling locks should be used to guarantee ordering.
+
+
+==========================
+KERNEL I/O BARRIER EFFECTS
+==========================
+
+When accessing I/O memory, drivers should use the appropriate accessor
+functions:
+
+ (*) inX(), outX():
+
+     These are intended to talk to I/O space rather than memory space, but
+     that's primarily a CPU-specific concept. The i386 and x86_64 processors do
+     indeed have special I/O space access cycles and instructions, but many
+     CPUs don't have such a concept.
+
+     The PCI bus, amongst others, defines an I/O space concept - which on such
+     CPUs as i386 and x86_64 cpus readily maps to the CPU's concept of I/O
+     space.  However, it may also mapped as a virtual I/O space in the CPU's
+     memory map, particularly on those CPUs that don't support alternate
+     I/O spaces.
+
+     Accesses to this space may be fully synchronous (as on i386), but
+     intermediary bridges (such as the PCI host bridge) may not fully honour
+     that.
+
+     They are guaranteed to be fully ordered with respect to each other.
+
+     They are not guaranteed to be fully ordered with respect to other types of
+     memory and I/O operation.
+
+ (*) readX(), writeX():
+
+     Whether these are guaranteed to be fully ordered and uncombined with
+     respect to each other on the issuing CPU depends on the characteristics
+     defined for the memory window through which they're accessing. On later
+     i386 architecture machines, for example, this is controlled by way of the
+     MTRR registers.
+
+     Ordinarily, these will be guaranteed to be fully ordered and uncombined,,
+     provided they're not accessing a prefetchable device.
+
+     However, intermediary hardware (such as a PCI bridge) may indulge in
+     deferral if it so wishes; to flush a store, a load from the same location
+     is preferred[*], but a load from the same device or from configuration
+     space should suffice for PCI.
+
+     [*] NOTE! attempting to load from the same location as was written to may
+        cause a malfunction - consider the 16550 Rx/Tx serial registers for
+        example.
+
+     Used with prefetchable I/O memory, an mmiowb() barrier may be required to
+     force stores to be ordered.
+
+     Please refer to the PCI specification for more information on interactions
+     between PCI transactions.
+
+ (*) readX_relaxed()
+
+     These are similar to readX(), but are not guaranteed to be ordered in any
+     way. Be aware that there is no I/O read barrier available.
+
+ (*) ioreadX(), iowriteX()
+
+     These will perform as appropriate for the type of access they're actually
+     doing, be it inX()/outX() or readX()/writeX().
+
+
+========================================
+ASSUMED MINIMUM EXECUTION ORDERING MODEL
+========================================
+
+It has to be assumed that the conceptual CPU is weakly-ordered but that it will
+maintain the appearance of program causality with respect to itself.  Some CPUs
+(such as i386 or x86_64) are more constrained than others (such as powerpc or
+frv), and so the most relaxed case (namely DEC Alpha) must be assumed outside
+of arch-specific code.
+
+This means that it must be considered that the CPU will execute its instruction
+stream in any order it feels like - or even in parallel - provided that if an
+instruction in the stream depends on the an earlier instruction, then that
+earlier instruction must be sufficiently complete[*] before the later
+instruction may proceed; in other words: provided that the appearance of
+causality is maintained.
+
+ [*] Some instructions have more than one effect - such as changing the
+     condition codes, changing registers or changing memory - and different
+     instructions may depend on different effects.
+
+A CPU may also discard any instruction sequence that winds up having no
+ultimate effect.  For example, if two adjacent instructions both load an
+immediate value into the same register, the first may be discarded.
+
+
+Similarly, it has to be assumed that compiler might reorder the instruction
+stream in any way it sees fit, again provided the appearance of causality is
+maintained.
+
+
+============================
+THE EFFECTS OF THE CPU CACHE
+============================
+
+The way cached memory operations are perceived across the system is affected to
+a certain extent by the caches that lie between CPUs and memory, and by the
+memory coherence system that maintains the consistency of state in the system.
+
+As far as the way a CPU interacts with another part of the system through the
+caches goes, the memory system has to include the CPU's caches, and memory
+barriers for the most part act at the interface between the CPU and its cache
+(memory barriers logically act on the dotted line in the following diagram):
+
+           <--- CPU --->         :       <----------- Memory ----------->
+                                 :
+       +--------+    +--------+  :   +--------+    +-----------+
+       |        |    |        |  :   |        |    |           |    +--------+
+       |  CPU   |    | Memory |  :   | CPU    |    |           |    |        |
+       |  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
+       |        |    | Queue  |  :   |        |    |           |--->| Memory |
+       |        |    |        |  :   |        |    |           |    |        |
+       +--------+    +--------+  :   +--------+    |           |    |        |
+                                 :                 | Cache     |    +--------+
+                                 :                 | Coherency |
+                                 :                 | Mechanism |    +--------+
+       +--------+    +--------+  :   +--------+    |           |    |        |
+       |        |    |        |  :   |        |    |           |    |        |
+       |  CPU   |    | Memory |  :   | CPU    |    |           |--->| Device |
+       |  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
+       |        |    | Queue  |  :   |        |    |           |    |        |
+       |        |    |        |  :   |        |    |           |    +--------+
+       +--------+    +--------+  :   +--------+    +-----------+
+                                 :
+                                 :
+
+Although any particular load or store may not actually appear outside of the
+CPU that issued it since it may have been satisfied within the CPU's own cache,
+it will still appear as if the full memory access had taken place as far as the
+other CPUs are concerned since the cache coherency mechanisms will migrate the
+cacheline over to the accessing CPU and propagate the effects upon conflict.
+
+The CPU core may execute instructions in any order it deems fit, provided the
+expected program causality appears to be maintained.  Some of the instructions
+generate load and store operations which then go into the queue of memory
+accesses to be performed.  The core may place these in the queue in any order
+it wishes, and continue execution until it is forced to wait for an instruction
+to complete.
+
+What memory barriers are concerned with is controlling the order in which
+accesses cross from the CPU side of things to the memory side of things, and
+the order in which the effects are perceived to happen by the other observers
+in the system.
+
+[!] Memory barriers are _not_ needed within a given CPU, as CPUs always see
+their own loads and stores as if they had happened in program order.
+
+[!] MMIO or other device accesses may bypass the cache system.  This depends on
+the properties of the memory window through which devices are accessed and/or
+the use of any special device communication instructions the CPU may have.
+
+
+CACHE COHERENCY
+---------------
+
+Life isn't quite as simple as it may appear above, however: for while the
+caches are expected to be coherent, there's no guarantee that that coherency
+will be ordered.  This means that whilst changes made on one CPU will
+eventually become visible on all CPUs, there's no guarantee that they will
+become apparent in the same order on those other CPUs.
+
+
+Consider dealing with a system that has pair of CPUs (1 & 2), each of which has
+a pair of parallel data caches (CPU 1 has A/B, and CPU 2 has C/D):
+
+                   :
+                   :                          +--------+
+                   :      +---------+         |        |
+       +--------+  : +--->| Cache A |<------->|        |
+       |        |  : |    +---------+         |        |
+       |  CPU 1 |<---+                        |        |
+       |        |  : |    +---------+         |        |
+       +--------+  : +--->| Cache B |<------->|        |
+                   :      +---------+         |        |
+                   :                          | Memory |
+                   :      +---------+         | System |
+       +--------+  : +--->| Cache C |<------->|        |
+       |        |  : |    +---------+         |        |
+       |  CPU 2 |<---+                        |        |
+       |        |  : |    +---------+         |        |
+       +--------+  : +--->| Cache D |<------->|        |
+                   :      +---------+         |        |
+                   :                          +--------+
+                   :
+
+Imagine the system has the following properties:
+
+ (*) an odd-numbered cache line may be in cache A, cache C or it may still be
+     resident in memory;
+
+ (*) an even-numbered cache line may be in cache B, cache D or it may still be
+     resident in memory;
+
+ (*) whilst the CPU core is interrogating one cache, the other cache may be
+     making use of the bus to access the rest of the system - perhaps to
+     displace a dirty cacheline or to do a speculative load;
+
+ (*) each cache has a queue of operations that need to be applied to that cache
+     to maintain coherency with the rest of the system;
+
+ (*) the coherency queue is not flushed by normal loads to lines already
+     present in the cache, even though the contents of the queue may
+     potentially effect those loads.
+
+Imagine, then, that two writes are made on the first CPU, with a write barrier
+between them to guarantee that they will appear to reach that CPU's caches in
+the requisite order:
+
+       CPU 1           CPU 2           COMMENT
+       =============== =============== =======================================
+                                       u == 0, v == 1 and p == &u, q == &u
+       v = 2;
+       smp_wmb();                      Make sure change to v visible before
+                                        change to p
+       <A:modify v=2>                  v is now in cache A exclusively
+       p = &v;
+       <B:modify p=&v>                 p is now in cache B exclusively
+
+The write memory barrier forces the other CPUs in the system to perceive that
+the local CPU's caches have apparently been updated in the correct order.  But
+now imagine that the second CPU that wants to read those values:
+
+       CPU 1           CPU 2           COMMENT
+       =============== =============== =======================================
+       ...
+                       q = p;
+                       x = *q;
+
+The above pair of reads may then fail to happen in expected order, as the
+cacheline holding p may get updated in one of the second CPU's caches whilst
+the update to the cacheline holding v is delayed in the other of the second
+CPU's caches by some other cache event:
+
+       CPU 1           CPU 2           COMMENT
+       =============== =============== =======================================
+                                       u == 0, v == 1 and p == &u, q == &u
+       v = 2;
+       smp_wmb();
+       <A:modify v=2>  <C:busy>
+                       <C:queue v=2>
+       p = &b;         q = p;
+                       <D:request p>
+       <B:modify p=&v> <D:commit p=&v>
+                       <D:read p>
+                       x = *q;
+                       <C:read *q>     Reads from v before v updated in cache
+                       <C:unbusy>
+                       <C:commit v=2>
+
+Basically, whilst both cachelines will be updated on CPU 2 eventually, there's
+no guarantee that, without intervention, the order of update will be the same
+as that committed on CPU 1.
+
+
+To intervene, we need to interpolate a data dependency barrier or a read
+barrier between the loads.  This will force the cache to commit its coherency
+queue before processing any further requests:
+
+       CPU 1           CPU 2           COMMENT
+       =============== =============== =======================================
+                                       u == 0, v == 1 and p == &u, q == &u
+       v = 2;
+       smp_wmb();
+       <A:modify v=2>  <C:busy>
+                       <C:queue v=2>
+       p = &b;         q = p;
+                       <D:request p>
+       <B:modify p=&v> <D:commit p=&v>
+                       <D:read p>
+                       smp_read_barrier_depends()
+                       <C:unbusy>
+                       <C:commit v=2>
+                       x = *q;
+                       <C:read *q>     Reads from v after v updated in cache
+
+
+This sort of problem can be encountered on DEC Alpha processors as they have a
+split cache that improves performance by making better use of the data bus.
+Whilst most CPUs do imply a data dependency barrier on the read when a memory
+access depends on a read, not all do, so it may not be relied on.
+
+Other CPUs may also have split caches, but must coordinate between the various
+cachelets for normal memory accesss.  The semantics of the Alpha removes the
+need for coordination in absence of memory barriers.
+
+
+CACHE COHERENCY VS DMA
+----------------------
+
+Not all systems maintain cache coherency with respect to devices doing DMA.  In
+such cases, a device attempting DMA may obtain stale data from RAM because
+dirty cache lines may be resident in the caches of various CPUs, and may not
+have been written back to RAM yet.  To deal with this, the appropriate part of
+the kernel must flush the overlapping bits of cache on each CPU (and maybe
+invalidate them as well).
+
+In addition, the data DMA'd to RAM by a device may be overwritten by dirty
+cache lines being written back to RAM from a CPU's cache after the device has
+installed its own data, or cache lines simply present in a CPUs cache may
+simply obscure the fact that RAM has been updated, until at such time as the
+cacheline is discarded from the CPU's cache and reloaded.  To deal with this,
+the appropriate part of the kernel must invalidate the overlapping bits of the
+cache on each CPU.
+
+See Documentation/cachetlb.txt for more information on cache management.
+
+
+CACHE COHERENCY VS MMIO
+-----------------------
+
+Memory mapped I/O usually takes place through memory locations that are part of
+a window in the CPU's memory space that have different properties assigned than
+the usual RAM directed window.
+
+Amongst these properties is usually the fact that such accesses bypass the
+caching entirely and go directly to the device buses.  This means MMIO accesses
+may, in effect, overtake accesses to cached memory that were emitted earlier.
+A memory barrier isn't sufficient in such a case, but rather the cache must be
+flushed between the cached memory write and the MMIO access if the two are in
+any way dependent.
+
+
+=========================
+THE THINGS CPUS GET UP TO
+=========================
+
+A programmer might take it for granted that the CPU will perform memory
+operations in exactly the order specified, so that if a CPU is, for example,
+given the following piece of code to execute:
+
+       a = *A;
+       *B = b;
+       c = *C;
+       d = *D;
+       *E = e;
+
+They would then expect that the CPU will complete the memory operation for each
+instruction before moving on to the next one, leading to a definite sequence of
+operations as seen by external observers in the system:
+
+       LOAD *A, STORE *B, LOAD *C, LOAD *D, STORE *E.
+
+
+Reality is, of course, much messier.  With many CPUs and compilers, the above
+assumption doesn't hold because:
+
+ (*) loads are more likely to need to be completed immediately to permit
+     execution progress, whereas stores can often be deferred without a
+     problem;
+
+ (*) loads may be done speculatively, and the result discarded should it prove
+     to have been unnecessary;
+
+ (*) loads may be done speculatively, leading to the result having being
+     fetched at the wrong time in the expected sequence of events;
+
+ (*) the order of the memory accesses may be rearranged to promote better use
+     of the CPU buses and caches;
+
+ (*) loads and stores may be combined to improve performance when talking to
+     memory or I/O hardware that can do batched accesses of adjacent locations,
+     thus cutting down on transaction setup costs (memory and PCI devices may
+     both be able to do this); and
+
+ (*) the CPU's data cache may affect the ordering, and whilst cache-coherency
+     mechanisms may alleviate this - once the store has actually hit the cache
+     - there's no guarantee that the coherency management will be propagated in
+     order to other CPUs.
+
+So what another CPU, say, might actually observe from the above piece of code
+is:
+
+       LOAD *A, ..., LOAD {*C,*D}, STORE *E, STORE *B
+
+       (Where "LOAD {*C,*D}" is a combined load)
+
+
+However, it is guaranteed that a CPU will be self-consistent: it will see its
+_own_ accesses appear to be correctly ordered, without the need for a memory
+barrier.  For instance with the following code:
+
+       U = *A;
+       *A = V;
+       *A = W;
+       X = *A;
+       *A = Y;
+       Z = *A;
+
+and assuming no intervention by an external influence, it can be assumed that
+the final result will appear to be:
+
+       U == the original value of *A
+       X == W
+       Z == Y
+       *A == Y
+
+The code above may cause the CPU to generate the full sequence of memory
+accesses:
+
+       U=LOAD *A, STORE *A=V, STORE *A=W, X=LOAD *A, STORE *A=Y, Z=LOAD *A
+
+in that order, but, without intervention, the sequence may have almost any
+combination of elements combined or discarded, provided the program's view of
+the world remains consistent.
+
+The compiler may also combine, discard or defer elements of the sequence before
+the CPU even sees them.
+
+For instance:
+
+       *A = V;
+       *A = W;
+
+may be reduced to:
+
+       *A = W;
+
+since, without a write barrier, it can be assumed that the effect of the
+storage of V to *A is lost.  Similarly:
+
+       *A = Y;
+       Z = *A;
+
+may, without a memory barrier, be reduced to:
+
+       *A = Y;
+       Z = Y;
+
+and the LOAD operation never appear outside of the CPU.
+
+
+AND THEN THERE'S THE ALPHA
+--------------------------
+
+The DEC Alpha CPU is one of the most relaxed CPUs there is.  Not only that,
+some versions of the Alpha CPU have a split data cache, permitting them to have
+two semantically related cache lines updating at separate times.  This is where
+the data dependency barrier really becomes necessary as this synchronises both
+caches with the memory coherence system, thus making it seem like pointer
+changes vs new data occur in the right order.
+
+The Alpha defines the Linux's kernel's memory barrier model.
+
+See the subsection on "Cache Coherency" above.
+
+
+==========
+REFERENCES
+==========
+
+Alpha AXP Architecture Reference Manual, Second Edition (Sites & Witek,
+Digital Press)
+       Chapter 5.2: Physical Address Space Characteristics
+       Chapter 5.4: Caches and Write Buffers
+       Chapter 5.5: Data Sharing
+       Chapter 5.6: Read/Write Ordering
+
+AMD64 Architecture Programmer's Manual Volume 2: System Programming
+       Chapter 7.1: Memory-Access Ordering
+       Chapter 7.4: Buffering and Combining Memory Writes
+
+IA-32 Intel Architecture Software Developer's Manual, Volume 3:
+System Programming Guide
+       Chapter 7.1: Locked Atomic Operations
+       Chapter 7.2: Memory Ordering
+       Chapter 7.4: Serializing Instructions
+
+The SPARC Architecture Manual, Version 9
+       Chapter 8: Memory Models
+       Appendix D: Formal Specification of the Memory Models
+       Appendix J: Programming with the Memory Models
+
+UltraSPARC Programmer Reference Manual
+       Chapter 5: Memory Accesses and Cacheability
+       Chapter 15: Sparc-V9 Memory Models
+
+UltraSPARC III Cu User's Manual
+       Chapter 9: Memory Models
+
+UltraSPARC IIIi Processor User's Manual
+       Chapter 8: Memory Models
+
+UltraSPARC Architecture 2005
+       Chapter 9: Memory
+       Appendix D: Formal Specifications of the Memory Models
+
+UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
+       Chapter 8: Memory Models
+       Appendix F: Caches and Cache Coherency
+
+Solaris Internals, Core Kernel Architecture, p63-68:
+       Chapter 3.3: Hardware Considerations for Locks and
+                       Synchronization
+
+Unix Systems for Modern Architectures, Symmetric Multiprocessing and Caching
+for Kernel Programmers:
+       Chapter 13: Other Memory Models
+
+Intel Itanium Architecture Software Developer's Manual: Volume 1:
+       Section 2.6: Speculation
+       Section 4.4: Memory Access
index 97420f0..4739c5c 100644 (file)
@@ -1,5 +1,11 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
 
+* New release helper (as of 2.6.17)
+   Instead of calling pcmcia_release_{configuration,io,irq,win}, all that's
+   necessary now is calling pcmcia_disable_device. As there is no valid
+   reason left to call pcmcia_release_io and pcmcia_release_irq, the
+   exports for them were removed.
+
 * Unify detach and REMOVAL event code, as well as attach and INSERTION
   code (as of 2.6.16)
        void (*remove)          (struct pcmcia_device *dev);
index 1898ea7..9d6186d 100644 (file)
@@ -216,8 +216,6 @@ EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memchr);
 
-EXPORT_SYMBOL(get_wchan);
-
 #ifdef CONFIG_ALPHA_IRONGATE
 EXPORT_SYMBOL(irongate_ioremap);
 EXPORT_SYMBOL(irongate_iounmap);
index 44866cb..7f6a984 100644 (file)
@@ -435,7 +435,7 @@ marvel_specify_io7(char *str)
                str = pchar;
        } while(*str);
 
-       return 0;
+       return 1;
 }
 __setup("io7=", marvel_specify_io7);
 
index dd87696..a15e18a 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
+#include <linux/platform_device.h>
 #include <linux/bootmem.h>
 #include <linux/pci.h>
 #include <linux/seq_file.h>
@@ -1478,3 +1479,20 @@ alpha_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
 #endif
         return NOTIFY_DONE;
 }
+
+static __init int add_pcspkr(void)
+{
+       struct platform_device *pd;
+       int ret;
+
+       pd = platform_device_alloc("pcspkr", -1);
+       if (!pd)
+               return -ENOMEM;
+
+       ret = platform_device_add(pd);
+       if (ret)
+               platform_device_put(pd);
+
+       return ret;
+}
+device_initcall(add_pcspkr);
index ba46d77..dc5a933 100644 (file)
@@ -77,6 +77,14 @@ config FIQ
 config ARCH_MTD_XIP
        bool
 
+config VECTORS_BASE
+       hex
+       default 0xffff0000 if MMU
+       default DRAM_BASE if REMAP_VECTORS_TO_RAM
+       default 0x00000000
+       help
+         The base address of exception vectors.
+
 source "init/Kconfig"
 
 menu "System Type"
@@ -839,6 +847,8 @@ source "drivers/misc/Kconfig"
 
 source "drivers/mfd/Kconfig"
 
+source "drivers/leds/Kconfig"
+
 source "drivers/media/Kconfig"
 
 source "drivers/video/Kconfig"
diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu
new file mode 100644 (file)
index 0000000..e1574be
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# Kconfig for uClinux(non-paged MM) depend configurations
+# Hyok S. Choi <hyok.choi@samsung.com>
+# 
+
+config SET_MEM_PARAM
+       bool "Set flash/sdram size and base addr"
+       help
+        Say Y to manually set the base addresses and sizes.
+        otherwise, the default values are assigned.
+
+config DRAM_BASE
+       hex '(S)DRAM Base Address' if SET_MEM_PARAM
+       default 0x00800000
+
+config DRAM_SIZE
+       hex '(S)DRAM SIZE' if SET_MEM_PARAM
+       default 0x00800000
+
+config FLASH_MEM_BASE
+       hex 'FLASH Base Address' if SET_MEM_PARAM
+       default 0x00400000
+
+config FLASH_SIZE
+       hex 'FLASH Size' if SET_MEM_PARAM
+       default 0x00400000
+
+config REMAP_VECTORS_TO_RAM
+       bool 'Install vectors to the begining of RAM' if DRAM_BASE
+       depends on DRAM_BASE
+       help
+         The kernel needs to change the hardware exception vectors.
+         In nommu mode, the hardware exception vectors are normally
+         placed at address 0x00000000. However, this region may be
+         occupied by read-only memory depending on H/W design.
+
+         If the region contains read-write memory, say 'n' here.
+
+         If your CPU provides a remap facility which allows the exception
+         vectors to be mapped to writable memory, say 'n' here.
+
+         Otherwise, say 'y' here.  In this case, the kernel will require
+         external support to redirect the hardware exception vectors to
+         the writable versions located at DRAM_BASE.
index ce3e804..95a9627 100644 (file)
@@ -20,6 +20,11 @@ GZFLAGS              :=-9
 # Select a platform tht is kept up-to-date
 KBUILD_DEFCONFIG := versatile_defconfig
 
+# defines filename extension depending memory manement type.
+ifeq ($(CONFIG_MMU),)
+MMUEXT         := -nommu
+endif
+
 ifeq ($(CONFIG_FRAME_POINTER),y)
 CFLAGS         +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
 endif
@@ -73,7 +78,7 @@ AFLAGS                +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
 CHECKFLAGS     += -D__arm__
 
 #Default value
-head-y         := arch/arm/kernel/head.o arch/arm/kernel/init_task.o
+head-y         := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
 textofs-y      := 0x00008000
 
  machine-$(CONFIG_ARCH_RPC)       := rpc
@@ -133,7 +138,7 @@ else
 MACHINE  :=
 endif
   
-export TEXT_OFFSET GZFLAGS
+export TEXT_OFFSET GZFLAGS MMUEXT
 
 # Do we have FASTFPE?
 FASTFPE                :=arch/arm/fastfpe
index 491c7e4..b56f5e6 100644 (file)
@@ -2,6 +2,7 @@
  *  linux/arch/arm/boot/compressed/head.S
  *
  *  Copyright (C) 1996-2002 Russell King
+ *  Copyright (C) 2004 Hyok S. Choi (MPU support)
  *
  * 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
@@ -320,6 +321,62 @@ params:            ldr     r0, =params_phys
 cache_on:      mov     r3, #8                  @ cache_on function
                b       call_cache_fn
 
+/*
+ * Initialize the highest priority protection region, PR7
+ * to cover all 32bit address and cacheable and bufferable.
+ */
+__armv4_mpu_cache_on:
+               mov     r0, #0x3f               @ 4G, the whole
+               mcr     p15, 0, r0, c6, c7, 0   @ PR7 Area Setting
+               mcr     p15, 0, r0, c6, c7, 1
+
+               mov     r0, #0x80               @ PR7
+               mcr     p15, 0, r0, c2, c0, 0   @ D-cache on
+               mcr     p15, 0, r0, c2, c0, 1   @ I-cache on
+               mcr     p15, 0, r0, c3, c0, 0   @ write-buffer on
+
+               mov     r0, #0xc000
+               mcr     p15, 0, r0, c5, c0, 1   @ I-access permission
+               mcr     p15, 0, r0, c5, c0, 0   @ D-access permission
+
+               mov     r0, #0
+               mcr     p15, 0, r0, c7, c10, 4  @ drain write buffer
+               mcr     p15, 0, r0, c7, c5, 0   @ flush(inval) I-Cache
+               mcr     p15, 0, r0, c7, c6, 0   @ flush(inval) D-Cache
+               mrc     p15, 0, r0, c1, c0, 0   @ read control reg
+                                               @ ...I .... ..D. WC.M
+               orr     r0, r0, #0x002d         @ .... .... ..1. 11.1
+               orr     r0, r0, #0x1000         @ ...1 .... .... ....
+
+               mcr     p15, 0, r0, c1, c0, 0   @ write control reg
+
+               mov     r0, #0
+               mcr     p15, 0, r0, c7, c5, 0   @ flush(inval) I-Cache
+               mcr     p15, 0, r0, c7, c6, 0   @ flush(inval) D-Cache
+               mov     pc, lr
+
+__armv3_mpu_cache_on:
+               mov     r0, #0x3f               @ 4G, the whole
+               mcr     p15, 0, r0, c6, c7, 0   @ PR7 Area Setting
+
+               mov     r0, #0x80               @ PR7
+               mcr     p15, 0, r0, c2, c0, 0   @ cache on
+               mcr     p15, 0, r0, c3, c0, 0   @ write-buffer on
+
+               mov     r0, #0xc000
+               mcr     p15, 0, r0, c5, c0, 0   @ access permission
+
+               mov     r0, #0
+               mcr     p15, 0, r0, c7, c0, 0   @ invalidate whole cache v3
+               mrc     p15, 0, r0, c1, c0, 0   @ read control reg
+                                               @ .... .... .... WC.M
+               orr     r0, r0, #0x000d         @ .... .... .... 11.1
+               mov     r0, #0
+               mcr     p15, 0, r0, c1, c0, 0   @ write control reg
+
+               mcr     p15, 0, r0, c7, c0, 0   @ invalidate whole cache v3
+               mov     pc, lr
+
 __setup_mmu:   sub     r3, r4, #16384          @ Page directory size
                bic     r3, r3, #0xff           @ Align the pointer
                bic     r3, r3, #0x3f00
@@ -496,6 +553,18 @@ proc_types:
                b       __armv4_mmu_cache_off
                mov     pc, lr
 
+               .word   0x41007400              @ ARM74x
+               .word   0xff00ff00
+               b       __armv3_mpu_cache_on
+               b       __armv3_mpu_cache_off
+               b       __armv3_mpu_cache_flush
+               
+               .word   0x41009400              @ ARM94x
+               .word   0xff00ff00
+               b       __armv4_mpu_cache_on
+               b       __armv4_mpu_cache_off
+               b       __armv4_mpu_cache_flush
+
                .word   0x00007000              @ ARM7 IDs
                .word   0x0000f000
                mov     pc, lr
@@ -562,6 +631,24 @@ proc_types:
 cache_off:     mov     r3, #12                 @ cache_off function
                b       call_cache_fn
 
+__armv4_mpu_cache_off:
+               mrc     p15, 0, r0, c1, c0
+               bic     r0, r0, #0x000d
+               mcr     p15, 0, r0, c1, c0      @ turn MPU and cache off
+               mov     r0, #0
+               mcr     p15, 0, r0, c7, c10, 4  @ drain write buffer
+               mcr     p15, 0, r0, c7, c6, 0   @ flush D-Cache
+               mcr     p15, 0, r0, c7, c5, 0   @ flush I-Cache
+               mov     pc, lr
+
+__armv3_mpu_cache_off:
+               mrc     p15, 0, r0, c1, c0
+               bic     r0, r0, #0x000d
+               mcr     p15, 0, r0, c1, c0, 0   @ turn MPU and cache off
+               mov     r0, #0
+               mcr     p15, 0, r0, c7, c0, 0   @ invalidate whole cache v3
+               mov     pc, lr
+
 __armv4_mmu_cache_off:
                mrc     p15, 0, r0, c1, c0
                bic     r0, r0, #0x000d
@@ -601,6 +688,24 @@ cache_clean_flush:
                mov     r3, #16
                b       call_cache_fn
 
+__armv4_mpu_cache_flush:
+               mov     r2, #1
+               mov     r3, #0
+               mcr     p15, 0, ip, c7, c6, 0   @ invalidate D cache
+               mov     r1, #7 << 5             @ 8 segments
+1:             orr     r3, r1, #63 << 26       @ 64 entries
+2:             mcr     p15, 0, r3, c7, c14, 2  @ clean & invalidate D index
+               subs    r3, r3, #1 << 26
+               bcs     2b                      @ entries 63 to 0
+               subs    r1, r1, #1 << 5
+               bcs     1b                      @ segments 7 to 0
+
+               teq     r2, #0
+               mcrne   p15, 0, ip, c7, c5, 0   @ invalidate I cache
+               mcr     p15, 0, ip, c7, c10, 4  @ drain WB
+               mov     pc, lr
+               
+
 __armv6_mmu_cache_flush:
                mov     r1, #0
                mcr     p15, 0, r1, c7, c14, 0  @ clean+invalidate D
@@ -638,6 +743,7 @@ no_cache_id:
                mov     pc, lr
 
 __armv3_mmu_cache_flush:
+__armv3_mpu_cache_flush:
                mov     r1, #0
                mcr     p15, 0, r0, c7, c0, 0   @ invalidate whole cache v3
                mov     pc, lr
index 978d32e..3cd8c9e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/leds.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -75,6 +76,7 @@ static void sharpsl_battery_thread(void *private_);
 struct sharpsl_pm_status sharpsl_pm;
 DECLARE_WORK(toggle_charger, sharpsl_charge_toggle, NULL);
 DECLARE_WORK(sharpsl_bat, sharpsl_battery_thread, NULL);
+DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
 
 
 static int get_percentage(int voltage)
@@ -190,10 +192,10 @@ void sharpsl_pm_led(int val)
                dev_err(sharpsl_pm.dev, "Charging Error!\n");
        } else if (val == SHARPSL_LED_ON) {
                dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
-
+               led_trigger_event(sharpsl_charge_led_trigger, LED_FULL);
        } else {
                dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
-
+               led_trigger_event(sharpsl_charge_led_trigger, LED_OFF);
        }
 }
 
@@ -786,6 +788,8 @@ static int __init sharpsl_pm_probe(struct platform_device *pdev)
        init_timer(&sharpsl_pm.chrg_full_timer);
        sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer;
 
+       led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger);
+
        sharpsl_pm.machinfo->init();
 
        device_create_file(&pdev->dev, &dev_attr_battery_percentage);
@@ -807,6 +811,8 @@ static int sharpsl_pm_remove(struct platform_device *pdev)
        device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
        device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
 
+       led_trigger_unregister_simple(sharpsl_charge_led_trigger);
+
        sharpsl_pm.machinfo->exit();
 
        del_timer_sync(&sharpsl_pm.chrg_full_timer);
index 355914f..ab8e600 100644 (file)
@@ -666,7 +666,7 @@ __kuser_helper_start:
  *
  * #define __kernel_dmb() \
  *         asm volatile ( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #95" \
- *             : : : "lr","cc" )
+ *             : : : "r0", "lr","cc" )
  */
 
 __kuser_memory_barrier:                                @ 0xffff0fa0
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
new file mode 100644 (file)
index 0000000..a52da0d
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ *  linux/arch/arm/kernel/head-common.S
+ *
+ *  Copyright (C) 1994-2002 Russell King
+ *  Copyright (c) 2003 ARM Limited
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+       .type   __switch_data, %object
+__switch_data:
+       .long   __mmap_switched
+       .long   __data_loc                      @ r4
+       .long   __data_start                    @ r5
+       .long   __bss_start                     @ r6
+       .long   _end                            @ r7
+       .long   processor_id                    @ r4
+       .long   __machine_arch_type             @ r5
+       .long   cr_alignment                    @ r6
+       .long   init_thread_union + THREAD_START_SP @ sp
+
+/*
+ * The following fragment of code is executed with the MMU on in MMU mode,
+ * and uses absolute addresses; this is not position independent.
+ *
+ *  r0  = cp#15 control register
+ *  r1  = machine ID
+ *  r9  = processor ID
+ */
+       .type   __mmap_switched, %function
+__mmap_switched:
+       adr     r3, __switch_data + 4
+
+       ldmia   r3!, {r4, r5, r6, r7}
+       cmp     r4, r5                          @ Copy data segment if needed
+1:     cmpne   r5, r6
+       ldrne   fp, [r4], #4
+       strne   fp, [r5], #4
+       bne     1b
+
+       mov     fp, #0                          @ Clear BSS (and zero fp)
+1:     cmp     r6, r7
+       strcc   fp, [r6],#4
+       bcc     1b
+
+       ldmia   r3, {r4, r5, r6, sp}
+       str     r9, [r4]                        @ Save processor ID
+       str     r1, [r5]                        @ Save machine type
+       bic     r4, r0, #CR_A                   @ Clear 'A' bit
+       stmia   r6, {r0, r4}                    @ Save control register values
+       b       start_kernel
+
+/*
+ * Exception handling.  Something went wrong and we can't proceed.  We
+ * ought to tell the user, but since we don't have any guarantee that
+ * we're even running on the right architecture, we do virtually nothing.
+ *
+ * If CONFIG_DEBUG_LL is set we try to print out something about the error
+ * and hope for the best (useful if bootloader fails to pass a proper
+ * machine ID for example).
+ */
+
+       .type   __error_p, %function
+__error_p:
+#ifdef CONFIG_DEBUG_LL
+       adr     r0, str_p1
+       bl      printascii
+       b       __error
+str_p1:        .asciz  "\nError: unrecognized/unsupported processor variant.\n"
+       .align
+#endif
+
+       .type   __error_a, %function
+__error_a:
+#ifdef CONFIG_DEBUG_LL
+       mov     r4, r1                          @ preserve machine ID
+       adr     r0, str_a1
+       bl      printascii
+       mov     r0, r4
+       bl      printhex8
+       adr     r0, str_a2
+       bl      printascii
+       adr     r3, 3f
+       ldmia   r3, {r4, r5, r6}                @ get machine desc list
+       sub     r4, r3, r4                      @ get offset between virt&phys
+       add     r5, r5, r4                      @ convert virt addresses to
+       add     r6, r6, r4                      @ physical address space
+1:     ldr     r0, [r5, #MACHINFO_TYPE]        @ get machine type
+       bl      printhex8
+       mov     r0, #'\t'
+       bl      printch
+       ldr     r0, [r5, #MACHINFO_NAME]        @ get machine name
+       add     r0, r0, r4
+       bl      printascii
+       mov     r0, #'\n'
+       bl      printch
+       add     r5, r5, #SIZEOF_MACHINE_DESC    @ next machine_desc
+       cmp     r5, r6
+       blo     1b
+       adr     r0, str_a3
+       bl      printascii
+       b       __error
+str_a1:        .asciz  "\nError: unrecognized/unsupported machine ID (r1 = 0x"
+str_a2:        .asciz  ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
+str_a3:        .asciz  "\nPlease check your kernel config and/or bootloader.\n"
+       .align
+#endif
+
+       .type   __error, %function
+__error:
+#ifdef CONFIG_ARCH_RPC
+/*
+ * Turn the screen red on a error - RiscPC only.
+ */
+       mov     r0, #0x02000000
+       mov     r3, #0x11
+       orr     r3, r3, r3, lsl #8
+       orr     r3, r3, r3, lsl #16
+       str     r3, [r0], #4
+       str     r3, [r0], #4
+       str     r3, [r0], #4
+       str     r3, [r0], #4
+#endif
+1:     mov     r0, r0
+       b       1b
+
+
+/*
+ * Read processor ID register (CP#15, CR0), and look up in the linker-built
+ * supported processor list.  Note that we can't use the absolute addresses
+ * for the __proc_info lists since we aren't running with the MMU on
+ * (and therefore, we are not in the correct address space).  We have to
+ * calculate the offset.
+ *
+ *     r9 = cpuid
+ * Returns:
+ *     r3, r4, r6 corrupted
+ *     r5 = proc_info pointer in physical address space
+ *     r9 = cpuid (preserved)
+ */
+       .type   __lookup_processor_type, %function
+__lookup_processor_type:
+       adr     r3, 3f
+       ldmda   r3, {r5 - r7}
+       sub     r3, r3, r7                      @ get offset between virt&phys
+       add     r5, r5, r3                      @ convert virt addresses to
+       add     r6, r6, r3                      @ physical address space
+1:     ldmia   r5, {r3, r4}                    @ value, mask
+       and     r4, r4, r9                      @ mask wanted bits
+       teq     r3, r4
+       beq     2f
+       add     r5, r5, #PROC_INFO_SZ           @ sizeof(proc_info_list)
+       cmp     r5, r6
+       blo     1b
+       mov     r5, #0                          @ unknown processor
+2:     mov     pc, lr
+
+/*
+ * This provides a C-API version of the above function.
+ */
+ENTRY(lookup_processor_type)
+       stmfd   sp!, {r4 - r7, r9, lr}
+       mov     r9, r0
+       bl      __lookup_processor_type
+       mov     r0, r5
+       ldmfd   sp!, {r4 - r7, r9, pc}
+
+/*
+ * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
+ * more information about the __proc_info and __arch_info structures.
+ */
+       .long   __proc_info_begin
+       .long   __proc_info_end
+3:     .long   .
+       .long   __arch_info_begin
+       .long   __arch_info_end
+
+/*
+ * Lookup machine architecture in the linker-build list of architectures.
+ * Note that we can't use the absolute addresses for the __arch_info
+ * lists since we aren't running with the MMU on (and therefore, we are
+ * not in the correct address space).  We have to calculate the offset.
+ *
+ *  r1 = machine architecture number
+ * Returns:
+ *  r3, r4, r6 corrupted
+ *  r5 = mach_info pointer in physical address space
+ */
+       .type   __lookup_machine_type, %function
+__lookup_machine_type:
+       adr     r3, 3b
+       ldmia   r3, {r4, r5, r6}
+       sub     r3, r3, r4                      @ get offset between virt&phys
+       add     r5, r5, r3                      @ convert virt addresses to
+       add     r6, r6, r3                      @ physical address space
+1:     ldr     r3, [r5, #MACHINFO_TYPE]        @ get machine type
+       teq     r3, r1                          @ matches loader number?
+       beq     2f                              @ found
+       add     r5, r5, #SIZEOF_MACHINE_DESC    @ next machine_desc
+       cmp     r5, r6
+       blo     1b
+       mov     r5, #0                          @ unknown machine
+2:     mov     pc, lr
+
+/*
+ * This provides a C-API version of the above function.
+ */
+ENTRY(lookup_machine_type)
+       stmfd   sp!, {r4 - r6, lr}
+       mov     r1, r0
+       bl      __lookup_machine_type
+       mov     r0, r5
+       ldmfd   sp!, {r4 - r6, pc}
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
new file mode 100644 (file)
index 0000000..b093ab8
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *  linux/arch/arm/kernel/head-nommu.S
+ *
+ *  Copyright (C) 1994-2002 Russell King
+ *  Copyright (C) 2003-2006 Hyok S. Choi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Common kernel startup code (non-paged MM)
+ *    for 32-bit CPUs which has a process ID register(CP15).
+ *
+ */
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/assembler.h>
+#include <asm/mach-types.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+#include <asm/constants.h>
+#include <asm/system.h>
+
+#define PROCINFO_INITFUNC       12
+
+/*
+ * Kernel startup entry point.
+ * ---------------------------
+ *
+ * This is normally called from the decompressor code.  The requirements
+ * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
+ * r1 = machine nr.
+ *
+ * See linux/arch/arm/tools/mach-types for the complete list of machine
+ * numbers for r1.
+ *
+ */
+       __INIT
+       .type   stext, %function
+ENTRY(stext)
+       msr     cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode
+                                               @ and irqs disabled
+       mrc     p15, 0, r9, c0, c0              @ get processor id
+       bl      __lookup_processor_type         @ r5=procinfo r9=cpuid
+       movs    r10, r5                         @ invalid processor (r5=0)?
+       beq     __error_p                               @ yes, error 'p'
+       bl      __lookup_machine_type           @ r5=machinfo
+       movs    r8, r5                          @ invalid machine (r5=0)?
+       beq     __error_a                       @ yes, error 'a'
+
+       ldr     r13, __switch_data              @ address to jump to after
+                                               @ the initialization is done
+       adr     lr, __after_proc_init           @ return (PIC) address
+       add     pc, r10, #PROCINFO_INITFUNC
+
+/*
+ * Set the Control Register and Read the process ID.
+ */
+       .type   __after_proc_init, %function
+__after_proc_init:
+       mrc     p15, 0, r0, c1, c0, 0           @ read control reg
+#ifdef CONFIG_ALIGNMENT_TRAP
+       orr     r0, r0, #CR_A
+#else
+       bic     r0, r0, #CR_A
+#endif
+#ifdef CONFIG_CPU_DCACHE_DISABLE
+       bic     r0, r0, #CR_C
+#endif
+#ifdef CONFIG_CPU_BPREDICT_DISABLE
+       bic     r0, r0, #CR_Z
+#endif
+#ifdef CONFIG_CPU_ICACHE_DISABLE
+       bic     r0, r0, #CR_I
+#endif
+       mcr     p15, 0, r0, c1, c0, 0           @ write control reg
+
+       mov     pc, r13                         @ clear the BSS and jump
+                                               @ to start_kernel
+
+#include "head-common.S"
index 53b6901..04b66a9 100644 (file)
@@ -102,49 +102,6 @@ ENTRY(stext)
        adr     lr, __enable_mmu                @ return (PIC) address
        add     pc, r10, #PROCINFO_INITFUNC
 
-       .type   __switch_data, %object
-__switch_data:
-       .long   __mmap_switched
-       .long   __data_loc                      @ r4
-       .long   __data_start                    @ r5
-       .long   __bss_start                     @ r6
-       .long   _end                            @ r7
-       .long   processor_id                    @ r4
-       .long   __machine_arch_type             @ r5
-       .long   cr_alignment                    @ r6
-       .long   init_thread_union + THREAD_START_SP @ sp
-
-/*
- * The following fragment of code is executed with the MMU on, and uses
- * absolute addresses; this is not position independent.
- *
- *  r0  = cp#15 control register
- *  r1  = machine ID
- *  r9  = processor ID
- */
-       .type   __mmap_switched, %function
-__mmap_switched:
-       adr     r3, __switch_data + 4
-
-       ldmia   r3!, {r4, r5, r6, r7}
-       cmp     r4, r5                          @ Copy data segment if needed
-1:     cmpne   r5, r6
-       ldrne   fp, [r4], #4
-       strne   fp, [r5], #4
-       bne     1b
-
-       mov     fp, #0                          @ Clear BSS (and zero fp)
-1:     cmp     r6, r7
-       strcc   fp, [r6],#4
-       bcc     1b
-
-       ldmia   r3, {r4, r5, r6, sp}
-       str     r9, [r4]                        @ Save processor ID
-       str     r1, [r5]                        @ Save machine type
-       bic     r4, r0, #CR_A                   @ Clear 'A' bit
-       stmia   r6, {r0, r4}                    @ Save control register values
-       b       start_kernel
-
 #if defined(CONFIG_SMP)
        .type   secondary_startup, #function
 ENTRY(secondary_startup)
@@ -367,166 +324,4 @@ __create_page_tables:
        mov     pc, lr
        .ltorg
 
-
-
-/*
- * Exception handling.  Something went wrong and we can't proceed.  We
- * ought to tell the user, but since we don't have any guarantee that
- * we're even running on the right architecture, we do virtually nothing.
- *
- * If CONFIG_DEBUG_LL is set we try to print out something about the error
- * and hope for the best (useful if bootloader fails to pass a proper
- * machine ID for example).
- */
-
-       .type   __error_p, %function
-__error_p:
-#ifdef CONFIG_DEBUG_LL
-       adr     r0, str_p1
-       bl      printascii
-       b       __error
-str_p1:        .asciz  "\nError: unrecognized/unsupported processor variant.\n"
-       .align
-#endif
-
-       .type   __error_a, %function
-__error_a:
-#ifdef CONFIG_DEBUG_LL
-       mov     r4, r1                          @ preserve machine ID
-       adr     r0, str_a1
-       bl      printascii
-       mov     r0, r4
-       bl      printhex8
-       adr     r0, str_a2
-       bl      printascii
-       adr     r3, 3f
-       ldmia   r3, {r4, r5, r6}                @ get machine desc list
-       sub     r4, r3, r4                      @ get offset between virt&phys
-       add     r5, r5, r4                      @ convert virt addresses to
-       add     r6, r6, r4                      @ physical address space
-1:     ldr     r0, [r5, #MACHINFO_TYPE]        @ get machine type
-       bl      printhex8
-       mov     r0, #'\t'
-       bl      printch
-       ldr     r0, [r5, #MACHINFO_NAME]        @ get machine name
-       add     r0, r0, r4
-       bl      printascii
-       mov     r0, #'\n'
-       bl      printch
-       add     r5, r5, #SIZEOF_MACHINE_DESC    @ next machine_desc
-       cmp     r5, r6
-       blo     1b
-       adr     r0, str_a3
-       bl      printascii
-       b       __error
-str_a1:        .asciz  "\nError: unrecognized/unsupported machine ID (r1 = 0x"
-str_a2:        .asciz  ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
-str_a3:        .asciz  "\nPlease check your kernel config and/or bootloader.\n"
-       .align
-#endif
-
-       .type   __error, %function
-__error:
-#ifdef CONFIG_ARCH_RPC
-/*
- * Turn the screen red on a error - RiscPC only.
- */
-       mov     r0, #0x02000000
-       mov     r3, #0x11
-       orr     r3, r3, r3, lsl #8
-       orr     r3, r3, r3, lsl #16
-       str     r3, [r0], #4
-       str     r3, [r0], #4
-       str     r3, [r0], #4
-       str     r3, [r0], #4
-#endif
-1:     mov     r0, r0
-       b       1b
-
-
-/*
- * Read processor ID register (CP#15, CR0), and look up in the linker-built
- * supported processor list.  Note that we can't use the absolute addresses
- * for the __proc_info lists since we aren't running with the MMU on
- * (and therefore, we are not in the correct address space).  We have to
- * calculate the offset.
- *
- *     r9 = cpuid
- * Returns:
- *     r3, r4, r6 corrupted
- *     r5 = proc_info pointer in physical address space
- *     r9 = cpuid (preserved)
- */
-       .type   __lookup_processor_type, %function
-__lookup_processor_type:
-       adr     r3, 3f
-       ldmda   r3, {r5 - r7}
-       sub     r3, r3, r7                      @ get offset between virt&phys
-       add     r5, r5, r3                      @ convert virt addresses to
-       add     r6, r6, r3                      @ physical address space
-1:     ldmia   r5, {r3, r4}                    @ value, mask
-       and     r4, r4, r9                      @ mask wanted bits
-       teq     r3, r4
-       beq     2f
-       add     r5, r5, #PROC_INFO_SZ           @ sizeof(proc_info_list)
-       cmp     r5, r6
-       blo     1b
-       mov     r5, #0                          @ unknown processor
-2:     mov     pc, lr
-
-/*
- * This provides a C-API version of the above function.
- */
-ENTRY(lookup_processor_type)
-       stmfd   sp!, {r4 - r7, r9, lr}
-       mov     r9, r0
-       bl      __lookup_processor_type
-       mov     r0, r5
-       ldmfd   sp!, {r4 - r7, r9, pc}
-
-/*
- * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
- * more information about the __proc_info and __arch_info structures.
- */
-       .long   __proc_info_begin
-       .long   __proc_info_end
-3:     .long   .
-       .long   __arch_info_begin
-       .long   __arch_info_end
-
-/*
- * Lookup machine architecture in the linker-build list of architectures.
- * Note that we can't use the absolute addresses for the __arch_info
- * lists since we aren't running with the MMU on (and therefore, we are
- * not in the correct address space).  We have to calculate the offset.
- *
- *  r1 = machine architecture number
- * Returns:
- *  r3, r4, r6 corrupted
- *  r5 = mach_info pointer in physical address space
- */
-       .type   __lookup_machine_type, %function
-__lookup_machine_type:
-       adr     r3, 3b
-       ldmia   r3, {r4, r5, r6}
-       sub     r3, r3, r4                      @ get offset between virt&phys
-       add     r5, r5, r3                      @ convert virt addresses to
-       add     r6, r6, r3                      @ physical address space
-1:     ldr     r3, [r5, #MACHINFO_TYPE]        @ get machine type
-       teq     r3, r1                          @ matches loader number?
-       beq     2f                              @ found
-       add     r5, r5, #SIZEOF_MACHINE_DESC    @ next machine_desc
-       cmp     r5, r6
-       blo     1b
-       mov     r5, #0                          @ unknown machine
-2:     mov     pc, lr
-
-/*
- * This provides a C-API version of the above function.
- */
-ENTRY(lookup_machine_type)
-       stmfd   sp!, {r4 - r6, lr}
-       mov     r1, r0
-       bl      __lookup_machine_type
-       mov     r0, r5
-       ldmfd   sp!, {r4 - r6, pc}
+#include "head-common.S"
index 489c069..1ff75ce 100644 (file)
@@ -474,4 +474,3 @@ unsigned long get_wchan(struct task_struct *p)
        } while (count ++ < 16);
        return 0;
 }
-EXPORT_SYMBOL(get_wchan);
index 9991049..27beece 100644 (file)
@@ -7,6 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define KERN_SIGRETURN_CODE    0xffff0500
+#define KERN_SIGRETURN_CODE    (CONFIG_VECTORS_BASE + 0x00000500)
 
 extern const unsigned long sigreturn_codes[7];
index d566d5f..35230a0 100644 (file)
@@ -688,6 +688,7 @@ EXPORT_SYMBOL(abort);
 
 void __init trap_init(void)
 {
+       unsigned long vectors = CONFIG_VECTORS_BASE;
        extern char __stubs_start[], __stubs_end[];
        extern char __vectors_start[], __vectors_end[];
        extern char __kuser_helper_start[], __kuser_helper_end[];
@@ -698,9 +699,9 @@ void __init trap_init(void)
         * into the vector page, mapped at 0xffff0000, and ensure these
         * are visible to the instruction stream.
         */
-       memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start);
-       memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start);
-       memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz);
+       memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
+       memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
+       memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
 
        /*
         * Copy signal return handlers into the vector page, and
@@ -709,6 +710,6 @@ void __init trap_init(void)
        memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
               sizeof(sigreturn_codes));
 
-       flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE);
+       flush_icache_range(vectors, vectors + PAGE_SIZE);
        modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
 }
index 68923b1..d6d7260 100644 (file)
@@ -141,6 +141,8 @@ struct corgissp_machinfo corgi_ssp_machinfo = {
  */
 static struct corgibl_machinfo corgi_bl_machinfo = {
        .max_intensity = 0x2f,
+       .default_intensity = 0x1f,
+       .limit_mask = 0x0b,
        .set_bl_intensity = corgi_bl_set_intensity,
 };
 
@@ -163,6 +165,14 @@ static struct platform_device corgikbd_device = {
 };
 
 
+/*
+ * Corgi LEDs
+ */
+static struct platform_device corgiled_device = {
+       .name           = "corgi-led",
+       .id             = -1,
+};
+
 /*
  * Corgi Touch Screen Device
  */
@@ -297,6 +307,7 @@ static struct platform_device *devices[] __initdata = {
        &corgikbd_device,
        &corgibl_device,
        &corgits_device,
+       &corgiled_device,
 };
 
 static void __init corgi_init(void)
index 0dbb079..19b372d 100644 (file)
@@ -220,6 +220,8 @@ struct corgissp_machinfo spitz_ssp_machinfo = {
  * Spitz Backlight Device
  */
 static struct corgibl_machinfo spitz_bl_machinfo = {
+       .default_intensity = 0x1f,
+       .limit_mask = 0x0b,
        .max_intensity = 0x2f,
 };
 
@@ -241,6 +243,14 @@ static struct platform_device spitzkbd_device = {
 };
 
 
+/*
+ * Spitz LEDs
+ */
+static struct platform_device spitzled_device = {
+       .name           = "spitz-led",
+       .id             = -1,
+};
+
 /*
  * Spitz Touch Screen Device
  */
@@ -418,6 +428,7 @@ static struct platform_device *devices[] __initdata = {
        &spitzkbd_device,
        &spitzts_device,
        &spitzbl_device,
+       &spitzled_device,
 };
 
 static void __init common_init(void)
index 66ec717..76c0e7f 100644 (file)
@@ -251,10 +251,19 @@ static struct platform_device tosakbd_device = {
        .id             = -1,
 };
 
+/*
+ * Tosa LEDs
+ */
+static struct platform_device tosaled_device = {
+    .name   = "tosa-led",
+    .id     = -1,
+};
+
 static struct platform_device *devices[] __initdata = {
        &tosascoop_device,
        &tosascoop_jc_device,
        &tosakbd_device,
+       &tosaled_device,
 };
 
 static void __init tosa_init(void)
index f90513e..b9dfce5 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/procinfo.h>
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
+#include <asm/pgtable-hwdef.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include "proc-macros.S"
index 811a637..a6a1b33 100644 (file)
@@ -212,8 +212,6 @@ EXPORT_SYMBOL(sys_open);
 EXPORT_SYMBOL(sys_exit);
 EXPORT_SYMBOL(sys_wait4);
 
-EXPORT_SYMBOL(get_wchan);
-
 #ifdef CONFIG_PREEMPT
 EXPORT_SYMBOL(kernel_flag);
 #endif
index aa6b7d0..07c8ffa 100644 (file)
@@ -79,8 +79,6 @@ EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(__outsl_ns);
 EXPORT_SYMBOL(__insl_ns);
 
-EXPORT_SYMBOL(get_wchan);
-
 #ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
 EXPORT_SYMBOL(atomic_test_and_ANDNOT_mask);
 EXPORT_SYMBOL(atomic_test_and_OR_mask);
index 69d6ad3..b6cd78c 100644 (file)
@@ -55,8 +55,6 @@ EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(memmove);
 
-EXPORT_SYMBOL(get_wchan);
-
 /*
  * libgcc functions - functions that are used internally by the
  * compiler...  (prototypes are not correct though, but that
index eb5279d..6273bf7 100644 (file)
@@ -415,6 +415,7 @@ void __init init_bsp_APIC(void)
 void __devinit setup_local_APIC(void)
 {
        unsigned long oldvalue, value, ver, maxlvt;
+       int i, j;
 
        /* Pound the ESR really hard over the head with a big hammer - mbligh */
        if (esr_disable) {
@@ -451,6 +452,25 @@ void __devinit setup_local_APIC(void)
        value &= ~APIC_TPRI_MASK;
        apic_write_around(APIC_TASKPRI, value);
 
+       /*
+        * After a crash, we no longer service the interrupts and a pending
+        * interrupt from previous kernel might still have ISR bit set.
+        *
+        * Most probably by now CPU has serviced that pending interrupt and
+        * it might not have done the ack_APIC_irq() because it thought,
+        * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it
+        * does not clear the ISR bit and cpu thinks it has already serivced
+        * the interrupt. Hence a vector might get locked. It was noticed
+        * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
+        */
+       for (i = APIC_ISR_NR - 1; i >= 0; i--) {
+               value = apic_read(APIC_ISR + i*0x10);
+               for (j = 31; j >= 0; j--) {
+                       if (value & (1<<j))
+                               ack_APIC_irq();
+               }
+       }
+
        /*
         * Now that we are all set up, enable the APIC
         */
@@ -732,7 +752,7 @@ static int __init apic_set_verbosity(char *str)
                printk(KERN_WARNING "APIC Verbosity level %s not recognised"
                                " use apic=verbose or apic=debug\n", str);
 
-       return 0;
+       return 1;
 }
 
 __setup("apic=", apic_set_verbosity);
index 6170af3..afa0888 100644 (file)
@@ -64,13 +64,13 @@ void mcheck_init(struct cpuinfo_x86 *c)
 static int __init mcheck_disable(char *str)
 {
        mce_disabled = 1;
-       return 0;
+       return 1;
 }
 
 static int __init mcheck_enable(char *str)
 {
        mce_disabled = -1;
-       return 0;
+       return 1;
 }
 
 __setup("nomce", mcheck_disable);
index 3b329af..f8f132a 100644 (file)
@@ -644,7 +644,7 @@ failed:
 int __init irqbalance_disable(char *str)
 {
        irqbalance_disabled = 1;
-       return 0;
+       return 1;
 }
 
 __setup("noirqbalance", irqbalance_disable);
index 24b3e74..6259afe 100644 (file)
@@ -781,7 +781,6 @@ unsigned long get_wchan(struct task_struct *p)
        } while (count++ < 16);
        return 0;
 }
-EXPORT_SYMBOL(get_wchan);
 
 /*
  * sys_alloc_thread_area: get a yet unused TLS descriptor index.
index 8c08660..eacc3f0 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
+#include <linux/platform_device.h>
 #include <linux/console.h>
 #include <linux/mca.h>
 #include <linux/root_dev.h>
@@ -1547,6 +1548,23 @@ void __init setup_arch(char **cmdline_p)
 #endif
 }
 
+static __init int add_pcspkr(void)
+{
+       struct platform_device *pd;
+       int ret;
+
+       pd = platform_device_alloc("pcspkr", -1);
+       if (!pd)
+               return -ENOMEM;
+
+       ret = platform_device_add(pd);
+       if (ret)
+               platform_device_put(pd);
+
+       return ret;
+}
+device_initcall(add_pcspkr);
+
 #include "setup_arch_post.h"
 /*
  * Local Variables:
index ce3ef4f..4f58b9c 100644 (file)
@@ -313,3 +313,4 @@ ENTRY(sys_call_table)
        .long sys_set_robust_list
        .long sys_get_robust_list
        .long sys_splice
+       .long sys_sync_file_range
index 6b63a5a..e385279 100644 (file)
@@ -1193,6 +1193,6 @@ void __init trap_init(void)
 static int __init kstack_setup(char *s)
 {
        kstack_depth_to_print = simple_strtoul(s, NULL, 0);
-       return 0;
+       return 1;
 }
 __setup("kstack=", kstack_setup);
index fadb5bc..a92262f 100644 (file)
@@ -44,7 +44,7 @@ __kernel_rt_sigreturn:
 .LSTARTCIEDLSI1:
        .long 0                 /* CIE ID */
        .byte 1                 /* Version number */
-       .string "zR           /* NUL-terminated augmentation string */
+       .string "zRS"           /* NUL-terminated augmentation string */
        .uleb128 1              /* Code alignment factor */
        .sleb128 -4             /* Data alignment factor */
        .byte 8                 /* Return address register column */
index 89faa60..6386f63 100644 (file)
@@ -240,7 +240,7 @@ cache_info(char *page)
                        }
                        p += sprintf(p,
                                     "%s Cache level %lu:\n"
-                                    "\tSize           : %lu bytes\n"
+                                    "\tSize           : %u bytes\n"
                                     "\tAttributes     : ",
                                     cache_types[j+cci.pcci_unified], i+1,
                                     cci.pcci_cache_size);
@@ -648,9 +648,9 @@ frequency_info(char *page)
        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",
+                    "Processor/Clock ratio   : %d/%d\n"
+                    "Bus/Clock ratio         : %d/%d\n"
+                    "ITC/Clock ratio         : %d/%d\n",
                     proc.num, proc.den, bus.num, bus.den, itc.num, itc.den);
 
        return p - page;
index ac16743..4995890 100644 (file)
@@ -188,7 +188,7 @@ ia64_init_itm (void)
        itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den;
 
        local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ;
-       printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, "
+       printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%u/%u, "
               "ITC freq=%lu.%03luMHz", smp_processor_id(),
               platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
               itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000);
index 3b6fd79..b47476d 100644 (file)
@@ -9,6 +9,8 @@
  *             2002/08/07 Erich Focht <efocht@ess.nec.de>
  * Populate cpu entries in sysfs for non-numa systems as well
  *     Intel Corporation - Ashok Raj
+ * 02/27/2006 Zhang, Yanmin
+ *     Populate cpu cache entries in sysfs for cpu cache info
  */
 
 #include <linux/config.h>
@@ -19,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/nodemask.h>
+#include <linux/notifier.h>
 #include <asm/mmzone.h>
 #include <asm/numa.h>
 #include <asm/cpu.h>
@@ -101,3 +104,367 @@ out:
 }
 
 subsys_initcall(topology_init);
+
+
+/*
+ * Export cpu cache information through sysfs
+ */
+
+/*
+ *  A bunch of string array to get pretty printing
+ */
+static const char *cache_types[] = {
+       "",                     /* not used */
+       "Instruction",
+       "Data",
+       "Unified"       /* unified */
+};
+
+static const char *cache_mattrib[]={
+       "WriteThrough",
+       "WriteBack",
+       "",             /* reserved */
+       ""              /* reserved */
+};
+
+struct cache_info {
+       pal_cache_config_info_t cci;
+       cpumask_t shared_cpu_map;
+       int level;
+       int type;
+       struct kobject kobj;
+};
+
+struct cpu_cache_info {
+       struct cache_info *cache_leaves;
+       int     num_cache_leaves;
+       struct kobject kobj;
+};
+
+static struct cpu_cache_info   all_cpu_cache_info[NR_CPUS];
+#define LEAF_KOBJECT_PTR(x,y)    (&all_cpu_cache_info[x].cache_leaves[y])
+
+#ifdef CONFIG_SMP
+static void cache_shared_cpu_map_setup( unsigned int cpu,
+               struct cache_info * this_leaf)
+{
+       pal_cache_shared_info_t csi;
+       int num_shared, i = 0;
+       unsigned int j;
+
+       if (cpu_data(cpu)->threads_per_core <= 1 &&
+               cpu_data(cpu)->cores_per_socket <= 1) {
+               cpu_set(cpu, this_leaf->shared_cpu_map);
+               return;
+       }
+
+       if (ia64_pal_cache_shared_info(this_leaf->level,
+                                       this_leaf->type,
+                                       0,
+                                       &csi) != PAL_STATUS_SUCCESS)
+               return;
+
+       num_shared = (int) csi.num_shared;
+       do {
+               for_each_cpu(j)
+                       if (cpu_data(cpu)->socket_id == cpu_data(j)->socket_id
+                               && cpu_data(j)->core_id == csi.log1_cid
+                               && cpu_data(j)->thread_id == csi.log1_tid)
+                               cpu_set(j, this_leaf->shared_cpu_map);
+
+               i++;
+       } while (i < num_shared &&
+               ia64_pal_cache_shared_info(this_leaf->level,
+                               this_leaf->type,
+                               i,
+                               &csi) == PAL_STATUS_SUCCESS);
+}
+#else
+static void cache_shared_cpu_map_setup(unsigned int cpu,
+               struct cache_info * this_leaf)
+{
+       cpu_set(cpu, this_leaf->shared_cpu_map);
+       return;
+}
+#endif
+
+static ssize_t show_coherency_line_size(struct cache_info *this_leaf,
+                                       char *buf)
+{
+       return sprintf(buf, "%u\n", 1 << this_leaf->cci.pcci_line_size);
+}
+
+static ssize_t show_ways_of_associativity(struct cache_info *this_leaf,
+                                       char *buf)
+{
+       return sprintf(buf, "%u\n", this_leaf->cci.pcci_assoc);
+}
+
+static ssize_t show_attributes(struct cache_info *this_leaf, char *buf)
+{
+       return sprintf(buf,
+                       "%s\n",
+                       cache_mattrib[this_leaf->cci.pcci_cache_attr]);
+}
+
+static ssize_t show_size(struct cache_info *this_leaf, char *buf)
+{
+       return sprintf(buf, "%uK\n", this_leaf->cci.pcci_cache_size / 1024);
+}
+
+static ssize_t show_number_of_sets(struct cache_info *this_leaf, char *buf)
+{
+       unsigned number_of_sets = this_leaf->cci.pcci_cache_size;
+       number_of_sets /= this_leaf->cci.pcci_assoc;
+       number_of_sets /= 1 << this_leaf->cci.pcci_line_size;
+
+       return sprintf(buf, "%u\n", number_of_sets);
+}
+
+static ssize_t show_shared_cpu_map(struct cache_info *this_leaf, char *buf)
+{
+       ssize_t len;
+       cpumask_t shared_cpu_map;
+
+       cpus_and(shared_cpu_map, this_leaf->shared_cpu_map, cpu_online_map);
+       len = cpumask_scnprintf(buf, NR_CPUS+1, shared_cpu_map);
+       len += sprintf(buf+len, "\n");
+       return len;
+}
+
+static ssize_t show_type(struct cache_info *this_leaf, char *buf)
+{
+       int type = this_leaf->type + this_leaf->cci.pcci_unified;
+       return sprintf(buf, "%s\n", cache_types[type]);
+}
+
+static ssize_t show_level(struct cache_info *this_leaf, char *buf)
+{
+       return sprintf(buf, "%u\n", this_leaf->level);
+}
+
+struct cache_attr {
+       struct attribute attr;
+       ssize_t (*show)(struct cache_info *, char *);
+       ssize_t (*store)(struct cache_info *, const char *, size_t count);
+};
+
+#ifdef define_one_ro
+       #undef define_one_ro
+#endif
+#define define_one_ro(_name) \
+       static struct cache_attr _name = \
+__ATTR(_name, 0444, show_##_name, NULL)
+
+define_one_ro(level);
+define_one_ro(type);
+define_one_ro(coherency_line_size);
+define_one_ro(ways_of_associativity);
+define_one_ro(size);
+define_one_ro(number_of_sets);
+define_one_ro(shared_cpu_map);
+define_one_ro(attributes);
+
+static struct attribute * cache_default_attrs[] = {
+       &type.attr,
+       &level.attr,
+       &coherency_line_size.attr,
+       &ways_of_associativity.attr,
+       &attributes.attr,
+       &size.attr,
+       &number_of_sets.attr,
+       &shared_cpu_map.attr,
+       NULL
+};
+
+#define to_object(k) container_of(k, struct cache_info, kobj)
+#define to_attr(a) container_of(a, struct cache_attr, attr)
+
+static ssize_t cache_show(struct kobject * kobj, struct attribute * attr, char * buf)
+{
+       struct cache_attr *fattr = to_attr(attr);
+       struct cache_info *this_leaf = to_object(kobj);
+       ssize_t ret;
+
+       ret = fattr->show ? fattr->show(this_leaf, buf) : 0;
+       return ret;
+}
+
+static struct sysfs_ops cache_sysfs_ops = {
+       .show   = cache_show
+};
+
+static struct kobj_type cache_ktype = {
+       .sysfs_ops      = &cache_sysfs_ops,
+       .default_attrs  = cache_default_attrs,
+};
+
+static struct kobj_type cache_ktype_percpu_entry = {
+       .sysfs_ops      = &cache_sysfs_ops,
+};
+
+static void __cpuinit cpu_cache_sysfs_exit(unsigned int cpu)
+{
+       if (all_cpu_cache_info[cpu].cache_leaves) {
+               kfree(all_cpu_cache_info[cpu].cache_leaves);
+               all_cpu_cache_info[cpu].cache_leaves = NULL;
+       }
+       all_cpu_cache_info[cpu].num_cache_leaves = 0;
+       memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject));
+
+       return;
+}
+
+static int __cpuinit cpu_cache_sysfs_init(unsigned int cpu)
+{
+       u64 i, levels, unique_caches;
+       pal_cache_config_info_t cci;
+       int j;
+       s64 status;
+       struct cache_info *this_cache;
+       int num_cache_leaves = 0;
+
+       if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) {
+               printk(KERN_ERR "ia64_pal_cache_summary=%ld\n", status);
+               return -1;
+       }
+
+       this_cache=kzalloc(sizeof(struct cache_info)*unique_caches,
+                       GFP_KERNEL);
+       if (this_cache == NULL)
+               return -ENOMEM;
+
+       for (i=0; i < levels; i++) {
+               for (j=2; j >0 ; j--) {
+                       if ((status=ia64_pal_cache_config_info(i,j, &cci)) !=
+                                       PAL_STATUS_SUCCESS)
+                               continue;
+
+                       this_cache[num_cache_leaves].cci = cci;
+                       this_cache[num_cache_leaves].level = i + 1;
+                       this_cache[num_cache_leaves].type = j;
+
+                       cache_shared_cpu_map_setup(cpu,
+                                       &this_cache[num_cache_leaves]);
+                       num_cache_leaves ++;
+               }
+       }
+
+       all_cpu_cache_info[cpu].cache_leaves = this_cache;
+       all_cpu_cache_info[cpu].num_cache_leaves = num_cache_leaves;
+
+       memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject));
+
+       return 0;
+}
+
+/* Add cache interface for CPU device */
+static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
+{
+       unsigned int cpu = sys_dev->id;
+       unsigned long i, j;
+       struct cache_info *this_object;
+       int retval = 0;
+       cpumask_t oldmask;
+
+       if (all_cpu_cache_info[cpu].kobj.parent)
+               return 0;
+
+       oldmask = current->cpus_allowed;
+       retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       if (unlikely(retval))
+               return retval;
+
+       retval = cpu_cache_sysfs_init(cpu);
+       set_cpus_allowed(current, oldmask);
+       if (unlikely(retval < 0))
+               return retval;
+
+       all_cpu_cache_info[cpu].kobj.parent = &sys_dev->kobj;
+       kobject_set_name(&all_cpu_cache_info[cpu].kobj, "%s", "cache");
+       all_cpu_cache_info[cpu].kobj.ktype = &cache_ktype_percpu_entry;
+       retval = kobject_register(&all_cpu_cache_info[cpu].kobj);
+
+       for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) {
+               this_object = LEAF_KOBJECT_PTR(cpu,i);
+               this_object->kobj.parent = &all_cpu_cache_info[cpu].kobj;
+               kobject_set_name(&(this_object->kobj), "index%1lu", i);
+               this_object->kobj.ktype = &cache_ktype;
+               retval = kobject_register(&(this_object->kobj));
+               if (unlikely(retval)) {
+                       for (j = 0; j < i; j++) {
+                               kobject_unregister(
+                                       &(LEAF_KOBJECT_PTR(cpu,j)->kobj));
+                       }
+                       kobject_unregister(&all_cpu_cache_info[cpu].kobj);
+                       cpu_cache_sysfs_exit(cpu);
+                       break;
+               }
+       }
+       return retval;
+}
+
+/* Remove cache interface for CPU device */
+static int __cpuinit cache_remove_dev(struct sys_device * sys_dev)
+{
+       unsigned int cpu = sys_dev->id;
+       unsigned long i;
+
+       for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++)
+               kobject_unregister(&(LEAF_KOBJECT_PTR(cpu,i)->kobj));
+
+       if (all_cpu_cache_info[cpu].kobj.parent) {
+               kobject_unregister(&all_cpu_cache_info[cpu].kobj);
+               memset(&all_cpu_cache_info[cpu].kobj,
+                       0,
+                       sizeof(struct kobject));
+       }
+
+       cpu_cache_sysfs_exit(cpu);
+
+       return 0;
+}
+
+/*
+ * When a cpu is hot-plugged, do a check and initiate
+ * cache kobject if necessary
+ */
+static int __cpuinit cache_cpu_callback(struct notifier_block *nfb,
+               unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+       struct sys_device *sys_dev;
+
+       sys_dev = get_cpu_sysdev(cpu);
+       switch (action) {
+       case CPU_ONLINE:
+               cache_add_dev(sys_dev);
+               break;
+       case CPU_DEAD:
+               cache_remove_dev(sys_dev);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block cache_cpu_notifier =
+{
+       .notifier_call = cache_cpu_callback
+};
+
+static int __cpuinit cache_sysfs_init(void)
+{
+       int i;
+
+       for_each_online_cpu(i) {
+               cache_cpu_callback(&cache_cpu_notifier, CPU_ONLINE,
+                               (void *)(long)i);
+       }
+
+       register_cpu_notifier(&cache_cpu_notifier);
+
+       return 0;
+}
+
+device_initcall(cache_sysfs_init);
+
index 3d7f200..c331951 100644 (file)
@@ -79,4 +79,3 @@ EXPORT_SYMBOL(__down_failed_interruptible);
 EXPORT_SYMBOL(__down_failed_trylock);
 EXPORT_SYMBOL(__up_wakeup);
 
-EXPORT_SYMBOL(get_wchan);
index d844c75..f9b4ea1 100644 (file)
@@ -57,8 +57,6 @@ EXPORT_SYMBOL(__down_failed_interruptible);
 EXPORT_SYMBOL(__down_failed_trylock);
 EXPORT_SYMBOL(__up_wakeup);
 
-EXPORT_SYMBOL(get_wchan);
-
 /*
  * libgcc functions - functions that are used internally by the
  * compiler...  (prototypes are not correct though, but that
index 5080ea1..e15709c 100644 (file)
@@ -233,6 +233,7 @@ config MACH_JAZZ
        select ARC32
        select ARCH_MAY_HAVE_PC_FDC
        select GENERIC_ISA_DMA
+       select I8253
        select I8259
        select ISA
        select SYS_HAS_CPU_R4X00
@@ -530,6 +531,7 @@ config QEMU
        select DMA_COHERENT
        select GENERIC_ISA_DMA
        select HAVE_STD_PC_SERIAL_PORT
+       select I8253
        select I8259
        select ISA
        select SWAP_IO_SPACE
@@ -714,6 +716,7 @@ config SNI_RM200_PCI
        select HAVE_STD_PC_SERIAL_PORT
        select HW_HAS_EISA
        select HW_HAS_PCI
+       select I8253
        select I8259
        select ISA
        select SYS_HAS_CPU_R4X00
@@ -1721,6 +1724,9 @@ config MMU
        bool
        default y
 
+config I8253
+       bool
+
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
index f36c4f2..309d54c 100644 (file)
@@ -59,6 +59,8 @@ obj-$(CONFIG_PROC_FS)         += proc.o
 
 obj-$(CONFIG_64BIT)            += cpu-bugs64.o
 
+obj-$(CONFIG_I8253)            += i8253.o
+
 CFLAGS_cpu-bugs64.o    = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
new file mode 100644 (file)
index 0000000..475df69
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2006 IBM Corporation
+ *
+ * Implements device information for i8253 timer chip
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation
+ */
+
+#include <linux/platform_device.h>
+
+static __init int add_pcspkr(void)
+{
+       struct platform_device *pd;
+       int ret;
+
+       pd = platform_device_alloc("pcspkr", -1);
+       if (!pd)
+               return -ENOMEM;
+
+       ret = platform_device_add(pd);
+       if (ret)
+               platform_device_put(pd);
+
+       return ret;
+}
+device_initcall(add_pcspkr);
index a8f435d..c66db5e 100644 (file)
@@ -419,4 +419,3 @@ unsigned long get_wchan(struct task_struct *p)
        return pc;
 }
 
-EXPORT_SYMBOL(get_wchan);
index 6b3c509..2fdf219 100644 (file)
@@ -177,14 +177,10 @@ config ARCH_DISCONTIGMEM_DEFAULT
        def_bool y
        depends on ARCH_DISCONTIGMEM_ENABLE
 
+source "kernel/Kconfig.preempt"
 source "kernel/Kconfig.hz"
 source "mm/Kconfig"
 
-config PREEMPT
-       bool
-#      bool "Preemptible Kernel"
-       default n
-
 config COMPAT
        def_bool y
        depends on 64BIT
index 3e013f5..41fd069 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc5-pa1
-# Fri Oct 21 23:04:34 2005
+# Linux kernel version: 2.6.16-pa6
+# Sun Mar 26 19:59:51 2006
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -10,14 +10,11 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -32,17 +29,18 @@ CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -51,8 +49,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -65,6 +65,23 @@ CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
 #
 # Processor type and features
 #
@@ -75,6 +92,10 @@ CONFIG_PA7100LC=y
 # CONFIG_PA8X00 is not set
 CONFIG_PA11=y
 # CONFIG_SMP is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
 # CONFIG_HZ_1000 is not set
@@ -86,7 +107,7 @@ CONFIG_FLATMEM_MANUAL=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_PREEMPT is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
 # CONFIG_HPUX is not set
 
 #
@@ -130,6 +151,7 @@ CONFIG_NET=y
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -165,7 +187,12 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
 # CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
@@ -182,64 +209,6 @@ CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
 CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-CONFIG_IP_NF_MATCH_SCTP=m
-# CONFIG_IP_NF_MATCH_DCCP is not set
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-# CONFIG_IP_NF_MATCH_STRING is not set
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-# CONFIG_IP_NF_TARGET_NFQUEUE is not set
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-# CONFIG_IP_NF_TARGET_TTL is not set
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
 
 #
 # DCCP Configuration (EXPERIMENTAL)
@@ -250,6 +219,11 @@ CONFIG_IP_NF_ARP_MANGLE=m
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -263,8 +237,11 @@ CONFIG_LLC2=m
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
 # CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -304,6 +281,7 @@ CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=m
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_NOT_PC=y
 CONFIG_PARPORT_GSC=y
 # CONFIG_PARPORT_1284 is not set
 
@@ -314,7 +292,6 @@ CONFIG_PARPORT_GSC=y
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -325,14 +302,6 @@ CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=6144
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 CONFIG_ATA_OVER_ETH=m
 
 #
@@ -376,6 +345,7 @@ CONFIG_SCSI_ISCSI_ATTRS=m
 #
 # SCSI low-level drivers
 #
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_IMM is not set
@@ -407,7 +377,6 @@ CONFIG_MD_RAID1=m
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
@@ -471,6 +440,7 @@ CONFIG_PPP_ASYNC=m
 CONFIG_PPP_SYNC_TTY=m
 CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
@@ -516,8 +486,8 @@ CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_KEYBOARD_HIL_OLD=y
-# CONFIG_KEYBOARD_HIL is not set
+# CONFIG_KEYBOARD_HIL_OLD is not set
+CONFIG_KEYBOARD_HIL=y
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_SERIAL=m
@@ -554,6 +524,7 @@ CONFIG_HW_CONSOLE=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=17
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
@@ -598,12 +569,20 @@ CONFIG_MAX_RAW_DEVS=256
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
 #
 # CONFIG_I2C is not set
 
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
 #
 # Dallas's 1-wire bus
 #
@@ -640,7 +619,6 @@ CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
 # CONFIG_FB_MACMODES is not set
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
@@ -655,6 +633,7 @@ CONFIG_DUMMY_CONSOLE=y
 CONFIG_DUMMY_CONSOLE_COLUMNS=128
 CONFIG_DUMMY_CONSOLE_ROWS=48
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 CONFIG_STI_CONSOLE=y
 CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
@@ -695,6 +674,8 @@ CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
 CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 
@@ -723,6 +704,10 @@ CONFIG_SND_HARMONY=y
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
 #
 # USB Gadget Support
 #
@@ -736,10 +721,9 @@ CONFIG_SND_HARMONY=y
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
@@ -765,6 +749,7 @@ CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -800,10 +785,10 @@ CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -821,7 +806,6 @@ CONFIG_RAMFS=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_SYSV_FS is not set
 CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
@@ -917,18 +901,22 @@ CONFIG_OPROFILE=m
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_IOREMAP is not set
 # CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_RODATA=y
 
 #
 # Security options
index 959ad3c..f3b812f 100644 (file)
@@ -1031,8 +1031,8 @@ CONFIG_NLS_CODEPAGE_850=m
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
index 37e9824..3509361 100644 (file)
@@ -939,10 +939,10 @@ CONFIG_MSDOS_PARTITION=y
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=m
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
+CONFIG_NLS_CODEPAGE_850=m
 # CONFIG_NLS_CODEPAGE_852 is not set
 # CONFIG_NLS_CODEPAGE_855 is not set
 # CONFIG_NLS_CODEPAGE_857 is not set
@@ -962,8 +962,8 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -973,10 +973,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_ISO8859_9 is not set
 # CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_ISO8859_15=m
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=m
 
 #
 # Kernel hacking
index 0b1c8c1..782906b 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc5-pa1
-# Fri Oct 21 23:06:31 2005
+# Linux kernel version: 2.6.16-pa6
+# Sun Mar 26 20:03:29 2006
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -10,14 +10,11 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -32,28 +29,30 @@ CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -66,6 +65,23 @@ CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
 #
 # Processor type and features
 #
@@ -78,6 +94,10 @@ CONFIG_PA20=y
 CONFIG_PREFETCH=y
 # CONFIG_64BIT is not set
 # CONFIG_SMP is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
 # CONFIG_HZ_1000 is not set
@@ -89,7 +109,7 @@ CONFIG_FLATMEM_MANUAL=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_PREEMPT is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_HPUX is not set
 
 #
@@ -135,6 +155,7 @@ CONFIG_NET=y
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -175,7 +196,12 @@ CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_DEBUG=y
+
+#
+# Core Netfilter Configuration
+#
 # CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
@@ -192,87 +218,11 @@ CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
 CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-# CONFIG_IP_NF_MATCH_SCTP is not set
-# CONFIG_IP_NF_MATCH_DCCP is not set
-# CONFIG_IP_NF_MATCH_COMMENT is not set
-# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
-# CONFIG_IP_NF_MATCH_STRING is not set
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-# CONFIG_IP_NF_TARGET_NFQUEUE is not set
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-# CONFIG_IP_NF_TARGET_TTL is not set
-# CONFIG_IP_NF_RAW is not set
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
 
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP6_NF_QUEUE is not set
-CONFIG_IP6_NF_IPTABLES=m
-# CONFIG_IP6_NF_MATCH_LIMIT is not set
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-# CONFIG_IP6_NF_MATCH_OPTS is not set
-# CONFIG_IP6_NF_MATCH_FRAG is not set
-# CONFIG_IP6_NF_MATCH_HL is not set
-# CONFIG_IP6_NF_MATCH_MULTIPORT is not set
-CONFIG_IP6_NF_MATCH_OWNER=m
-# CONFIG_IP6_NF_MATCH_MARK is not set
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-# CONFIG_IP6_NF_MATCH_AHESP is not set
-CONFIG_IP6_NF_MATCH_LENGTH=m
-# CONFIG_IP6_NF_MATCH_EUI64 is not set
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_TARGET_REJECT=m
-# CONFIG_IP6_NF_TARGET_NFQUEUE is not set
-CONFIG_IP6_NF_MANGLE=m
-# CONFIG_IP6_NF_TARGET_MARK is not set
-# CONFIG_IP6_NF_TARGET_HL is not set
-# CONFIG_IP6_NF_RAW is not set
 
 #
 # DCCP Configuration (EXPERIMENTAL)
@@ -283,6 +233,11 @@ CONFIG_IP6_NF_MANGLE=m
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -295,8 +250,11 @@ CONFIG_IP6_NF_MANGLE=m
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
 # CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -341,7 +299,6 @@ CONFIG_FW_LOADER=y
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -355,14 +312,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -458,6 +407,7 @@ CONFIG_SCSI_ISCSI_ATTRS=m
 #
 # SCSI low-level drivers
 #
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -466,7 +416,6 @@ CONFIG_SCSI_ISCSI_ATTRS=m
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
@@ -476,18 +425,18 @@ CONFIG_SCSI_SATA=y
 CONFIG_SCSI_ATA_PIIX=m
 # CONFIG_SCSI_SATA_MV is not set
 # CONFIG_SCSI_SATA_NV is not set
-CONFIG_SCSI_SATA_PROMISE=m
+# CONFIG_SCSI_PDC_ADMA is not set
 # CONFIG_SCSI_SATA_QSTOR is not set
+CONFIG_SCSI_SATA_PROMISE=m
 # CONFIG_SCSI_SATA_SX4 is not set
 CONFIG_SCSI_SATA_SIL=m
+# CONFIG_SCSI_SATA_SIL24 is not set
 # CONFIG_SCSI_SATA_SIS is not set
 # CONFIG_SCSI_SATA_ULI is not set
 CONFIG_SCSI_SATA_VIA=m
 # CONFIG_SCSI_SATA_VITESSE is not set
 CONFIG_SCSI_SATA_INTEL_COMBINED=y
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
@@ -496,18 +445,11 @@ CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -633,6 +575,7 @@ CONFIG_E1000=m
 # CONFIG_R8169 is not set
 # CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=m
@@ -668,6 +611,7 @@ CONFIG_PPP_ASYNC=m
 CONFIG_PPP_SYNC_TTY=m
 CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
 # CONFIG_NET_FC is not set
@@ -744,6 +688,7 @@ CONFIG_HW_CONSOLE=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=13
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
@@ -753,7 +698,6 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_MUX is not set
 # CONFIG_PDC_CONSOLE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
@@ -788,12 +732,19 @@ CONFIG_MAX_RAW_DEVS=256
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
 #
 # CONFIG_I2C is not set
 
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
 #
 # Dallas's 1-wire bus
 #
@@ -830,7 +781,6 @@ CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
@@ -840,6 +790,7 @@ CONFIG_FB_SOFT_CURSOR=y
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 CONFIG_FB_STI=y
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
@@ -853,10 +804,7 @@ CONFIG_FB_STI=y
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -866,6 +814,7 @@ CONFIG_DUMMY_CONSOLE=y
 CONFIG_DUMMY_CONSOLE_COLUMNS=160
 CONFIG_DUMMY_CONSOLE_ROWS=64
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 CONFIG_STI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
@@ -898,23 +847,27 @@ CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
 CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 
 #
 # Generic devices
 #
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_VIRMIDI is not set
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_AC97_BUS=y
 
 #
 # PCI devices
 #
+CONFIG_SND_AD1889=y
+# CONFIG_SND_AD1889_OPL3 is not set
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -923,39 +876,38 @@ CONFIG_SND_AC97_BUS=y
 # CONFIG_SND_AU8830 is not set
 # CONFIG_SND_AZT3328 is not set
 # CONFIG_SND_BT87X is not set
-# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-CONFIG_SND_AD1889=y
-# CONFIG_SND_AD1889_OPL3 is not set
-# CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_ENS1370 is not set
 # CONFIG_SND_ENS1371 is not set
 # CONFIG_SND_ES1938 is not set
 # CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
 # CONFIG_SND_ICE1712 is not set
 # CONFIG_SND_ICE1724 is not set
 # CONFIG_SND_INTEL8X0 is not set
 # CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
 # CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
 # CONFIG_SND_VIA82XX is not set
 # CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
-# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_YMFPCI is not set
 
 #
 # USB devices
@@ -998,12 +950,15 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # USB Device Class drivers
 #
 # CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
-# CONFIG_USB_BLUETOOTH_TTY is not set
 # CONFIG_USB_ACM is not set
 CONFIG_USB_PRINTER=m
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
 #
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -1015,12 +970,15 @@ CONFIG_USB_STORAGE_USBAT=y
 CONFIG_USB_STORAGE_SDDR09=y
 CONFIG_USB_STORAGE_SDDR55=y
 CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
@@ -1034,6 +992,7 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
 
@@ -1108,7 +1067,7 @@ CONFIG_USB_LEGOTOWER=m
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
@@ -1130,6 +1089,7 @@ CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -1164,10 +1124,10 @@ CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1225,10 +1185,10 @@ CONFIG_MSDOS_PARTITION=y
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=m
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
+CONFIG_NLS_CODEPAGE_850=m
 # CONFIG_NLS_CODEPAGE_852 is not set
 # CONFIG_NLS_CODEPAGE_855 is not set
 # CONFIG_NLS_CODEPAGE_857 is not set
@@ -1248,8 +1208,8 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -1259,10 +1219,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_ISO8859_9 is not set
 # CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_ISO8859_15=m
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=m
 
 #
 # Profiling support
@@ -1274,18 +1234,22 @@ CONFIG_OPROFILE=m
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_IOREMAP is not set
 # CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_RODATA=y
 
 #
 # Security options
index f38a462..59f7bc3 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc5-pa1
-# Fri Oct 21 23:01:33 2005
+# Linux kernel version: 2.6.16-pa6
+# Sun Mar 26 19:50:07 2006
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -15,7 +15,6 @@ CONFIG_GENERIC_IRQ_PROBE=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -30,17 +29,18 @@ CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -49,14 +49,33 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
 #
 # CONFIG_MODULES is not set
 
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
 #
 # Processor type and features
 #
@@ -67,6 +86,10 @@ CONFIG_PA7000=y
 # CONFIG_PA8X00 is not set
 CONFIG_PA11=y
 # CONFIG_SMP is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
 # CONFIG_HZ_1000 is not set
@@ -78,7 +101,7 @@ CONFIG_FLATMEM_MANUAL=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_PREEMPT is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
 # CONFIG_HPUX is not set
 
 #
@@ -132,6 +155,7 @@ CONFIG_NET=y
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -174,6 +198,11 @@ CONFIG_IPV6=y
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -186,8 +215,11 @@ CONFIG_IPV6=y
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
 # CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -228,6 +260,7 @@ CONFIG_PARPORT_PC=y
 # CONFIG_PARPORT_SERIAL is not set
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_NOT_PC=y
 CONFIG_PARPORT_GSC=y
 # CONFIG_PARPORT_1284 is not set
 
@@ -254,14 +287,6 @@ CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -305,6 +330,7 @@ CONFIG_SCSI_SPI_ATTRS=y
 #
 # SCSI low-level drivers
 #
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -331,7 +357,7 @@ CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 # CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_ZALON=y
 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
@@ -340,13 +366,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_DC395x is not set
@@ -471,6 +491,7 @@ CONFIG_ACENIC=y
 # CONFIG_R8169 is not set
 # CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
@@ -562,13 +583,13 @@ CONFIG_INPUT_KEYBOARD=y
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_KEYBOARD_HIL_OLD=y
+# CONFIG_KEYBOARD_HIL_OLD is not set
 CONFIG_KEYBOARD_HIL=y
 CONFIG_INPUT_MOUSE=y
 # CONFIG_MOUSE_PS2 is not set
 # CONFIG_MOUSE_SERIAL is not set
 # CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_MOUSE_HIL is not set
+CONFIG_MOUSE_HIL=y
 CONFIG_INPUT_JOYSTICK=y
 # CONFIG_JOYSTICK_ANALOG is not set
 # CONFIG_JOYSTICK_A3D is not set
@@ -628,6 +649,7 @@ CONFIG_HW_CONSOLE=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=13
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
@@ -675,12 +697,19 @@ CONFIG_GEN_RTC=y
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
 #
 # CONFIG_I2C is not set
 
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
 #
 # Dallas's 1-wire bus
 #
@@ -691,6 +720,7 @@ CONFIG_GEN_RTC=y
 #
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -718,7 +748,6 @@ CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
@@ -728,6 +757,7 @@ CONFIG_FB_SOFT_CURSOR=y
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 CONFIG_FB_STI=y
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
@@ -741,9 +771,7 @@ CONFIG_FB_STI=y
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -753,15 +781,28 @@ CONFIG_DUMMY_CONSOLE=y
 CONFIG_DUMMY_CONSOLE_COLUMNS=160
 CONFIG_DUMMY_CONSOLE_ROWS=64
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 CONFIG_STI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
 CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
 
 #
 # Logo configuration
 #
-# CONFIG_LOGO is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_PARISC_CLUT224=y
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -781,23 +822,27 @@ CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
 CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 
 #
 # Generic devices
 #
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_VIRMIDI is not set
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_AC97_BUS=y
 
 #
 # PCI devices
 #
+CONFIG_SND_AD1889=y
+# CONFIG_SND_AD1889_OPL3 is not set
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -806,39 +851,38 @@ CONFIG_SND_AC97_BUS=y
 # CONFIG_SND_AU8830 is not set
 # CONFIG_SND_AZT3328 is not set
 # CONFIG_SND_BT87X is not set
-# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-CONFIG_SND_AD1889=y
-# CONFIG_SND_AD1889_OPL3 is not set
-# CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_ENS1370 is not set
 # CONFIG_SND_ENS1371 is not set
 # CONFIG_SND_ES1938 is not set
 # CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
 # CONFIG_SND_ICE1712 is not set
 # CONFIG_SND_ICE1724 is not set
 # CONFIG_SND_INTEL8X0 is not set
 # CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
 # CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
 # CONFIG_SND_VIA82XX is not set
 # CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
-# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_YMFPCI is not set
 
 #
 # USB devices
@@ -888,14 +932,18 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # USB Device Class drivers
 #
 # CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
-# CONFIG_USB_BLUETOOTH_TTY is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
 #
 # CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
@@ -918,6 +966,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
 
@@ -994,7 +1043,7 @@ CONFIG_USB_MON=y
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
@@ -1011,6 +1060,7 @@ CONFIG_JBD=y
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -1045,6 +1095,7 @@ CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1151,18 +1202,22 @@ CONFIG_OPROFILE=y
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=15
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_IOREMAP is not set
 # CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_RODATA=y
 
 #
 # Security options
index d8a4ca0..360b739 100644 (file)
@@ -89,7 +89,7 @@ update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
        if (pfn_valid(page_to_pfn(page)) && page_mapping(page) &&
            test_bit(PG_dcache_dirty, &page->flags)) {
 
-               flush_kernel_dcache_page(page_address(page));
+               flush_kernel_dcache_page(page);
                clear_bit(PG_dcache_dirty, &page->flags);
        }
 }
@@ -278,7 +278,7 @@ void flush_dcache_page(struct page *page)
                return;
        }
 
-       flush_kernel_dcache_page(page_address(page));
+       flush_kernel_dcache_page(page);
 
        if (!mapping)
                return;
@@ -317,7 +317,7 @@ EXPORT_SYMBOL(flush_dcache_page);
 
 /* Defined in arch/parisc/kernel/pacache.S */
 EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
-EXPORT_SYMBOL(flush_kernel_dcache_page);
+EXPORT_SYMBOL(flush_kernel_dcache_page_asm);
 EXPORT_SYMBOL(flush_data_cache_local);
 EXPORT_SYMBOL(flush_kernel_icache_range_asm);
 
index 9af4b22..7c95d76 100644 (file)
        extrd,u,*=      \pte,_PAGE_GATEWAY_BIT+32,1,%r0
        depd            %r0,11,2,\prot  /* If Gateway, Set PL2 to 0 */
 
-       /* Get rid of prot bits and convert to page addr for iitlbt */
+       /* Get rid of prot bits and convert to page addr for iitlbt and idtlbt */
 
        depd            %r0,63,PAGE_SHIFT,\pte
-       extrd,u         \pte,56,32,\pte
+       extrd,s         \pte,(63-PAGE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte
        .endm
 
        /* Identical macro to make_insert_tlb above, except it
 
        /* Get rid of prot bits and convert to page addr for iitlba */
 
-       depi            0,31,12,\pte
+       depi            0,31,PAGE_SHIFT,\pte
        extru           \pte,24,25,\pte
 
        .endm
@@ -1014,14 +1014,21 @@ intr_restore:
        nop
        nop
 
+#ifndef CONFIG_PREEMPT
+# define intr_do_preempt       intr_restore
+#endif /* !CONFIG_PREEMPT */
+
        .import schedule,code
 intr_do_resched:
-       /* Only do reschedule if we are returning to user space */
+       /* Only call schedule on return to userspace. If we're returning
+        * to kernel space, we may schedule if CONFIG_PREEMPT, otherwise
+        * we jump back to intr_restore.
+        */
        LDREG   PT_IASQ0(%r16), %r20
-       CMPIB= 0,%r20,intr_restore /* backward */
+       CMPIB=  0, %r20, intr_do_preempt
        nop
        LDREG   PT_IASQ1(%r16), %r20
-       CMPIB= 0,%r20,intr_restore /* backward */
+       CMPIB=  0, %r20, intr_do_preempt
        nop
 
 #ifdef CONFIG_64BIT
@@ -1037,6 +1044,32 @@ intr_do_resched:
 #endif
        ldo     R%intr_check_sig(%r2), %r2
 
+       /* preempt the current task on returning to kernel
+        * mode from an interrupt, iff need_resched is set,
+        * and preempt_count is 0. otherwise, we continue on
+        * our merry way back to the current running task.
+        */
+#ifdef CONFIG_PREEMPT
+       .import preempt_schedule_irq,code
+intr_do_preempt:
+       rsm     PSW_SM_I, %r0           /* disable interrupts */
+
+       /* current_thread_info()->preempt_count */
+       mfctl   %cr30, %r1
+       LDREG   TI_PRE_COUNT(%r1), %r19
+       CMPIB<> 0, %r19, intr_restore   /* if preempt_count > 0 */
+       nop                             /* prev insn branched backwards */
+
+       /* check if we interrupted a critical path */
+       LDREG   PT_PSW(%r16), %r20
+       bb,<,n  %r20, 31 - PSW_SM_I, intr_restore
+       nop
+
+       BL      preempt_schedule_irq, %r2
+       nop
+
+       b       intr_restore            /* ssm PSW_SM_I done by intr_restore */
+#endif /* CONFIG_PREEMPT */
 
        .import do_signal,code
 intr_do_signal:
index 9534ee1..7a4f07e 100644 (file)
@@ -621,9 +621,9 @@ __clear_user_page_asm:
 
        .procend
 
-       .export flush_kernel_dcache_page
+       .export flush_kernel_dcache_page_asm
 
-flush_kernel_dcache_page:
+flush_kernel_dcache_page_asm:
        .proc
        .callinfo NO_CALLS
        .entry
index 1d00c36..47ca5c0 100644 (file)
 #include <linux/syscalls.h>
 
 #include <linux/string.h>
-EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strpbrk);
 
 #include <asm/atomic.h>
@@ -82,16 +67,12 @@ EXPORT_SYMBOL($global$);
 #endif
 
 #include <asm/io.h>
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(memcpy_toio);
 EXPORT_SYMBOL(memcpy_fromio);
 EXPORT_SYMBOL(memset_io);
 
 #include <asm/unistd.h>
-EXPORT_SYMBOL(sys_open);
 EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_read);
 EXPORT_SYMBOL(sys_write);
 
 #include <asm/semaphore.h>
index 0cea695..a45e2e2 100644 (file)
@@ -5,9 +5,8 @@
  *    Copyright (C) 2002-2004 Thibaut VARENE <varenet@parisc-linux.org>
  *
  *    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.
+ *    it under the terms of the GNU General Public License, version 2, as
+ *    published by the Free Software Foundation.
  *
  *    This program is distributed in the hope that it will be useful,
  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
index 53f861c..ac8ee20 100644 (file)
@@ -805,7 +805,7 @@ static int perf_write_image(uint64_t *memaddr)
                return -1;
        }
 
-       runway = ioremap(cpu_device->hpa.start, 4096);
+       runway = ioremap_nocache(cpu_device->hpa.start, 4096);
 
        /* Merge intrigue bits into Runway STATUS 0 */
        tmp64 = __raw_readq(runway + RUNWAY_STATUS) & 0xffecfffffffffffful;
index 89b6c56..bbeeb61 100644 (file)
        ENTRY_SAME(chown)               /* 180 */
        /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
        ENTRY_COMP(setsockopt)
-       ENTRY_SAME(getsockopt)
+       ENTRY_COMP(getsockopt)
        ENTRY_COMP(sendmsg)
        ENTRY_COMP(recvmsg)
        ENTRY_SAME(semop)               /* 185 */
index 01bec8f..f4a8116 100644 (file)
@@ -263,11 +263,7 @@ static const struct iomap_ops iomem_ops = {
 
 const struct iomap_ops *iomap_ops[8] = {
        [0] = &ioport_ops,
-#ifdef CONFIG_DEBUG_IOREMAP
-       [6] = &iomem_ops,
-#else
        [7] = &iomem_ops
-#endif
 };
 
 
index 852eda3..3796be6 100644 (file)
@@ -1013,9 +1013,9 @@ void flush_tlb_all(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-#if 0
-       if (start < end)
-               printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+       if (start >= end)
+               return;
+       printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
                init_page_count(virt_to_page(start));
@@ -1023,6 +1023,5 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                num_physpages++;
                totalram_pages++;
        }
-#endif
 }
 #endif
index edd9a95..0db1281 100644 (file)
@@ -72,7 +72,6 @@ remap_area_pmd(pmd_t *pmd, unsigned long address, unsigned long size,
        return 0;
 }
 
-#if USE_HPPA_IOREMAP
 static int 
 remap_area_pages(unsigned long address, unsigned long phys_addr,
                 unsigned long size, unsigned long flags)
@@ -114,31 +113,6 @@ remap_area_pages(unsigned long address, unsigned long phys_addr,
 
        return error;
 }
-#endif /* USE_HPPA_IOREMAP */
-
-#ifdef CONFIG_DEBUG_IOREMAP
-static unsigned long last = 0;
-
-void gsc_bad_addr(unsigned long addr)
-{
-       if (time_after(jiffies, last + HZ*10)) {
-               printk("gsc_foo() called with bad address 0x%lx\n", addr);
-               dump_stack();
-               last = jiffies;
-       }
-}
-EXPORT_SYMBOL(gsc_bad_addr);
-
-void __raw_bad_addr(const volatile void __iomem *addr)
-{
-       if (time_after(jiffies, last + HZ*10)) {
-               printk("__raw_foo() called with bad address 0x%p\n", addr);
-               dump_stack();
-               last = jiffies;
-       }
-}
-EXPORT_SYMBOL(__raw_bad_addr);
-#endif
 
 /*
  * Generic mapping function (not visible outside):
@@ -154,26 +128,19 @@ EXPORT_SYMBOL(__raw_bad_addr);
  */
 void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
 {
-#if !(USE_HPPA_IOREMAP)
+       void *addr;
+       struct vm_struct *area;
+       unsigned long offset, last_addr;
 
+#ifdef CONFIG_EISA
        unsigned long end = phys_addr + size - 1;
        /* Support EISA addresses */
-       if ((phys_addr >= 0x00080000 && end < 0x000fffff)
-                       || (phys_addr >= 0x00500000 && end < 0x03bfffff)) {
-               phys_addr |= 0xfc000000;
+       if ((phys_addr >= 0x00080000 && end < 0x000fffff) ||
+           (phys_addr >= 0x00500000 && end < 0x03bfffff)) {
+               phys_addr |= F_EXTEND(0xfc000000);
        }
-
-#ifdef CONFIG_DEBUG_IOREMAP
-       return (void __iomem *)(phys_addr - (0x1UL << NYBBLE_SHIFT));
-#else
-       return (void __iomem *)phys_addr;
 #endif
 
-#else
-       void *addr;
-       struct vm_struct *area;
-       unsigned long offset, last_addr;
-
        /* Don't allow wraparound or zero size */
        last_addr = phys_addr + size - 1;
        if (!size || last_addr < phys_addr)
@@ -217,15 +184,12 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
        }
 
        return (void __iomem *) (offset + (char *)addr);
-#endif
 }
+EXPORT_SYMBOL(__ioremap);
 
 void iounmap(void __iomem *addr)
 {
-#if !(USE_HPPA_IOREMAP)
-       return;
-#else
        if (addr > high_memory)
                return vfree((void *) (PAGE_MASK & (unsigned long __force) addr));
-#endif
 }
+EXPORT_SYMBOL(iounmap);
index 211d726..764d073 100644 (file)
@@ -61,7 +61,7 @@ static int __init parse_elfcorehdr(char *p)
        if (p)
                elfcorehdr_addr = memparse(p, &p);
 
-       return 0;
+       return 1;
 }
 __setup("elfcorehdr=", parse_elfcorehdr);
 #endif
@@ -71,7 +71,7 @@ static int __init parse_savemaxmem(char *p)
        if (p)
                saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
 
-       return 0;
+       return 1;
 }
 __setup("savemaxmem=", parse_savemaxmem);
 
index 1b73508..2cbde86 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/prom.h>
 #include <asm/vdso_datapage.h>
 
-#define MODULE_VERS "1.6"
+#define MODULE_VERS "1.7"
 #define MODULE_NAME "lparcfg"
 
 /* #define LPARCFG_DEBUG */
@@ -149,17 +149,17 @@ static void log_plpar_hcall_return(unsigned long rc, char *tag)
        if (rc == 0)            /* success, return */
                return;
 /* check for null tag ? */
-       if (rc == H_Hardware)
+       if (rc == H_HARDWARE)
                printk(KERN_INFO
                       "plpar-hcall (%s) failed with hardware fault\n", tag);
-       else if (rc == H_Function)
+       else if (rc == H_FUNCTION)
                printk(KERN_INFO
                       "plpar-hcall (%s) failed; function not allowed\n", tag);
-       else if (rc == H_Authority)
+       else if (rc == H_AUTHORITY)
                printk(KERN_INFO
-                      "plpar-hcall (%s) failed; not authorized to this function\n",
-                      tag);
-       else if (rc == H_Parameter)
+                      "plpar-hcall (%s) failed; not authorized to this"
+                      " function\n", tag);
+       else if (rc == H_PARAMETER)
                printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",
                       tag);
        else
@@ -209,7 +209,7 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
        unsigned long dummy;
        rc = plpar_hcall(H_PIC, 0, 0, 0, 0, pool_idle_time, num_procs, &dummy);
 
-       if (rc != H_Authority)
+       if (rc != H_AUTHORITY)
                log_plpar_hcall_return(rc, "H_PIC");
 }
 
@@ -242,7 +242,7 @@ static void parse_system_parameter_string(struct seq_file *m)
 {
        int call_status;
 
-       char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+       unsigned char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
        if (!local_buffer) {
                printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
                       __FILE__, __FUNCTION__, __LINE__);
@@ -254,7 +254,8 @@ static void parse_system_parameter_string(struct seq_file *m)
        call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
                                NULL,
                                SPLPAR_CHARACTERISTICS_TOKEN,
-                               __pa(rtas_data_buf));
+                               __pa(rtas_data_buf),
+                               RTAS_DATA_BUF_SIZE);
        memcpy(local_buffer, rtas_data_buf, SPLPAR_MAXLENGTH);
        spin_unlock(&rtas_data_buf_lock);
 
@@ -275,7 +276,7 @@ static void parse_system_parameter_string(struct seq_file *m)
 #ifdef LPARCFG_DEBUG
                printk(KERN_INFO "success calling get-system-parameter \n");
 #endif
-               splpar_strlen = local_buffer[0] * 16 + local_buffer[1];
+               splpar_strlen = local_buffer[0] * 256 + local_buffer[1];
                local_buffer += 2;      /* step over strlen value */
 
                memset(workbuffer, 0, SPLPAR_MAXLENGTH);
@@ -529,13 +530,13 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
        retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
                                    *new_weight_ptr);
 
-       if (retval == H_Success || retval == H_Constrained) {
+       if (retval == H_SUCCESS || retval == H_CONSTRAINED) {
                retval = count;
-       } else if (retval == H_Busy) {
+       } else if (retval == H_BUSY) {
                retval = -EBUSY;
-       } else if (retval == H_Hardware) {
+       } else if (retval == H_HARDWARE) {
                retval = -EIO;
-       } else if (retval == H_Parameter) {
+       } else if (retval == H_PARAMETER) {
                retval = -EINVAL;
        } else {
                printk(KERN_WARNING "%s: received unknown hv return code %ld",
index 706090c..2dd47d2 100644 (file)
@@ -834,7 +834,6 @@ unsigned long get_wchan(struct task_struct *p)
        } while (count++ < 16);
        return 0;
 }
-EXPORT_SYMBOL(get_wchan);
 
 static int kstack_depth_to_print = 64;
 
index 06636c9..0112318 100644 (file)
@@ -578,18 +578,18 @@ static void rtas_percpu_suspend_me(void *info)
         * We use "waiting" to indicate our state.  As long
         * as it is >0, we are still trying to all join up.
         * If it goes to 0, we have successfully joined up and
-        * one thread got H_Continue.  If any error happens,
+        * one thread got H_CONTINUE.  If any error happens,
         * we set it to <0.
         */
        local_irq_save(flags);
        do {
                rc = plpar_hcall_norets(H_JOIN);
                smp_rmb();
-       } while (rc == H_Success && data->waiting > 0);
-       if (rc == H_Success)
+       } while (rc == H_SUCCESS && data->waiting > 0);
+       if (rc == H_SUCCESS)
                goto out;
 
-       if (rc == H_Continue) {
+       if (rc == H_CONTINUE) {
                data->waiting = 0;
                data->args->args[data->args->nargs] =
                        rtas_call(ibm_suspend_me_token, 0, 1, NULL);
@@ -597,7 +597,7 @@ static void rtas_percpu_suspend_me(void *info)
                        plpar_hcall_norets(H_PROD,i);
        } else {
                data->waiting = -EBUSY;
-               printk(KERN_ERR "Error on H_Join hypervisor call\n");
+               printk(KERN_ERR "Error on H_JOIN hypervisor call\n");
        }
 
 out:
@@ -624,7 +624,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
                printk(KERN_ERR "Error doing global join\n");
 
        /* Prod each CPU.  This won't hurt, and will wake
-        * anyone we successfully put to sleep with H_Join
+        * anyone we successfully put to sleep with H_JOIN.
         */
        for_each_possible_cpu(i)
                plpar_hcall_norets(H_PROD, i);
index c607f3b..1d93e73 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/reboot.h>
 #include <linux/delay.h>
 #include <linux/initrd.h>
+#include <linux/platform_device.h>
 #include <linux/ide.h>
 #include <linux/seq_file.h>
 #include <linux/ioport.h>
@@ -462,6 +463,29 @@ static int __init early_xmon(char *p)
 early_param("xmon", early_xmon);
 #endif
 
+static __init int add_pcspkr(void)
+{
+       struct device_node *np;
+       struct platform_device *pd;
+       int ret;
+
+       np = of_find_compatible_node(NULL, NULL, "pnpPNP,100");
+       of_node_put(np);
+       if (!np)
+               return -ENODEV;
+
+       pd = platform_device_alloc("pcspkr", -1);
+       if (!pd)
+               return -ENOMEM;
+
+       ret = platform_device_add(pd);
+       if (ret)
+               platform_device_put(pd);
+
+       return ret;
+}
+device_initcall(add_pcspkr);
+
 void probe_machine(void)
 {
        extern struct machdep_calls __machine_desc_start;
index a72bf5d..69ac257 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/kgdb.h>
 #endif
 
-extern void platform_init(void);
 extern void bootx_init(unsigned long r4, unsigned long phys);
 
 boot_infos_t *boot_infos;
@@ -138,12 +137,7 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys)
                strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
 #endif /* CONFIG_CMDLINE */
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
        probe_machine();
-#else
-       /* Base init based on machine type. Obsoloete, please kill ! */
-       platform_init();
-#endif
 
 #ifdef CONFIG_6xx
        if (cpu_has_feature(CPU_FTR_CAN_DOZE) ||
index 59aa92c..13e91c4 100644 (file)
@@ -215,12 +215,10 @@ void __init early_setup(unsigned long dt_ptr)
        /*
         * Initialize stab / SLB management except on iSeries
         */
-       if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
-               if (cpu_has_feature(CPU_FTR_SLB))
-                       slb_initialize();
-               else
-                       stab_initialize(get_paca()->stab_real);
-       }
+       if (cpu_has_feature(CPU_FTR_SLB))
+               slb_initialize();
+       else if (!firmware_has_feature(FW_FEATURE_ISERIES))
+               stab_initialize(get_paca()->stab_real);
 
        DBG(" <- early_setup()\n");
 }
index 1ad55f0..1424eab 100644 (file)
@@ -322,3 +322,4 @@ SYSCALL(spu_create)
 COMPAT_SYS(pselect6)
 COMPAT_SYS(ppoll)
 SYSCALL(unshare)
+SYSCALL(splice)
index 4cbde21..064a525 100644 (file)
@@ -228,7 +228,7 @@ void system_reset_exception(struct pt_regs *regs)
  */
 static inline int check_io_access(struct pt_regs *regs)
 {
-#ifdef CONFIG_PPC_PMAC
+#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
        unsigned long msr = regs->msr;
        const struct exception_table_entry *entry;
        unsigned int *nip = (unsigned int *)regs->nip;
@@ -261,7 +261,7 @@ static inline int check_io_access(struct pt_regs *regs)
                        return 1;
                }
        }
-#endif /* CONFIG_PPC_PMAC */
+#endif /* CONFIG_PPC_PMAC && CONFIG_PPC32 */
        return 0;
 }
 
@@ -308,8 +308,8 @@ platform_machine_check(struct pt_regs *regs)
 
 void machine_check_exception(struct pt_regs *regs)
 {
-#ifdef CONFIG_PPC64
        int recover = 0;
+       unsigned long reason = get_mc_reason(regs);
 
        /* See if any machine dependent calls */
        if (ppc_md.machine_check_exception)
@@ -317,8 +317,6 @@ void machine_check_exception(struct pt_regs *regs)
 
        if (recover)
                return;
-#else
-       unsigned long reason = get_mc_reason(regs);
 
        if (user_mode(regs)) {
                regs->msr |= MSR_RI;
@@ -462,7 +460,6 @@ void machine_check_exception(struct pt_regs *regs)
         * additional info, e.g. bus error registers.
         */
        platform_machine_check(regs);
-#endif /* CONFIG_PPC64 */
 
        if (debugger_fault_handler(regs))
                return;
index e046427..0c6a37b 100644 (file)
@@ -261,7 +261,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt32)
 .Lcie_start:
        .long 0                 /* CIE ID */
        .byte 1                 /* Version number */
-       .string "zR           /* NUL-terminated augmentation string */
+       .string "zRS"           /* NUL-terminated augmentation string */
        .uleb128 4              /* Code alignment factor */
        .sleb128 -4             /* Data alignment factor */
        .byte 67                /* Return address register column, ap */
index 31b604a..7479edb 100644 (file)
@@ -263,7 +263,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt64)
 .Lcie_start:
        .long 0                 /* CIE ID */
        .byte 1                 /* Version number */
-       .string "zR           /* NUL-terminated augmentation string */
+       .string "zRS"           /* NUL-terminated augmentation string */
        .uleb128 4              /* Code alignment factor */
        .sleb128 -8             /* Data alignment factor */
        .byte 67                /* Return address register column, ap */
index 5aea090..fdbba42 100644 (file)
@@ -177,15 +177,15 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
 
        /* When running in the kernel we expect faults to occur only to
         * addresses in user space.  All other faults represent errors in the
-        * kernel and should generate an OOPS.  Unfortunatly, in the case of an
-        * erroneous fault occuring in a code path which already holds mmap_sem
+        * kernel and should generate an OOPS.  Unfortunately, in the case of an
+        * erroneous fault occurring in a code path which already holds mmap_sem
         * we will deadlock attempting to validate the fault against the
         * address space.  Luckily the kernel only validly references user
         * space from well defined areas of code, which are listed in the
         * exceptions table.
         *
         * As the vast majority of faults will be valid we will only perform
-        * the source reference check when there is a possibilty of a deadlock.
+        * the source reference check when there is a possibility of a deadlock.
         * Attempt to lock the address space, if we cannot we then validate the
         * source.  If this is invalid we can skip the address space check,
         * thus avoiding the deadlock.
index 7c18b4c..7e789d2 100644 (file)
@@ -158,25 +158,25 @@ static int __init mpc834x_rtc_hookup(void)
 late_initcall(mpc834x_rtc_hookup);
 #endif
 
-void __init platform_init(void)
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc834x_sys_probe(void)
 {
-       /* setup the PowerPC module struct */
-       ppc_md.setup_arch = mpc834x_sys_setup_arch;
-
-       ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
-       ppc_md.get_irq = ipic_get_irq;
-
-       ppc_md.restart = mpc83xx_restart;
-
-       ppc_md.time_init = mpc83xx_time_init;
-       ppc_md.set_rtc_time = NULL;
-       ppc_md.get_rtc_time = NULL;
-       ppc_md.calibrate_decr = generic_calibrate_decr;
-
-       ppc_md.progress = udbg_progress;
-
-       if (ppc_md.progress)
-               ppc_md.progress("mpc834x_sys_init(): exit", 0);
-
-       return;
+       /* We always match for now, eventually we should look at the flat
+          dev tree to ensure this is the board we are suppose to run on
+       */
+       return 1;
 }
+
+define_machine(mpc834x_sys) {
+       .name                   = "MPC834x SYS",
+       .probe                  = mpc834x_sys_probe,
+       .setup_arch             = mpc834x_sys_setup_arch,
+       .init_IRQ               = mpc834x_sys_init_IRQ,
+       .get_irq                = ipic_get_irq,
+       .restart                = mpc83xx_restart,
+       .time_init              = mpc83xx_time_init,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
index b7821db..5eeff37 100644 (file)
@@ -220,25 +220,25 @@ void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
        seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
 }
 
-void __init platform_init(void)
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc85xx_ads_probe(void)
 {
-       ppc_md.setup_arch = mpc85xx_ads_setup_arch;
-       ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
-
-       ppc_md.init_IRQ = mpc85xx_ads_pic_init;
-       ppc_md.get_irq = mpic_get_irq;
-
-       ppc_md.restart = mpc85xx_restart;
-       ppc_md.power_off = NULL;
-       ppc_md.halt = NULL;
-
-       ppc_md.time_init = NULL;
-       ppc_md.set_rtc_time = NULL;
-       ppc_md.get_rtc_time = NULL;
-       ppc_md.calibrate_decr = generic_calibrate_decr;
-
-       ppc_md.progress = udbg_progress;
-
-       if (ppc_md.progress)
-               ppc_md.progress("mpc85xx_ads platform_init(): exit", 0);
+       /* We always match for now, eventually we should look at the flat
+          dev tree to ensure this is the board we are suppose to run on
+       */
+       return 1;
 }
+
+define_machine(mpc85xx_ads) {
+       .name                   = "MPC85xx ADS",
+       .probe                  = mpc85xx_ads_probe,
+       .setup_arch             = mpc85xx_ads_setup_arch,
+       .init_IRQ               = mpc85xx_ads_pic_init,
+       .show_cpuinfo           = mpc85xx_ads_show_cpuinfo,
+       .get_irq                = mpic_get_irq,
+       .restart                = mpc85xx_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
index 3a4245c..6594bec 100644 (file)
@@ -316,6 +316,7 @@ void *spu_syscall_table[] = {
        [__NR_pselect6]                 sys_ni_syscall, /* sys_pselect */
        [__NR_ppoll]                    sys_ni_syscall, /* sys_ppoll */
        [__NR_unshare]                  sys_unshare,
+       [__NR_splice]                   sys_splice,
 };
 
 long spu_sys_callback(struct spu_syscall_block *s)
index c04e078..483c8b7 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/ptrace.h>
 
 #include <asm/spu.h>
+#include <asm/unistd.h>
 
 #include "spufs.h"
 
index 9b2b1cb..780fb27 100644 (file)
@@ -865,7 +865,7 @@ void __init eeh_init(void)
  * on the CEC architecture, type of the device, on earlier boot
  * command-line arguments & etc.
  */
-void eeh_add_device_early(struct device_node *dn)
+static void eeh_add_device_early(struct device_node *dn)
 {
        struct pci_controller *phb;
        struct eeh_early_enable_info info;
@@ -882,7 +882,6 @@ void eeh_add_device_early(struct device_node *dn)
        info.buid_lo = BUID_LO(phb->buid);
        early_enable_eeh(dn, &info);
 }
-EXPORT_SYMBOL_GPL(eeh_add_device_early);
 
 void eeh_add_device_tree_early(struct device_node *dn)
 {
@@ -893,20 +892,6 @@ void eeh_add_device_tree_early(struct device_node *dn)
 }
 EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
 
-void eeh_add_device_tree_late(struct pci_bus *bus)
-{
-       struct pci_dev *dev;
-
-       list_for_each_entry(dev, &bus->devices, bus_list) {
-               eeh_add_device_late(dev);
-               if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-                       struct pci_bus *subbus = dev->subordinate;
-                       if (subbus)
-                               eeh_add_device_tree_late(subbus);
-               }
-       }
-}
-
 /**
  * eeh_add_device_late - perform EEH initialization for the indicated pci device
  * @dev: pci device for which to set up EEH
@@ -914,7 +899,7 @@ void eeh_add_device_tree_late(struct pci_bus *bus)
  * This routine must be used to complete EEH initialization for PCI
  * devices that were added after system boot (e.g. hotplug, dlpar).
  */
-void eeh_add_device_late(struct pci_dev *dev)
+static void eeh_add_device_late(struct pci_dev *dev)
 {
        struct device_node *dn;
        struct pci_dn *pdn;
@@ -933,16 +918,33 @@ void eeh_add_device_late(struct pci_dev *dev)
 
        pci_addr_cache_insert_device (dev);
 }
-EXPORT_SYMBOL_GPL(eeh_add_device_late);
+
+void eeh_add_device_tree_late(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               eeh_add_device_late(dev);
+               if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+                       struct pci_bus *subbus = dev->subordinate;
+                       if (subbus)
+                               eeh_add_device_tree_late(subbus);
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
 
 /**
  * eeh_remove_device - undo EEH setup for the indicated pci device
  * @dev: pci device to be removed
  *
- * This routine should be when a device is removed from a running
- * system (e.g. by hotplug or dlpar).
+ * This routine should be called when a device is removed from
+ * a running system (e.g. by hotplug or dlpar).  It unregisters
+ * the PCI device from the EEH subsystem.  I/O errors affecting
+ * this device will no longer be detected after this call; thus,
+ * i/o errors affecting this slot may leave this device unusable.
  */
-void eeh_remove_device(struct pci_dev *dev)
+static void eeh_remove_device(struct pci_dev *dev)
 {
        struct device_node *dn;
        if (!dev || !eeh_subsystem_enabled)
@@ -958,21 +960,17 @@ void eeh_remove_device(struct pci_dev *dev)
        PCI_DN(dn)->pcidev = NULL;
        pci_dev_put (dev);
 }
-EXPORT_SYMBOL_GPL(eeh_remove_device);
 
 void eeh_remove_bus_device(struct pci_dev *dev)
 {
+       struct pci_bus *bus = dev->subordinate;
+       struct pci_dev *child, *tmp;
+
        eeh_remove_device(dev);
-       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-               struct pci_bus *bus = dev->subordinate;
-               struct list_head *ln;
-               if (!bus)
-                       return; 
-               for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
-                       struct pci_dev *pdev = pci_dev_b(ln);
-                       if (pdev)
-                               eeh_remove_bus_device(pdev);
-               }
+
+       if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+               list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+                        eeh_remove_bus_device(child);
        }
 }
 EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
index cc2495a..1fba695 100644 (file)
@@ -293,15 +293,16 @@ void handle_eeh_events (struct eeh_event *event)
        frozen_pdn = PCI_DN(frozen_dn);
        frozen_pdn->eeh_freeze_count++;
 
-       pci_str = pci_name (frozen_pdn->pcidev);
-       drv_str = pcid_name (frozen_pdn->pcidev);
-       if (!pci_str) {
+       if (frozen_pdn->pcidev) {
+               pci_str = pci_name (frozen_pdn->pcidev);
+               drv_str = pcid_name (frozen_pdn->pcidev);
+       } else {
                pci_str = pci_name (event->dev);
                drv_str = pcid_name (event->dev);
        }
        
        if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
-               goto hard_fail;
+               goto excess_failures;
 
        /* If the reset state is a '5' and the time to reset is 0 (infinity)
         * or is more then 15 seconds, then mark this as a permanent failure.
@@ -356,7 +357,7 @@ void handle_eeh_events (struct eeh_event *event)
 
        return;
        
-hard_fail:
+excess_failures:
        /*
         * About 90% of all real-life EEH failures in the field
         * are due to poorly seated PCI cards. Only 10% or so are
@@ -367,7 +368,15 @@ hard_fail:
           "and has been permanently disabled.  Please try reseating\n"
           "this device or replacing it.\n",
                drv_str, pci_str, frozen_pdn->eeh_freeze_count);
+       goto perm_error;
+
+hard_fail:
+       printk(KERN_ERR
+          "EEH: Unable to recover from failure of PCI device %s - %s\n"
+          "Please try reseating this device or replacing it.\n",
+               drv_str, pci_str);
 
+perm_error:
        eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
 
        /* Notify all devices that they're about to go down. */
index 9a9961f..a1bda6f 100644 (file)
@@ -19,7 +19,9 @@
  */
 
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/pci.h>
+#include <linux/workqueue.h>
 #include <asm/eeh_event.h>
 #include <asm/ppc-pci.h>
 
@@ -37,14 +39,18 @@ LIST_HEAD(eeh_eventlist);
 static void eeh_thread_launcher(void *);
 DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
 
+/* Serialize reset sequences for a given pci device */
+DEFINE_MUTEX(eeh_event_mutex);
+
 /**
- * eeh_event_handler - dispatch EEH events.  The detection of a frozen
- * slot can occur inside an interrupt, where it can be hard to do
- * anything about it.  The goal of this routine is to pull these
- * detection events out of the context of the interrupt handler, and
- * re-dispatch them for processing at a later time in a normal context.
- *
+ * eeh_event_handler - dispatch EEH events.
  * @dummy - unused
+ *
+ * The detection of a frozen slot can occur inside an interrupt,
+ * where it can be hard to do anything about it.  The goal of this
+ * routine is to pull these detection events out of the context
+ * of the interrupt handler, and re-dispatch them for processing
+ * at a later time in a normal context.
  */
 static int eeh_event_handler(void * dummy)
 {
@@ -64,23 +70,24 @@ static int eeh_event_handler(void * dummy)
                        event = list_entry(eeh_eventlist.next, struct eeh_event, list);
                        list_del(&event->list);
                }
-               
-               if (event)
-                       eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
-
                spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+
                if (event == NULL)
                        break;
 
+               /* Serialize processing of EEH events */
+               mutex_lock(&eeh_event_mutex);
+               eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
+
                printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
                       pci_name(event->dev));
 
                handle_eeh_events(event);
 
                eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
-
                pci_dev_put(event->dev);
                kfree(event);
+               mutex_unlock(&eeh_event_mutex);
        }
 
        return 0;
@@ -88,7 +95,6 @@ static int eeh_event_handler(void * dummy)
 
 /**
  * eeh_thread_launcher
- *
  * @dummy - unused
  */
 static void eeh_thread_launcher(void *dummy)
index db7c19f..c9ff547 100644 (file)
@@ -127,3 +127,103 @@ _GLOBAL(plpar_hcall_4out)
 
        mtcrf   0xff,r0
        blr                             /* return r3 = status */
+
+/* plpar_hcall_7arg_7ret(unsigned long opcode,         R3
+                        unsigned long arg1,            R4
+                        unsigned long arg2,            R5
+                        unsigned long arg3,            R6
+                        unsigned long arg4,            R7
+                        unsigned long arg5,            R8
+                        unsigned long arg6,            R9
+                        unsigned long arg7,            R10
+                        unsigned long *out1,           112(R1)
+                        unsigned long *out2,           110(R1)
+                        unsigned long *out3,           108(R1)
+                        unsigned long *out4,           106(R1)
+                        unsigned long *out5,           104(R1)
+                        unsigned long *out6,           102(R1)
+                        unsigned long *out7);          100(R1)
+*/
+_GLOBAL(plpar_hcall_7arg_7ret)
+       HMT_MEDIUM
+
+       mfcr    r0
+       stw     r0,8(r1)
+
+       HVSC                            /* invoke the hypervisor */
+
+       lwz     r0,8(r1)
+
+       ld      r11,STK_PARM(r11)(r1)   /* Fetch r4 ret arg */
+       std     r4,0(r11)
+       ld      r11,STK_PARM(r12)(r1)   /* Fetch r5 ret arg */
+       std     r5,0(r11)
+       ld      r11,STK_PARM(r13)(r1)   /* Fetch r6 ret arg */
+       std     r6,0(r11)
+       ld      r11,STK_PARM(r14)(r1)   /* Fetch r7 ret arg */
+       std     r7,0(r11)
+       ld      r11,STK_PARM(r15)(r1)   /* Fetch r8 ret arg */
+       std     r8,0(r11)
+       ld      r11,STK_PARM(r16)(r1)   /* Fetch r9 ret arg */
+       std     r9,0(r11)
+       ld      r11,STK_PARM(r17)(r1)   /* Fetch r10 ret arg */
+       std     r10,0(r11)
+
+       mtcrf   0xff,r0
+
+       blr                             /* return r3 = status */
+
+/* plpar_hcall_9arg_9ret(unsigned long opcode,         R3
+                        unsigned long arg1,            R4
+                        unsigned long arg2,            R5
+                        unsigned long arg3,            R6
+                        unsigned long arg4,            R7
+                        unsigned long arg5,            R8
+                        unsigned long arg6,            R9
+                        unsigned long arg7,            R10
+                        unsigned long arg8,            112(R1)
+                        unsigned long arg9,            110(R1)
+                        unsigned long *out1,           108(R1)
+                        unsigned long *out2,           106(R1)
+                        unsigned long *out3,           104(R1)
+                        unsigned long *out4,           102(R1)
+                        unsigned long *out5,           100(R1)
+                        unsigned long *out6,            98(R1)
+                        unsigned long *out7);           96(R1)
+                        unsigned long *out8,            94(R1)
+                        unsigned long *out9,            92(R1)
+*/
+_GLOBAL(plpar_hcall_9arg_9ret)
+       HMT_MEDIUM
+
+       mfcr    r0
+       stw     r0,8(r1)
+
+       ld      r11,STK_PARM(r11)(r1)    /* put arg8 in R11 */
+       ld      r12,STK_PARM(r12)(r1)    /* put arg9 in R12 */
+
+       HVSC                            /* invoke the hypervisor */
+
+       ld      r0,STK_PARM(r13)(r1)    /* Fetch r4 ret arg */
+       stdx    r4,r0,r0
+       ld      r0,STK_PARM(r14)(r1)    /* Fetch r5 ret arg */
+       stdx    r5,r0,r0
+       ld      r0,STK_PARM(r15)(r1)    /* Fetch r6 ret arg */
+       stdx    r6,r0,r0
+       ld      r0,STK_PARM(r16)(r1)    /* Fetch r7 ret arg */
+       stdx    r7,r0,r0
+       ld      r0,STK_PARM(r17)(r1)    /* Fetch r8 ret arg */
+       stdx    r8,r0,r0
+       ld      r0,STK_PARM(r18)(r1)    /* Fetch r9 ret arg */
+       stdx    r9,r0,r0
+       ld      r0,STK_PARM(r19)(r1)    /* Fetch r10 ret arg */
+       stdx    r10,r0,r0
+       ld      r0,STK_PARM(r20)(r1)    /* Fetch r11 ret arg */
+       stdx    r11,r0,r0
+       ld      r0,STK_PARM(r21)(r1)    /* Fetch r12 ret arg */
+       stdx    r12,r0,r0
+
+       lwz     r0,8(r1)
+       mtcrf   0xff,r0
+
+       blr                             /* return r3 = status */
index ba6befd..a72a987 100644 (file)
@@ -41,7 +41,7 @@ int hvc_get_chars(uint32_t vtermno, char *buf, int count)
        unsigned long got;
 
        if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
-               (unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
+               (unsigned long *)buf, (unsigned long *)buf+1) == H_SUCCESS)
                return got;
        return 0;
 }
@@ -69,9 +69,9 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
 
        ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0],
                                 lbuf[1]);
-       if (ret == H_Success)
+       if (ret == H_SUCCESS)
                return count;
-       if (ret == H_Busy)
+       if (ret == H_BUSY)
                return 0;
        return -EIO;
 }
index 22bfb5c..fcf4b4c 100644 (file)
@@ -43,21 +43,21 @@ MODULE_VERSION(HVCS_ARCH_VERSION);
 static int hvcs_convert(long to_convert)
 {
        switch (to_convert) {
-               case H_Success:
+               case H_SUCCESS:
                        return 0;
-               case H_Parameter:
+               case H_PARAMETER:
                        return -EINVAL;
-               case H_Hardware:
+               case H_HARDWARE:
                        return -EIO;
-               case H_Busy:
-               case H_LongBusyOrder1msec:
-               case H_LongBusyOrder10msec:
-               case H_LongBusyOrder100msec:
-               case H_LongBusyOrder1sec:
-               case H_LongBusyOrder10sec:
-               case H_LongBusyOrder100sec:
+               case H_BUSY:
+               case H_LONG_BUSY_ORDER_1_MSEC:
+               case H_LONG_BUSY_ORDER_10_MSEC:
+               case H_LONG_BUSY_ORDER_100_MSEC:
+               case H_LONG_BUSY_ORDER_1_SEC:
+               case H_LONG_BUSY_ORDER_10_SEC:
+               case H_LONG_BUSY_ORDER_100_SEC:
                        return -EBUSY;
-               case H_Function: /* fall through */
+               case H_FUNCTION: /* fall through */
                default:
                        return -EPERM;
        }
index 8952528..634b7d0 100644 (file)
@@ -54,7 +54,8 @@ EXPORT_SYMBOL(plpar_hcall);
 EXPORT_SYMBOL(plpar_hcall_4out);
 EXPORT_SYMBOL(plpar_hcall_norets);
 EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
-
+EXPORT_SYMBOL(plpar_hcall_7arg_7ret);
+EXPORT_SYMBOL(plpar_hcall_9arg_9ret);
 extern void pSeries_find_serial_port(void);
 
 
@@ -72,7 +73,7 @@ static void udbg_hvsi_putc(char c)
 
        do {
                rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
-       } while (rc == H_Busy);
+       } while (rc == H_BUSY);
 }
 
 static long hvsi_udbg_buf_len;
@@ -85,7 +86,7 @@ static int udbg_hvsi_getc_poll(void)
 
        if (hvsi_udbg_buf_len == 0) {
                rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
-               if (rc != H_Success || hvsi_udbg_buf[0] != 0xff) {
+               if (rc != H_SUCCESS || hvsi_udbg_buf[0] != 0xff) {
                        /* bad read or non-data packet */
                        hvsi_udbg_buf_len = 0;
                } else {
@@ -139,7 +140,7 @@ static void udbg_putcLP(char c)
        buf[0] = c;
        do {
                rc = plpar_put_term_char(vtermno, 1, buf);
-       } while(rc == H_Busy);
+       } while(rc == H_BUSY);
 }
 
 /* Buffered chars getc */
@@ -158,7 +159,7 @@ static int udbg_getc_pollLP(void)
                /* get some more chars. */
                inbuflen = 0;
                rc = plpar_get_term_char(vtermno, &inbuflen, buf);
-               if (rc != H_Success)
+               if (rc != H_SUCCESS)
                        inbuflen = 0;   /* otherwise inbuflen is garbage */
        }
        if (inbuflen <= 0 || inbuflen > 16) {
@@ -304,7 +305,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 
        lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v,
                              hpte_r, &slot, &dummy0, &dummy1);
-       if (unlikely(lpar_rc == H_PTEG_Full)) {
+       if (unlikely(lpar_rc == H_PTEG_FULL)) {
                if (!(vflags & HPTE_V_BOLTED))
                        DBG_LOW(" full\n");
                return -1;
@@ -315,7 +316,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
         * will fail. However we must catch the failure in hash_page
         * or we will loop forever, so return -2 in this case.
         */
-       if (unlikely(lpar_rc != H_Success)) {
+       if (unlikely(lpar_rc != H_SUCCESS)) {
                if (!(vflags & HPTE_V_BOLTED))
                        DBG_LOW(" lpar err %d\n", lpar_rc);
                return -2;
@@ -346,9 +347,9 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
                /* don't remove a bolted entry */
                lpar_rc = plpar_pte_remove(H_ANDCOND, hpte_group + slot_offset,
                                           (0x1UL << 4), &dummy1, &dummy2);
-               if (lpar_rc == H_Success)
+               if (lpar_rc == H_SUCCESS)
                        return i;
-               BUG_ON(lpar_rc != H_Not_Found);
+               BUG_ON(lpar_rc != H_NOT_FOUND);
 
                slot_offset++;
                slot_offset &= 0x7;
@@ -391,14 +392,14 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
 
        lpar_rc = plpar_pte_protect(flags, slot, want_v & HPTE_V_AVPN);
 
-       if (lpar_rc == H_Not_Found) {
+       if (lpar_rc == H_NOT_FOUND) {
                DBG_LOW("not found !\n");
                return -1;
        }
 
        DBG_LOW("ok\n");
 
-       BUG_ON(lpar_rc != H_Success);
+       BUG_ON(lpar_rc != H_SUCCESS);
 
        return 0;
 }
@@ -417,7 +418,7 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
 
        lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
 
-       BUG_ON(lpar_rc != H_Success);
+       BUG_ON(lpar_rc != H_SUCCESS);
 
        return dword0;
 }
@@ -468,7 +469,7 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
        flags = newpp & 7;
        lpar_rc = plpar_pte_protect(flags, slot, 0);
 
-       BUG_ON(lpar_rc != H_Success);
+       BUG_ON(lpar_rc != H_SUCCESS);
 }
 
 static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
@@ -484,10 +485,10 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
        want_v = hpte_encode_v(va, psize);
        lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v & HPTE_V_AVPN,
                                   &dummy1, &dummy2);
-       if (lpar_rc == H_Not_Found)
+       if (lpar_rc == H_NOT_FOUND)
                return;
 
-       BUG_ON(lpar_rc != H_Success);
+       BUG_ON(lpar_rc != H_SUCCESS);
 }
 
 /*
index b2fbf8b..5eb55ef 100644 (file)
@@ -463,7 +463,7 @@ static void pseries_dedicated_idle_sleep(void)
         * very low priority.  The cede enables interrupts, which
         * doesn't matter here.
         */
-       if (!lppaca[cpu ^ 1].idle || poll_pending() == H_Pending)
+       if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING)
                cede_processor();
 
 out:
index 866379b..8e53e04 100644 (file)
@@ -258,7 +258,7 @@ EXPORT_SYMBOL(vio_find_node);
 int vio_enable_interrupts(struct vio_dev *dev)
 {
        int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
-       if (rc != H_Success)
+       if (rc != H_SUCCESS)
                printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
        return rc;
 }
@@ -267,7 +267,7 @@ EXPORT_SYMBOL(vio_enable_interrupts);
 int vio_disable_interrupts(struct vio_dev *dev)
 {
        int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
-       if (rc != H_Success)
+       if (rc != H_SUCCESS)
                printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
        return rc;
 }
index 4864cb3..2d60ea3 100644 (file)
@@ -168,7 +168,7 @@ static int pSeriesLP_xirr_info_get(int n_cpu)
        unsigned long return_value;
 
        lpar_rc = plpar_xirr(&return_value);
-       if (lpar_rc != H_Success)
+       if (lpar_rc != H_SUCCESS)
                panic(" bad return code xirr - rc = %lx \n", lpar_rc);
        return (int)return_value;
 }
@@ -179,7 +179,7 @@ static void pSeriesLP_xirr_info_set(int n_cpu, int value)
        unsigned long val64 = value & 0xffffffff;
 
        lpar_rc = plpar_eoi(val64);
-       if (lpar_rc != H_Success)
+       if (lpar_rc != H_SUCCESS)
                panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc,
                      val64);
 }
@@ -189,7 +189,7 @@ void pSeriesLP_cppr_info(int n_cpu, u8 value)
        unsigned long lpar_rc;
 
        lpar_rc = plpar_cppr(value);
-       if (lpar_rc != H_Success)
+       if (lpar_rc != H_SUCCESS)
                panic("bad return code cppr - rc = %lx\n", lpar_rc);
 }
 
@@ -198,7 +198,7 @@ static void pSeriesLP_qirr_info(int n_cpu , u8 value)
        unsigned long lpar_rc;
 
        lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu), value);
-       if (lpar_rc != H_Success)
+       if (lpar_rc != H_SUCCESS)
                panic("bad return code qirr - rc = %lx\n", lpar_rc);
 }
 
index 2b8841f..343120c 100644 (file)
@@ -801,7 +801,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
          */
        print_cpu_info(&S390_lowcore.cpu_data);
 
-        for_each_cpu(i) {
+        for_each_possible_cpu(i) {
                lowcore_ptr[i] = (struct _lowcore *)
                        __get_free_pages(GFP_KERNEL|GFP_DMA, 
                                        sizeof(void*) == 8 ? 1 : 0);
@@ -831,7 +831,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 #endif
        set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]);
 
-       for_each_cpu(cpu)
+       for_each_possible_cpu(cpu)
                if (cpu != smp_processor_id())
                        smp_create_idle(cpu);
 }
@@ -868,7 +868,7 @@ static int __init topology_init(void)
        int cpu;
        int ret;
 
-       for_each_cpu(cpu) {
+       for_each_possible_cpu(cpu) {
                ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL);
                if (ret)
                        printk(KERN_WARNING "topology_init: register_cpu %d "
index cf94e8e..868e68b 100644 (file)
@@ -30,7 +30,7 @@ static int x##_disabled __initdata = 0;               \
 static int __init x##_setup(char *opts)                \
 {                                              \
        x##_disabled = 1;                       \
-       return 0;                               \
+       return 1;                               \
 }                                              \
 __setup("no" __stringify(x), x##_setup);
 
index 7ee4ca2..bb229ef 100644 (file)
@@ -401,7 +401,7 @@ static int __init topology_init(void)
 {
        int cpu_id;
 
-       for_each_cpu(cpu_id)
+       for_each_possible_cpu(cpu_id)
                register_cpu(&cpu[cpu_id], cpu_id, NULL);
 
        return 0;
index 768de64..fbbec5e 100644 (file)
@@ -64,13 +64,13 @@ sys_call_table:
 /*215*/        .long sys_ipc, sys_sigreturn, sys_clone, sys_ioprio_get, sys_adjtimex
 /*220*/        .long sys_sigprocmask, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
 /*225*/        .long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16
-/*230*/        .long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_statfs64
+/*230*/        .long sys_select, sys_time, sys_splice, sys_stime, sys_statfs64
                                          /* "We are the Knights of the Forest of Ni!!" */
 /*235*/        .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/        .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
 /*245*/        .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
 /*250*/        .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
-/*255*/        .long sys_nis_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+/*255*/        .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
 /*260*/        .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
 /*265*/        .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
 /*270*/        .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
index 900fb0b..3038908 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.16
-# Sun Mar 26 14:58:11 2006
+# Fri Mar 31 01:40:57 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -180,6 +180,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -203,6 +204,7 @@ CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 # CONFIG_NETFILTER is not set
@@ -308,7 +310,6 @@ CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_UB=m
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
 # CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -449,6 +450,7 @@ CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 # CONFIG_MD_FAULTY is not set
@@ -741,9 +743,7 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -826,6 +826,7 @@ CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+# CONFIG_FB_FIRMWARE_EDID is not set
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -1116,6 +1117,11 @@ CONFIG_USB_HIDDEV=y
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
 #
 # Misc Linux/SPARC drivers
 #
index 7dc28a4..8175a69 100644 (file)
@@ -830,9 +830,16 @@ void smp_call_function_client(int irq, struct pt_regs *regs)
 
 static void tsb_sync(void *info)
 {
+       struct trap_per_cpu *tp = &trap_block[raw_smp_processor_id()];
        struct mm_struct *mm = info;
 
-       if (current->active_mm == mm)
+       /* It is not valid to test "currrent->active_mm == mm" here.
+        *
+        * The value of "current" is not changed atomically with
+        * switch_mm().  But that's OK, we just need to check the
+        * current cpu's trap block PGD physical address.
+        */
+       if (tp->pgd_paddr == __pa(mm->pgd))
                tsb_context_switch(mm);
 }
 
index c4a1cef..86dd5cb 100644 (file)
@@ -136,6 +136,8 @@ SIGN1(sys32_getpeername, sys_getpeername, %o0)
 SIGN1(sys32_getsockname, sys_getsockname, %o0)
 SIGN2(sys32_ioprio_get, sys_ioprio_get, %o0, %o1)
 SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
+SIGN2(sys32_splice, sys_splice, %o0, %o1)
+SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
 
        .globl          sys32_mmap2
 sys32_mmap2:
index 2e906ba..31030bf 100644 (file)
@@ -1069,3 +1069,11 @@ long sys32_lookup_dcookie(unsigned long cookie_high,
        return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
                                  buf, len);
 }
+
+long compat_sync_file_range(int fd, unsigned long off_high, unsigned long off_low, unsigned long nb_high, unsigned long nb_low, int flags)
+{
+       return sys_sync_file_range(fd,
+                                  (off_high << 32) | off_low,
+                                  (nb_high << 32) | nb_low,
+                                  flags);
+}
index 3b250f2..857b82c 100644 (file)
@@ -66,12 +66,12 @@ sys_call_table32:
        .word sys32_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, compat_sys_adjtimex
 /*220*/        .word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid
        .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
-/*230*/        .word sys32_select, compat_sys_time, sys_nis_syscall, compat_sys_stime, compat_sys_statfs64
+/*230*/        .word sys32_select, compat_sys_time, sys32_splice, compat_sys_stime, compat_sys_statfs64
        .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
 /*240*/        .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
        .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
 /*250*/        .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
-       .word sys_ni_syscall, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
+       .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
 /*260*/        .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
        .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 /*270*/        .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
@@ -135,12 +135,12 @@ sys_call_table:
        .word sys_ipc, sys_nis_syscall, sys_clone, sys_ioprio_get, sys_adjtimex
 /*220*/        .word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
        .word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
-/*230*/        .word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_statfs64
+/*230*/        .word sys_select, sys_nis_syscall, sys_splice, sys_stime, sys_statfs64
        .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/        .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
        .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
 /*250*/        .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
-       .word sys_ni_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+       .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
 /*260*/        .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
        .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
 /*270*/        .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
index 0db2f7d..6e002aa 100644 (file)
@@ -327,8 +327,12 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
                insn = get_fault_insn(regs, 0);
                if (!insn)
                        goto continue_fault;
+               /* All loads, stores and atomics have bits 30 and 31 both set
+                * in the instruction.  Bit 21 is set in all stores, but we
+                * have to avoid prefetches which also have bit 21 set.
+                */
                if ((insn & 0xc0200000) == 0xc0200000 &&
-                   (insn & 0x1780000) != 0x1680000) {
+                   (insn & 0x01780000) != 0x01680000) {
                        /* Don't bother updating thread struct value,
                         * because update_mmu_cache only cares which tlb
                         * the access came from.
index 074620d..fbbbebb 100644 (file)
@@ -198,6 +198,13 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
        pmd_t *pmd;
        pte_t *pte = NULL;
 
+       /* We must align the address, because our caller will run
+        * set_huge_pte_at() on whatever we return, which writes out
+        * all of the sub-ptes for the hugepage range.  So we have
+        * to give it the first such sub-pte.
+        */
+       addr &= HPAGE_MASK;
+
        pgd = pgd_offset(mm, addr);
        pud = pud_alloc(mm, pgd, addr);
        if (pud) {
index 5982fe2..05fbb20 100644 (file)
@@ -22,6 +22,9 @@ config SBUS
 config PCI
        bool
 
+config PCMCIA
+       bool
+
 config GENERIC_CALIBRATE_DELAY
        bool
        default y
index 8d14c7a..24790be 100644 (file)
@@ -20,7 +20,7 @@ core-y                        += $(ARCH_DIR)/kernel/          \
 
 # Have to precede the include because the included Makefiles reference them.
 SYMLINK_HEADERS := archparam.h system.h sigcontext.h processor.h ptrace.h \
-       module.h vm-flags.h elf.h ldt.h
+       module.h vm-flags.h elf.h host_ldt.h
 SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
 
 # XXX: The "os" symlink is only used by arch/um/include/os.h, which includes
@@ -129,7 +129,7 @@ CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \
        -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
        -DELF_FORMAT="$(ELF_FORMAT)" $(CPP_MODE-y) \
        -DKERNEL_STACK_SIZE=$(STACK_SIZE) \
-       -DUNMAP_PATH=arch/um/sys-$(SUBARCH)/unmap_fin.o
+       -DUNMAP_PATH=arch/um/sys-$(SUBARCH)/unmap.o
 
 #The wrappers will select whether using "malloc" or the kernel allocator.
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
@@ -150,8 +150,7 @@ CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \
        $(ARCH_DIR)/include/user_constants.h \
        $(ARCH_DIR)/include/kern_constants.h $(ARCH_DIR)/Kconfig.arch
 
-MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
-       $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os
+MRPROPER_FILES += $(ARCH_SYMLINKS)
 
 archclean:
        @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
index 38df311..dfd88b6 100644 (file)
@@ -1,7 +1,7 @@
 # Copyright 2003 - 2004 Pathscale, Inc
 # Released under the GPL
 
-libs-y += arch/um/sys-x86_64/
+core-y += arch/um/sys-x86_64/
 START := 0x60000000
 
 #We #undef __x86_64__ for kernelspace, not for userspace where
index a61b7b4..53d09ed 100644 (file)
@@ -95,18 +95,7 @@ static struct transport daemon_transport = {
 static int register_daemon(void)
 {
        register_transport(&daemon_transport);
-       return(1);
+       return 0;
 }
 
 __initcall(register_daemon);
-
-/*
- * 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-file-style: "linux"
- * End:
- */
index 49acb2b..d18a974 100644 (file)
@@ -104,7 +104,7 @@ static int harddog_release(struct inode *inode, struct file *file)
 
 extern int ping_watchdog(int fd);
 
-static ssize_t harddog_write(struct file *file, const char *data, size_t len,
+static ssize_t harddog_write(struct file *file, const char __user *data, size_t len,
                             loff_t *ppos)
 {
        /*
@@ -118,6 +118,7 @@ static ssize_t harddog_write(struct file *file, const char *data, size_t len,
 static int harddog_ioctl(struct inode *inode, struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
+       void __user *argp= (void __user *)arg;
        static struct watchdog_info ident = {
                WDIOC_SETTIMEOUT,
                0,
@@ -127,13 +128,12 @@ static int harddog_ioctl(struct inode *inode, struct file *file,
                default:
                        return -ENOTTY;
                case WDIOC_GETSUPPORT:
-                       if(copy_to_user((struct harddog_info *)arg, &ident,
-                                       sizeof(ident)))
+                       if(copy_to_user(argp, &ident, sizeof(ident)))
                                return -EFAULT;
                        return 0;
                case WDIOC_GETSTATUS:
                case WDIOC_GETBOOTSTATUS:
-                       return put_user(0,(int *)arg);
+                       return put_user(0,(int __user *)argp);
                case WDIOC_KEEPALIVE:
                        return(ping_watchdog(harddog_out_fd));
        }
index 59602b8..37232f9 100644 (file)
@@ -67,8 +67,8 @@ MODULE_PARM_DESC(mixer, MIXER_HELP);
 
 /* /dev/dsp file operations */
 
-static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count, 
-                             loff_t *ppos)
+static ssize_t hostaudio_read(struct file *file, char __user *buffer,
+                             size_t count, loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
        void *kbuf;
@@ -94,7 +94,7 @@ static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count,
        return(err);
 }
 
-static ssize_t hostaudio_write(struct file *file, const char *buffer, 
+static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
                               size_t count, loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
@@ -152,7 +152,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
        case SNDCTL_DSP_CHANNELS:
        case SNDCTL_DSP_SUBDIVIDE:
        case SNDCTL_DSP_SETFRAGMENT:
-               if(get_user(data, (int *) arg))
+               if(get_user(data, (int __user *) arg))
                        return(-EFAULT);
                break;
        default:
@@ -168,7 +168,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
        case SNDCTL_DSP_CHANNELS:
        case SNDCTL_DSP_SUBDIVIDE:
        case SNDCTL_DSP_SETFRAGMENT:
-               if(put_user(data, (int *) arg))
+               if(put_user(data, (int __user *) arg))
                        return(-EFAULT);
                break;
        default:
index c9b078f..3a7af18 100644 (file)
@@ -124,18 +124,7 @@ static struct transport mcast_transport = {
 static int register_mcast(void)
 {
        register_transport(&mcast_transport);
-       return(1);
+       return 0;
 }
 
 __initcall(register_mcast);
-
-/*
- * 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-file-style: "linux"
- * End:
- */
index 1488816..28e3760 100644 (file)
@@ -20,6 +20,8 @@
 #include "linux/namei.h"
 #include "linux/proc_fs.h"
 #include "linux/syscalls.h"
+#include "linux/list.h"
+#include "linux/mm.h"
 #include "linux/console.h"
 #include "asm/irq.h"
 #include "asm/uaccess.h"
@@ -347,6 +349,142 @@ static struct mc_device *mconsole_find_dev(char *name)
        return(NULL);
 }
 
+#define UNPLUGGED_PER_PAGE \
+       ((PAGE_SIZE - sizeof(struct list_head)) / sizeof(unsigned long))
+
+struct unplugged_pages {
+       struct list_head list;
+       void *pages[UNPLUGGED_PER_PAGE];
+};
+
+static unsigned long long unplugged_pages_count = 0;
+static struct list_head unplugged_pages = LIST_HEAD_INIT(unplugged_pages);
+static int unplug_index = UNPLUGGED_PER_PAGE;
+
+static int mem_config(char *str)
+{
+       unsigned long long diff;
+       int err = -EINVAL, i, add;
+       char *ret;
+
+       if(str[0] != '=')
+               goto out;
+
+       str++;
+       if(str[0] == '-')
+               add = 0;
+       else if(str[0] == '+'){
+               add = 1;
+       }
+       else goto out;
+
+       str++;
+       diff = memparse(str, &ret);
+       if(*ret != '\0')
+               goto out;
+
+       diff /= PAGE_SIZE;
+
+       for(i = 0; i < diff; i++){
+               struct unplugged_pages *unplugged;
+               void *addr;
+
+               if(add){
+                       if(list_empty(&unplugged_pages))
+                               break;
+
+                       unplugged = list_entry(unplugged_pages.next,
+                                              struct unplugged_pages, list);
+                       if(unplug_index > 0)
+                               addr = unplugged->pages[--unplug_index];
+                       else {
+                               list_del(&unplugged->list);
+                               addr = unplugged;
+                               unplug_index = UNPLUGGED_PER_PAGE;
+                       }
+
+                       free_page((unsigned long) addr);
+                       unplugged_pages_count--;
+               }
+               else {
+                       struct page *page;
+
+                       page = alloc_page(GFP_ATOMIC);
+                       if(page == NULL)
+                               break;
+
+                       unplugged = page_address(page);
+                       if(unplug_index == UNPLUGGED_PER_PAGE){
+                               INIT_LIST_HEAD(&unplugged->list);
+                               list_add(&unplugged->list, &unplugged_pages);
+                               unplug_index = 0;
+                       }
+                       else {
+                               struct list_head *entry = unplugged_pages.next;
+                               addr = unplugged;
+
+                               unplugged = list_entry(entry,
+                                                      struct unplugged_pages,
+                                                      list);
+                               unplugged->pages[unplug_index++] = addr;
+                               err = os_drop_memory(addr, PAGE_SIZE);
+                               if(err)
+                                       printk("Failed to release memory - "
+                                              "errno = %d\n", err);
+                       }
+
+                       unplugged_pages_count++;
+               }
+       }
+
+       err = 0;
+out:
+       return err;
+}
+
+static int mem_get_config(char *name, char *str, int size, char **error_out)
+{
+       char buf[sizeof("18446744073709551615")];
+       int len = 0;
+
+       sprintf(buf, "%ld", uml_physmem);
+       CONFIG_CHUNK(str, size, len, buf, 1);
+
+       return len;
+}
+
+static int mem_id(char **str, int *start_out, int *end_out)
+{
+       *start_out = 0;
+       *end_out = 0;
+
+       return 0;
+}
+
+static int mem_remove(int n)
+{
+       return -EBUSY;
+}
+
+static struct mc_device mem_mc = {
+       .name           = "mem",
+       .config         = mem_config,
+       .get_config     = mem_get_config,
+       .id             = mem_id,
+       .remove         = mem_remove,
+};
+
+static int mem_mc_init(void)
+{
+       if(can_drop_memory())
+               mconsole_register_dev(&mem_mc);
+       else printk("Can't release memory to the host - memory hotplug won't "
+                   "be supported\n");
+       return 0;
+}
+
+__initcall(mem_mc_init);
+
 #define CONFIG_BUF_SIZE 64
 
 static void mconsole_get_config(int (*get_config)(char *, char *, int,
@@ -478,7 +616,7 @@ static void console_write(struct console *console, const char *string,
                return;
 
        while(1){
-               n = min(len, ARRAY_SIZE(console_buf) - console_index);
+               n = min((size_t)len, ARRAY_SIZE(console_buf) - console_index);
                strncpy(&console_buf[console_index], string, n);
                console_index += n;
                string += n;
index 07c80f2..466ff2c 100644 (file)
@@ -106,18 +106,7 @@ static struct transport pcap_transport = {
 static int register_pcap(void)
 {
        register_transport(&pcap_transport);
-       return(1);
+       return 0;
 }
 
 __initcall(register_pcap);
-
-/*
- * 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-file-style: "linux"
- * End:
- */
index a62f5ef..163ee0d 100644 (file)
@@ -93,18 +93,7 @@ static struct transport slip_transport = {
 static int register_slip(void)
 {
        register_transport(&slip_transport);
-       return(1);
+       return 0;
 }
 
 __initcall(register_slip);
-
-/*
- * 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-file-style: "linux"
- * End:
- */
index 33d7982..95e50c9 100644 (file)
@@ -77,7 +77,7 @@ static int slirp_setup(char *str, char **mac_out, void *data)
        int i=0;
 
        *init = ((struct slirp_init)
-               { argw :                { { "slirp", NULL  } } });
+               { .argw = { { "slirp", NULL  } } });
 
        str = split_if_spec(str, mac_out, NULL);
 
@@ -116,18 +116,7 @@ static struct transport slirp_transport = {
 static int register_slirp(void)
 {
        register_transport(&slirp_transport);
-       return(1);
+       return 0;
 }
 
 __initcall(register_slirp);
-
-/*
- * 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-file-style: "linux"
- * End:
- */
index 0336575..0897852 100644 (file)
@@ -891,7 +891,7 @@ int ubd_driver_init(void){
                             SA_INTERRUPT, "ubd", ubd_dev);
        if(err != 0)
                printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
-       return(err);
+       return 0;
 }
 
 device_initcall(ubd_driver_init);
index 07176d9..4255713 100644 (file)
@@ -116,7 +116,11 @@ extern void *get_current(void);
 extern struct task_struct *get_task(int pid, int require);
 extern void machine_halt(void);
 extern int is_syscall(unsigned long addr);
-extern void arch_switch(void);
+
+extern void arch_switch_to_tt(struct task_struct *from, struct task_struct *to);
+
+extern void arch_switch_to_skas(struct task_struct *from, struct task_struct *to);
+
 extern void free_irq(unsigned int, void *);
 extern int cpu(void);
 
index 6f4d680..6ac0f82 100644 (file)
@@ -58,23 +58,17 @@ struct line {
 };
 
 #define LINE_INIT(str, d) \
-       { init_str :    str, \
-         init_pri :    INIT_STATIC, \
-         valid :       1, \
-         throttled :   0, \
-         lock :        SPIN_LOCK_UNLOCKED, \
-         buffer :      NULL, \
-         head :        NULL, \
-         tail :        NULL, \
-         sigio :       0, \
-         driver :      d, \
-         have_irq :    0 }
+       { .init_str =   str, \
+         .init_pri =   INIT_STATIC, \
+         .valid =      1, \
+         .lock =       SPIN_LOCK_UNLOCKED, \
+         .driver =     d }
 
 struct lines {
        int num;
 };
 
-#define LINES_INIT(n) {  num :         n }
+#define LINES_INIT(n) {  .num =        n }
 
 extern void line_close(struct tty_struct *tty, struct file * filp);
 extern int line_open(struct line *lines, struct tty_struct *tty);
index a1064c5..a54514d 100644 (file)
@@ -49,7 +49,6 @@ extern int iomem_size;
 extern unsigned long host_task_size;
 extern unsigned long task_size;
 
-extern void check_devanon(void);
 extern int init_mem_user(void);
 extern void setup_memory(void *entry);
 extern unsigned long find_iomem(char *driver, unsigned long *len_out);
index d3d1bc6..f88856c 100644 (file)
@@ -13,6 +13,7 @@
 #include "kern_util.h"
 #include "skas/mm_id.h"
 #include "irq_user.h"
+#include "sysdep/tls.h"
 
 #define OS_TYPE_FILE 1 
 #define OS_TYPE_DIR 2 
@@ -172,6 +173,7 @@ extern int os_fchange_dir(int fd);
 extern void os_early_checks(void);
 extern int can_do_skas(void);
 extern void os_check_bugs(void);
+extern void check_host_supports_tls(int *supports_tls, int *tls_min);
 
 /* Make sure they are clear when running in TT mode. Required by
  * SEGV_MAYBE_FIXABLE */
@@ -205,6 +207,8 @@ extern int os_map_memory(void *virt, int fd, unsigned long long off,
 extern int os_protect_memory(void *addr, unsigned long len, 
                             int r, int w, int x);
 extern int os_unmap_memory(void *addr, int len);
+extern int os_drop_memory(void *addr, int length);
+extern int can_drop_memory(void);
 extern void os_flush_stdout(void);
 
 /* tt.c
@@ -234,8 +238,12 @@ extern int run_helper_thread(int (*proc)(void *), void *arg,
                             int stack_order);
 extern int helper_wait(int pid);
 
-/* umid.c */
 
+/* tls.c */
+extern int os_set_thread_area(user_desc_t *info, int pid);
+extern int os_get_thread_area(user_desc_t *info, int pid);
+
+/* umid.c */
 extern int umid_file_name(char *name, char *buf, int len);
 extern int set_umid(char *name);
 extern char *get_umid(void);
index 7d3d202..052bb06 100644 (file)
@@ -48,7 +48,8 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
  */
 
 static __inline__
-unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
+unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
+                                        unsigned char *dst,
                                         int len, int sum, int *err_ptr)
 {
        if(copy_from_user(dst, src, len)){
@@ -192,7 +193,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
  */
 #define HAVE_CSUM_COPY_USER
 static __inline__ unsigned int csum_and_copy_to_user(const unsigned char *src,
-                                                    unsigned char *dst,
+                                                    unsigned char __user *dst,
                                                     int len, int sum, int *err_ptr)
 {
        if (access_ok(VERIFY_WRITE, dst, len)){
index c8ee955..6670cc9 100644 (file)
 #define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
 #define MAX_REG_OFFSET (UM_FRAME_SIZE)
 
+#ifdef UML_CONFIG_PT_PROXY
 extern void update_debugregs(int seq);
+#else
+static inline void update_debugregs(int seq) {}
+#endif
+
 
 /* syscall emulation path in ptrace */
 
diff --git a/arch/um/include/sysdep-i386/tls.h b/arch/um/include/sysdep-i386/tls.h
new file mode 100644 (file)
index 0000000..918fd3c
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _SYSDEP_TLS_H
+#define _SYSDEP_TLS_H
+
+# ifndef __KERNEL__
+
+/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
+ * may be named user_desc (but in 2.4 and in header matching its API was named
+ * modify_ldt_ldt_s). */
+
+typedef struct um_dup_user_desc {
+       unsigned int  entry_number;
+       unsigned int  base_addr;
+       unsigned int  limit;
+       unsigned int  seg_32bit:1;
+       unsigned int  contents:2;
+       unsigned int  read_exec_only:1;
+       unsigned int  limit_in_pages:1;
+       unsigned int  seg_not_present:1;
+       unsigned int  useable:1;
+} user_desc_t;
+
+# else /* __KERNEL__ */
+
+#  include <asm/ldt.h>
+typedef struct user_desc user_desc_t;
+
+# endif /* __KERNEL__ */
+
+#define GDT_ENTRY_TLS_MIN_I386 6
+#define GDT_ENTRY_TLS_MIN_X86_64 12
+
+#endif /* _SYSDEP_TLS_H */
diff --git a/arch/um/include/sysdep-x86_64/tls.h b/arch/um/include/sysdep-x86_64/tls.h
new file mode 100644 (file)
index 0000000..35f19f2
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _SYSDEP_TLS_H
+#define _SYSDEP_TLS_H
+
+# ifndef __KERNEL__
+
+/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
+ * may be named user_desc (but in 2.4 and in header matching its API was named
+ * modify_ldt_ldt_s). */
+
+typedef struct um_dup_user_desc {
+       unsigned int  entry_number;
+       unsigned int  base_addr;
+       unsigned int  limit;
+       unsigned int  seg_32bit:1;
+       unsigned int  contents:2;
+       unsigned int  read_exec_only:1;
+       unsigned int  limit_in_pages:1;
+       unsigned int  seg_not_present:1;
+       unsigned int  useable:1;
+       unsigned int  lm:1;
+} user_desc_t;
+
+# else /* __KERNEL__ */
+
+#  include <asm/ldt.h>
+typedef struct user_desc user_desc_t;
+
+# endif /* __KERNEL__ */
+#endif /* _SYSDEP_TLS_H */
index 992a7e1..fe0c29b 100644 (file)
@@ -8,6 +8,9 @@
 
 #include "sysdep/ptrace.h"
 
+/* Copied from kernel.h */
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
 #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
 
 extern int mode_tt;
@@ -31,7 +34,7 @@ extern unsigned long uml_physmem;
 extern unsigned long uml_reserved;
 extern unsigned long end_vm;
 extern unsigned long start_vm;
-extern unsigned long highmem;
+extern unsigned long long highmem;
 
 extern char host_info[];
 
index 1ca8431..c0cb627 100644 (file)
@@ -22,6 +22,7 @@
 
 void flush_thread(void)
 {
+       arch_flush_thread(&current->thread.arch);
        CHOOSE_MODE(flush_thread_tt(), flush_thread_skas());
 }
 
@@ -58,14 +59,14 @@ long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
        return(err);
 }
 
-long sys_execve(char *file, char __user *__user *argv,
+long sys_execve(char __user *file, char __user *__user *argv,
                char __user *__user *env)
 {
        long error;
        char *filename;
 
        lock_kernel();
-       filename = getname((char __user *) file);
+       filename = getname(file);
        error = PTR_ERR(filename);
        if (IS_ERR(filename)) goto out;
        error = execve1(filename, argv, env);
@@ -74,14 +75,3 @@ long sys_execve(char *file, char __user *__user *argv,
        unlock_kernel();
        return(error);
 }
-
-/*
- * 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-file-style: "linux"
- * End:
- */
index 92cce96..44e41a3 100644 (file)
@@ -30,7 +30,7 @@ extern char __binary_start;
 unsigned long *empty_zero_page = NULL;
 unsigned long *empty_bad_page = NULL;
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
-unsigned long highmem;
+unsigned long long highmem;
 int kmalloc_ok = 0;
 
 static unsigned long brk_end;
index 3113cab..f6a5a50 100644 (file)
@@ -156,9 +156,25 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
                unsigned long stack_top, struct task_struct * p, 
                struct pt_regs *regs)
 {
+       int ret;
+
        p->thread = (struct thread_struct) INIT_THREAD;
-       return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, 
-                               clone_flags, sp, stack_top, p, regs));
+       ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
+                               clone_flags, sp, stack_top, p, regs);
+
+       if (ret || !current->thread.forking)
+               goto out;
+
+       clear_flushed_tls(p);
+
+       /*
+        * Set a new TLS for the child thread?
+        */
+       if (clone_flags & CLONE_SETTLS)
+               ret = arch_copy_tls(p);
+
+out:
+       return ret;
 }
 
 void initial_thread_cb(void (*proc)(void *), void *arg)
@@ -185,10 +201,6 @@ void default_idle(void)
 {
        CHOOSE_MODE(uml_idle_timer(), (void) 0);
 
-       atomic_inc(&init_mm.mm_count);
-       current->mm = &init_mm;
-       current->active_mm = &init_mm;
-
        while(1){
                /* endless idle loop with no priority at all */
 
@@ -407,7 +419,7 @@ static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int
        return strlen(buf);
 }
 
-static int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
+static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
 {
        char tmp[2];
 
index 98e0939..60d2eda 100644 (file)
@@ -46,6 +46,7 @@ extern int poke_user(struct task_struct * child, long addr, long data);
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
        int i, ret;
+       unsigned long __user *p = (void __user *)(unsigned long)data;
 
        switch (request) {
                /* when I and D space are separate, these will need to be fixed. */
@@ -58,7 +59,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
                if (copied != sizeof(tmp))
                        break;
-               ret = put_user(tmp, (unsigned long __user *) data);
+               ret = put_user(tmp, p);
                break;
        }
 
@@ -136,15 +137,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 
 #ifdef PTRACE_GETREGS
        case PTRACE_GETREGS: { /* Get all gp regs from the child. */
-               if (!access_ok(VERIFY_WRITE, (unsigned long *)data, 
-                              MAX_REG_OFFSET)) {
+               if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) {
                        ret = -EIO;
                        break;
                }
                for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
-                       __put_user(getreg(child, i),
-                                  (unsigned long __user *) data);
-                       data += sizeof(long);
+                       __put_user(getreg(child, i), p);
+                       p++;
                }
                ret = 0;
                break;
@@ -153,15 +152,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 #ifdef PTRACE_SETREGS
        case PTRACE_SETREGS: { /* Set all gp regs in the child. */
                unsigned long tmp = 0;
-               if (!access_ok(VERIFY_READ, (unsigned *)data, 
-                              MAX_REG_OFFSET)) {
+               if (!access_ok(VERIFY_READ, p, MAX_REG_OFFSET)) {
                        ret = -EIO;
                        break;
                }
                for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
-                       __get_user(tmp, (unsigned long __user *) data);
+                       __get_user(tmp, p);
                        putreg(child, i, tmp);
-                       data += sizeof(long);
+                       p++;
                }
                ret = 0;
                break;
@@ -187,14 +185,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                ret = set_fpxregs(data, child);
                break;
 #endif
+       case PTRACE_GET_THREAD_AREA:
+               ret = ptrace_get_thread_area(child, addr,
+                                            (struct user_desc __user *) data);
+               break;
+
+       case PTRACE_SET_THREAD_AREA:
+               ret = ptrace_set_thread_area(child, addr,
+                                            (struct user_desc __user *) data);
+               break;
+
        case PTRACE_FAULTINFO: {
-                /* Take the info from thread->arch->faultinfo,
-                 * but transfer max. sizeof(struct ptrace_faultinfo).
-                 * On i386, ptrace_faultinfo is smaller!
-                 */
-                ret = copy_to_user((unsigned long __user *) data,
-                                   &child->thread.arch.faultinfo,
-                                   sizeof(struct ptrace_faultinfo));
+               /* Take the info from thread->arch->faultinfo,
+                * but transfer max. sizeof(struct ptrace_faultinfo).
+                * On i386, ptrace_faultinfo is smaller!
+                */
+               ret = copy_to_user(p, &child->thread.arch.faultinfo,
+                                  sizeof(struct ptrace_faultinfo));
                if(ret)
                        break;
                break;
@@ -204,8 +211,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        case PTRACE_LDT: {
                struct ptrace_ldt ldt;
 
-               if(copy_from_user(&ldt, (unsigned long __user *) data,
-                                 sizeof(ldt))){
+               if(copy_from_user(&ldt, p, sizeof(ldt))){
                        ret = -EIO;
                        break;
                }
index 3f70a2e..2135eaf 100644 (file)
@@ -35,6 +35,8 @@ void switch_to_skas(void *prev, void *next)
        switch_threads(&from->thread.mode.skas.switch_buf,
                       to->thread.mode.skas.switch_buf);
 
+       arch_switch_to_skas(current->thread.prev_sched, current);
+
        if(current->pid == 0)
                switch_timers(1);
 }
@@ -89,10 +91,17 @@ void fork_handler(int sig)
                panic("blech");
 
        schedule_tail(current->thread.prev_sched);
+
+       /* XXX: if interrupt_end() calls schedule, this call to
+        * arch_switch_to_skas isn't needed. We could want to apply this to
+        * improve performance. -bb */
+       arch_switch_to_skas(current->thread.prev_sched, current);
+
        current->thread.prev_sched = NULL;
 
 /* Handle any immediate reschedules or signals */
        interrupt_end();
+
        userspace(&current->thread.regs.regs);
 }
 
@@ -109,6 +118,8 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
                if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
 
                handler = fork_handler;
+
+               arch_copy_thread(&current->thread.arch, &p->thread.arch);
        }
        else {
                init_thread_registers(&p->thread.regs.regs);
index 8e1a350..37d3978 100644 (file)
@@ -104,7 +104,7 @@ long sys_pipe(unsigned long __user * fildes)
 }
 
 
-long sys_uname(struct old_utsname * name)
+long sys_uname(struct old_utsname __user * name)
 {
        long err;
        if (!name)
@@ -115,7 +115,7 @@ long sys_uname(struct old_utsname * name)
        return err?-EFAULT:0;
 }
 
-long sys_olduname(struct oldold_utsname * name)
+long sys_olduname(struct oldold_utsname __user * name)
 {
        long error;
 
index d56046c..02f6d4d 100644 (file)
@@ -198,7 +198,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
                si.si_signo = SIGBUS;
                si.si_errno = 0;
                si.si_code = BUS_ADRERR;
-               si.si_addr = (void *)address;
+               si.si_addr = (void __user *)address;
                 current->thread.arch.faultinfo = fi;
                force_sig_info(SIGBUS, &si, current);
        } else if (err == -ENOMEM) {
@@ -207,7 +207,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
        } else {
                BUG_ON(err != -EFAULT);
                si.si_signo = SIGSEGV;
-               si.si_addr = (void *) address;
+               si.si_addr = (void __user *) address;
                 current->thread.arch.faultinfo = fi;
                force_sig_info(SIGSEGV, &si, current);
        }
@@ -220,8 +220,8 @@ void bad_segv(struct faultinfo fi, unsigned long ip)
 
        si.si_signo = SIGSEGV;
        si.si_code = SEGV_ACCERR;
-        si.si_addr = (void *) FAULT_ADDRESS(fi);
-        current->thread.arch.faultinfo = fi;
+       si.si_addr = (void __user *) FAULT_ADDRESS(fi);
+       current->thread.arch.faultinfo = fi;
        force_sig_info(SIGSEGV, &si, current);
 }
 
index 295c1ac..a9c1443 100644 (file)
@@ -51,6 +51,13 @@ void switch_to_tt(void *prev, void *next)
 
        c = 0;
 
+       /* Notice that here we "up" the semaphore on which "to" is waiting, and
+        * below (the read) we wait on this semaphore (which is implemented by
+        * switch_pipe) and go sleeping. Thus, after that, we have resumed in
+        * "to", and can't use any more the value of "from" (which is outdated),
+        * nor the value in "to" (since it was the task which stole us the CPU,
+        * which we don't care about). */
+
        err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
        if(err != sizeof(c))
                panic("write of switch_pipe failed, err = %d", -err);
@@ -77,7 +84,7 @@ void switch_to_tt(void *prev, void *next)
        change_sig(SIGALRM, alrm);
        change_sig(SIGPROF, prof);
 
-       arch_switch();
+       arch_switch_to_tt(prev_sched, current);
 
        flush_tlb_all();
        local_irq_restore(flags);
@@ -141,7 +148,6 @@ static void new_thread_handler(int sig)
        set_cmdline("(kernel thread)");
 
        change_sig(SIGUSR1, 1);
-       change_sig(SIGVTALRM, 1);
        change_sig(SIGPROF, 1);
        local_irq_enable();
        if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))
index 1659386..f4bfc4c 100644 (file)
@@ -4,7 +4,7 @@
 #
 
 obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \
-       signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o \
+       signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \
        user_syms.o util.o drivers/ sys-$(SUBARCH)/
 
 obj-$(CONFIG_MODE_SKAS) += skas/
@@ -12,12 +12,9 @@ obj-$(CONFIG_TTY_LOG) += tty_log.o
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
 USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \
-       process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o \
+       process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \
        uaccess.o umid.o util.o
 
-elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
-CFLAGS_elf_aux.o += -I$(objtree)/arch/um
-
 CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
 
 HAVE_AIO_ABI := $(shell [ -r /usr/include/linux/aio_abi.h ] && \
index 6ae4b19..768606b 100644 (file)
@@ -102,18 +102,7 @@ static struct transport ethertap_transport = {
 static int register_ethertap(void)
 {
        register_transport(&ethertap_transport);
-       return(1);
+       return 0;
 }
 
 __initcall(register_ethertap);
-
-/*
- * 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-file-style: "linux"
- * End:
- */
index 4202b9e..190009a 100644 (file)
@@ -87,18 +87,7 @@ static struct transport tuntap_transport = {
 static int register_tuntap(void)
 {
        register_transport(&tuntap_transport);
-       return(1);
+       return 0;
 }
 
 __initcall(register_tuntap);
-
-/*
- * 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-file-style: "linux"
- * End:
- */
index 9d7d69a..6ab372d 100644 (file)
@@ -121,36 +121,11 @@ int create_tmp_file(unsigned long long len)
        return(fd);
 }
 
-static int create_anon_file(unsigned long long len)
-{
-       void *addr;
-       int fd;
-
-       fd = open("/dev/anon", O_RDWR);
-       if(fd < 0) {
-               perror("opening /dev/anon");
-               exit(1);
-       }
-
-       addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
-       if(addr == MAP_FAILED){
-               perror("mapping physmem file");
-               exit(1);
-       }
-       munmap(addr, len);
-
-       return(fd);
-}
-
-extern int have_devanon;
-
 int create_mem_file(unsigned long long len)
 {
        int err, fd;
 
-       if(have_devanon)
-               fd = create_anon_file(len);
-       else fd = create_tmp_file(len);
+       fd = create_tmp_file(len);
 
        err = os_set_exec_close(fd, 1);
        if(err < 0){
index d261888..8176b0b 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/unistd.h>
 #include <sys/mman.h>
 #include <sys/wait.h>
+#include <sys/mman.h>
 #include "ptrace_user.h"
 #include "os.h"
 #include "user.h"
@@ -20,6 +21,7 @@
 #include "kern_util.h"
 #include "longjmp.h"
 #include "skas_ptrace.h"
+#include "kern_constants.h"
 
 #define ARBITRARY_ADDR -1
 #define FAILURE_PID    -1
@@ -187,6 +189,48 @@ int os_unmap_memory(void *addr, int len)
         return(0);
 }
 
+#ifndef MADV_REMOVE
+#define MADV_REMOVE    0x5             /* remove these pages & resources */
+#endif
+
+int os_drop_memory(void *addr, int length)
+{
+       int err;
+
+       err = madvise(addr, length, MADV_REMOVE);
+       if(err < 0)
+               err = -errno;
+       return err;
+}
+
+int can_drop_memory(void)
+{
+       void *addr;
+       int fd;
+
+       printk("Checking host MADV_REMOVE support...");
+       fd = create_mem_file(UM_KERN_PAGE_SIZE);
+       if(fd < 0){
+               printk("Creating test memory file failed, err = %d\n", -fd);
+               return 0;
+       }
+
+       addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
+                     MAP_PRIVATE, fd, 0);
+       if(addr == MAP_FAILED){
+               printk("Mapping test memory file failed, err = %d\n", -errno);
+               return 0;
+       }
+
+       if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){
+               printk("MADV_REMOVE failed, err = %d\n", -errno);
+               return 0;
+       }
+
+       printk("OK\n");
+       return 1;
+}
+
 void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
 {
        int flags = 0, pages;
index 3275313..387e26a 100644 (file)
@@ -470,25 +470,6 @@ int can_do_skas(void)
 }
 #endif
 
-int have_devanon = 0;
-
-/* Runs on boot kernel stack - already safe to use printk. */
-
-void check_devanon(void)
-{
-       int fd;
-
-       printk("Checking for /dev/anon on the host...");
-       fd = open("/dev/anon", O_RDWR);
-       if(fd < 0){
-               printk("Not available (open failed with errno %d)\n", errno);
-               return;
-       }
-
-       printk("OK\n");
-       have_devanon = 1;
-}
-
 int __init parse_iomem(char *str, int *add)
 {
        struct iomem_region *new;
@@ -664,6 +645,5 @@ void os_check_bugs(void)
 {
        check_ptrace();
        check_sigio();
-       check_devanon();
 }
 
index 340ef26..b321361 100644 (file)
@@ -3,7 +3,7 @@
 # Licensed under the GPL
 #
 
-obj-$(CONFIG_MODE_SKAS) = registers.o
+obj-$(CONFIG_MODE_SKAS) = registers.o tls.o
 
 USER_OBJS := $(obj-y)
 
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c
new file mode 100644 (file)
index 0000000..ba21f0e
--- /dev/null
@@ -0,0 +1,33 @@
+#include <linux/unistd.h>
+#include "sysdep/tls.h"
+#include "user_util.h"
+
+static _syscall1(int, get_thread_area, user_desc_t *, u_info);
+
+/* Checks whether host supports TLS, and sets *tls_min according to the value
+ * valid on the host.
+ * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
+void check_host_supports_tls(int *supports_tls, int *tls_min) {
+       /* Values for x86 and x86_64.*/
+       int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(val); i++) {
+               user_desc_t info;
+               info.entry_number = val[i];
+
+               if (get_thread_area(&info) == 0) {
+                       *tls_min = val[i];
+                       *supports_tls = 1;
+                       return;
+               } else {
+                       if (errno == EINVAL)
+                               continue;
+                       else if (errno == ENOSYS)
+                               *supports_tls = 0;
+                               return;
+               }
+       }
+
+       *supports_tls = 0;
+}
diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c
new file mode 100644 (file)
index 0000000..9cb09a4
--- /dev/null
@@ -0,0 +1,76 @@
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <asm/ldt.h>
+#include "sysdep/tls.h"
+#include "uml-config.h"
+
+/* TLS support - we basically rely on the host's one.*/
+
+/* In TT mode, this should be called only by the tracing thread, and makes sense
+ * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally.
+ *
+ */
+
+#ifndef PTRACE_GET_THREAD_AREA
+#define PTRACE_GET_THREAD_AREA 25
+#endif
+
+#ifndef PTRACE_SET_THREAD_AREA
+#define PTRACE_SET_THREAD_AREA 26
+#endif
+
+int os_set_thread_area(user_desc_t *info, int pid)
+{
+       int ret;
+
+       ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
+                    (unsigned long) info);
+       if (ret < 0)
+               ret = -errno;
+       return ret;
+}
+
+#ifdef UML_CONFIG_MODE_SKAS
+
+int os_get_thread_area(user_desc_t *info, int pid)
+{
+       int ret;
+
+       ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
+                    (unsigned long) info);
+       if (ret < 0)
+               ret = -errno;
+       return ret;
+}
+
+#endif
+
+#ifdef UML_CONFIG_MODE_TT
+#include "linux/unistd.h"
+
+static _syscall1(int, get_thread_area, user_desc_t *, u_info);
+static _syscall1(int, set_thread_area, user_desc_t *, u_info);
+
+int do_set_thread_area_tt(user_desc_t *info)
+{
+       int ret;
+
+       ret = set_thread_area(info);
+       if (ret < 0) {
+               ret = -errno;
+       }
+       return ret;
+}
+
+int do_get_thread_area_tt(user_desc_t *info)
+{
+       int ret;
+
+       ret = get_thread_area(info);
+       if (ret < 0) {
+               ret = -errno;
+       }
+       return ret;
+}
+
+#endif /* UML_CONFIG_MODE_TT */
index 2e41cab..b696b45 100644 (file)
@@ -20,25 +20,7 @@ define unprofile
        $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
 endef
 
-
-# cmd_make_link checks to see if the $(foo-dir) variable starts with a /.  If
-# so, it's considered to be a path relative to $(srcdir) rather than
-# $(srcdir)/arch/$(SUBARCH).  This is because x86_64 wants to get ldt.c from
-# arch/um/sys-i386 rather than arch/i386 like the other borrowed files.  So,
-# it sets $(ldt.c-dir) to /arch/um/sys-i386.
-quiet_cmd_make_link = SYMLINK $@
-cmd_make_link       = rm -f $@; ln -sf $(srctree)$(if $(filter-out /%,$($(notdir $@)-dir)),/arch/$(SUBARCH))/$($(notdir $@)-dir)/$(notdir $@) $@
-
-# this needs to be before the foreach, because targets does not accept
-# complete paths like $(obj)/$(f). To make sure this works, use a := assignment
-# or we will get $(obj)/$(f) in the "targets" value.
-# Also, this forces you to use the := syntax when assigning to targets.
-# Otherwise the line below will cause an infinite loop (if you don't know why,
-# just do it).
-
-targets := $(targets) $(SYMLINKS)
-
-SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$(f))
-
-$(SYMLINKS): FORCE
-       $(call if_changed,make_link)
+ifdef subarch-obj-y
+obj-y += subarch.o
+subarch-y = $(addprefix ../../$(SUBARCH)/,$(subarch-obj-y))
+endif
diff --git a/arch/um/scripts/Makefile.unmap b/arch/um/scripts/Makefile.unmap
deleted file mode 100644 (file)
index b216518..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-clean-files += unmap_tmp.o unmap_fin.o unmap.o
-
-ifdef CONFIG_MODE_TT
-
-#Always build unmap_fin.o
-extra-y += unmap_fin.o
-#Do dependency tracking for unmap.o (it will be always built, but won't get the tracking unless we use this).
-targets += unmap.o
-
-#XXX: partially copied from arch/um/scripts/Makefile.rules
-$(obj)/unmap.o: _c_flags = $(call unprofile,$(CFLAGS))
-
-quiet_cmd_wrapld = LD      $@
-define cmd_wrapld
-       $(LD) $(LDFLAGS) -r -o $(obj)/unmap_tmp.o $< ; \
-       $(OBJCOPY) $(UML_OBJCOPYFLAGS) $(obj)/unmap_tmp.o $@ -G switcheroo
-endef
-
-$(obj)/unmap_fin.o : $(obj)/unmap.o FORCE
-       $(call if_changed,wrapld)
-
-endif
index f5fd5b0..98b20b7 100644 (file)
@@ -1,23 +1,18 @@
-obj-y := bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
-       ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o \
-       sys_call_table.o
+obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
+       ptrace_user.o signal.o sigcontext.o syscalls.o sysrq.o \
+       sys_call_table.o tls.o
 
 obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
 
-obj-$(CONFIG_HIGHMEM) += highmem.o
-obj-$(CONFIG_MODULES) += module.o
+subarch-obj-y = lib/bitops.o kernel/semaphore.o
+subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o
+subarch-obj-$(CONFIG_MODULES) += kernel/module.o
 
 USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o stub_segv.o
 
-SYMLINKS = bitops.c semaphore.c highmem.c module.c
-
 include arch/um/scripts/Makefile.rules
 
-bitops.c-dir = lib
-semaphore.c-dir = kernel
-highmem.c-dir = mm
-module.c-dir = kernel
-
-$(obj)/stub_segv.o : _c_flags = $(call unprofile,$(CFLAGS))
+extra-$(CONFIG_MODE_TT) += unmap.o
 
-include arch/um/scripts/Makefile.unmap
+$(obj)/stub_segv.o $(obj)/unmap.o: \
+       _c_flags = $(call unprofile,$(CFLAGS))
index 8032a10..6028bc7 100644 (file)
 #include "sysdep/sigcontext.h"
 #include "sysdep/sc.h"
 
-void arch_switch(void)
+void arch_switch_to_tt(struct task_struct *from, struct task_struct *to)
 {
-       update_debugregs(current->thread.arch.debugregs_seq);
+       update_debugregs(to->thread.arch.debugregs_seq);
+       arch_switch_tls_tt(from, to);
+}
+
+void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
+{
+       int err = arch_switch_tls_skas(from, to);
+       if (!err)
+               return;
+
+       if (err != -EINVAL)
+               printk(KERN_WARNING "arch_switch_tls_skas failed, errno %d, not EINVAL\n", -err);
+       else
+               printk(KERN_WARNING "arch_switch_tls_skas failed, errno = EINVAL\n");
 }
 
 int is_syscall(unsigned long addr)
@@ -124,22 +137,22 @@ unsigned long getreg(struct task_struct *child, int regno)
 int peek_user(struct task_struct *child, long addr, long data)
 {
 /* read the word at location addr in the USER area. */
-        unsigned long tmp;
+       unsigned long tmp;
 
-        if ((addr & 3) || addr < 0)
-                return -EIO;
+       if ((addr & 3) || addr < 0)
+               return -EIO;
 
-        tmp = 0;  /* Default return condition */
-        if(addr < MAX_REG_OFFSET){
-                tmp = getreg(child, addr);
-        }
-        else if((addr >= offsetof(struct user, u_debugreg[0])) &&
-                (addr <= offsetof(struct user, u_debugreg[7]))){
-                addr -= offsetof(struct user, u_debugreg[0]);
-                addr = addr >> 2;
-                tmp = child->thread.arch.debugregs[addr];
-        }
-        return put_user(tmp, (unsigned long *) data);
+       tmp = 0;  /* Default return condition */
+       if(addr < MAX_REG_OFFSET){
+               tmp = getreg(child, addr);
+       }
+       else if((addr >= offsetof(struct user, u_debugreg[0])) &&
+               (addr <= offsetof(struct user, u_debugreg[7]))){
+               addr -= offsetof(struct user, u_debugreg[0]);
+               addr = addr >> 2;
+               tmp = child->thread.arch.debugregs[addr];
+       }
+       return put_user(tmp, (unsigned long __user *) data);
 }
 
 struct i387_fxsave_struct {
index 7c376c9..9f3bd8e 100644 (file)
@@ -14,6 +14,7 @@
 #include "sysdep/thread.h"
 #include "user.h"
 #include "os.h"
+#include "uml-config.h"
 
 int ptrace_getregs(long pid, unsigned long *regs_out)
 {
@@ -43,6 +44,7 @@ int ptrace_setfpregs(long pid, unsigned long *regs)
        return 0;
 }
 
+/* All the below stuff is of interest for TT mode only */
 static void write_debugregs(int pid, unsigned long *regs)
 {
        struct user *dummy;
@@ -75,7 +77,6 @@ static void read_debugregs(int pid, unsigned long *regs)
 
 /* Accessed only by the tracing thread */
 static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 };
-static int debugregs_seq = 0;
 
 void arch_enter_kernel(void *task, int pid)
 {
@@ -89,6 +90,11 @@ void arch_leave_kernel(void *task, int pid)
        write_debugregs(pid, TASK_DEBUGREGS(task));
 }
 
+#ifdef UML_CONFIG_PT_PROXY
+/* Accessed only by the tracing thread */
+static int debugregs_seq;
+
+/* Only called by the ptrace proxy */
 void ptrace_pokeuser(unsigned long addr, unsigned long data)
 {
        if((addr < offsetof(struct user, u_debugreg[0])) ||
@@ -109,6 +115,7 @@ static void update_debugregs_cb(void *arg)
        write_debugregs(pid, kernel_debugregs);
 }
 
+/* Optimized out in its header when not defined */
 void update_debugregs(int seq)
 {
        int me;
@@ -118,6 +125,7 @@ void update_debugregs(int seq)
        me = os_getpid();
        initial_thread_cb(update_debugregs_cb, &me);
 }
+#endif
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 33a40f5..f5d0e1c 100644 (file)
@@ -19,7 +19,7 @@
 #include "skas.h"
 
 static int copy_sc_from_user_skas(struct pt_regs *regs,
-                                 struct sigcontext *from)
+                                 struct sigcontext __user *from)
 {
        struct sigcontext sc;
        unsigned long fpregs[HOST_FP_SIZE];
@@ -57,7 +57,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
        return(0);
 }
 
-int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
+int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate __user *to_fp,
                          struct pt_regs *regs, unsigned long sp)
 {
        struct sigcontext sc;
@@ -92,7 +92,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
                       "errno = %d\n", err);
                return(1);
        }
-       to_fp = (to_fp ? to_fp : (struct _fpstate *) (to + 1));
+       to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
        sc.fpstate = to_fp;
 
        if(err)
@@ -113,10 +113,11 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
  * saved pointer is in the kernel, but the sigcontext is in userspace, so we
  * copy_to_user it.
  */
-int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
+int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
                         int fpsize)
 {
-       struct _fpstate *to_fp, *from_fp;
+       struct _fpstate *to_fp;
+       struct _fpstate __user *from_fp;
        unsigned long sigs;
        int err;
 
@@ -131,13 +132,14 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
        return(err);
 }
 
-int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
+int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate __user *fp,
                       struct sigcontext *from, int fpsize, unsigned long sp)
 {
-       struct _fpstate *to_fp, *from_fp;
+       struct _fpstate __user *to_fp;
+       struct _fpstate *from_fp;
        int err;
 
-       to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
+       to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1));
        from_fp = from->fpstate;
        err = copy_to_user(to, from, sizeof(*to));
 
@@ -165,7 +167,7 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
        return(ret);
 }
 
-static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
+static int copy_sc_to_user(struct sigcontext *to, struct _fpstate __user *fp,
                           struct pt_regs *from, unsigned long sp)
 {
        return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
@@ -173,7 +175,7 @@ static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
                            copy_sc_to_user_skas(to, fp, from, sp)));
 }
 
-static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
+static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp,
                                 sigset_t *set, unsigned long sp)
 {
        int err = 0;
@@ -188,7 +190,7 @@ static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
 
 struct sigframe
 {
-       char *pretcode;
+       char __user *pretcode;
        int sig;
        struct sigcontext sc;
        struct _fpstate fpstate;
@@ -198,10 +200,10 @@ struct sigframe
 
 struct rt_sigframe
 {
-       char *pretcode;
+       char __user *pretcode;
        int sig;
-       struct siginfo *pinfo;
-       void *puc;
+       struct siginfo __user *pinfo;
+       void __user *puc;
        struct siginfo info;
        struct ucontext uc;
        struct _fpstate fpstate;
@@ -213,16 +215,16 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
                          sigset_t *mask)
 {
        struct sigframe __user *frame;
-       void *restorer;
+       void __user *restorer;
        unsigned long save_sp = PT_REGS_SP(regs);
        int err = 0;
 
        stack_top &= -8UL;
-       frame = (struct sigframe *) stack_top - 1;
+       frame = (struct sigframe __user *) stack_top - 1;
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
                return 1;
 
-       restorer = (void *) frame->retcode;
+       restorer = frame->retcode;
        if(ka->sa.sa_flags & SA_RESTORER)
                restorer = ka->sa.sa_restorer;
 
@@ -278,16 +280,16 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
                          siginfo_t *info, sigset_t *mask)
 {
        struct rt_sigframe __user *frame;
-       void *restorer;
+       void __user *restorer;
        unsigned long save_sp = PT_REGS_SP(regs);
        int err = 0;
 
        stack_top &= -8UL;
-       frame = (struct rt_sigframe *) stack_top - 1;
+       frame = (struct rt_sigframe __user *) stack_top - 1;
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
                return 1;
 
-       restorer = (void *) frame->retcode;
+       restorer = frame->retcode;
        if(ka->sa.sa_flags & SA_RESTORER)
                restorer = ka->sa.sa_restorer;
 
@@ -333,7 +335,7 @@ err:
 long sys_sigreturn(struct pt_regs regs)
 {
        unsigned long sp = PT_REGS_SP(&current->thread.regs);
-       struct sigframe __user *frame = (struct sigframe *)(sp - 8);
+       struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
        sigset_t set;
        struct sigcontext __user *sc = &frame->sc;
        unsigned long __user *oldmask = &sc->oldmask;
@@ -365,8 +367,8 @@ long sys_sigreturn(struct pt_regs regs)
 
 long sys_rt_sigreturn(struct pt_regs regs)
 {
-       unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
-       struct rt_sigframe __user *frame = (struct rt_sigframe *) (sp - 4);
+       unsigned long sp = PT_REGS_SP(&current->thread.regs);
+       struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (sp - 4);
        sigset_t set;
        struct ucontext __user *uc = &frame->uc;
        int sig_size = _NSIG_WORDS * sizeof(unsigned long);
index ad75c27..1ff6147 100644 (file)
@@ -6,8 +6,6 @@
 
 #define sys_vm86old sys_ni_syscall
 #define sys_vm86 sys_ni_syscall
-#define sys_set_thread_area sys_ni_syscall
-#define sys_get_thread_area sys_ni_syscall
 
 #define sys_stime um_stime
 #define sys_time um_time
index 83e9be8..749dd1b 100644 (file)
@@ -61,21 +61,27 @@ long old_select(struct sel_arg_struct __user *arg)
        return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
 }
 
-/* The i386 version skips reading from %esi, the fourth argument. So we must do
- * this, too.
+/*
+ * The prototype on i386 is:
+ *
+ *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
+ *
+ * and the "newtls" arg. on i386 is read by copy_thread directly from the
+ * register saved on the stack.
  */
 long sys_clone(unsigned long clone_flags, unsigned long newsp,
-              int __user *parent_tid, int unused, int __user *child_tid)
+              int __user *parent_tid, void *newtls, int __user *child_tid)
 {
        long ret;
 
        if (!newsp)
                newsp = UPT_SP(&current->thread.regs.regs);
+
        current->thread.forking = 1;
        ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
                      child_tid);
        current->thread.forking = 0;
-       return(ret);
+       return ret;
 }
 
 /*
@@ -104,7 +110,7 @@ long sys_ipc (uint call, int first, int second,
                union semun fourth;
                if (!ptr)
                        return -EINVAL;
-               if (get_user(fourth.__pad, (void **) ptr))
+               if (get_user(fourth.__pad, (void __user * __user *) ptr))
                        return -EFAULT;
                return sys_semctl (first, second, third, fourth);
        }
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
new file mode 100644 (file)
index 0000000..a3188e8
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
+ * Licensed under the GPL
+ */
+
+#include "linux/config.h"
+#include "linux/kernel.h"
+#include "linux/sched.h"
+#include "linux/slab.h"
+#include "linux/types.h"
+#include "asm/uaccess.h"
+#include "asm/ptrace.h"
+#include "asm/segment.h"
+#include "asm/smp.h"
+#include "asm/desc.h"
+#include "choose-mode.h"
+#include "kern.h"
+#include "kern_util.h"
+#include "mode_kern.h"
+#include "os.h"
+#include "mode.h"
+
+#ifdef CONFIG_MODE_SKAS
+#include "skas.h"
+#endif
+
+/* If needed we can detect when it's uninitialized. */
+static int host_supports_tls = -1;
+int host_gdt_entry_tls_min = -1;
+
+#ifdef CONFIG_MODE_SKAS
+int do_set_thread_area_skas(struct user_desc *info)
+{
+       int ret;
+       u32 cpu;
+
+       cpu = get_cpu();
+       ret = os_set_thread_area(info, userspace_pid[cpu]);
+       put_cpu();
+       return ret;
+}
+
+int do_get_thread_area_skas(struct user_desc *info)
+{
+       int ret;
+       u32 cpu;
+
+       cpu = get_cpu();
+       ret = os_get_thread_area(info, userspace_pid[cpu]);
+       put_cpu();
+       return ret;
+}
+#endif
+
+/*
+ * sys_get_thread_area: get a yet unused TLS descriptor index.
+ * XXX: Consider leaving one free slot for glibc usage at first place. This must
+ * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else.
+ *
+ * Also, this must be tested when compiling in SKAS mode with dinamic linking
+ * and running against NPTL.
+ */
+static int get_free_idx(struct task_struct* task)
+{
+       struct thread_struct *t = &task->thread;
+       int idx;
+
+       if (!t->arch.tls_array)
+               return GDT_ENTRY_TLS_MIN;
+
+       for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
+               if (!t->arch.tls_array[idx].present)
+                       return idx + GDT_ENTRY_TLS_MIN;
+       return -ESRCH;
+}
+
+static inline void clear_user_desc(struct user_desc* info)
+{
+       /* Postcondition: LDT_empty(info) returns true. */
+       memset(info, 0, sizeof(*info));
+
+       /* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
+        * indeed an empty user_desc.
+        */
+       info->read_exec_only = 1;
+       info->seg_not_present = 1;
+}
+
+#define O_FORCE 1
+
+static int load_TLS(int flags, struct task_struct *to)
+{
+       int ret = 0;
+       int idx;
+
+       for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
+               struct uml_tls_struct* curr = &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
+
+               /* Actually, now if it wasn't flushed it gets cleared and
+                * flushed to the host, which will clear it.*/
+               if (!curr->present) {
+                       if (!curr->flushed) {
+                               clear_user_desc(&curr->tls);
+                               curr->tls.entry_number = idx;
+                       } else {
+                               WARN_ON(!LDT_empty(&curr->tls));
+                               continue;
+                       }
+               }
+
+               if (!(flags & O_FORCE) && curr->flushed)
+                       continue;
+
+               ret = do_set_thread_area(&curr->tls);
+               if (ret)
+                       goto out;
+
+               curr->flushed = 1;
+       }
+out:
+       return ret;
+}
+
+/* Verify if we need to do a flush for the new process, i.e. if there are any
+ * present desc's, only if they haven't been flushed.
+ */
+static inline int needs_TLS_update(struct task_struct *task)
+{
+       int i;
+       int ret = 0;
+
+       for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
+               struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+
+               /* Can't test curr->present, we may need to clear a descriptor
+                * which had a value. */
+               if (curr->flushed)
+                       continue;
+               ret = 1;
+               break;
+       }
+       return ret;
+}
+
+/* On a newly forked process, the TLS descriptors haven't yet been flushed. So
+ * we mark them as such and the first switch_to will do the job.
+ */
+void clear_flushed_tls(struct task_struct *task)
+{
+       int i;
+
+       for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
+               struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+
+               /* Still correct to do this, if it wasn't present on the host it
+                * will remain as flushed as it was. */
+               if (!curr->present)
+                       continue;
+
+               curr->flushed = 0;
+       }
+}
+
+/* In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
+ * common host process. So this is needed in SKAS0 too.
+ *
+ * However, if each thread had a different host process (and this was discussed
+ * for SMP support) this won't be needed.
+ *
+ * And this will not need be used when (and if) we'll add support to the host
+ * SKAS patch. */
+
+int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to)
+{
+       if (!host_supports_tls)
+               return 0;
+
+       /* We have no need whatsoever to switch TLS for kernel threads; beyond
+        * that, that would also result in us calling os_set_thread_area with
+        * userspace_pid[cpu] == 0, which gives an error. */
+       if (likely(to->mm))
+               return load_TLS(O_FORCE, to);
+
+       return 0;
+}
+
+int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to)
+{
+       if (!host_supports_tls)
+               return 0;
+
+       if (needs_TLS_update(to))
+               return load_TLS(0, to);
+
+       return 0;
+}
+
+static int set_tls_entry(struct task_struct* task, struct user_desc *info,
+                        int idx, int flushed)
+{
+       struct thread_struct *t = &task->thread;
+
+       if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+               return -EINVAL;
+
+       t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info;
+       t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1;
+       t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed;
+
+       return 0;
+}
+
+int arch_copy_tls(struct task_struct *new)
+{
+       struct user_desc info;
+       int idx, ret = -EFAULT;
+
+       if (copy_from_user(&info,
+                          (void __user *) UPT_ESI(&new->thread.regs.regs),
+                          sizeof(info)))
+               goto out;
+
+       ret = -EINVAL;
+       if (LDT_empty(&info))
+               goto out;
+
+       idx = info.entry_number;
+
+       ret = set_tls_entry(new, &info, idx, 0);
+out:
+       return ret;
+}
+
+/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
+static int get_tls_entry(struct task_struct* task, struct user_desc *info, int idx)
+{
+       struct thread_struct *t = &task->thread;
+
+       if (!t->arch.tls_array)
+               goto clear;
+
+       if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+               return -EINVAL;
+
+       if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present)
+               goto clear;
+
+       *info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
+
+out:
+       /* Temporary debugging check, to make sure that things have been
+        * flushed. This could be triggered if load_TLS() failed.
+        */
+       if (unlikely(task == current && !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
+               printk(KERN_ERR "get_tls_entry: task with pid %d got here "
+                               "without flushed TLS.", current->pid);
+       }
+
+       return 0;
+clear:
+       /* When the TLS entry has not been set, the values read to user in the
+        * tls_array are 0 (because it's cleared at boot, see
+        * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
+        */
+       clear_user_desc(info);
+       info->entry_number = idx;
+       goto out;
+}
+
+asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
+{
+       struct user_desc info;
+       int idx, ret;
+
+       if (!host_supports_tls)
+               return -ENOSYS;
+
+       if (copy_from_user(&info, user_desc, sizeof(info)))
+               return -EFAULT;
+
+       idx = info.entry_number;
+
+       if (idx == -1) {
+               idx = get_free_idx(current);
+               if (idx < 0)
+                       return idx;
+               info.entry_number = idx;
+               /* Tell the user which slot we chose for him.*/
+               if (put_user(idx, &user_desc->entry_number))
+                       return -EFAULT;
+       }
+
+       ret = CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, &info);
+       if (ret)
+               return ret;
+       return set_tls_entry(current, &info, idx, 1);
+}
+
+/*
+ * Perform set_thread_area on behalf of the traced child.
+ * Note: error handling is not done on the deferred load, and this differ from
+ * i386. However the only possible error are caused by bugs.
+ */
+int ptrace_set_thread_area(struct task_struct *child, int idx,
+               struct user_desc __user *user_desc)
+{
+       struct user_desc info;
+
+       if (!host_supports_tls)
+               return -EIO;
+
+       if (copy_from_user(&info, user_desc, sizeof(info)))
+               return -EFAULT;
+
+       return set_tls_entry(child, &info, idx, 0);
+}
+
+asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc)
+{
+       struct user_desc info;
+       int idx, ret;
+
+       if (!host_supports_tls)
+               return -ENOSYS;
+
+       if (get_user(idx, &user_desc->entry_number))
+               return -EFAULT;
+
+       ret = get_tls_entry(current, &info, idx);
+       if (ret < 0)
+               goto out;
+
+       if (copy_to_user(user_desc, &info, sizeof(info)))
+               ret = -EFAULT;
+
+out:
+       return ret;
+}
+
+/*
+ * Perform get_thread_area on behalf of the traced child.
+ */
+int ptrace_get_thread_area(struct task_struct *child, int idx,
+               struct user_desc __user *user_desc)
+{
+       struct user_desc info;
+       int ret;
+
+       if (!host_supports_tls)
+               return -EIO;
+
+       ret = get_tls_entry(child, &info, idx);
+       if (ret < 0)
+               goto out;
+
+       if (copy_to_user(user_desc, &info, sizeof(info)))
+               ret = -EFAULT;
+out:
+       return ret;
+}
+
+
+/* XXX: This part is probably common to i386 and x86-64. Don't create a common
+ * file for now, do that when implementing x86-64 support.*/
+static int __init __setup_host_supports_tls(void) {
+       check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
+       if (host_supports_tls) {
+               printk(KERN_INFO "Host TLS support detected\n");
+               printk(KERN_INFO "Detected host type: ");
+               switch (host_gdt_entry_tls_min) {
+                       case GDT_ENTRY_TLS_MIN_I386:
+                               printk("i386\n");
+                               break;
+                       case GDT_ENTRY_TLS_MIN_X86_64:
+                               printk("x86_64\n");
+                               break;
+               }
+       } else
+               printk(KERN_ERR "  Host TLS support NOT detected! "
+                               "TLS support inside UML will not work\n");
+       return 1;
+}
+
+__initcall(__setup_host_supports_tls);
index a351091..b5fc22b 100644 (file)
@@ -4,31 +4,23 @@
 # Licensed under the GPL
 #
 
-#XXX: why into lib-y?
-lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o ldt.o mem.o memcpy.o \
-       ptrace.o ptrace_user.o sigcontext.o signal.o syscalls.o \
-       syscall_table.o sysrq.o thunk.o
-lib-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
+obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
+       sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o ksyms.o \
+       tls.o
 
-obj-y := ksyms.o
-obj-$(CONFIG_MODULES) += module.o um_module.o
+obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
+obj-$(CONFIG_MODULES) += um_module.o
 
-USER_OBJS := ptrace_user.o sigcontext.o stub_segv.o
+subarch-obj-y = lib/bitops.o lib/csum-partial.o lib/memcpy.o lib/thunk.o
+subarch-obj-$(CONFIG_MODULES) += kernel/module.o
 
-SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \
-       thunk.S module.c
+ldt-y = ../sys-i386/ldt.o
 
-include arch/um/scripts/Makefile.rules
+USER_OBJS := ptrace_user.o sigcontext.o stub_segv.o
 
-bitops.c-dir = lib
-csum-copy.S-dir = lib
-csum-partial.c-dir = lib
-csum-wrappers.c-dir = lib
-ldt.c-dir = /arch/um/sys-i386
-memcpy.S-dir = lib
-thunk.S-dir = lib
-module.c-dir = kernel
+include arch/um/scripts/Makefile.rules
 
-$(obj)/stub_segv.o: _c_flags = $(call unprofile,$(CFLAGS))
+extra-$(CONFIG_MODE_TT) += unmap.o
 
-include arch/um/scripts/Makefile.unmap
+$(obj)/stub_segv.o $(obj)/unmap.o: \
+       _c_flags = $(call unprofile,$(CFLAGS))
diff --git a/arch/um/sys-x86_64/tls.c b/arch/um/sys-x86_64/tls.c
new file mode 100644 (file)
index 0000000..ce1bf1b
--- /dev/null
@@ -0,0 +1,14 @@
+#include "linux/sched.h"
+
+void debug_arch_force_load_TLS(void)
+{
+}
+
+void clear_flushed_tls(struct task_struct *task)
+{
+}
+
+int arch_copy_tls(struct task_struct *t)
+{
+        return 0;
+}
index d90321f..1384367 100644 (file)
@@ -32,9 +32,28 @@ __kernel_rt_sigreturn:
        .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn
 
        .section .eh_frame,"a",@progbits
+.LSTARTFRAMES:
+        .long .LENDCIES-.LSTARTCIES
+.LSTARTCIES:
+       .long 0                 /* CIE ID */
+       .byte 1                 /* Version number */
+       .string "zRS"           /* NUL-terminated augmentation string */
+       .uleb128 1              /* Code alignment factor */
+       .sleb128 -4             /* Data alignment factor */
+       .byte 8                 /* Return address register column */
+       .uleb128 1              /* Augmentation value length */
+       .byte 0x1b              /* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */
+       .byte 0x0c              /* DW_CFA_def_cfa */
+       .uleb128 4
+       .uleb128 4
+       .byte 0x88              /* DW_CFA_offset, column 0x8 */
+       .uleb128 1
+       .align 4
+.LENDCIES:
+
        .long .LENDFDE2-.LSTARTFDE2     /* Length FDE */
 .LSTARTFDE2:
-       .long .LSTARTFDE2-.LSTARTFRAME  /* CIE pointer */
+       .long .LSTARTFDE2-.LSTARTFRAMES /* CIE pointer */
        /* HACK: The dwarf2 unwind routines will subtract 1 from the
           return address to get an address in the middle of the
           presumed call instruction.  Since we didn't get here via
@@ -97,7 +116,7 @@ __kernel_rt_sigreturn:
 
        .long .LENDFDE3-.LSTARTFDE3     /* Length FDE */
 .LSTARTFDE3:
-       .long .LSTARTFDE3-.LSTARTFRAME  /* CIE pointer */
+       .long .LSTARTFDE3-.LSTARTFRAMES /* CIE pointer */
        /* HACK: See above wrt unwind library assumptions.  */
        .long .LSTART_rt_sigreturn-1-.  /* PC-relative start address */
        .long .LEND_rt_sigreturn-.LSTART_rt_sigreturn+1
index d546201..100a30c 100644 (file)
@@ -615,7 +615,7 @@ static int __init apic_set_verbosity(char *str)
                printk(KERN_WARNING "APIC Verbosity level %s not recognised"
                                " use apic=verbose or apic=debug", str);
 
-       return 0;
+       return 1;
 }
 
 __setup("apic=", apic_set_verbosity);
@@ -1137,35 +1137,35 @@ int __init APIC_init_uniprocessor (void)
 static __init int setup_disableapic(char *str) 
 { 
        disable_apic = 1;
-       return 0;
+       return 1;
 } 
 
 static __init int setup_nolapic(char *str) 
 { 
        disable_apic = 1;
-       return 0;
+       return 1;
 } 
 
 static __init int setup_noapictimer(char *str) 
 { 
        if (str[0] != ' ' && str[0] != 0)
-               return -1;
+               return 0;
        disable_apic_timer = 1;
-       return 0;
+       return 1;
 } 
 
 static __init int setup_apicmaintimer(char *str)
 {
        apic_runs_main_timer = 1;
        nohpet = 1;
-       return 0;
+       return 1;
 }
 __setup("apicmaintimer", setup_apicmaintimer);
 
 static __init int setup_noapicmaintimer(char *str)
 {
        apic_runs_main_timer = -1;
-       return 0;
+       return 1;
 }
 __setup("noapicmaintimer", setup_noapicmaintimer);
 
index 13af920..b93ef5b 100644 (file)
@@ -221,7 +221,7 @@ int __init setup_early_printk(char *opt)
        char buf[256];
 
        if (early_console_initialized)
-               return -1;
+               return 1;
 
        strlcpy(buf,opt,sizeof(buf));
        space = strchr(buf, ' ');
index 04282ef..10b3e34 100644 (file)
@@ -501,7 +501,7 @@ static struct miscdevice mce_log_device = {
 static int __init mcheck_disable(char *str)
 {
        mce_dont_init = 1;
-       return 0;
+       return 1;
 }
 
 /* mce=off disables machine check. Note you can reenable it later
@@ -521,7 +521,7 @@ static int __init mcheck_enable(char *str)
                get_option(&str, &tolerant);
        else
                printk("mce= argument %s ignored. Please use /sys", str); 
-       return 0;
+       return 1;
 }
 
 __setup("nomce", mcheck_disable);
index ee5ee48..b0444a4 100644 (file)
@@ -121,7 +121,7 @@ unsigned int do_gettimeoffset_pm(void)
 static int __init nopmtimer_setup(char *s)
 {
        pmtmr_ioport = 0;
-       return 0;
+       return 1;
 }
 
 __setup("nopmtimer", nopmtimer_setup);
index d1f3e92..0856ad4 100644 (file)
@@ -540,7 +540,7 @@ void __init alternative_instructions(void)
 static int __init noreplacement_setup(char *s)
 { 
      no_replacement = 1; 
-     return 0; 
+     return 1;
 } 
 
 __setup("noreplacement", noreplacement_setup); 
index eabdb63..8a691fa 100644 (file)
@@ -55,7 +55,7 @@ int __init nonx_setup(char *str)
                do_not_nx = 1;
                __supported_pte_mask &= ~_PAGE_NX;
         }
-       return 0;
+       return 1;
 } 
 __setup("noexec=", nonx_setup);        /* parsed early actually */
 
@@ -74,7 +74,7 @@ static int __init nonx32_setup(char *str)
                force_personality32 &= ~READ_IMPLIES_EXEC;
        else if (!strcmp(str, "off"))
                force_personality32 |= READ_IMPLIES_EXEC;
-       return 0;
+       return 1;
 }
 __setup("noexec32=", nonx32_setup);
 
index ea48fa6..71a7222 100644 (file)
@@ -353,7 +353,7 @@ static void __cpuinit tsc_sync_wait(void)
 static __init int notscsync_setup(char *s)
 {
        notscsync = 1;
-       return 0;
+       return 1;
 }
 __setup("notscsync", notscsync_setup);
 
index 473b514..ef8bc46 100644 (file)
@@ -1306,7 +1306,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static int __init nohpet_setup(char *s) 
 { 
        nohpet = 1;
-       return 0;
+       return 1;
 } 
 
 __setup("nohpet", nohpet_setup);
@@ -1314,7 +1314,7 @@ __setup("nohpet", nohpet_setup);
 int __init notsc_setup(char *s)
 {
        notsc = 1;
-       return 0;
+       return 1;
 }
 
 __setup("notsc", notsc_setup);
index edaa9fe..6bda322 100644 (file)
@@ -973,14 +973,14 @@ void __init trap_init(void)
 static int __init oops_dummy(char *s)
 { 
        panic_on_oops = 1;
-       return -1; 
+       return 1;
 } 
 __setup("oops=", oops_dummy); 
 
 static int __init kstack_setup(char *s)
 {
        kstack_depth_to_print = simple_strtoul(s,NULL,0);
-       return 0;
+       return 1;
 }
 __setup("kstack=", kstack_setup);
 
index d96a934..d78f460 100644 (file)
@@ -102,8 +102,6 @@ EXPORT_SYMBOL(cpu_callout_map);
 EXPORT_SYMBOL(screen_info);
 #endif
 
-EXPORT_SYMBOL(get_wchan);
-
 EXPORT_SYMBOL(rtc_lock);
 
 EXPORT_SYMBOL_GPL(set_nmi_callback);
index 316c53d..5525059 100644 (file)
@@ -623,6 +623,6 @@ void vmalloc_sync_all(void)
 static int __init enable_pagefaulttrace(char *str)
 {
        page_fault_trace = 1;
-       return 0;
+       return 1;
 }
 __setup("pagefaulttrace", enable_pagefaulttrace);
index efae56a..152b937 100644 (file)
@@ -113,8 +113,6 @@ EXPORT_SYMBOL(__xtensa_copy_user);
 // FIXME EXPORT_SYMBOL(screen_info);
 #endif
 
-EXPORT_SYMBOL(get_wchan);
-
 EXPORT_SYMBOL(outsb);
 EXPORT_SYMBOL(outsw);
 EXPORT_SYMBOL(outsl);
index 5536839..b6f5f0a 100644 (file)
@@ -27,10 +27,10 @@ config BLK_DEV_IO_TRACE
 config LSF
        bool "Support for Large Single Files"
        depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML
-       default n
        help
-         When CONFIG_LBD is disabled, say Y here if you want to
-         handle large file(bigger than 2TB), otherwise say N.
-         When CONFIG_LBD is enabled, Y is set automatically.
+         Say Y here if you want to be able to handle very large files (bigger
+         than 2TB), otherwise say N.
+
+         If unsure, say Y.
 
 source block/Kconfig.iosched
index 56c2ed0..0d6be03 100644 (file)
@@ -145,7 +145,7 @@ static int __init elevator_setup(char *str)
                strcpy(chosen_elevator, "anticipatory");
        else
                strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1);
-       return 0;
+       return 1;
 }
 
 __setup("elevator=", elevator_setup);
index db4c60c..5a8d3bf 100644 (file)
@@ -17,8 +17,6 @@
 #include <linux/buffer_head.h>
 #include <linux/mutex.h>
 
-#define MAX_PROBE_HASH 255     /* random */
-
 static struct subsystem block_subsys;
 
 static DEFINE_MUTEX(block_subsys_lock);
@@ -31,108 +29,29 @@ static struct blk_major_name {
        struct blk_major_name *next;
        int major;
        char name[16];
-} *major_names[MAX_PROBE_HASH];
+} *major_names[BLKDEV_MAJOR_HASH_SIZE];
 
 /* index in the above - for now: assume no multimajor ranges */
 static inline int major_to_index(int major)
 {
-       return major % MAX_PROBE_HASH;
-}
-
-struct blkdev_info {
-        int index;
-        struct blk_major_name *bd;
-};
-
-/*
- * iterate over a list of blkdev_info structures.  allows
- * the major_names array to be iterated over from outside this file
- * must be called with the block_subsys_lock held
- */
-void *get_next_blkdev(void *dev)
-{
-        struct blkdev_info *info;
-
-        if (dev == NULL) {
-                info = kmalloc(sizeof(*info), GFP_KERNEL);
-                if (!info)
-                        goto out;
-                info->index=0;
-                info->bd = major_names[info->index];
-                if (info->bd)
-                        goto out;
-        } else {
-                info = dev;
-        }
-
-        while (info->index < ARRAY_SIZE(major_names)) {
-                if (info->bd)
-                        info->bd = info->bd->next;
-                if (info->bd)
-                        goto out;
-                /*
-                 * No devices on this chain, move to the next
-                 */
-                info->index++;
-                info->bd = (info->index < ARRAY_SIZE(major_names)) ?
-                       major_names[info->index] : NULL;
-                if (info->bd)
-                        goto out;
-        }
-
-out:
-        return info;
-}
-
-void *acquire_blkdev_list(void)
-{
-        mutex_lock(&block_subsys_lock);
-        return get_next_blkdev(NULL);
-}
-
-void release_blkdev_list(void *dev)
-{
-        mutex_unlock(&block_subsys_lock);
-        kfree(dev);
+       return major % BLKDEV_MAJOR_HASH_SIZE;
 }
 
+#ifdef CONFIG_PROC_FS
 
-/*
- * Count the number of records in the blkdev_list.
- * must be called with the block_subsys_lock held
- */
-int count_blkdev_list(void)
+void blkdev_show(struct seq_file *f, off_t offset)
 {
-       struct blk_major_name *n;
-       int i, count;
+       struct blk_major_name *dp;
 
-       count = 0;
-
-       for (i = 0; i < ARRAY_SIZE(major_names); i++) {
-               for (n = major_names[i]; n; n = n->next)
-                               count++;
+       if (offset < BLKDEV_MAJOR_HASH_SIZE) {
+               mutex_lock(&block_subsys_lock);
+               for (dp = major_names[offset]; dp; dp = dp->next)
+                       seq_printf(f, "%3d %s\n", dp->major, dp->name);
+               mutex_unlock(&block_subsys_lock);
        }
-
-       return count;
-}
-
-/*
- * extract the major and name values from a blkdev_info struct
- * passed in as a void to *dev.  Must be called with
- * block_subsys_lock held
- */
-int get_blkdev_info(void *dev, int *major, char **name)
-{
-        struct blkdev_info *info = dev;
-
-        if (info->bd == NULL)
-                return 1;
-
-        *major = info->bd->major;
-        *name = info->bd->name;
-        return 0;
 }
 
+#endif /* CONFIG_PROC_FS */
 
 int register_blkdev(unsigned int major, const char *name)
 {
index 9f5c0da..5c91d6a 100644 (file)
@@ -64,6 +64,8 @@ source "drivers/usb/Kconfig"
 
 source "drivers/mmc/Kconfig"
 
+source "drivers/leds/Kconfig"
+
 source "drivers/infiniband/Kconfig"
 
 source "drivers/sn/Kconfig"
index 2449ec5..447d8e6 100644 (file)
@@ -25,9 +25,6 @@ obj-$(CONFIG_CONNECTOR)               += connector/
 obj-$(CONFIG_FB_I810)           += video/i810/
 obj-$(CONFIG_FB_INTEL)          += video/intelfb/
 
-# we also need input/serio early so serio bus is initialized by the time
-# serial drivers start registering their serio ports
-obj-$(CONFIG_SERIO)            += input/serio/
 obj-y                          += serial/
 obj-$(CONFIG_PARPORT)          += parport/
 obj-y                          += base/ block/ misc/ mfd/ net/ media/
@@ -53,6 +50,7 @@ obj-$(CONFIG_TC)              += tc/
 obj-$(CONFIG_USB)              += usb/
 obj-$(CONFIG_PCI)              += usb/
 obj-$(CONFIG_USB_GADGET)       += usb/gadget/
+obj-$(CONFIG_SERIO)            += input/serio/
 obj-$(CONFIG_GAMEPORT)         += input/gameport/
 obj-$(CONFIG_INPUT)            += input/
 obj-$(CONFIG_I2O)              += message/
@@ -69,6 +67,7 @@ obj-$(CONFIG_MCA)             += mca/
 obj-$(CONFIG_EISA)             += eisa/
 obj-$(CONFIG_CPU_FREQ)         += cpufreq/
 obj-$(CONFIG_MMC)              += mmc/
+obj-$(CONFIG_NEW_LEDS)         += leds/
 obj-$(CONFIG_INFINIBAND)       += infiniband/
 obj-$(CONFIG_IPATH_CORE)       += infiniband/
 obj-$(CONFIG_SGI_SN)           += sn/
index 79b09d7..eee0864 100644 (file)
@@ -1572,7 +1572,7 @@ static void __exit acpi_ec_exit(void)
 static int __init acpi_fake_ecdt_setup(char *str)
 {
        acpi_fake_ecdt_enabled = 1;
-       return 0;
+       return 1;
 }
 
 __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
@@ -1591,7 +1591,7 @@ static int __init acpi_ec_set_intr_mode(char *str)
                acpi_ec_driver.ops.add = acpi_ec_poll_add;
        }
        printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling");
-       return 0;
+       return 1;
 }
 
 __setup("ec_intr=", acpi_ec_set_intr_mode);
index b6e2909..2a8af68 100644 (file)
@@ -1850,6 +1850,7 @@ static int __init amiga_floppy_setup (char *str)
                return 0;
        printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n);
        fd_def_df0 = n;
+       return 1;
 }
 
 __setup("floppy=", amiga_floppy_setup);
index 9888bc1..473a13b 100644 (file)
@@ -65,7 +65,7 @@ MODULE_LICENSE("GPL");
 
 
 typedef struct bluecard_info_t {
-       dev_link_t link;
+       struct pcmcia_device *p_dev;
        dev_node_t node;
 
        struct hci_dev *hdev;
@@ -85,8 +85,8 @@ typedef struct bluecard_info_t {
 } bluecard_info_t;
 
 
-static void bluecard_config(dev_link_t *link);
-static void bluecard_release(dev_link_t *link);
+static int bluecard_config(struct pcmcia_device *link);
+static void bluecard_release(struct pcmcia_device *link);
 
 static void bluecard_detach(struct pcmcia_device *p_dev);
 
@@ -162,7 +162,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev);
 static void bluecard_activity_led_timeout(u_long arg)
 {
        bluecard_info_t *info = (bluecard_info_t *)arg;
-       unsigned int iobase = info->link.io.BasePort1;
+       unsigned int iobase = info->p_dev->io.BasePort1;
 
        if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
                return;
@@ -179,7 +179,7 @@ static void bluecard_activity_led_timeout(u_long arg)
 
 static void bluecard_enable_activity_led(bluecard_info_t *info)
 {
-       unsigned int iobase = info->link.io.BasePort1;
+       unsigned int iobase = info->p_dev->io.BasePort1;
 
        if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
                return;
@@ -235,7 +235,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
        }
 
        do {
-               register unsigned int iobase = info->link.io.BasePort1;
+               register unsigned int iobase = info->p_dev->io.BasePort1;
                register unsigned int offset;
                register unsigned char command;
                register unsigned long ready_bit;
@@ -244,7 +244,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
 
                clear_bit(XMIT_WAKEUP, &(info->tx_state));
 
-               if (!(info->link.state & DEV_PRESENT))
+               if (!pcmcia_dev_present(info->p_dev))
                        return;
 
                if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) {
@@ -382,7 +382,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
                return;
        }
 
-       iobase = info->link.io.BasePort1;
+       iobase = info->p_dev->io.BasePort1;
 
        if (test_bit(XMIT_SENDING_READY, &(info->tx_state)))
                bluecard_enable_activity_led(info);
@@ -512,7 +512,7 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst, struct pt_regs *r
        if (!test_bit(CARD_READY, &(info->hw_state)))
                return IRQ_HANDLED;
 
-       iobase = info->link.io.BasePort1;
+       iobase = info->p_dev->io.BasePort1;
 
        spin_lock(&(info->lock));
 
@@ -626,7 +626,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
 static int bluecard_hci_open(struct hci_dev *hdev)
 {
        bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
-       unsigned int iobase = info->link.io.BasePort1;
+       unsigned int iobase = info->p_dev->io.BasePort1;
 
        if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
                bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
@@ -646,7 +646,7 @@ static int bluecard_hci_open(struct hci_dev *hdev)
 static int bluecard_hci_close(struct hci_dev *hdev)
 {
        bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
-       unsigned int iobase = info->link.io.BasePort1;
+       unsigned int iobase = info->p_dev->io.BasePort1;
 
        if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
                return 0;
@@ -713,7 +713,7 @@ static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned l
 
 static int bluecard_open(bluecard_info_t *info)
 {
-       unsigned int iobase = info->link.io.BasePort1;
+       unsigned int iobase = info->p_dev->io.BasePort1;
        struct hci_dev *hdev;
        unsigned char id;
 
@@ -831,7 +831,7 @@ static int bluecard_open(bluecard_info_t *info)
 
 static int bluecard_close(bluecard_info_t *info)
 {
-       unsigned int iobase = info->link.io.BasePort1;
+       unsigned int iobase = info->p_dev->io.BasePort1;
        struct hci_dev *hdev = info->hdev;
 
        if (!hdev)
@@ -856,17 +856,16 @@ static int bluecard_close(bluecard_info_t *info)
        return 0;
 }
 
-static int bluecard_attach(struct pcmcia_device *p_dev)
+static int bluecard_probe(struct pcmcia_device *link)
 {
        bluecard_info_t *info;
-       dev_link_t *link;
 
        /* Create new info device */
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
-       link = &info->link;
+       info->p_dev = link;
        link->priv = info;
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -878,32 +877,22 @@ static int bluecard_attach(struct pcmcia_device *p_dev)
        link->irq.Instance = info;
 
        link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.Vcc = 50;
        link->conf.IntType = INT_MEMORY_AND_IO;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       bluecard_config(link);
-
-       return 0;
+       return bluecard_config(link);
 }
 
 
-static void bluecard_detach(struct pcmcia_device *p_dev)
+static void bluecard_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        bluecard_info_t *info = link->priv;
 
-       if (link->state & DEV_CONFIG)
-               bluecard_release(link);
-
+       bluecard_release(link);
        kfree(info);
 }
 
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        int i;
 
@@ -918,14 +907,12 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse
        return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static void bluecard_config(dev_link_t *link)
+static int bluecard_config(struct pcmcia_device *link)
 {
-       client_handle_t handle = link->handle;
        bluecard_info_t *info = link->priv;
        tuple_t tuple;
        u_short buf[256];
        cisparse_t parse;
-       config_info_t config;
        int i, n, last_ret, last_fn;
 
        tuple.TupleData = (cisdata_t *)buf;
@@ -935,7 +922,7 @@ static void bluecard_config(dev_link_t *link)
 
        /* Get configuration register information */
        tuple.DesiredTuple = CISTPL_CONFIG;
-       last_ret = first_tuple(handle, &tuple, &parse);
+       last_ret = first_tuple(link, &tuple, &parse);
        if (last_ret != CS_SUCCESS) {
                last_fn = ParseTuple;
                goto cs_failed;
@@ -943,36 +930,31 @@ static void bluecard_config(dev_link_t *link)
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-       i = pcmcia_get_configuration_info(handle, &config);
-       link->conf.Vcc = config.Vcc;
-
        link->conf.ConfigIndex = 0x20;
        link->io.NumPorts1 = 64;
        link->io.IOAddrLines = 6;
 
        for (n = 0; n < 0x400; n += 0x40) {
                link->io.BasePort1 = n ^ 0x300;
-               i = pcmcia_request_io(link->handle, &link->io);
+               i = pcmcia_request_io(link, &link->io);
                if (i == CS_SUCCESS)
                        break;
        }
 
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestIO, i);
+               cs_error(link, RequestIO, i);
                goto failed;
        }
 
-       i = pcmcia_request_irq(link->handle, &link->irq);
+       i = pcmcia_request_irq(link, &link->irq);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestIRQ, i);
+               cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
 
-       i = pcmcia_request_configuration(link->handle, &link->conf);
+       i = pcmcia_request_configuration(link, &link->conf);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestConfiguration, i);
+               cs_error(link, RequestConfiguration, i);
                goto failed;
        }
 
@@ -980,57 +962,28 @@ static void bluecard_config(dev_link_t *link)
                goto failed;
 
        strcpy(info->node.dev_name, info->hdev->name);
-       link->dev = &info->node;
-       link->state &= ~DEV_CONFIG_PENDING;
+       link->dev_node = &info->node;
 
-       return;
+       return 0;
 
 cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 
 failed:
        bluecard_release(link);
+       return -ENODEV;
 }
 
 
-static void bluecard_release(dev_link_t *link)
+static void bluecard_release(struct pcmcia_device *link)
 {
        bluecard_info_t *info = link->priv;
 
-       if (link->state & DEV_PRESENT)
-               bluecard_close(info);
+       bluecard_close(info);
 
        del_timer(&(info->timer));
 
-       link->dev = NULL;
-
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
-
-       link->state &= ~DEV_CONFIG;
-}
-
-static int bluecard_suspend(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int bluecard_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (DEV_OK(link))
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-       return 0;
+       pcmcia_disable_device(link);
 }
 
 static struct pcmcia_device_id bluecard_ids[] = {
@@ -1046,11 +999,9 @@ static struct pcmcia_driver bluecard_driver = {
        .drv            = {
                .name   = "bluecard_cs",
        },
-       .probe          = bluecard_attach,
+       .probe          = bluecard_probe,
        .remove         = bluecard_detach,
        .id_table       = bluecard_ids,
-       .suspend        = bluecard_suspend,
-       .resume         = bluecard_resume,
 };
 
 static int __init init_bluecard_cs(void)
index 7e21b1f..b94ac2f 100644 (file)
@@ -72,7 +72,7 @@ MODULE_LICENSE("GPL");
 
 
 typedef struct bt3c_info_t {
-       dev_link_t link;
+       struct pcmcia_device *p_dev;
        dev_node_t node;
 
        struct hci_dev *hdev;
@@ -88,8 +88,8 @@ typedef struct bt3c_info_t {
 } bt3c_info_t;
 
 
-static void bt3c_config(dev_link_t *link);
-static void bt3c_release(dev_link_t *link);
+static int bt3c_config(struct pcmcia_device *link);
+static void bt3c_release(struct pcmcia_device *link);
 
 static void bt3c_detach(struct pcmcia_device *p_dev);
 
@@ -191,11 +191,11 @@ static void bt3c_write_wakeup(bt3c_info_t *info)
                return;
 
        do {
-               register unsigned int iobase = info->link.io.BasePort1;
+               register unsigned int iobase = info->p_dev->io.BasePort1;
                register struct sk_buff *skb;
                register int len;
 
-               if (!(info->link.state & DEV_PRESENT))
+               if (!pcmcia_dev_present(info->p_dev))
                        break;
 
 
@@ -229,7 +229,7 @@ static void bt3c_receive(bt3c_info_t *info)
                return;
        }
 
-       iobase = info->link.io.BasePort1;
+       iobase = info->p_dev->io.BasePort1;
 
        avail = bt3c_read(iobase, 0x7006);
        //printk("bt3c_cs: receiving %d bytes\n", avail);
@@ -350,7 +350,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
                return IRQ_NONE;
        }
 
-       iobase = info->link.io.BasePort1;
+       iobase = info->p_dev->io.BasePort1;
 
        spin_lock(&(info->lock));
 
@@ -481,7 +481,7 @@ static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int co
        unsigned int iobase, size, addr, fcs, tmp;
        int i, err = 0;
 
-       iobase = info->link.io.BasePort1;
+       iobase = info->p_dev->io.BasePort1;
 
        /* Reset */
        bt3c_io_write(iobase, 0x8040, 0x0404);
@@ -562,7 +562,6 @@ static int bt3c_open(bt3c_info_t *info)
 {
        const struct firmware *firmware;
        struct hci_dev *hdev;
-       client_handle_t handle;
        int err;
 
        spin_lock_init(&(info->lock));
@@ -594,10 +593,8 @@ static int bt3c_open(bt3c_info_t *info)
 
        hdev->owner = THIS_MODULE;
 
-       handle = info->link.handle;
-
        /* Load firmware */
-       err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle));
+       err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
        if (err < 0) {
                BT_ERR("Firmware request failed");
                goto error;
@@ -648,17 +645,16 @@ static int bt3c_close(bt3c_info_t *info)
        return 0;
 }
 
-static int bt3c_attach(struct pcmcia_device *p_dev)
+static int bt3c_probe(struct pcmcia_device *link)
 {
        bt3c_info_t *info;
-       dev_link_t *link;
 
        /* Create new info device */
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
-       link = &info->link;
+       info->p_dev = link;
        link->priv = info;
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -670,31 +666,21 @@ static int bt3c_attach(struct pcmcia_device *p_dev)
        link->irq.Instance = info;
 
        link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.Vcc = 50;
        link->conf.IntType = INT_MEMORY_AND_IO;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       bt3c_config(link);
-
-       return 0;
+       return bt3c_config(link);
 }
 
 
-static void bt3c_detach(struct pcmcia_device *p_dev)
+static void bt3c_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        bt3c_info_t *info = link->priv;
 
-       if (link->state & DEV_CONFIG)
-               bt3c_release(link);
-
+       bt3c_release(link);
        kfree(info);
 }
 
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        int i;
 
@@ -705,30 +691,28 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
        return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
                return CS_NO_MORE_ITEMS;
        return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
                return CS_NO_MORE_ITEMS;
        return get_tuple(handle, tuple, parse);
 }
 
-static void bt3c_config(dev_link_t *link)
+static int bt3c_config(struct pcmcia_device *link)
 {
        static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
-       client_handle_t handle = link->handle;
        bt3c_info_t *info = link->priv;
        tuple_t tuple;
        u_short buf[256];
        cisparse_t parse;
        cistpl_cftable_entry_t *cf = &parse.cftable_entry;
-       config_info_t config;
        int i, j, try, last_ret, last_fn;
 
        tuple.TupleData = (cisdata_t *)buf;
@@ -738,7 +722,7 @@ static void bt3c_config(dev_link_t *link)
 
        /* Get configuration register information */
        tuple.DesiredTuple = CISTPL_CONFIG;
-       last_ret = first_tuple(handle, &tuple, &parse);
+       last_ret = first_tuple(link, &tuple, &parse);
        if (last_ret != CS_SUCCESS) {
                last_fn = ParseTuple;
                goto cs_failed;
@@ -746,11 +730,6 @@ static void bt3c_config(dev_link_t *link)
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-       i = pcmcia_get_configuration_info(handle, &config);
-       link->conf.Vcc = config.Vcc;
-
        /* First pass: look for a config entry that looks normal. */
        tuple.TupleData = (cisdata_t *)buf;
        tuple.TupleOffset = 0;
@@ -759,59 +738,59 @@ static void bt3c_config(dev_link_t *link)
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
        /* Two tries: without IO aliases, then with aliases */
        for (try = 0; try < 2; try++) {
-               i = first_tuple(handle, &tuple, &parse);
+               i = first_tuple(link, &tuple, &parse);
                while (i != CS_NO_MORE_ITEMS) {
                        if (i != CS_SUCCESS)
                                goto next_entry;
                        if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                               link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+                               link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
                        if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
                                link->conf.ConfigIndex = cf->index;
                                link->io.BasePort1 = cf->io.win[0].base;
                                link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
-                               i = pcmcia_request_io(link->handle, &link->io);
+                               i = pcmcia_request_io(link, &link->io);
                                if (i == CS_SUCCESS)
                                        goto found_port;
                        }
 next_entry:
-                       i = next_tuple(handle, &tuple, &parse);
+                       i = next_tuple(link, &tuple, &parse);
                }
        }
 
        /* Second pass: try to find an entry that isn't picky about
           its base address, then try to grab any standard serial port
           address, and finally try to get any free port. */
-       i = first_tuple(handle, &tuple, &parse);
+       i = first_tuple(link, &tuple, &parse);
        while (i != CS_NO_MORE_ITEMS) {
                if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
                        link->conf.ConfigIndex = cf->index;
                        for (j = 0; j < 5; j++) {
                                link->io.BasePort1 = base[j];
                                link->io.IOAddrLines = base[j] ? 16 : 3;
-                               i = pcmcia_request_io(link->handle, &link->io);
+                               i = pcmcia_request_io(link, &link->io);
                                if (i == CS_SUCCESS)
                                        goto found_port;
                        }
                }
-               i = next_tuple(handle, &tuple, &parse);
+               i = next_tuple(link, &tuple, &parse);
        }
 
 found_port:
        if (i != CS_SUCCESS) {
                BT_ERR("No usable port range found");
-               cs_error(link->handle, RequestIO, i);
+               cs_error(link, RequestIO, i);
                goto failed;
        }
 
-       i = pcmcia_request_irq(link->handle, &link->irq);
+       i = pcmcia_request_irq(link, &link->irq);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestIRQ, i);
+               cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
 
-       i = pcmcia_request_configuration(link->handle, &link->conf);
+       i = pcmcia_request_configuration(link, &link->conf);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestConfiguration, i);
+               cs_error(link, RequestConfiguration, i);
                goto failed;
        }
 
@@ -819,55 +798,26 @@ found_port:
                goto failed;
 
        strcpy(info->node.dev_name, info->hdev->name);
-       link->dev = &info->node;
-       link->state &= ~DEV_CONFIG_PENDING;
+       link->dev_node = &info->node;
 
-       return;
+       return 0;
 
 cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 
 failed:
        bt3c_release(link);
+       return -ENODEV;
 }
 
 
-static void bt3c_release(dev_link_t *link)
+static void bt3c_release(struct pcmcia_device *link)
 {
        bt3c_info_t *info = link->priv;
 
-       if (link->state & DEV_PRESENT)
-               bt3c_close(info);
-
-       link->dev = NULL;
-
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
-
-       link->state &= ~DEV_CONFIG;
-}
-
-static int bt3c_suspend(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
+       bt3c_close(info);
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int bt3c_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (DEV_OK(link))
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-       return 0;
+       pcmcia_disable_device(link);
 }
 
 
@@ -882,11 +832,9 @@ static struct pcmcia_driver bt3c_driver = {
        .drv            = {
                .name   = "bt3c_cs",
        },
-       .probe          = bt3c_attach,
+       .probe          = bt3c_probe,
        .remove         = bt3c_detach,
        .id_table       = bt3c_ids,
-       .suspend        = bt3c_suspend,
-       .resume         = bt3c_resume,
 };
 
 static int __init init_bt3c_cs(void)
index 7b4bff4..9ce4c93 100644 (file)
@@ -68,7 +68,7 @@ MODULE_LICENSE("GPL");
 
 
 typedef struct btuart_info_t {
-       dev_link_t link;
+       struct pcmcia_device *p_dev;
        dev_node_t node;
 
        struct hci_dev *hdev;
@@ -84,8 +84,8 @@ typedef struct btuart_info_t {
 } btuart_info_t;
 
 
-static void btuart_config(dev_link_t *link);
-static void btuart_release(dev_link_t *link);
+static int btuart_config(struct pcmcia_device *link);
+static void btuart_release(struct pcmcia_device *link);
 
 static void btuart_detach(struct pcmcia_device *p_dev);
 
@@ -146,13 +146,13 @@ static void btuart_write_wakeup(btuart_info_t *info)
        }
 
        do {
-               register unsigned int iobase = info->link.io.BasePort1;
+               register unsigned int iobase = info->p_dev->io.BasePort1;
                register struct sk_buff *skb;
                register int len;
 
                clear_bit(XMIT_WAKEUP, &(info->tx_state));
 
-               if (!(info->link.state & DEV_PRESENT))
+               if (!pcmcia_dev_present(info->p_dev))
                        return;
 
                if (!(skb = skb_dequeue(&(info->txq))))
@@ -187,7 +187,7 @@ static void btuart_receive(btuart_info_t *info)
                return;
        }
 
-       iobase = info->link.io.BasePort1;
+       iobase = info->p_dev->io.BasePort1;
 
        do {
                info->hdev->stat.byte_rx++;
@@ -301,7 +301,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst, struct pt_regs *reg
                return IRQ_NONE;
        }
 
-       iobase = info->link.io.BasePort1;
+       iobase = info->p_dev->io.BasePort1;
 
        spin_lock(&(info->lock));
 
@@ -357,7 +357,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
                return;
        }
 
-       iobase = info->link.io.BasePort1;
+       iobase = info->p_dev->io.BasePort1;
 
        spin_lock_irqsave(&(info->lock), flags);
 
@@ -481,7 +481,7 @@ static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned lon
 static int btuart_open(btuart_info_t *info)
 {
        unsigned long flags;
-       unsigned int iobase = info->link.io.BasePort1;
+       unsigned int iobase = info->p_dev->io.BasePort1;
        struct hci_dev *hdev;
 
        spin_lock_init(&(info->lock));
@@ -550,7 +550,7 @@ static int btuart_open(btuart_info_t *info)
 static int btuart_close(btuart_info_t *info)
 {
        unsigned long flags;
-       unsigned int iobase = info->link.io.BasePort1;
+       unsigned int iobase = info->p_dev->io.BasePort1;
        struct hci_dev *hdev = info->hdev;
 
        if (!hdev)
@@ -576,17 +576,16 @@ static int btuart_close(btuart_info_t *info)
        return 0;
 }
 
-static int btuart_attach(struct pcmcia_device *p_dev)
+static int btuart_probe(struct pcmcia_device *link)
 {
        btuart_info_t *info;
-       dev_link_t *link;
 
        /* Create new info device */
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
-       link = &info->link;
+       info->p_dev = link;
        link->priv = info;
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -598,31 +597,21 @@ static int btuart_attach(struct pcmcia_device *p_dev)
        link->irq.Instance = info;
 
        link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.Vcc = 50;
        link->conf.IntType = INT_MEMORY_AND_IO;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       btuart_config(link);
-
-       return 0;
+       return btuart_config(link);
 }
 
 
-static void btuart_detach(struct pcmcia_device *p_dev)
+static void btuart_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        btuart_info_t *info = link->priv;
 
-       if (link->state & DEV_CONFIG)
-               btuart_release(link);
-
+       btuart_release(link);
        kfree(info);
 }
 
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        int i;
 
@@ -633,30 +622,28 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
        return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
                return CS_NO_MORE_ITEMS;
        return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
                return CS_NO_MORE_ITEMS;
        return get_tuple(handle, tuple, parse);
 }
 
-static void btuart_config(dev_link_t *link)
+static int btuart_config(struct pcmcia_device *link)
 {
        static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
-       client_handle_t handle = link->handle;
        btuart_info_t *info = link->priv;
        tuple_t tuple;
        u_short buf[256];
        cisparse_t parse;
        cistpl_cftable_entry_t *cf = &parse.cftable_entry;
-       config_info_t config;
        int i, j, try, last_ret, last_fn;
 
        tuple.TupleData = (cisdata_t *)buf;
@@ -666,7 +653,7 @@ static void btuart_config(dev_link_t *link)
 
        /* Get configuration register information */
        tuple.DesiredTuple = CISTPL_CONFIG;
-       last_ret = first_tuple(handle, &tuple, &parse);
+       last_ret = first_tuple(link, &tuple, &parse);
        if (last_ret != CS_SUCCESS) {
                last_fn = ParseTuple;
                goto cs_failed;
@@ -674,11 +661,6 @@ static void btuart_config(dev_link_t *link)
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-       i = pcmcia_get_configuration_info(handle, &config);
-       link->conf.Vcc = config.Vcc;
-
        /* First pass: look for a config entry that looks normal. */
        tuple.TupleData = (cisdata_t *) buf;
        tuple.TupleOffset = 0;
@@ -687,29 +669,29 @@ static void btuart_config(dev_link_t *link)
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
        /* Two tries: without IO aliases, then with aliases */
        for (try = 0; try < 2; try++) {
-               i = first_tuple(handle, &tuple, &parse);
+               i = first_tuple(link, &tuple, &parse);
                while (i != CS_NO_MORE_ITEMS) {
                        if (i != CS_SUCCESS)
                                goto next_entry;
                        if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                               link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+                               link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
                        if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
                                link->conf.ConfigIndex = cf->index;
                                link->io.BasePort1 = cf->io.win[0].base;
                                link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
-                               i = pcmcia_request_io(link->handle, &link->io);
+                               i = pcmcia_request_io(link, &link->io);
                                if (i == CS_SUCCESS)
                                        goto found_port;
                        }
 next_entry:
-                       i = next_tuple(handle, &tuple, &parse);
+                       i = next_tuple(link, &tuple, &parse);
                }
        }
 
        /* Second pass: try to find an entry that isn't picky about
           its base address, then try to grab any standard serial port
           address, and finally try to get any free port. */
-       i = first_tuple(handle, &tuple, &parse);
+       i = first_tuple(link, &tuple, &parse);
        while (i != CS_NO_MORE_ITEMS) {
                if ((i == CS_SUCCESS) && (cf->io.nwin > 0)
                    && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
@@ -717,30 +699,30 @@ next_entry:
                        for (j = 0; j < 5; j++) {
                                link->io.BasePort1 = base[j];
                                link->io.IOAddrLines = base[j] ? 16 : 3;
-                               i = pcmcia_request_io(link->handle, &link->io);
+                               i = pcmcia_request_io(link, &link->io);
                                if (i == CS_SUCCESS)
                                        goto found_port;
                        }
                }
-               i = next_tuple(handle, &tuple, &parse);
+               i = next_tuple(link, &tuple, &parse);
        }
 
 found_port:
        if (i != CS_SUCCESS) {
                BT_ERR("No usable port range found");
-               cs_error(link->handle, RequestIO, i);
+               cs_error(link, RequestIO, i);
                goto failed;
        }
 
-       i = pcmcia_request_irq(link->handle, &link->irq);
+       i = pcmcia_request_irq(link, &link->irq);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestIRQ, i);
+               cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
 
-       i = pcmcia_request_configuration(link->handle, &link->conf);
+       i = pcmcia_request_configuration(link, &link->conf);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestConfiguration, i);
+               cs_error(link, RequestConfiguration, i);
                goto failed;
        }
 
@@ -748,58 +730,28 @@ found_port:
                goto failed;
 
        strcpy(info->node.dev_name, info->hdev->name);
-       link->dev = &info->node;
-       link->state &= ~DEV_CONFIG_PENDING;
+       link->dev_node = &info->node;
 
-       return;
+       return 0;
 
 cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 
 failed:
        btuart_release(link);
+       return -ENODEV;
 }
 
 
-static void btuart_release(dev_link_t *link)
+static void btuart_release(struct pcmcia_device *link)
 {
        btuart_info_t *info = link->priv;
 
-       if (link->state & DEV_PRESENT)
-               btuart_close(info);
-
-       link->dev = NULL;
-
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
-
-       link->state &= ~DEV_CONFIG;
-}
-
-static int btuart_suspend(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
+       btuart_close(info);
 
-       return 0;
+       pcmcia_disable_device(link);
 }
 
-static int btuart_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (DEV_OK(link))
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-       return 0;
-}
-
-
 static struct pcmcia_device_id btuart_ids[] = {
        /* don't use this driver. Use serial_cs + hci_uart instead */
        PCMCIA_DEVICE_NULL
@@ -811,11 +763,9 @@ static struct pcmcia_driver btuart_driver = {
        .drv            = {
                .name   = "btuart_cs",
        },
-       .probe          = btuart_attach,
+       .probe          = btuart_probe,
        .remove         = btuart_detach,
        .id_table       = btuart_ids,
-       .suspend        = btuart_suspend,
-       .resume         = btuart_resume,
 };
 
 static int __init init_btuart_cs(void)
index 0449bc4..a71a240 100644 (file)
@@ -68,7 +68,7 @@ MODULE_LICENSE("GPL");
 
 
 typedef struct dtl1_info_t {
-       dev_link_t link;
+       struct pcmcia_device *p_dev;
        dev_node_t node;
 
        struct hci_dev *hdev;
@@ -87,8 +87,8 @@ typedef struct dtl1_info_t {
 } dtl1_info_t;
 
 
-static void dtl1_config(dev_link_t *link);
-static void dtl1_release(dev_link_t *link);
+static int dtl1_config(struct pcmcia_device *link);
+static void dtl1_release(struct pcmcia_device *link);
 
 static void dtl1_detach(struct pcmcia_device *p_dev);
 
@@ -153,13 +153,13 @@ static void dtl1_write_wakeup(dtl1_info_t *info)
        }
 
        do {
-               register unsigned int iobase = info->link.io.BasePort1;
+               register unsigned int iobase = info->p_dev->io.BasePort1;
                register struct sk_buff *skb;
                register int len;
 
                clear_bit(XMIT_WAKEUP, &(info->tx_state));
 
-               if (!(info->link.state & DEV_PRESENT))
+               if (!pcmcia_dev_present(info->p_dev))
                        return;
 
                if (!(skb = skb_dequeue(&(info->txq))))
@@ -218,7 +218,7 @@ static void dtl1_receive(dtl1_info_t *info)
                return;
        }
 
-       iobase = info->link.io.BasePort1;
+       iobase = info->p_dev->io.BasePort1;
 
        do {
                info->hdev->stat.byte_rx++;
@@ -305,7 +305,7 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
                return IRQ_NONE;
        }
 
-       iobase = info->link.io.BasePort1;
+       iobase = info->p_dev->io.BasePort1;
 
        spin_lock(&(info->lock));
 
@@ -458,7 +458,7 @@ static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,  unsigned long
 static int dtl1_open(dtl1_info_t *info)
 {
        unsigned long flags;
-       unsigned int iobase = info->link.io.BasePort1;
+       unsigned int iobase = info->p_dev->io.BasePort1;
        struct hci_dev *hdev;
 
        spin_lock_init(&(info->lock));
@@ -504,7 +504,7 @@ static int dtl1_open(dtl1_info_t *info)
        outb(UART_LCR_WLEN8, iobase + UART_LCR);        /* Reset DLAB */
        outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
 
-       info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI;
+       info->ri_latch = inb(info->p_dev->io.BasePort1 + UART_MSR) & UART_MSR_RI;
 
        /* Turn on interrupts */
        outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
@@ -529,7 +529,7 @@ static int dtl1_open(dtl1_info_t *info)
 static int dtl1_close(dtl1_info_t *info)
 {
        unsigned long flags;
-       unsigned int iobase = info->link.io.BasePort1;
+       unsigned int iobase = info->p_dev->io.BasePort1;
        struct hci_dev *hdev = info->hdev;
 
        if (!hdev)
@@ -555,17 +555,16 @@ static int dtl1_close(dtl1_info_t *info)
        return 0;
 }
 
-static int dtl1_attach(struct pcmcia_device *p_dev)
+static int dtl1_probe(struct pcmcia_device *link)
 {
        dtl1_info_t *info;
-       dev_link_t *link;
 
        /* Create new info device */
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
-       link = &info->link;
+       info->p_dev = link;
        link->priv = info;
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -577,31 +576,22 @@ static int dtl1_attach(struct pcmcia_device *p_dev)
        link->irq.Instance = info;
 
        link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.Vcc = 50;
        link->conf.IntType = INT_MEMORY_AND_IO;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       dtl1_config(link);
-
-       return 0;
+       return dtl1_config(link);
 }
 
 
-static void dtl1_detach(struct pcmcia_device *p_dev)
+static void dtl1_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        dtl1_info_t *info = link->priv;
 
-       if (link->state & DEV_CONFIG)
-               dtl1_release(link);
+       dtl1_release(link);
 
        kfree(info);
 }
 
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        int i;
 
@@ -612,29 +602,27 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
        return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
                return CS_NO_MORE_ITEMS;
        return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
                return CS_NO_MORE_ITEMS;
        return get_tuple(handle, tuple, parse);
 }
 
-static void dtl1_config(dev_link_t *link)
+static int dtl1_config(struct pcmcia_device *link)
 {
-       client_handle_t handle = link->handle;
        dtl1_info_t *info = link->priv;
        tuple_t tuple;
        u_short buf[256];
        cisparse_t parse;
        cistpl_cftable_entry_t *cf = &parse.cftable_entry;
-       config_info_t config;
        int i, last_ret, last_fn;
 
        tuple.TupleData = (cisdata_t *)buf;
@@ -644,7 +632,7 @@ static void dtl1_config(dev_link_t *link)
 
        /* Get configuration register information */
        tuple.DesiredTuple = CISTPL_CONFIG;
-       last_ret = first_tuple(handle, &tuple, &parse);
+       last_ret = first_tuple(link, &tuple, &parse);
        if (last_ret != CS_SUCCESS) {
                last_fn = ParseTuple;
                goto cs_failed;
@@ -652,11 +640,6 @@ static void dtl1_config(dev_link_t *link)
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-       i = pcmcia_get_configuration_info(handle, &config);
-       link->conf.Vcc = config.Vcc;
-
        tuple.TupleData = (cisdata_t *)buf;
        tuple.TupleOffset = 0;
        tuple.TupleDataMax = 255;
@@ -665,34 +648,34 @@ static void dtl1_config(dev_link_t *link)
 
        /* Look for a generic full-sized window */
        link->io.NumPorts1 = 8;
-       i = first_tuple(handle, &tuple, &parse);
+       i = first_tuple(link, &tuple, &parse);
        while (i != CS_NO_MORE_ITEMS) {
                if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
                        link->conf.ConfigIndex = cf->index;
                        link->io.BasePort1 = cf->io.win[0].base;
                        link->io.NumPorts1 = cf->io.win[0].len; /*yo */
                        link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-                       i = pcmcia_request_io(link->handle, &link->io);
+                       i = pcmcia_request_io(link, &link->io);
                        if (i == CS_SUCCESS)
                                break;
                }
-               i = next_tuple(handle, &tuple, &parse);
+               i = next_tuple(link, &tuple, &parse);
        }
 
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestIO, i);
+               cs_error(link, RequestIO, i);
                goto failed;
        }
 
-       i = pcmcia_request_irq(link->handle, &link->irq);
+       i = pcmcia_request_irq(link, &link->irq);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestIRQ, i);
+               cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
 
-       i = pcmcia_request_configuration(link->handle, &link->conf);
+       i = pcmcia_request_configuration(link, &link->conf);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestConfiguration, i);
+               cs_error(link, RequestConfiguration, i);
                goto failed;
        }
 
@@ -700,55 +683,26 @@ static void dtl1_config(dev_link_t *link)
                goto failed;
 
        strcpy(info->node.dev_name, info->hdev->name);
-       link->dev = &info->node;
-       link->state &= ~DEV_CONFIG_PENDING;
+       link->dev_node = &info->node;
 
-       return;
+       return 0;
 
 cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 
 failed:
        dtl1_release(link);
+       return -ENODEV;
 }
 
 
-static void dtl1_release(dev_link_t *link)
+static void dtl1_release(struct pcmcia_device *link)
 {
        dtl1_info_t *info = link->priv;
 
-       if (link->state & DEV_PRESENT)
-               dtl1_close(info);
-
-       link->dev = NULL;
-
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
-
-       link->state &= ~DEV_CONFIG;
-}
-
-static int dtl1_suspend(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int dtl1_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
+       dtl1_close(info);
 
-       link->state &= ~DEV_SUSPEND;
-       if (DEV_OK(link))
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-       return 0;
+       pcmcia_disable_device(link);
 }
 
 
@@ -765,11 +719,9 @@ static struct pcmcia_driver dtl1_driver = {
        .drv            = {
                .name   = "dtl1_cs",
        },
-       .probe          = dtl1_attach,
+       .probe          = dtl1_probe,
        .remove         = dtl1_detach,
        .id_table       = dtl1_ids,
-       .suspend        = dtl1_suspend,
-       .resume         = dtl1_resume,
 };
 
 static int __init init_dtl1_cs(void)
index 327b00c..8d97b39 100644 (file)
@@ -904,7 +904,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
                 * It is possible the vty-server was removed after the irq was
                 * requested but before we have time to enable interrupts.
                 */
-               if (vio_enable_interrupts(vdev) == H_Success)
+               if (vio_enable_interrupts(vdev) == H_SUCCESS)
                        return 0;
                else {
                        printk(KERN_ERR "HVCS: int enable failed for"
index 932feed..e1c9537 100644 (file)
@@ -42,7 +42,7 @@
 #include <linux/slab.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/ipmi.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/compat.h>
@@ -55,7 +55,7 @@ struct ipmi_file_private
        struct file          *file;
        struct fasync_struct *fasync_queue;
        wait_queue_head_t    wait;
-       struct semaphore     recv_sem;
+       struct mutex         recv_mutex;
        int                  default_retries;
        unsigned int         default_retry_time_ms;
 };
@@ -141,7 +141,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
        INIT_LIST_HEAD(&(priv->recv_msgs));
        init_waitqueue_head(&priv->wait);
        priv->fasync_queue = NULL;
-       sema_init(&(priv->recv_sem), 1);
+       mutex_init(&priv->recv_mutex);
 
        /* Use the low-level defaults. */
        priv->default_retries = -1;
@@ -285,15 +285,15 @@ static int ipmi_ioctl(struct inode  *inode,
                        break;
                }
 
-               /* We claim a semaphore because we don't want two
+               /* We claim a mutex because we don't want two
                    users getting something from the queue at a time.
                    Since we have to release the spinlock before we can
                    copy the data to the user, it's possible another
                    user will grab something from the queue, too.  Then
                    the messages might get out of order if something
                    fails and the message gets put back onto the
-                   queue.  This semaphore prevents that problem. */
-               down(&(priv->recv_sem));
+                   queue.  This mutex prevents that problem. */
+               mutex_lock(&priv->recv_mutex);
 
                /* Grab the message off the list. */
                spin_lock_irqsave(&(priv->recv_msg_lock), flags);
@@ -352,7 +352,7 @@ static int ipmi_ioctl(struct inode  *inode,
                        goto recv_putback_on_err;
                }
 
-               up(&(priv->recv_sem));
+               mutex_unlock(&priv->recv_mutex);
                ipmi_free_recv_msg(msg);
                break;
 
@@ -362,11 +362,11 @@ static int ipmi_ioctl(struct inode  *inode,
                spin_lock_irqsave(&(priv->recv_msg_lock), flags);
                list_add(entry, &(priv->recv_msgs));
                spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
-               up(&(priv->recv_sem));
+               mutex_unlock(&priv->recv_mutex);
                break;
 
        recv_err:
-               up(&(priv->recv_sem));
+               mutex_unlock(&priv->recv_mutex);
                break;
        }
 
index da15541..2062675 100644 (file)
@@ -227,7 +227,7 @@ static inline int check_ibf(struct si_sm_data *kcs, unsigned char status,
 static inline int check_obf(struct si_sm_data *kcs, unsigned char status,
                            long time)
 {
-       if (! GET_STATUS_OBF(status)) {
+       if (!GET_STATUS_OBF(status)) {
                kcs->obf_timeout -= time;
                if (kcs->obf_timeout < 0) {
                    start_error_recovery(kcs, "OBF not ready in time");
@@ -407,7 +407,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                }
 
                if (state == KCS_READ_STATE) {
-                       if (! check_obf(kcs, status, time))
+                       if (!check_obf(kcs, status, time))
                                return SI_SM_CALL_WITH_DELAY;
                        read_next_byte(kcs);
                } else {
@@ -447,7 +447,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                                             "Not in read state for error2");
                        break;
                }
-               if (! check_obf(kcs, status, time))
+               if (!check_obf(kcs, status, time))
                        return SI_SM_CALL_WITH_DELAY;
 
                clear_obf(kcs, status);
@@ -462,7 +462,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                        break;
                }
 
-               if (! check_obf(kcs, status, time))
+               if (!check_obf(kcs, status, time))
                        return SI_SM_CALL_WITH_DELAY;
 
                clear_obf(kcs, status);
index 40eb005..0ded046 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/ipmi.h>
 #include <linux/ipmi_smi.h>
@@ -234,7 +235,7 @@ struct ipmi_smi
 
        /* The list of command receivers that are registered for commands
           on this interface. */
-       struct semaphore cmd_rcvrs_lock;
+       struct mutex     cmd_rcvrs_mutex;
        struct list_head cmd_rcvrs;
 
        /* Events that were queues because no one was there to receive
@@ -387,10 +388,10 @@ static void clean_up_interface_data(ipmi_smi_t intf)
 
        /* Wholesale remove all the entries from the list in the
         * interface and wait for RCU to know that none are in use. */
-       down(&intf->cmd_rcvrs_lock);
+       mutex_lock(&intf->cmd_rcvrs_mutex);
        list_add_rcu(&list, &intf->cmd_rcvrs);
        list_del_rcu(&intf->cmd_rcvrs);
-       up(&intf->cmd_rcvrs_lock);
+       mutex_unlock(&intf->cmd_rcvrs_mutex);
        synchronize_rcu();
 
        list_for_each_entry_safe(rcvr, rcvr2, &list, link)
@@ -557,7 +558,7 @@ unsigned int ipmi_addr_length(int addr_type)
 
 static void deliver_response(struct ipmi_recv_msg *msg)
 {
-       if (! msg->user) {
+       if (!msg->user) {
                ipmi_smi_t    intf = msg->user_msg_data;
                unsigned long flags;
 
@@ -598,11 +599,11 @@ static int intf_next_seq(ipmi_smi_t           intf,
             (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
             i = (i+1)%IPMI_IPMB_NUM_SEQ)
        {
-               if (! intf->seq_table[i].inuse)
+               if (!intf->seq_table[i].inuse)
                        break;
        }
 
-       if (! intf->seq_table[i].inuse) {
+       if (!intf->seq_table[i].inuse) {
                intf->seq_table[i].recv_msg = recv_msg;
 
                /* Start with the maximum timeout, when the send response
@@ -763,7 +764,7 @@ int ipmi_create_user(unsigned int          if_num,
        }
 
        new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
-       if (! new_user)
+       if (!new_user)
                return -ENOMEM;
 
        spin_lock_irqsave(&interfaces_lock, flags);
@@ -819,14 +820,13 @@ static void free_user(struct kref *ref)
 
 int ipmi_destroy_user(ipmi_user_t user)
 {
-       int              rv = -ENODEV;
        ipmi_smi_t       intf = user->intf;
        int              i;
        unsigned long    flags;
        struct cmd_rcvr  *rcvr;
        struct cmd_rcvr  *rcvrs = NULL;
 
-       user->valid = 1;
+       user->valid = 0;
 
        /* Remove the user from the interface's sequence table. */
        spin_lock_irqsave(&intf->seq_lock, flags);
@@ -847,7 +847,7 @@ int ipmi_destroy_user(ipmi_user_t user)
         * since other things may be using it till we do
         * synchronize_rcu()) then free everything in that list.
         */
-       down(&intf->cmd_rcvrs_lock);
+       mutex_lock(&intf->cmd_rcvrs_mutex);
        list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
                if (rcvr->user == user) {
                        list_del_rcu(&rcvr->link);
@@ -855,7 +855,7 @@ int ipmi_destroy_user(ipmi_user_t user)
                        rcvrs = rcvr;
                }
        }
-       up(&intf->cmd_rcvrs_lock);
+       mutex_unlock(&intf->cmd_rcvrs_mutex);
        synchronize_rcu();
        while (rcvrs) {
                rcvr = rcvrs;
@@ -871,7 +871,7 @@ int ipmi_destroy_user(ipmi_user_t user)
 
        kref_put(&user->refcount, free_user);
 
-       return rv;
+       return 0;
 }
 
 void ipmi_get_version(ipmi_user_t   user,
@@ -936,7 +936,8 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
 
        if (val) {
                /* Deliver any queued events. */
-               list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) {
+               list_for_each_entry_safe(msg, msg2, &intf->waiting_events,
+                                        link) {
                        list_del(&msg->link);
                        list_add_tail(&msg->link, &msgs);
                }
@@ -978,13 +979,13 @@ int ipmi_register_for_cmd(ipmi_user_t   user,
 
 
        rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL);
-       if (! rcvr)
+       if (!rcvr)
                return -ENOMEM;
        rcvr->cmd = cmd;
        rcvr->netfn = netfn;
        rcvr->user = user;
 
-       down(&intf->cmd_rcvrs_lock);
+       mutex_lock(&intf->cmd_rcvrs_mutex);
        /* Make sure the command/netfn is not already registered. */
        entry = find_cmd_rcvr(intf, netfn, cmd);
        if (entry) {
@@ -995,7 +996,7 @@ int ipmi_register_for_cmd(ipmi_user_t   user,
        list_add_rcu(&rcvr->link, &intf->cmd_rcvrs);
 
  out_unlock:
-       up(&intf->cmd_rcvrs_lock);
+       mutex_unlock(&intf->cmd_rcvrs_mutex);
        if (rv)
                kfree(rcvr);
 
@@ -1009,17 +1010,17 @@ int ipmi_unregister_for_cmd(ipmi_user_t   user,
        ipmi_smi_t      intf = user->intf;
        struct cmd_rcvr *rcvr;
 
-       down(&intf->cmd_rcvrs_lock);
+       mutex_lock(&intf->cmd_rcvrs_mutex);
        /* Make sure the command/netfn is not already registered. */
        rcvr = find_cmd_rcvr(intf, netfn, cmd);
        if ((rcvr) && (rcvr->user == user)) {
                list_del_rcu(&rcvr->link);
-               up(&intf->cmd_rcvrs_lock);
+               mutex_unlock(&intf->cmd_rcvrs_mutex);
                synchronize_rcu();
                kfree(rcvr);
                return 0;
        } else {
-               up(&intf->cmd_rcvrs_lock);
+               mutex_unlock(&intf->cmd_rcvrs_mutex);
                return -ENOENT;
        }
 }
@@ -1514,7 +1515,7 @@ int ipmi_request_settime(ipmi_user_t      user,
        unsigned char saddr, lun;
        int           rv;
 
-       if (! user)
+       if (!user)
                return -EINVAL;
        rv = check_addr(user->intf, addr, &saddr, &lun);
        if (rv)
@@ -1545,7 +1546,7 @@ int ipmi_request_supply_msgs(ipmi_user_t          user,
        unsigned char saddr, lun;
        int           rv;
 
-       if (! user)
+       if (!user)
                return -EINVAL;
        rv = check_addr(user->intf, addr, &saddr, &lun);
        if (rv)
@@ -1570,7 +1571,7 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off,
        char       *out = (char *) page;
        ipmi_smi_t intf = data;
        int        i;
-       int        rv= 0;
+       int        rv = 0;
 
        for (i = 0; i < IPMI_MAX_CHANNELS; i++)
                rv += sprintf(out+rv, "%x ", intf->channels[i].address);
@@ -1989,7 +1990,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf)
        } else {
                bmc->dev = platform_device_alloc("ipmi_bmc",
                                                 bmc->id.device_id);
-               if (! bmc->dev) {
+               if (!bmc->dev) {
                        printk(KERN_ERR
                               "ipmi_msghandler:"
                               " Unable to allocate platform device\n");
@@ -2305,8 +2306,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
                      void                     *send_info,
                      struct ipmi_device_id    *device_id,
                      struct device            *si_dev,
-                     unsigned char            slave_addr,
-                     ipmi_smi_t               *new_intf)
+                     unsigned char            slave_addr)
 {
        int              i, j;
        int              rv;
@@ -2366,7 +2366,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
        spin_lock_init(&intf->events_lock);
        INIT_LIST_HEAD(&intf->waiting_events);
        intf->waiting_events_count = 0;
-       init_MUTEX(&intf->cmd_rcvrs_lock);
+       mutex_init(&intf->cmd_rcvrs_mutex);
        INIT_LIST_HEAD(&intf->cmd_rcvrs);
        init_waitqueue_head(&intf->waitq);
 
@@ -2388,9 +2388,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
        if (rv)
                goto out;
 
-       /* FIXME - this is an ugly kludge, this sets the intf for the
-          caller before sending any messages with it. */
-       *new_intf = intf;
+       rv = handlers->start_processing(send_info, intf);
+       if (rv)
+               goto out;
 
        get_guid(intf);
 
@@ -2622,7 +2622,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
                spin_unlock_irqrestore(&intf->counter_lock, flags);
 
                recv_msg = ipmi_alloc_recv_msg();
-               if (! recv_msg) {
+               if (!recv_msg) {
                        /* We couldn't allocate memory for the
                            message, so requeue it for handling
                            later. */
@@ -2777,7 +2777,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t          intf,
                spin_unlock_irqrestore(&intf->counter_lock, flags);
 
                recv_msg = ipmi_alloc_recv_msg();
-               if (! recv_msg) {
+               if (!recv_msg) {
                        /* We couldn't allocate memory for the
                            message, so requeue it for handling
                            later. */
@@ -2869,13 +2869,14 @@ static int handle_read_event_rsp(ipmi_smi_t          intf,
           events. */
        rcu_read_lock();
        list_for_each_entry_rcu(user, &intf->users, link) {
-               if (! user->gets_events)
+               if (!user->gets_events)
                        continue;
 
                recv_msg = ipmi_alloc_recv_msg();
-               if (! recv_msg) {
+               if (!recv_msg) {
                        rcu_read_unlock();
-                       list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) {
+                       list_for_each_entry_safe(recv_msg, recv_msg2, &msgs,
+                                                link) {
                                list_del(&recv_msg->link);
                                ipmi_free_recv_msg(recv_msg);
                        }
@@ -2905,7 +2906,7 @@ static int handle_read_event_rsp(ipmi_smi_t          intf,
                /* No one to receive the message, put it in queue if there's
                   not already too many things in the queue. */
                recv_msg = ipmi_alloc_recv_msg();
-               if (! recv_msg) {
+               if (!recv_msg) {
                        /* We couldn't allocate memory for the
                            message, so requeue it for handling
                            later. */
@@ -3190,7 +3191,7 @@ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
 
        rcu_read_lock();
        list_for_each_entry_rcu(user, &intf->users, link) {
-               if (! user->handler->ipmi_watchdog_pretimeout)
+               if (!user->handler->ipmi_watchdog_pretimeout)
                        continue;
 
                user->handler->ipmi_watchdog_pretimeout(user->handler_data);
@@ -3278,7 +3279,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
 
                smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot,
                                            ent->seqid);
-               if (! smi_msg)
+               if (!smi_msg)
                        return;
 
                spin_unlock_irqrestore(&intf->seq_lock, *flags);
@@ -3314,8 +3315,9 @@ static void ipmi_timeout_handler(long timeout_period)
 
                /* See if any waiting messages need to be processed. */
                spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
-               list_for_each_entry_safe(smi_msg, smi_msg2, &intf->waiting_msgs, link) {
-                       if (! handle_new_recv_msg(intf, smi_msg)) {
+               list_for_each_entry_safe(smi_msg, smi_msg2,
+                                        &intf->waiting_msgs, link) {
+                       if (!handle_new_recv_msg(intf, smi_msg)) {
                                list_del(&smi_msg->link);
                                ipmi_free_smi_msg(smi_msg);
                        } else {
index 786a280..d0b5c08 100644 (file)
@@ -346,7 +346,7 @@ static int ipmi_dell_chassis_detect (ipmi_user_t user)
 {
        const char ipmi_version_major = ipmi_version & 0xF;
        const char ipmi_version_minor = (ipmi_version >> 4) & 0xF;
-       const char mfr[3]=DELL_IANA_MFR_ID;
+       const char mfr[3] = DELL_IANA_MFR_ID;
        if (!memcmp(mfr, &mfg_id, sizeof(mfr)) &&
            ipmi_version_major <= 1 &&
            ipmi_version_minor < 5)
index 35fbd4d..a86c0f2 100644 (file)
@@ -803,7 +803,7 @@ static int ipmi_thread(void *data)
        set_user_nice(current, 19);
        while (!kthread_should_stop()) {
                spin_lock_irqsave(&(smi_info->si_lock), flags);
-               smi_result=smi_event_handler(smi_info, 0);
+               smi_result = smi_event_handler(smi_info, 0);
                spin_unlock_irqrestore(&(smi_info->si_lock), flags);
                if (smi_result == SI_SM_CALL_WITHOUT_DELAY) {
                        /* do nothing */
@@ -972,10 +972,37 @@ static irqreturn_t si_bt_irq_handler(int irq, void *data, struct pt_regs *regs)
        return si_irq_handler(irq, data, regs);
 }
 
+static int smi_start_processing(void       *send_info,
+                               ipmi_smi_t intf)
+{
+       struct smi_info *new_smi = send_info;
+
+       new_smi->intf = intf;
+
+       /* Set up the timer that drives the interface. */
+       setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
+       new_smi->last_timeout_jiffies = jiffies;
+       mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
+
+       if (new_smi->si_type != SI_BT) {
+               new_smi->thread = kthread_run(ipmi_thread, new_smi,
+                                             "kipmi%d", new_smi->intf_num);
+               if (IS_ERR(new_smi->thread)) {
+                       printk(KERN_NOTICE "ipmi_si_intf: Could not start"
+                              " kernel thread due to error %ld, only using"
+                              " timers to drive the interface\n",
+                              PTR_ERR(new_smi->thread));
+                       new_smi->thread = NULL;
+               }
+       }
+
+       return 0;
+}
 
 static struct ipmi_smi_handlers handlers =
 {
        .owner                  = THIS_MODULE,
+       .start_processing       = smi_start_processing,
        .sender                 = sender,
        .request_events         = request_events,
        .set_run_to_completion  = set_run_to_completion,
@@ -987,7 +1014,7 @@ static struct ipmi_smi_handlers handlers =
 
 #define SI_MAX_PARMS 4
 static LIST_HEAD(smi_infos);
-static DECLARE_MUTEX(smi_infos_lock);
+static DEFINE_MUTEX(smi_infos_lock);
 static int smi_num; /* Used to sequence the SMIs */
 
 #define DEFAULT_REGSPACING     1
@@ -2162,9 +2189,13 @@ static void setup_xaction_handlers(struct smi_info *smi_info)
 
 static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
 {
-       if (smi_info->thread != NULL && smi_info->thread != ERR_PTR(-ENOMEM))
-               kthread_stop(smi_info->thread);
-       del_timer_sync(&smi_info->si_timer);
+       if (smi_info->intf) {
+               /* The timer and thread are only running if the
+                  interface has been started up and registered. */
+               if (smi_info->thread != NULL)
+                       kthread_stop(smi_info->thread);
+               del_timer_sync(&smi_info->si_timer);
+       }
 }
 
 static struct ipmi_default_vals
@@ -2245,7 +2276,7 @@ static int try_smi_init(struct smi_info *new_smi)
                       new_smi->slave_addr, new_smi->irq);
        }
 
-       down(&smi_infos_lock);
+       mutex_lock(&smi_infos_lock);
        if (!is_new_interface(new_smi)) {
                printk(KERN_WARNING "ipmi_si: duplicate interface\n");
                rv = -EBUSY;
@@ -2341,21 +2372,6 @@ static int try_smi_init(struct smi_info *new_smi)
        if (new_smi->irq)
                new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
 
-       /* The ipmi_register_smi() code does some operations to
-          determine the channel information, so we must be ready to
-          handle operations before it is called.  This means we have
-          to stop the timer if we get an error after this point. */
-       init_timer(&(new_smi->si_timer));
-       new_smi->si_timer.data = (long) new_smi;
-       new_smi->si_timer.function = smi_timeout;
-       new_smi->last_timeout_jiffies = jiffies;
-       new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
-
-       add_timer(&(new_smi->si_timer));
-       if (new_smi->si_type != SI_BT)
-               new_smi->thread = kthread_run(ipmi_thread, new_smi,
-                                             "kipmi%d", new_smi->intf_num);
-
        if (!new_smi->dev) {
                /* If we don't already have a device from something
                 * else (like PCI), then register a new one. */
@@ -2365,7 +2381,7 @@ static int try_smi_init(struct smi_info *new_smi)
                        printk(KERN_ERR
                               "ipmi_si_intf:"
                               " Unable to allocate platform device\n");
-                       goto out_err_stop_timer;
+                       goto out_err;
                }
                new_smi->dev = &new_smi->pdev->dev;
                new_smi->dev->driver = &ipmi_driver;
@@ -2377,7 +2393,7 @@ static int try_smi_init(struct smi_info *new_smi)
                               " Unable to register system interface device:"
                               " %d\n",
                               rv);
-                       goto out_err_stop_timer;
+                       goto out_err;
                }
                new_smi->dev_registered = 1;
        }
@@ -2386,8 +2402,7 @@ static int try_smi_init(struct smi_info *new_smi)
                               new_smi,
                               &new_smi->device_id,
                               new_smi->dev,
-                              new_smi->slave_addr,
-                              &(new_smi->intf));
+                              new_smi->slave_addr);
        if (rv) {
                printk(KERN_ERR
                       "ipmi_si: Unable to register device: error %d\n",
@@ -2417,7 +2432,7 @@ static int try_smi_init(struct smi_info *new_smi)
 
        list_add_tail(&new_smi->link, &smi_infos);
 
-       up(&smi_infos_lock);
+       mutex_unlock(&smi_infos_lock);
 
        printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
 
@@ -2454,7 +2469,7 @@ static int try_smi_init(struct smi_info *new_smi)
 
        kfree(new_smi);
 
-       up(&smi_infos_lock);
+       mutex_unlock(&smi_infos_lock);
 
        return rv;
 }
@@ -2512,26 +2527,26 @@ static __devinit int init_ipmi_si(void)
 #endif
 
        if (si_trydefaults) {
-               down(&smi_infos_lock);
+               mutex_lock(&smi_infos_lock);
                if (list_empty(&smi_infos)) {
                        /* No BMC was found, try defaults. */
-                       up(&smi_infos_lock);
+                       mutex_unlock(&smi_infos_lock);
                        default_find_bmc();
                } else {
-                       up(&smi_infos_lock);
+                       mutex_unlock(&smi_infos_lock);
                }
        }
 
-       down(&smi_infos_lock);
+       mutex_lock(&smi_infos_lock);
        if (list_empty(&smi_infos)) {
-               up(&smi_infos_lock);
+               mutex_unlock(&smi_infos_lock);
 #ifdef CONFIG_PCI
                pci_unregister_driver(&ipmi_pci_driver);
 #endif
                printk("ipmi_si: Unable to find any System Interface(s)\n");
                return -ENODEV;
        } else {
-               up(&smi_infos_lock);
+               mutex_unlock(&smi_infos_lock);
                return 0;
        }
 }
@@ -2607,10 +2622,10 @@ static __exit void cleanup_ipmi_si(void)
        pci_unregister_driver(&ipmi_pci_driver);
 #endif
 
-       down(&smi_infos_lock);
+       mutex_lock(&smi_infos_lock);
        list_for_each_entry_safe(e, tmp_e, &smi_infos, link)
                cleanup_one_si(e);
-       up(&smi_infos_lock);
+       mutex_unlock(&smi_infos_lock);
 
        driver_unregister(&ipmi_driver);
 }
index 7ece9f3..2d11ddd 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
+#include <linux/completion.h>
 #include <linux/rwsem.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
@@ -303,21 +304,22 @@ static int ipmi_heartbeat(void);
 static void panic_halt_ipmi_heartbeat(void);
 
 
-/* We use a semaphore to make sure that only one thing can send a set
+/* We use a mutex to make sure that only one thing can send a set
    timeout at one time, because we only have one copy of the data.
-   The semaphore is claimed when the set_timeout is sent and freed
+   The mutex is claimed when the set_timeout is sent and freed
    when both messages are free. */
 static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
-static DECLARE_MUTEX(set_timeout_lock);
+static DEFINE_MUTEX(set_timeout_lock);
+static DECLARE_COMPLETION(set_timeout_wait);
 static void set_timeout_free_smi(struct ipmi_smi_msg *msg)
 {
     if (atomic_dec_and_test(&set_timeout_tofree))
-           up(&set_timeout_lock);
+           complete(&set_timeout_wait);
 }
 static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
 {
     if (atomic_dec_and_test(&set_timeout_tofree))
-           up(&set_timeout_lock);
+           complete(&set_timeout_wait);
 }
 static struct ipmi_smi_msg set_timeout_smi_msg =
 {
@@ -399,7 +401,7 @@ static int ipmi_set_timeout(int do_heartbeat)
 
 
        /* We can only send one of these at a time. */
-       down(&set_timeout_lock);
+       mutex_lock(&set_timeout_lock);
 
        atomic_set(&set_timeout_tofree, 2);
 
@@ -407,16 +409,21 @@ static int ipmi_set_timeout(int do_heartbeat)
                                &set_timeout_recv_msg,
                                &send_heartbeat_now);
        if (rv) {
-               up(&set_timeout_lock);
-       } else {
-               if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
-                   || ((send_heartbeat_now)
-                       && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
-               {
-                       rv = ipmi_heartbeat();
-               }
+               mutex_unlock(&set_timeout_lock);
+               goto out;
        }
 
+       wait_for_completion(&set_timeout_wait);
+
+       if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
+           || ((send_heartbeat_now)
+               && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
+       {
+               rv = ipmi_heartbeat();
+       }
+       mutex_unlock(&set_timeout_lock);
+
+out:
        return rv;
 }
 
@@ -458,17 +465,17 @@ static void panic_halt_ipmi_set_timeout(void)
    The semaphore is claimed when the set_timeout is sent and freed
    when both messages are free. */
 static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
-static DECLARE_MUTEX(heartbeat_lock);
-static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock);
+static DEFINE_MUTEX(heartbeat_lock);
+static DECLARE_COMPLETION(heartbeat_wait);
 static void heartbeat_free_smi(struct ipmi_smi_msg *msg)
 {
     if (atomic_dec_and_test(&heartbeat_tofree))
-           up(&heartbeat_wait_lock);
+           complete(&heartbeat_wait);
 }
 static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
 {
     if (atomic_dec_and_test(&heartbeat_tofree))
-           up(&heartbeat_wait_lock);
+           complete(&heartbeat_wait);
 }
 static struct ipmi_smi_msg heartbeat_smi_msg =
 {
@@ -511,14 +518,14 @@ static int ipmi_heartbeat(void)
                return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
        }
 
-       down(&heartbeat_lock);
+       mutex_lock(&heartbeat_lock);
 
        atomic_set(&heartbeat_tofree, 2);
 
        /* Don't reset the timer if we have the timer turned off, that
            re-enables the watchdog. */
        if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
-               up(&heartbeat_lock);
+               mutex_unlock(&heartbeat_lock);
                return 0;
        }
 
@@ -539,14 +546,14 @@ static int ipmi_heartbeat(void)
                                      &heartbeat_recv_msg,
                                      1);
        if (rv) {
-               up(&heartbeat_lock);
+               mutex_unlock(&heartbeat_lock);
                printk(KERN_WARNING PFX "heartbeat failure: %d\n",
                       rv);
                return rv;
        }
 
        /* Wait for the heartbeat to be sent. */
-       down(&heartbeat_wait_lock);
+       wait_for_completion(&heartbeat_wait);
 
        if (heartbeat_recv_msg.msg.data[0] != 0) {
            /* Got an error in the heartbeat response.  It was already
@@ -555,7 +562,7 @@ static int ipmi_heartbeat(void)
            rv = -EINVAL;
        }
 
-       up(&heartbeat_lock);
+       mutex_unlock(&heartbeat_lock);
 
        return rv;
 }
@@ -589,7 +596,7 @@ static void panic_halt_ipmi_heartbeat(void)
                                 1);
 }
 
-static struct watchdog_info ident=
+static struct watchdog_info ident =
 {
        .options        = 0,    /* WDIOF_SETTIMEOUT, */
        .firmware_version = 1,
@@ -790,13 +797,13 @@ static int ipmi_fasync(int fd, struct file *file, int on)
 
 static int ipmi_close(struct inode *ino, struct file *filep)
 {
-       if (iminor(ino)==WATCHDOG_MINOR)
-       {
+       if (iminor(ino) == WATCHDOG_MINOR) {
                if (expect_close == 42) {
                        ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
                        ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
                } else {
-                       printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+                       printk(KERN_CRIT PFX
+                              "Unexpected close, not stopping watchdog!\n");
                        ipmi_heartbeat();
                }
                clear_bit(0, &ipmi_wdog_open);
index e5247f8..ef20c1f 100644 (file)
@@ -706,7 +706,6 @@ static int  stli_portcmdstats(stliport_t *portp);
 static int     stli_clrportstats(stliport_t *portp, comstats_t __user *cp);
 static int     stli_getportstruct(stliport_t __user *arg);
 static int     stli_getbrdstruct(stlibrd_t __user *arg);
-static void    *stli_memalloc(int len);
 static stlibrd_t *stli_allocbrd(void);
 
 static void    stli_ecpinit(stlibrd_t *brdp);
@@ -997,17 +996,6 @@ static int stli_parsebrd(stlconf_t *confp, char **argp)
 
 /*****************************************************************************/
 
-/*
- *     Local driver kernel malloc routine.
- */
-
-static void *stli_memalloc(int len)
-{
-       return((void *) kmalloc(len, GFP_KERNEL));
-}
-
-/*****************************************************************************/
-
 static int stli_open(struct tty_struct *tty, struct file *filp)
 {
        stlibrd_t       *brdp;
@@ -3227,13 +3215,12 @@ static int stli_initports(stlibrd_t *brdp)
 #endif
 
        for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
-               portp = (stliport_t *) stli_memalloc(sizeof(stliport_t));
-               if (portp == (stliport_t *) NULL) {
+               portp = kzalloc(sizeof(stliport_t), GFP_KERNEL);
+               if (!portp) {
                        printk("STALLION: failed to allocate port structure\n");
                        continue;
                }
 
-               memset(portp, 0, sizeof(stliport_t));
                portp->magic = STLI_PORTMAGIC;
                portp->portnr = i;
                portp->brdnr = brdp->brdnr;
@@ -4610,14 +4597,13 @@ static stlibrd_t *stli_allocbrd(void)
 {
        stlibrd_t       *brdp;
 
-       brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t));
-       if (brdp == (stlibrd_t *) NULL) {
+       brdp = kzalloc(sizeof(stlibrd_t), GFP_KERNEL);
+       if (!brdp) {
                printk(KERN_ERR "STALLION: failed to allocate memory "
                                "(size=%d)\n", sizeof(stlibrd_t));
-               return((stlibrd_t *) NULL);
+               return NULL;
        }
 
-       memset(brdp, 0, sizeof(stlibrd_t));
        brdp->magic = STLI_BOARDMAGIC;
        return(brdp);
 }
@@ -5210,12 +5196,12 @@ int __init stli_init(void)
 /*
  *     Allocate a temporary write buffer.
  */
-       stli_tmpwritebuf = (char *) stli_memalloc(STLI_TXBUFSIZE);
-       if (stli_tmpwritebuf == (char *) NULL)
+       stli_tmpwritebuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
+       if (!stli_tmpwritebuf)
                printk(KERN_ERR "STALLION: failed to allocate memory "
                                "(size=%d)\n", STLI_TXBUFSIZE);
-       stli_txcookbuf = stli_memalloc(STLI_TXBUFSIZE);
-       if (stli_txcookbuf == (char *) NULL)
+       stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
+       if (!stli_txcookbuf)
                printk(KERN_ERR "STALLION: failed to allocate memory "
                                "(size=%d)\n", STLI_TXBUFSIZE);
 
index 8b603b2..935670a 100644 (file)
@@ -74,7 +74,7 @@ void compute_shiftstate(void);
        k_self,         k_fn,           k_spec,         k_pad,\
        k_dead,         k_cons,         k_cur,          k_shift,\
        k_meta,         k_ascii,        k_lock,         k_lowercase,\
-       k_slock,        k_dead2,        k_ignore,       k_ignore
+       k_slock,        k_dead2,        k_brl,          k_ignore
 
 typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
                            char up_flag, struct pt_regs *regs);
@@ -100,7 +100,7 @@ static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
 const int max_vals[] = {
        255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
        NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
-       255, NR_LOCK - 1, 255
+       255, NR_LOCK - 1, 255, NR_BRL - 1
 };
 
 const int NR_TYPES = ARRAY_SIZE(max_vals);
@@ -126,7 +126,7 @@ static unsigned long key_down[NBITS(KEY_MAX)];              /* keyboard key bitmap */
 static unsigned char shift_down[NR_SHIFT];             /* shift state counters.. */
 static int dead_key_next;
 static int npadch = -1;                                        /* -1 or number assembled on pad */
-static unsigned char diacr;
+static unsigned int diacr;
 static char rep;                                       /* flag telling character repeat */
 
 static unsigned char ledstate = 0xff;                  /* undefined */
@@ -394,22 +394,30 @@ void compute_shiftstate(void)
  * Otherwise, conclude that DIACR was not combining after all,
  * queue it and return CH.
  */
-static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
+static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
 {
-       int d = diacr;
+       unsigned int d = diacr;
        unsigned int i;
 
        diacr = 0;
 
-       for (i = 0; i < accent_table_size; i++) {
-               if (accent_table[i].diacr == d && accent_table[i].base == ch)
-                       return accent_table[i].result;
+       if ((d & ~0xff) == BRL_UC_ROW) {
+               if ((ch & ~0xff) == BRL_UC_ROW)
+                       return d | ch;
+       } else {
+               for (i = 0; i < accent_table_size; i++)
+                       if (accent_table[i].diacr == d && accent_table[i].base == ch)
+                               return accent_table[i].result;
        }
 
-       if (ch == ' ' || ch == d)
+       if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
                return d;
 
-       put_queue(vc, d);
+       if (kbd->kbdmode == VC_UNICODE)
+               to_utf8(vc, d);
+       else if (d < 0x100)
+               put_queue(vc, d);
+
        return ch;
 }
 
@@ -419,7 +427,10 @@ static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
 static void fn_enter(struct vc_data *vc, struct pt_regs *regs)
 {
        if (diacr) {
-               put_queue(vc, diacr);
+               if (kbd->kbdmode == VC_UNICODE)
+                       to_utf8(vc, diacr);
+               else if (diacr < 0x100)
+                       put_queue(vc, diacr);
                diacr = 0;
        }
        put_queue(vc, 13);
@@ -615,7 +626,7 @@ static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag, s
        printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
 }
 
-static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs)
 {
        if (up_flag)
                return;         /* no action, if this is a key release */
@@ -628,7 +639,10 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct
                diacr = value;
                return;
        }
-       put_queue(vc, value);
+       if (kbd->kbdmode == VC_UNICODE)
+               to_utf8(vc, value);
+       else if (value < 0x100)
+               put_queue(vc, value);
 }
 
 /*
@@ -636,13 +650,23 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct
  * dead keys modifying the same character. Very useful
  * for Vietnamese.
  */
-static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs)
 {
        if (up_flag)
                return;
        diacr = (diacr ? handle_diacr(vc, value) : value);
 }
 
+static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+{
+       k_unicode(vc, value, up_flag, regs);
+}
+
+static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+{
+       k_deadunicode(vc, value, up_flag, regs);
+}
+
 /*
  * Obsolete - for backwards compatibility only
  */
@@ -650,7 +674,7 @@ static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct
 {
        static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
        value = ret_diacr[value];
-       k_dead2(vc, value, up_flag, regs);
+       k_deadunicode(vc, value, up_flag, regs);
 }
 
 static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
@@ -835,6 +859,62 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag, struc
        }
 }
 
+/* by default, 300ms interval for combination release */
+static long brl_timeout = 300;
+MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for combination on first release, < 0 for dead characters)");
+module_param(brl_timeout, long, 0644);
+static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+{
+       static unsigned pressed,committing;
+       static unsigned long releasestart;
+
+       if (kbd->kbdmode != VC_UNICODE) {
+               if (!up_flag)
+                       printk("keyboard mode must be unicode for braille patterns\n");
+               return;
+       }
+
+       if (!value) {
+               k_unicode(vc, BRL_UC_ROW, up_flag, regs);
+               return;
+       }
+
+       if (value > 8)
+               return;
+
+       if (brl_timeout < 0) {
+               k_deadunicode(vc, BRL_UC_ROW | (1 << (value - 1)), up_flag, regs);
+               return;
+       }
+
+       if (up_flag) {
+               if (brl_timeout) {
+                       if (!committing ||
+                           jiffies - releasestart > (brl_timeout * HZ) / 1000) {
+                               committing = pressed;
+                               releasestart = jiffies;
+                       }
+                       pressed &= ~(1 << (value - 1));
+                       if (!pressed) {
+                               if (committing) {
+                                       k_unicode(vc, BRL_UC_ROW | committing, 0, regs);
+                                       committing = 0;
+                               }
+                       }
+               } else {
+                       if (committing) {
+                               k_unicode(vc, BRL_UC_ROW | committing, 0, regs);
+                               committing = 0;
+                       }
+                       pressed &= ~(1 << (value - 1));
+               }
+       } else {
+               pressed |= 1 << (value - 1);
+               if (!brl_timeout)
+                       committing = pressed;
+       }
+}
+
 /*
  * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
  * or (ii) whatever pattern of lights people want to show using KDSETLED,
@@ -1125,9 +1205,13 @@ static void kbd_keycode(unsigned int keycode, int down,
        }
 
        if (keycode > NR_KEYS)
-               return;
+               if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
+                       keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
+               else
+                       return;
+       else
+               keysym = key_map[keycode];
 
-       keysym = key_map[keycode];
        type = KTYP(keysym);
 
        if (type < 0xf0) {
index 5fdf185..02114a0 100644 (file)
@@ -46,7 +46,7 @@
 /* #define ATR_CSUM */
 
 #ifdef PCMCIA_DEBUG
-#define reader_to_dev(x)       (&handle_to_dev(x->link.handle))
+#define reader_to_dev(x)       (&handle_to_dev(x->p_dev->handle))
 static int pc_debug = PCMCIA_DEBUG;
 module_param(pc_debug, int, 0600);
 #define DEBUGP(n, rdr, x, args...) do {                                \
@@ -67,7 +67,7 @@ static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";
 #define        T_100MSEC       msecs_to_jiffies(100)
 #define        T_500MSEC       msecs_to_jiffies(500)
 
-static void cm4000_release(dev_link_t *link);
+static void cm4000_release(struct pcmcia_device *link);
 
 static int major;              /* major number we get from the kernel */
 
@@ -106,7 +106,7 @@ static int major;           /* major number we get from the kernel */
 #define REG_STOPBITS(x)                (x + 7)
 
 struct cm4000_dev {
-       dev_link_t link;                /* pcmcia link */
+       struct pcmcia_device *p_dev;
        dev_node_t node;                /* OS node (major,minor) */
 
        unsigned char atr[MAX_ATR];
@@ -149,14 +149,14 @@ struct cm4000_dev {
 #define        ZERO_DEV(dev)                                           \
        memset(&dev->atr_csum,0,                                \
                sizeof(struct cm4000_dev) -                     \
-               /*link*/ sizeof(dev_link_t) -                   \
+               /*link*/ sizeof(struct pcmcia_device) -         \
                /*node*/ sizeof(dev_node_t) -                   \
                /*atr*/ MAX_ATR*sizeof(char) -                  \
                /*rbuf*/ 512*sizeof(char) -                     \
                /*sbuf*/ 512*sizeof(char) -                     \
                /*queue*/ 4*sizeof(wait_queue_head_t))
 
-static dev_link_t *dev_table[CM4000_MAX_DEV];
+static struct pcmcia_device *dev_table[CM4000_MAX_DEV];
 static struct class *cmm_class;
 
 /* This table doesn't use spaces after the comma between fields and thus
@@ -454,7 +454,7 @@ static struct card_fixup card_fixups[] = {
 static void set_cardparameter(struct cm4000_dev *dev)
 {
        int i;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
        u_int8_t stopbits = 0x02; /* ISO default */
 
        DEBUGP(3, dev, "-> set_cardparameter\n");
@@ -487,7 +487,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
        unsigned short num_bytes_read;
        unsigned char pts_reply[4];
        ssize_t rc;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
 
        rc = 0;
 
@@ -699,7 +699,7 @@ static void terminate_monitor(struct cm4000_dev *dev)
 static void monitor_card(unsigned long p)
 {
        struct cm4000_dev *dev = (struct cm4000_dev *) p;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
        unsigned short s;
        struct ptsreq ptsreq;
        int i, atrc;
@@ -962,7 +962,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
                        loff_t *ppos)
 {
        struct cm4000_dev *dev = filp->private_data;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
        ssize_t rc;
        int i, j, k;
 
@@ -971,7 +971,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
        if (count == 0)         /* according to manpage */
                return 0;
 
-       if ((dev->link.state & DEV_PRESENT) == 0 ||     /* socket removed */
+       if (!pcmcia_dev_present(dev->p_dev) || /* device removed */
            test_bit(IS_CMM_ABSENT, &dev->flags))
                return -ENODEV;
 
@@ -1083,7 +1083,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
                         size_t count, loff_t *ppos)
 {
        struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
        unsigned short s;
        unsigned char tmp;
        unsigned char infolen;
@@ -1108,7 +1108,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
 
        sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0;
 
-       if ((dev->link.state & DEV_PRESENT) == 0 ||     /* socket removed */
+       if (!pcmcia_dev_present(dev->p_dev) || /* device removed */
            test_bit(IS_CMM_ABSENT, &dev->flags))
                return -ENODEV;
 
@@ -1440,8 +1440,8 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                     unsigned long arg)
 {
        struct cm4000_dev *dev = filp->private_data;
-       ioaddr_t iobase = dev->link.io.BasePort1;
-       dev_link_t *link;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
+       struct pcmcia_device *link;
        int size;
        int rc;
        void __user *argp = (void __user *)arg;
@@ -1458,7 +1458,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
               iminor(inode), ioctl_names[_IOC_NR(cmd)]);
 
        link = dev_table[iminor(inode)];
-       if (!(DEV_OK(link))) {
+       if (!pcmcia_dev_present(link)) {
                DEBUGP(4, dev, "DEV_OK false\n");
                return -ENODEV;
        }
@@ -1660,14 +1660,14 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 static int cmm_open(struct inode *inode, struct file *filp)
 {
        struct cm4000_dev *dev;
-       dev_link_t *link;
+       struct pcmcia_device *link;
        int rc, minor = iminor(inode);
 
        if (minor >= CM4000_MAX_DEV)
                return -ENODEV;
 
        link = dev_table[minor];
-       if (link == NULL || !(DEV_OK(link)))
+       if (link == NULL || !pcmcia_dev_present(link))
                return -ENODEV;
 
        if (link->open)
@@ -1709,7 +1709,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
 static int cmm_close(struct inode *inode, struct file *filp)
 {
        struct cm4000_dev *dev;
-       dev_link_t *link;
+       struct pcmcia_device *link;
        int minor = iminor(inode);
 
        if (minor >= CM4000_MAX_DEV)
@@ -1735,7 +1735,7 @@ static int cmm_close(struct inode *inode, struct file *filp)
        return 0;
 }
 
-static void cmm_cm4000_release(dev_link_t * link)
+static void cmm_cm4000_release(struct pcmcia_device * link)
 {
        struct cm4000_dev *dev = link->priv;
 
@@ -1759,13 +1759,11 @@ static void cmm_cm4000_release(dev_link_t * link)
 
 /*==== Interface to PCMCIA Layer =======================================*/
 
-static void cm4000_config(dev_link_t * link, int devno)
+static int cm4000_config(struct pcmcia_device * link, int devno)
 {
-       client_handle_t handle = link->handle;
        struct cm4000_dev *dev;
        tuple_t tuple;
        cisparse_t parse;
-       config_info_t conf;
        u_char buf[64];
        int fail_fn, fail_rc;
        int rc;
@@ -1777,41 +1775,34 @@ static void cm4000_config(dev_link_t * link, int devno)
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
 
-       if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) {
+       if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
                fail_fn = GetFirstTuple;
                goto cs_failed;
        }
-       if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) {
+       if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
                fail_fn = GetTupleData;
                goto cs_failed;
        }
        if ((fail_rc =
-            pcmcia_parse_tuple(handle, &tuple, &parse)) != CS_SUCCESS) {
+            pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) {
                fail_fn = ParseTuple;
                goto cs_failed;
        }
-       if ((fail_rc =
-            pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) {
-               fail_fn = GetConfigurationInfo;
-               goto cs_failed;
-       }
 
-       link->state |= DEV_CONFIG;
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
-       link->conf.Vcc = conf.Vcc;
 
        link->io.BasePort2 = 0;
        link->io.NumPorts2 = 0;
        link->io.Attributes2 = 0;
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       for (rc = pcmcia_get_first_tuple(handle, &tuple);
-            rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(handle, &tuple)) {
+       for (rc = pcmcia_get_first_tuple(link, &tuple);
+            rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) {
 
-               rc = pcmcia_get_tuple_data(handle, &tuple);
+               rc = pcmcia_get_tuple_data(link, &tuple);
                if (rc != CS_SUCCESS)
                        continue;
-               rc = pcmcia_parse_tuple(handle, &tuple, &parse);
+               rc = pcmcia_parse_tuple(link, &tuple, &parse);
                if (rc != CS_SUCCESS)
                        continue;
 
@@ -1831,7 +1822,7 @@ static void cm4000_config(dev_link_t * link, int devno)
                link->io.IOAddrLines = parse.cftable_entry.io.flags
                    & CISTPL_IO_LINES_MASK;
 
-               rc = pcmcia_request_io(handle, &link->io);
+               rc = pcmcia_request_io(link, &link->io);
                if (rc == CS_SUCCESS)
                        break;  /* we are done */
        }
@@ -1841,7 +1832,7 @@ static void cm4000_config(dev_link_t * link, int devno)
        link->conf.IntType = 00000002;
 
        if ((fail_rc =
-            pcmcia_request_configuration(handle, &link->conf)) != CS_SUCCESS) {
+            pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) {
                fail_fn = RequestConfiguration;
                goto cs_release;
        }
@@ -1851,63 +1842,48 @@ static void cm4000_config(dev_link_t * link, int devno)
        dev->node.major = major;
        dev->node.minor = devno;
        dev->node.next = NULL;
-       link->dev = &dev->node;
-       link->state &= ~DEV_CONFIG_PENDING;
+       link->dev_node = &dev->node;
 
-       return;
+       return 0;
 
 cs_failed:
-       cs_error(handle, fail_fn, fail_rc);
+       cs_error(link, fail_fn, fail_rc);
 cs_release:
        cm4000_release(link);
-
-       link->state &= ~DEV_CONFIG_PENDING;
+       return -ENODEV;
 }
 
-static int cm4000_suspend(struct pcmcia_device *p_dev)
+static int cm4000_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct cm4000_dev *dev;
 
        dev = link->priv;
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
        stop_monitor(dev);
 
        return 0;
 }
 
-static int cm4000_resume(struct pcmcia_device *p_dev)
+static int cm4000_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct cm4000_dev *dev;
 
        dev = link->priv;
-
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
-
        if (link->open)
                start_monitor(dev);
 
        return 0;
 }
 
-static void cm4000_release(dev_link_t *link)
+static void cm4000_release(struct pcmcia_device *link)
 {
        cmm_cm4000_release(link->priv); /* delay release until device closed */
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
+       pcmcia_disable_device(link);
 }
 
-static int cm4000_attach(struct pcmcia_device *p_dev)
+static int cm4000_probe(struct pcmcia_device *link)
 {
        struct cm4000_dev *dev;
-       dev_link_t *link;
-       int i;
+       int i, ret;
 
        for (i = 0; i < CM4000_MAX_DEV; i++)
                if (dev_table[i] == NULL)
@@ -1923,7 +1899,7 @@ static int cm4000_attach(struct pcmcia_device *p_dev)
        if (dev == NULL)
                return -ENOMEM;
 
-       link = &dev->link;
+       dev->p_dev = link;
        link->priv = dev;
        link->conf.IntType = INT_MEMORY_AND_IO;
        dev_table[i] = link;
@@ -1933,11 +1909,9 @@ static int cm4000_attach(struct pcmcia_device *p_dev)
        init_waitqueue_head(&dev->atrq);
        init_waitqueue_head(&dev->readq);
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       cm4000_config(link, i);
+       ret = cm4000_config(link, i);
+       if (ret)
+               return ret;
 
        class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,
                            "cmm%d", i);
@@ -1945,9 +1919,8 @@ static int cm4000_attach(struct pcmcia_device *p_dev)
        return 0;
 }
 
-static void cm4000_detach(struct pcmcia_device *p_dev)
+static void cm4000_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct cm4000_dev *dev = link->priv;
        int devno;
 
@@ -1958,11 +1931,9 @@ static void cm4000_detach(struct pcmcia_device *p_dev)
        if (devno == CM4000_MAX_DEV)
                return;
 
-       link->state &= ~DEV_PRESENT;
        stop_monitor(dev);
 
-       if (link->state & DEV_CONFIG)
-               cm4000_release(link);
+       cm4000_release(link);
 
        dev_table[devno] = NULL;
        kfree(dev);
@@ -1993,7 +1964,7 @@ static struct pcmcia_driver cm4000_driver = {
        .drv      = {
                .name = "cm4000_cs",
                },
-       .probe    = cm4000_attach,
+       .probe    = cm4000_probe,
        .remove   = cm4000_detach,
        .suspend  = cm4000_suspend,
        .resume   = cm4000_resume,
index 466e33b..29efa64 100644 (file)
@@ -41,7 +41,7 @@
 
 
 #ifdef PCMCIA_DEBUG
-#define reader_to_dev(x)       (&handle_to_dev(x->link.handle))
+#define reader_to_dev(x)       (&handle_to_dev(x->p_dev->handle))
 static int pc_debug = PCMCIA_DEBUG;
 module_param(pc_debug, int, 0600);
 #define DEBUGP(n, rdr, x, args...) do {                                \
@@ -65,7 +65,7 @@ static char *version =
 /* how often to poll for fifo status change */
 #define POLL_PERIOD                            msecs_to_jiffies(10)
 
-static void reader_release(dev_link_t *link);
+static void reader_release(struct pcmcia_device *link);
 
 static int major;
 static struct class *cmx_class;
@@ -74,7 +74,7 @@ static struct class *cmx_class;
 #define                BS_WRITABLE     0x02
 
 struct reader_dev {
-       dev_link_t              link;
+       struct pcmcia_device    *p_dev;
        dev_node_t              node;
        wait_queue_head_t       devq;
        wait_queue_head_t       poll_wait;
@@ -87,7 +87,7 @@ struct reader_dev {
        struct timer_list       poll_timer;
 };
 
-static dev_link_t *dev_table[CM_MAX_DEV];
+static struct pcmcia_device *dev_table[CM_MAX_DEV];
 
 #ifndef PCMCIA_DEBUG
 #define        xoutb   outb
@@ -116,7 +116,7 @@ static inline unsigned char xinb(unsigned short port)
 static void cm4040_do_poll(unsigned long dummy)
 {
        struct reader_dev *dev = (struct reader_dev *) dummy;
-       unsigned int obs = xinb(dev->link.io.BasePort1
+       unsigned int obs = xinb(dev->p_dev->io.BasePort1
                                + REG_OFFSET_BUFFER_STATUS);
 
        if ((obs & BSR_BULK_IN_FULL)) {
@@ -147,7 +147,7 @@ static void cm4040_stop_poll(struct reader_dev *dev)
 static int wait_for_bulk_out_ready(struct reader_dev *dev)
 {
        int i, rc;
-       int iobase = dev->link.io.BasePort1;
+       int iobase = dev->p_dev->io.BasePort1;
 
        for (i = 0; i < POLL_LOOP_COUNT; i++) {
                if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
@@ -177,7 +177,7 @@ static int wait_for_bulk_out_ready(struct reader_dev *dev)
 /* Write to Sync Control Register */
 static int write_sync_reg(unsigned char val, struct reader_dev *dev)
 {
-       int iobase = dev->link.io.BasePort1;
+       int iobase = dev->p_dev->io.BasePort1;
        int rc;
 
        rc = wait_for_bulk_out_ready(dev);
@@ -195,7 +195,7 @@ static int write_sync_reg(unsigned char val, struct reader_dev *dev)
 static int wait_for_bulk_in_ready(struct reader_dev *dev)
 {
        int i, rc;
-       int iobase = dev->link.io.BasePort1;
+       int iobase = dev->p_dev->io.BasePort1;
 
        for (i = 0; i < POLL_LOOP_COUNT; i++) {
                if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
@@ -225,7 +225,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,
                        size_t count, loff_t *ppos)
 {
        struct reader_dev *dev = filp->private_data;
-       int iobase = dev->link.io.BasePort1;
+       int iobase = dev->p_dev->io.BasePort1;
        size_t bytes_to_read;
        unsigned long i;
        size_t min_bytes_to_read;
@@ -246,7 +246,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,
                return -EAGAIN;
        }
 
-       if ((dev->link.state & DEV_PRESENT)==0)
+       if (!pcmcia_dev_present(dev->p_dev))
                return -ENODEV;
 
        for (i = 0; i < 5; i++) {
@@ -328,7 +328,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
                         size_t count, loff_t *ppos)
 {
        struct reader_dev *dev = filp->private_data;
-       int iobase = dev->link.io.BasePort1;
+       int iobase = dev->p_dev->io.BasePort1;
        ssize_t rc;
        int i;
        unsigned int bytes_to_write;
@@ -351,7 +351,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
                return -EAGAIN;
        }
 
-       if ((dev->link.state & DEV_PRESENT) == 0)
+       if (!pcmcia_dev_present(dev->p_dev))
                return -ENODEV;
 
        bytes_to_write = count;
@@ -445,14 +445,14 @@ static unsigned int cm4040_poll(struct file *filp, poll_table *wait)
 static int cm4040_open(struct inode *inode, struct file *filp)
 {
        struct reader_dev *dev;
-       dev_link_t *link;
+       struct pcmcia_device *link;
        int minor = iminor(inode);
 
        if (minor >= CM_MAX_DEV)
                return -ENODEV;
 
        link = dev_table[minor];
-       if (link == NULL || !(DEV_OK(link)))
+       if (link == NULL || !pcmcia_dev_present(link))
                return -ENODEV;
 
        if (link->open)
@@ -478,7 +478,7 @@ static int cm4040_open(struct inode *inode, struct file *filp)
 static int cm4040_close(struct inode *inode, struct file *filp)
 {
        struct reader_dev *dev = filp->private_data;
-       dev_link_t *link;
+       struct pcmcia_device *link;
        int minor = iminor(inode);
 
        DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode),
@@ -500,7 +500,7 @@ static int cm4040_close(struct inode *inode, struct file *filp)
        return 0;
 }
 
-static void cm4040_reader_release(dev_link_t *link)
+static void cm4040_reader_release(struct pcmcia_device *link)
 {
        struct reader_dev *dev = link->priv;
 
@@ -514,60 +514,49 @@ static void cm4040_reader_release(dev_link_t *link)
        return;
 }
 
-static void reader_config(dev_link_t *link, int devno)
+static int reader_config(struct pcmcia_device *link, int devno)
 {
-       client_handle_t handle;
        struct reader_dev *dev;
        tuple_t tuple;
        cisparse_t parse;
-       config_info_t conf;
        u_char buf[64];
        int fail_fn, fail_rc;
        int rc;
 
-       handle = link->handle;
-
        tuple.DesiredTuple = CISTPL_CONFIG;
        tuple.Attributes = 0;
        tuple.TupleData = buf;
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
 
-       if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) {
+       if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
                fail_fn = GetFirstTuple;
                goto cs_failed;
        }
-       if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) {
+       if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
                fail_fn = GetTupleData;
                goto cs_failed;
        }
-       if ((fail_rc = pcmcia_parse_tuple(handle, &tuple, &parse))
+       if ((fail_rc = pcmcia_parse_tuple(link, &tuple, &parse))
                                                        != CS_SUCCESS) {
                fail_fn = ParseTuple;
                goto cs_failed;
        }
-       if ((fail_rc = pcmcia_get_configuration_info(handle, &conf))
-                                                       != CS_SUCCESS) {
-               fail_fn = GetConfigurationInfo;
-               goto cs_failed;
-       }
 
-       link->state |= DEV_CONFIG;
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
-       link->conf.Vcc = conf.Vcc;
 
        link->io.BasePort2 = 0;
        link->io.NumPorts2 = 0;
        link->io.Attributes2 = 0;
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       for (rc = pcmcia_get_first_tuple(handle, &tuple);
+       for (rc = pcmcia_get_first_tuple(link, &tuple);
             rc == CS_SUCCESS;
-            rc = pcmcia_get_next_tuple(handle, &tuple)) {
-               rc = pcmcia_get_tuple_data(handle, &tuple);
+            rc = pcmcia_get_next_tuple(link, &tuple)) {
+               rc = pcmcia_get_tuple_data(link, &tuple);
                if (rc != CS_SUCCESS)
                        continue;
-               rc = pcmcia_parse_tuple(handle, &tuple, &parse);
+               rc = pcmcia_parse_tuple(link, &tuple, &parse);
                if (rc != CS_SUCCESS)
                        continue;
 
@@ -585,13 +574,13 @@ static void reader_config(dev_link_t *link, int devno)
                        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
                link->io.IOAddrLines = parse.cftable_entry.io.flags
                                                & CISTPL_IO_LINES_MASK;
-               rc = pcmcia_request_io(handle, &link->io);
+               rc = pcmcia_request_io(link, &link->io);
 
-               dev_printk(KERN_INFO, &handle_to_dev(handle), "foo");
+               dev_printk(KERN_INFO, &handle_to_dev(link), "foo");
                if (rc == CS_SUCCESS)
                        break;
                else
-                       dev_printk(KERN_INFO, &handle_to_dev(handle),
+                       dev_printk(KERN_INFO, &handle_to_dev(link),
                                   "pcmcia_request_io failed 0x%x\n", rc);
        }
        if (rc != CS_SUCCESS)
@@ -599,10 +588,10 @@ static void reader_config(dev_link_t *link, int devno)
 
        link->conf.IntType = 00000002;
 
-       if ((fail_rc = pcmcia_request_configuration(handle,&link->conf))
+       if ((fail_rc = pcmcia_request_configuration(link,&link->conf))
                                                                !=CS_SUCCESS) {
                fail_fn = RequestConfiguration;
-               dev_printk(KERN_INFO, &handle_to_dev(handle),
+               dev_printk(KERN_INFO, &handle_to_dev(link),
                           "pcmcia_request_configuration failed 0x%x\n",
                           fail_rc);
                goto cs_release;
@@ -612,57 +601,31 @@ static void reader_config(dev_link_t *link, int devno)
        sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno);
        dev->node.major = major;
        dev->node.minor = devno;
-       dev->node.next = NULL;
-       link->dev = &dev->node;
-       link->state &= ~DEV_CONFIG_PENDING;
+       dev->node.next = &dev->node;
 
        DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno,
              link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1);
        DEBUGP(2, dev, "<- reader_config (succ)\n");
 
-       return;
+       return 0;
 
 cs_failed:
-       cs_error(handle, fail_fn, fail_rc);
+       cs_error(link, fail_fn, fail_rc);
 cs_release:
        reader_release(link);
-       link->state &= ~DEV_CONFIG_PENDING;
-}
-
-static int reader_suspend(struct pcmcia_device *p_dev)
-{
-       dev_link_t *link = dev_to_instance(p_dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
+       return -ENODEV;
 }
 
-static int reader_resume(struct pcmcia_device *p_dev)
-{
-       dev_link_t *link = dev_to_instance(p_dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-       return 0;
-}
-
-static void reader_release(dev_link_t *link)
+static void reader_release(struct pcmcia_device *link)
 {
        cm4040_reader_release(link->priv);
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
+       pcmcia_disable_device(link);
 }
 
-static int reader_attach(struct pcmcia_device *p_dev)
+static int reader_probe(struct pcmcia_device *link)
 {
        struct reader_dev *dev;
-       dev_link_t *link;
-       int i;
+       int i, ret;
 
        for (i = 0; i < CM_MAX_DEV; i++) {
                if (dev_table[i] == NULL)
@@ -679,8 +642,8 @@ static int reader_attach(struct pcmcia_device *p_dev)
        dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
        dev->buffer_status = 0;
 
-       link = &dev->link;
        link->priv = dev;
+       dev->p_dev = link;
 
        link->conf.IntType = INT_MEMORY_AND_IO;
        dev_table[i] = link;
@@ -692,11 +655,9 @@ static int reader_attach(struct pcmcia_device *p_dev)
        init_timer(&dev->poll_timer);
        dev->poll_timer.function = &cm4040_do_poll;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       reader_config(link, i);
+       ret = reader_config(link, i);
+       if (ret)
+               return ret;
 
        class_device_create(cmx_class, NULL, MKDEV(major, i), NULL,
                            "cmx%d", i);
@@ -704,9 +665,8 @@ static int reader_attach(struct pcmcia_device *p_dev)
        return 0;
 }
 
-static void reader_detach(struct pcmcia_device *p_dev)
+static void reader_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct reader_dev *dev = link->priv;
        int devno;
 
@@ -718,10 +678,7 @@ static void reader_detach(struct pcmcia_device *p_dev)
        if (devno == CM_MAX_DEV)
                return;
 
-       link->state &= ~DEV_PRESENT;
-
-       if (link->state & DEV_CONFIG)
-               reader_release(link);
+       reader_release(link);
 
        dev_table[devno] = NULL;
        kfree(dev);
@@ -753,10 +710,8 @@ static struct pcmcia_driver reader_driver = {
        .drv            = {
                .name   = "cm4040_cs",
        },
-       .probe          = reader_attach,
+       .probe          = reader_probe,
        .remove         = reader_detach,
-       .suspend        = reader_suspend,
-       .resume         = reader_resume,
        .id_table       = cm4040_ids,
 };
 
index e6b714b..0721345 100644 (file)
@@ -228,7 +228,7 @@ typedef struct _mgslpc_info {
        struct  _input_signal_events    input_signal_events;
 
        /* PCMCIA support */
-       dev_link_t            link;
+       struct pcmcia_device    *p_dev;
        dev_node_t            node;
        int                   stop;
 
@@ -484,7 +484,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
 
 /* PCMCIA prototypes */
 
-static void mgslpc_config(dev_link_t *link);
+static int mgslpc_config(struct pcmcia_device *link);
 static void mgslpc_release(u_long arg);
 static void mgslpc_detach(struct pcmcia_device *p_dev);
 
@@ -533,14 +533,14 @@ static void ldisc_receive_buf(struct tty_struct *tty,
        }
 }
 
-static int mgslpc_attach(struct pcmcia_device *p_dev)
+static int mgslpc_probe(struct pcmcia_device *link)
 {
     MGSLPC_INFO *info;
-    dev_link_t *link;
-    
+    int ret;
+
     if (debug_level >= DEBUG_LEVEL_INFO)
            printk("mgslpc_attach\n");
-       
+
     info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
     if (!info) {
            printk("Error can't allocate device instance data\n");
@@ -565,25 +565,22 @@ static int mgslpc_attach(struct pcmcia_device *p_dev)
     info->imrb_value = 0xffff;
     info->pim_value = 0xff;
 
-    link = &info->link;
+    info->p_dev = link;
     link->priv = info;
-    
-    /* Initialize the dev_link_t structure */
+
+    /* Initialize the struct pcmcia_device structure */
 
     /* Interrupt setup */
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1   = IRQ_LEVEL_ID;
     link->irq.Handler = NULL;
-    
+
     link->conf.Attributes = 0;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    mgslpc_config(link);
+    ret = mgslpc_config(link);
+    if (ret)
+           return ret;
 
     mgslpc_add_device(info);
 
@@ -596,15 +593,13 @@ static int mgslpc_attach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void mgslpc_config(dev_link_t *link)
+static int mgslpc_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     MGSLPC_INFO *info = link->priv;
     tuple_t tuple;
     cisparse_t parse;
     int last_fn, last_ret;
     u_char buf[64];
-    config_info_t conf;
     cistpl_cftable_entry_t dflt = { 0 };
     cistpl_cftable_entry_t *cfg;
     
@@ -617,27 +612,20 @@ static void mgslpc_config(dev_link_t *link)
     tuple.TupleData = buf;
     tuple.TupleDataMax = sizeof(buf);
     tuple.TupleOffset = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
-    /* Look up the current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-    link->conf.Vcc = conf.Vcc;
 
     /* get CIS configuration entry */
 
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 
     cfg = &(parse.cftable_entry);
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 
     if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
     if (cfg->index == 0)
@@ -658,11 +646,10 @@ static void mgslpc_config(dev_link_t *link)
            link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
            link->io.BasePort1 = io->win[0].base;
            link->io.NumPorts1 = io->win[0].len;
-           CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+           CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
     }
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 8;
     link->conf.Present = PRESENT_OPTION;
@@ -670,9 +657,9 @@ static void mgslpc_config(dev_link_t *link)
     link->irq.Attributes |= IRQ_HANDLE_PRESENT;
     link->irq.Handler     = mgslpc_isr;
     link->irq.Instance    = info;
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     info->io_base = link->io.BasePort1;
     info->irq_level = link->irq.AssignedIRQ;
@@ -680,7 +667,7 @@ static void mgslpc_config(dev_link_t *link)
     /* add to linked list of devices */
     sprintf(info->node.dev_name, "mgslpc0");
     info->node.major = info->node.minor = 0;
-    link->dev = &info->node;
+    link->dev_node = &info->node;
 
     printk(KERN_INFO "%s: index 0x%02x:",
           info->node.dev_name, link->conf.ConfigIndex);
@@ -690,13 +677,12 @@ static void mgslpc_config(dev_link_t *link)
            printk(", io 0x%04x-0x%04x", link->io.BasePort1,
                   link->io.BasePort1+link->io.NumPorts1-1);
     printk("\n");
-    
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
     mgslpc_release((u_long)link);
+    return -ENODEV;
 }
 
 /* Card has been removed.
@@ -705,58 +691,38 @@ cs_failed:
  */
 static void mgslpc_release(u_long arg)
 {
-    dev_link_t *link = (dev_link_t *)arg;
+       struct pcmcia_device *link = (struct pcmcia_device *)arg;
 
-    if (debug_level >= DEBUG_LEVEL_INFO)
-           printk("mgslpc_release(0x%p)\n", link);
-
-    /* Unlink the device chain */
-    link->dev = NULL;
-    link->state &= ~DEV_CONFIG;
+       if (debug_level >= DEBUG_LEVEL_INFO)
+               printk("mgslpc_release(0x%p)\n", link);
 
-    pcmcia_release_configuration(link->handle);
-    if (link->io.NumPorts1)
-           pcmcia_release_io(link->handle, &link->io);
-    if (link->irq.AssignedIRQ)
-           pcmcia_release_irq(link->handle, &link->irq);
+       pcmcia_disable_device(link);
 }
 
-static void mgslpc_detach(struct pcmcia_device *p_dev)
+static void mgslpc_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-
-    if (debug_level >= DEBUG_LEVEL_INFO)
-           printk("mgslpc_detach(0x%p)\n", link);
+       if (debug_level >= DEBUG_LEVEL_INFO)
+               printk("mgslpc_detach(0x%p)\n", link);
 
-    if (link->state & DEV_CONFIG) {
-           ((MGSLPC_INFO *)link->priv)->stop = 1;
-           mgslpc_release((u_long)link);
-    }
+       ((MGSLPC_INFO *)link->priv)->stop = 1;
+       mgslpc_release((u_long)link);
 
-    mgslpc_remove_device((MGSLPC_INFO *)link->priv);
+       mgslpc_remove_device((MGSLPC_INFO *)link->priv);
 }
 
-static int mgslpc_suspend(struct pcmcia_device *dev)
+static int mgslpc_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        MGSLPC_INFO *info = link->priv;
 
-       link->state |= DEV_SUSPEND;
        info->stop = 1;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
 
        return 0;
 }
 
-static int mgslpc_resume(struct pcmcia_device *dev)
+static int mgslpc_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        MGSLPC_INFO *info = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
        info->stop = 0;
 
        return 0;
@@ -1280,7 +1246,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs)
        if (!info)
                return IRQ_NONE;
                
-       if (!(info->link.state & DEV_CONFIG))
+       if (!(info->p_dev->_locked))
                return IRQ_HANDLED;
 
        spin_lock(&info->lock);
@@ -3033,7 +2999,7 @@ static struct pcmcia_driver mgslpc_driver = {
        .drv            = {
                .name   = "synclink_cs",
        },
-       .probe          = mgslpc_attach,
+       .probe          = mgslpc_probe,
        .remove         = mgslpc_detach,
        .id_table       = mgslpc_ids,
        .suspend        = mgslpc_suspend,
index 3f5d607..a9c5a72 100644 (file)
@@ -504,7 +504,6 @@ static int  stl_echmcaintr(stlbrd_t *brdp);
 static int     stl_echpciintr(stlbrd_t *brdp);
 static int     stl_echpci64intr(stlbrd_t *brdp);
 static void    stl_offintr(void *private);
-static void    *stl_memalloc(int len);
 static stlbrd_t *stl_allocbrd(void);
 static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
 
@@ -939,17 +938,6 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
 
 /*****************************************************************************/
 
-/*
- *     Local driver kernel memory allocation routine.
- */
-
-static void *stl_memalloc(int len)
-{
-       return (void *) kmalloc(len, GFP_KERNEL);
-}
-
-/*****************************************************************************/
-
 /*
  *     Allocate a new board structure. Fill out the basic info in it.
  */
@@ -958,14 +946,13 @@ static stlbrd_t *stl_allocbrd(void)
 {
        stlbrd_t        *brdp;
 
-       brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
-       if (brdp == (stlbrd_t *) NULL) {
+       brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL);
+       if (!brdp) {
                printk("STALLION: failed to allocate memory (size=%d)\n",
                        sizeof(stlbrd_t));
-               return (stlbrd_t *) NULL;
+               return NULL;
        }
 
-       memset(brdp, 0, sizeof(stlbrd_t));
        brdp->magic = STL_BOARDMAGIC;
        return brdp;
 }
@@ -1017,9 +1004,9 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
        portp->refcount++;
 
        if ((portp->flags & ASYNC_INITIALIZED) == 0) {
-               if (portp->tx.buf == (char *) NULL) {
-                       portp->tx.buf = (char *) stl_memalloc(STL_TXBUFSIZE);
-                       if (portp->tx.buf == (char *) NULL)
+               if (!portp->tx.buf) {
+                       portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
+                       if (!portp->tx.buf)
                                return -ENOMEM;
                        portp->tx.head = portp->tx.buf;
                        portp->tx.tail = portp->tx.buf;
@@ -2178,13 +2165,12 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
  *     each ports data structures.
  */
        for (i = 0; (i < panelp->nrports); i++) {
-               portp = (stlport_t *) stl_memalloc(sizeof(stlport_t));
-               if (portp == (stlport_t *) NULL) {
+               portp = kzalloc(sizeof(stlport_t), GFP_KERNEL);
+               if (!portp) {
                        printk("STALLION: failed to allocate memory "
                                "(size=%d)\n", sizeof(stlport_t));
                        break;
                }
-               memset(portp, 0, sizeof(stlport_t));
 
                portp->magic = STL_PORTMAGIC;
                portp->portnr = i;
@@ -2315,13 +2301,12 @@ static inline int stl_initeio(stlbrd_t *brdp)
  *     can complete the setup.
  */
 
-       panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t));
-       if (panelp == (stlpanel_t *) NULL) {
+       panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
+       if (!panelp) {
                printk(KERN_WARNING "STALLION: failed to allocate memory "
                        "(size=%d)\n", sizeof(stlpanel_t));
-               return(-ENOMEM);
+               return -ENOMEM;
        }
-       memset(panelp, 0, sizeof(stlpanel_t));
 
        panelp->magic = STL_PANELMAGIC;
        panelp->brdnr = brdp->brdnr;
@@ -2490,13 +2475,12 @@ static inline int stl_initech(stlbrd_t *brdp)
                status = inb(ioaddr + ECH_PNLSTATUS);
                if ((status & ECH_PNLIDMASK) != nxtid)
                        break;
-               panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t));
-               if (panelp == (stlpanel_t *) NULL) {
+               panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
+               if (!panelp) {
                        printk("STALLION: failed to allocate memory "
                                "(size=%d)\n", sizeof(stlpanel_t));
                        break;
                }
-               memset(panelp, 0, sizeof(stlpanel_t));
                panelp->magic = STL_PANELMAGIC;
                panelp->brdnr = brdp->brdnr;
                panelp->panelnr = panelnr;
@@ -3074,8 +3058,8 @@ static int __init stl_init(void)
 /*
  *     Allocate a temporary write buffer.
  */
-       stl_tmpwritebuf = (char *) stl_memalloc(STL_TXBUFSIZE);
-       if (stl_tmpwritebuf == (char *) NULL)
+       stl_tmpwritebuf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
+       if (!stl_tmpwritebuf)
                printk("STALLION: failed to allocate memory (size=%d)\n",
                        STL_TXBUFSIZE);
 
index 0bfd1b6..98b126c 100644 (file)
@@ -376,7 +376,7 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, s
        return copied;
 }
 
-EXPORT_SYMBOL_GPL(tty_insert_flip_string);
+EXPORT_SYMBOL(tty_insert_flip_string);
 
 int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size)
 {
index ca4844c..acc5d47 100644 (file)
@@ -2328,6 +2328,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                case TIOCL_SETVESABLANK:
                        set_vesa_blanking(p);
                        break;
+               case TIOCL_GETKMSGREDIRECT:
+                       data = kmsg_redirect;
+                       ret = __put_user(data, p);
+                       break;
                case TIOCL_SETKMSGREDIRECT:
                        if (!capable(CAP_SYS_ADMIN)) {
                                ret = -EPERM;
index b582d0c..4f08984 100644 (file)
@@ -71,7 +71,7 @@ config EDAC_E7XXX
 
 config EDAC_E752X
        tristate "Intel e752x (e7520, e7525, e7320)"
-       depends on EDAC_MM_EDAC && PCI && X86
+       depends on EDAC_MM_EDAC && PCI && X86 && HOTPLUG
        help
          Support for error detection and correction on the Intel
          E7520, E7525, E7320 server chipsets.
index ccf528d..a5017de 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+#include <linux/leds.h>
 
 #define _IDE_DISK
 
@@ -317,6 +318,8 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
                return ide_stopped;
        }
 
+       ledtrig_ide_activity();
+
        pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
                 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
                 (unsigned long long)block, rq->nr_sectors,
index 0606bd2..9233b81 100644 (file)
@@ -375,7 +375,13 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
                }
        }
 
-       ide_end_request(drive, 1, rq->hard_nr_sectors);
+       if (rq->rq_disk) {
+               ide_driver_t *drv;
+
+               drv = *(ide_driver_t **)rq->rq_disk->private_data;;
+               drv->end_request(drive, 1, rq->hard_nr_sectors);
+       } else
+               ide_end_request(drive, 1, rq->hard_nr_sectors);
 }
 
 /*
index 6213bd3..4961f1e 100644 (file)
@@ -81,14 +81,14 @@ static const char ide_major[] = {
 };
 
 typedef struct ide_info_t {
-    dev_link_t link;
+       struct pcmcia_device    *p_dev;
     int                ndev;
     dev_node_t node;
     int                hd;
 } ide_info_t;
 
-static void ide_release(dev_link_t *);
-static void ide_config(dev_link_t *);
+static void ide_release(struct pcmcia_device *);
+static int ide_config(struct pcmcia_device *);
 
 static void ide_detach(struct pcmcia_device *p_dev);
 
@@ -103,10 +103,9 @@ static void ide_detach(struct pcmcia_device *p_dev);
 
 ======================================================================*/
 
-static int ide_attach(struct pcmcia_device *p_dev)
+static int ide_probe(struct pcmcia_device *link)
 {
     ide_info_t *info;
-    dev_link_t *link;
 
     DEBUG(0, "ide_attach()\n");
 
@@ -114,7 +113,9 @@ static int ide_attach(struct pcmcia_device *p_dev)
     info = kzalloc(sizeof(*info), GFP_KERNEL);
     if (!info)
        return -ENOMEM;
-    link = &info->link; link->priv = info;
+
+    info->p_dev = link;
+    link->priv = info;
 
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
@@ -122,16 +123,9 @@ static int ide_attach(struct pcmcia_device *p_dev)
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    ide_config(link);
-
-    return 0;
+    return ide_config(link);
 } /* ide_attach */
 
 /*======================================================================
@@ -143,14 +137,11 @@ static int ide_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void ide_detach(struct pcmcia_device *p_dev)
+static void ide_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-
     DEBUG(0, "ide_detach(0x%p)\n", link);
 
-    if (link->state & DEV_CONFIG)
-       ide_release(link);
+    ide_release(link);
 
     kfree(link->priv);
 } /* ide_detach */
@@ -177,9 +168,8 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void ide_config(dev_link_t *link)
+static int ide_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     ide_info_t *info = link->priv;
     tuple_t tuple;
     struct {
@@ -203,34 +193,30 @@ static void ide_config(dev_link_t *link)
     tuple.TupleDataMax = 255;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &stk->parse));
     link->conf.ConfigBase = stk->parse.config.base;
     link->conf.Present = stk->parse.config.rmask[0];
 
     tuple.DesiredTuple = CISTPL_MANFID;
-    if (!pcmcia_get_first_tuple(handle, &tuple) &&
-       !pcmcia_get_tuple_data(handle, &tuple) &&
-       !pcmcia_parse_tuple(handle, &tuple, &stk->parse))
+    if (!pcmcia_get_first_tuple(link, &tuple) &&
+       !pcmcia_get_tuple_data(link, &tuple) &&
+       !pcmcia_parse_tuple(link, &tuple, &stk->parse))
        is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
                  ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
                   (stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     /* Not sure if this is right... look up the current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf));
-    link->conf.Vcc = stk->conf.Vcc;
+    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
 
     pass = io_base = ctl_base = 0;
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
     tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (1) {
-       if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry;
-       if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry;
+       if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
+       if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
 
        /* Check for matching Vcc, unless we're desperate */
        if (!pass) {
@@ -244,10 +230,10 @@ static void ide_config(dev_link_t *link)
        }
 
        if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-           link->conf.Vpp1 = link->conf.Vpp2 =
+           link->conf.Vpp =
                cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
        else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-           link->conf.Vpp1 = link->conf.Vpp2 =
+           link->conf.Vpp =
                stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
        if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
@@ -261,14 +247,14 @@ static void ide_config(dev_link_t *link)
                link->io.NumPorts1 = 8;
                link->io.BasePort2 = io->win[1].base;
                link->io.NumPorts2 = (is_kme) ? 2 : 1;
-               if (pcmcia_request_io(link->handle, &link->io) != 0)
+               if (pcmcia_request_io(link, &link->io) != 0)
                        goto next_entry;
                io_base = link->io.BasePort1;
                ctl_base = link->io.BasePort2;
            } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
                link->io.NumPorts1 = io->win[0].len;
                link->io.NumPorts2 = 0;
-               if (pcmcia_request_io(link->handle, &link->io) != 0)
+               if (pcmcia_request_io(link, &link->io) != 0)
                        goto next_entry;
                io_base = link->io.BasePort1;
                ctl_base = link->io.BasePort1 + 0x0e;
@@ -281,16 +267,16 @@ static void ide_config(dev_link_t *link)
        if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
            memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
        if (pass) {
-           CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
-       } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) {
-           CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+           CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+       } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
+           CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
            memset(&stk->dflt, 0, sizeof(stk->dflt));
            pass++;
        }
     }
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     /* disable drive interrupts during IDE probe */
     outb(0x02, ctl_base);
@@ -301,12 +287,12 @@ static void ide_config(dev_link_t *link)
 
     /* retry registration in case device is still spinning up */
     for (hd = -1, i = 0; i < 10; i++) {
-       hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, handle);
+       hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
        if (hd >= 0) break;
        if (link->io.NumPorts1 == 0x20) {
            outb(0x02, ctl_base + 0x10);
            hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
-                               link->irq.AssignedIRQ, handle);
+                               link->irq.AssignedIRQ, link);
            if (hd >= 0) {
                io_base += 0x10;
                ctl_base += 0x10;
@@ -328,25 +314,23 @@ static void ide_config(dev_link_t *link)
     info->node.major = ide_major[hd];
     info->node.minor = 0;
     info->hd = hd;
-    link->dev = &info->node;
-    printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
-          info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10,
-          link->conf.Vpp1 / 10, link->conf.Vpp1 % 10);
+    link->dev_node = &info->node;
+    printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
+          info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
 
-    link->state &= ~DEV_CONFIG_PENDING;
     kfree(stk);
-    return;
+    return 0;
 
 err_mem:
     printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
     goto failed;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     kfree(stk);
     ide_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
+    return -ENODEV;
 } /* ide_config */
 
 /*======================================================================
@@ -357,7 +341,7 @@ failed:
     
 ======================================================================*/
 
-void ide_release(dev_link_t *link)
+void ide_release(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
     
@@ -369,37 +353,10 @@ void ide_release(dev_link_t *link)
        ide_unregister(info->hd);
     }
     info->ndev = 0;
-    link->dev = NULL;
-    
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    
-    link->state &= ~DEV_CONFIG;
 
+    pcmcia_disable_device(link);
 } /* ide_release */
 
-static int ide_suspend(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int ide_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (DEV_OK(link))
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-       return 0;
-}
 
 /*======================================================================
 
@@ -459,11 +416,9 @@ static struct pcmcia_driver ide_cs_driver = {
        .drv            = {
                .name   = "ide-cs",
        },
-       .probe          = ide_attach,
+       .probe          = ide_probe,
        .remove         = ide_detach,
        .id_table       = ide_ids,
-       .suspend        = ide_suspend,
-       .resume         = ide_resume,
 };
 
 static int __init init_ide_cs(void)
index d782893..07358fb 100644 (file)
@@ -49,9 +49,8 @@ static struct input_handle *evbug_connect(struct input_handler *handler, struct
 {
        struct input_handle *handle;
 
-       if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+       if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
                return NULL;
-       memset(handle, 0, sizeof(struct input_handle));
 
        handle->dev = dev;
        handle->handler = handler;
index 745979f..a34e3d9 100644 (file)
@@ -130,9 +130,8 @@ static int evdev_open(struct inode * inode, struct file * file)
        if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
                return accept_err;
 
-       if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
+       if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
                return -ENOMEM;
-       memset(list, 0, sizeof(struct evdev_list));
 
        list->evdev = evdev_table[i];
        list_add_tail(&list->node, &evdev_table[i]->list);
@@ -609,9 +608,8 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
                return NULL;
        }
 
-       if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL)))
+       if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL)))
                return NULL;
-       memset(evdev, 0, sizeof(struct evdev));
 
        INIT_LIST_HEAD(&evdev->list);
        init_waitqueue_head(&evdev->wait);
index b765a15..36644bf 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>       /* HZ */
+#include <linux/mutex.h>
 
 /*#include <asm/io.h>*/
 
@@ -43,10 +44,10 @@ EXPORT_SYMBOL(gameport_start_polling);
 EXPORT_SYMBOL(gameport_stop_polling);
 
 /*
- * gameport_sem protects entire gameport subsystem and is taken
+ * gameport_mutex protects entire gameport subsystem and is taken
  * every time gameport port or driver registrered or unregistered.
  */
-static DECLARE_MUTEX(gameport_sem);
+static DEFINE_MUTEX(gameport_mutex);
 
 static LIST_HEAD(gameport_list);
 
@@ -265,6 +266,7 @@ static void gameport_queue_event(void *object, struct module *owner,
        if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) {
                if (!try_module_get(owner)) {
                        printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type);
+                       kfree(event);
                        goto out;
                }
 
@@ -342,7 +344,7 @@ static void gameport_handle_event(void)
        struct gameport_event *event;
        struct gameport_driver *gameport_drv;
 
-       down(&gameport_sem);
+       mutex_lock(&gameport_mutex);
 
        /*
         * Note that we handle only one event here to give swsusp
@@ -379,7 +381,7 @@ static void gameport_handle_event(void)
                gameport_free_event(event);
        }
 
-       up(&gameport_sem);
+       mutex_unlock(&gameport_mutex);
 }
 
 /*
@@ -464,7 +466,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
        struct device_driver *drv;
        int retval;
 
-       retval = down_interruptible(&gameport_sem);
+       retval = mutex_lock_interruptible(&gameport_mutex);
        if (retval)
                return retval;
 
@@ -484,7 +486,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
                retval = -EINVAL;
        }
 
-       up(&gameport_sem);
+       mutex_unlock(&gameport_mutex);
 
        return retval;
 }
@@ -521,7 +523,7 @@ static void gameport_init_port(struct gameport *gameport)
 
        __module_get(THIS_MODULE);
 
-       init_MUTEX(&gameport->drv_sem);
+       mutex_init(&gameport->drv_mutex);
        device_initialize(&gameport->dev);
        snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id),
                 "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
@@ -661,10 +663,10 @@ void __gameport_register_port(struct gameport *gameport, struct module *owner)
  */
 void gameport_unregister_port(struct gameport *gameport)
 {
-       down(&gameport_sem);
+       mutex_lock(&gameport_mutex);
        gameport_disconnect_port(gameport);
        gameport_destroy_port(gameport);
-       up(&gameport_sem);
+       mutex_unlock(&gameport_mutex);
 }
 
 
@@ -717,7 +719,7 @@ void gameport_unregister_driver(struct gameport_driver *drv)
 {
        struct gameport *gameport;
 
-       down(&gameport_sem);
+       mutex_lock(&gameport_mutex);
        drv->ignore = 1;        /* so gameport_find_driver ignores it */
 
 start_over:
@@ -731,7 +733,7 @@ start_over:
        }
 
        driver_unregister(&drv->driver);
-       up(&gameport_sem);
+       mutex_unlock(&gameport_mutex);
 }
 
 static int gameport_bus_match(struct device *dev, struct device_driver *drv)
@@ -743,9 +745,9 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv)
 
 static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
 {
-       down(&gameport->drv_sem);
+       mutex_lock(&gameport->drv_mutex);
        gameport->drv = drv;
-       up(&gameport->drv_sem);
+       mutex_unlock(&gameport->drv_mutex);
 }
 
 int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
@@ -796,5 +798,5 @@ static void __exit gameport_exit(void)
        kthread_stop(gameport_task);
 }
 
-module_init(gameport_init);
+subsys_initcall(gameport_init);
 module_exit(gameport_exit);
index d2e55dc..3e2d28f 100644 (file)
@@ -252,14 +252,14 @@ static struct pnp_driver ns558_pnp_driver;
 
 #endif
 
-static int pnp_registered = 0;
-
 static int __init ns558_init(void)
 {
        int i = 0;
+       int error;
 
-       if (pnp_register_driver(&ns558_pnp_driver) >= 0)
-               pnp_registered = 1;
+       error = pnp_register_driver(&ns558_pnp_driver);
+       if (error && error != -ENODEV)  /* should be ENOSYS really */
+               return error;
 
 /*
  * Probe ISA ports after PnP, so that PnP ports that are already
@@ -270,7 +270,7 @@ static int __init ns558_init(void)
        while (ns558_isa_portlist[i])
                ns558_isa_probe(ns558_isa_portlist[i++]);
 
-       return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0;
+       return list_empty(&ns558_list) && error ? -ENODEV : 0;
 }
 
 static void __exit ns558_exit(void)
@@ -283,8 +283,7 @@ static void __exit ns558_exit(void)
                kfree(ns558);
        }
 
-       if (pnp_registered)
-               pnp_unregister_driver(&ns558_pnp_driver);
+       pnp_unregister_driver(&ns558_pnp_driver);
 }
 
 module_init(ns558_init);
index f8af094..a935abe 100644 (file)
 #include <linux/random.h>
 #include <linux/major.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/device.h>
+#include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
@@ -224,7 +226,7 @@ int input_open_device(struct input_handle *handle)
        struct input_dev *dev = handle->dev;
        int err;
 
-       err = down_interruptible(&dev->sem);
+       err = mutex_lock_interruptible(&dev->mutex);
        if (err)
                return err;
 
@@ -236,7 +238,7 @@ int input_open_device(struct input_handle *handle)
        if (err)
                handle->open--;
 
-       up(&dev->sem);
+       mutex_unlock(&dev->mutex);
 
        return err;
 }
@@ -255,13 +257,13 @@ void input_close_device(struct input_handle *handle)
 
        input_release_device(handle);
 
-       down(&dev->sem);
+       mutex_lock(&dev->mutex);
 
        if (!--dev->users && dev->close)
                dev->close(dev);
        handle->open--;
 
-       up(&dev->sem);
+       mutex_unlock(&dev->mutex);
 }
 
 static void input_link_handle(struct input_handle *handle)
@@ -315,21 +317,6 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
        return NULL;
 }
 
-static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, int max)
-{
-       int i;
-       int len = 0;
-
-       for (i = NBITS(max) - 1; i > 0; i--)
-               if (bitmap[i])
-                       break;
-
-       for (; i >= 0; i--)
-               len += snprintf(buf + len, max(buf_size - len, 0),
-                               "%lx%s", bitmap[i], i > 0 ? " " : "");
-       return len;
-}
-
 #ifdef CONFIG_PROC_FS
 
 static struct proc_dir_entry *proc_bus_input_dir;
@@ -342,7 +329,7 @@ static inline void input_wakeup_procfs_readers(void)
        wake_up(&input_devices_poll_wait);
 }
 
-static unsigned int input_devices_poll(struct file *file, poll_table *wait)
+static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
 {
        int state = input_devices_state;
        poll_wait(file, &input_devices_poll_wait, wait);
@@ -351,115 +338,171 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait)
        return 0;
 }
 
-#define SPRINTF_BIT(ev, bm)                                            \
-       do {                                                            \
-               len += sprintf(buf + len, "B: %s=", #ev);               \
-               len += input_print_bitmap(buf + len, INT_MAX,           \
-                                       dev->bm##bit, ev##_MAX);        \
-               len += sprintf(buf + len, "\n");                        \
-       } while (0)
+static struct list_head *list_get_nth_element(struct list_head *list, loff_t *pos)
+{
+       struct list_head *node;
+       loff_t i = 0;
 
-#define TEST_AND_SPRINTF_BIT(ev, bm)                                   \
-       do {                                                            \
-               if (test_bit(EV_##ev, dev->evbit))                      \
-                       SPRINTF_BIT(ev, bm);                            \
-       } while (0)
+       list_for_each(node, list)
+               if (i++ == *pos)
+                       return node;
+
+       return NULL;
+}
 
-static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+static struct list_head *list_get_next_element(struct list_head *list, struct list_head *element, loff_t *pos)
 {
-       struct input_dev *dev;
-       struct input_handle *handle;
-       const char *path;
+       if (element->next == list)
+               return NULL;
+
+       ++(*pos);
+       return element->next;
+}
+
+static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       /* acquire lock here ... Yes, we do need locking, I knowi, I know... */
+
+       return list_get_nth_element(&input_dev_list, pos);
+}
 
-       off_t at = 0;
-       int len, cnt = 0;
+static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       return list_get_next_element(&input_dev_list, v, pos);
+}
 
-       list_for_each_entry(dev, &input_dev_list, node) {
+static void input_devices_seq_stop(struct seq_file *seq, void *v)
+{
+       /* release lock here */
+}
 
-               path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
+                                  unsigned long *bitmap, int max)
+{
+       int i;
 
-               len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
-                       dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
+       for (i = NBITS(max) - 1; i > 0; i--)
+               if (bitmap[i])
+                       break;
 
-               len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
-               len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
-               len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : "");
-               len += sprintf(buf + len, "H: Handlers=");
+       seq_printf(seq, "B: %s=", name);
+       for (; i >= 0; i--)
+               seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : "");
+       seq_putc(seq, '\n');
+}
 
-               list_for_each_entry(handle, &dev->h_list, d_node)
-                       len += sprintf(buf + len, "%s ", handle->name);
-
-               len += sprintf(buf + len, "\n");
-
-               SPRINTF_BIT(EV, ev);
-               TEST_AND_SPRINTF_BIT(KEY, key);
-               TEST_AND_SPRINTF_BIT(REL, rel);
-               TEST_AND_SPRINTF_BIT(ABS, abs);
-               TEST_AND_SPRINTF_BIT(MSC, msc);
-               TEST_AND_SPRINTF_BIT(LED, led);
-               TEST_AND_SPRINTF_BIT(SND, snd);
-               TEST_AND_SPRINTF_BIT(FF, ff);
-               TEST_AND_SPRINTF_BIT(SW, sw);
-
-               len += sprintf(buf + len, "\n");
-
-               at += len;
-
-               if (at >= pos) {
-                       if (!*start) {
-                               *start = buf + (pos - (at - len));
-                               cnt = at - pos;
-                       } else  cnt += len;
-                       buf += len;
-                       if (cnt >= count)
-                               break;
-               }
+static int input_devices_seq_show(struct seq_file *seq, void *v)
+{
+       struct input_dev *dev = container_of(v, struct input_dev, node);
+       const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+       struct input_handle *handle;
 
-               kfree(path);
-       }
+       seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
+                  dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
 
-       if (&dev->node == &input_dev_list)
-               *eof = 1;
+       seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
+       seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+       seq_printf(seq, "S: Sysfs=%s\n", path ? path : "");
+       seq_printf(seq, "H: Handlers=");
 
-       return (count > cnt) ? cnt : count;
+       list_for_each_entry(handle, &dev->h_list, d_node)
+               seq_printf(seq, "%s ", handle->name);
+       seq_putc(seq, '\n');
+
+       input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
+       if (test_bit(EV_KEY, dev->evbit))
+               input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
+       if (test_bit(EV_REL, dev->evbit))
+               input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX);
+       if (test_bit(EV_ABS, dev->evbit))
+               input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX);
+       if (test_bit(EV_MSC, dev->evbit))
+               input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX);
+       if (test_bit(EV_LED, dev->evbit))
+               input_seq_print_bitmap(seq, "LED", dev->ledbit, LED_MAX);
+       if (test_bit(EV_SND, dev->evbit))
+               input_seq_print_bitmap(seq, "SND", dev->sndbit, SND_MAX);
+       if (test_bit(EV_FF, dev->evbit))
+               input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
+       if (test_bit(EV_SW, dev->evbit))
+               input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
+
+       seq_putc(seq, '\n');
+
+       kfree(path);
+       return 0;
 }
 
-static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+static struct seq_operations input_devices_seq_ops = {
+       .start  = input_devices_seq_start,
+       .next   = input_devices_seq_next,
+       .stop   = input_devices_seq_stop,
+       .show   = input_devices_seq_show,
+};
+
+static int input_proc_devices_open(struct inode *inode, struct file *file)
 {
-       struct input_handler *handler;
+       return seq_open(file, &input_devices_seq_ops);
+}
 
-       off_t at = 0;
-       int len = 0, cnt = 0;
-       int i = 0;
+static struct file_operations input_devices_fileops = {
+       .owner          = THIS_MODULE,
+       .open           = input_proc_devices_open,
+       .poll           = input_proc_devices_poll,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
 
-       list_for_each_entry(handler, &input_handler_list, node) {
+static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       /* acquire lock here ... Yes, we do need locking, I knowi, I know... */
+       seq->private = (void *)(unsigned long)*pos;
+       return list_get_nth_element(&input_handler_list, pos);
+}
+
+static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       seq->private = (void *)(unsigned long)(*pos + 1);
+       return list_get_next_element(&input_handler_list, v, pos);
+}
 
-               if (handler->fops)
-                       len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",
-                               i++, handler->name, handler->minor);
-               else
-                       len = sprintf(buf, "N: Number=%d Name=%s\n",
-                               i++, handler->name);
+static void input_handlers_seq_stop(struct seq_file *seq, void *v)
+{
+       /* release lock here */
+}
 
-               at += len;
+static int input_handlers_seq_show(struct seq_file *seq, void *v)
+{
+       struct input_handler *handler = container_of(v, struct input_handler, node);
 
-               if (at >= pos) {
-                       if (!*start) {
-                               *start = buf + (pos - (at - len));
-                               cnt = at - pos;
-                       } else  cnt += len;
-                       buf += len;
-                       if (cnt >= count)
-                               break;
-               }
-       }
-       if (&handler->node == &input_handler_list)
-               *eof = 1;
+       seq_printf(seq, "N: Number=%ld Name=%s",
+                  (unsigned long)seq->private, handler->name);
+       if (handler->fops)
+               seq_printf(seq, " Minor=%d", handler->minor);
+       seq_putc(seq, '\n');
 
-       return (count > cnt) ? cnt : count;
+       return 0;
 }
+static struct seq_operations input_handlers_seq_ops = {
+       .start  = input_handlers_seq_start,
+       .next   = input_handlers_seq_next,
+       .stop   = input_handlers_seq_stop,
+       .show   = input_handlers_seq_show,
+};
 
-static struct file_operations input_fileops;
+static int input_proc_handlers_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &input_handlers_seq_ops);
+}
+
+static struct file_operations input_handlers_fileops = {
+       .owner          = THIS_MODULE,
+       .open           = input_proc_handlers_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
 
 static int __init input_proc_init(void)
 {
@@ -471,20 +514,19 @@ static int __init input_proc_init(void)
 
        proc_bus_input_dir->owner = THIS_MODULE;
 
-       entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);
+       entry = create_proc_entry("devices", 0, proc_bus_input_dir);
        if (!entry)
                goto fail1;
 
        entry->owner = THIS_MODULE;
-       input_fileops = *entry->proc_fops;
-       input_fileops.poll = input_devices_poll;
-       entry->proc_fops = &input_fileops;
+       entry->proc_fops = &input_devices_fileops;
 
-       entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
+       entry = create_proc_entry("handlers", 0, proc_bus_input_dir);
        if (!entry)
                goto fail2;
 
        entry->owner = THIS_MODULE;
+       entry->proc_fops = &input_handlers_fileops;
 
        return 0;
 
@@ -512,13 +554,14 @@ static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
        struct input_dev *input_dev = to_input_dev(dev);                        \
        int retval;                                                             \
                                                                                \
-       retval = down_interruptible(&input_dev->sem);                           \
+       retval = mutex_lock_interruptible(&input_dev->mutex);                   \
        if (retval)                                                             \
                return retval;                                                  \
                                                                                \
-       retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : "");  \
+       retval = scnprintf(buf, PAGE_SIZE,                                      \
+                          "%s\n", input_dev->name ? input_dev->name : "");     \
                                                                                \
-       up(&input_dev->sem);                                                    \
+       mutex_unlock(&input_dev->mutex);                                        \
                                                                                \
        return retval;                                                          \
 }                                                                              \
@@ -528,46 +571,51 @@ INPUT_DEV_STRING_ATTR_SHOW(name);
 INPUT_DEV_STRING_ATTR_SHOW(phys);
 INPUT_DEV_STRING_ATTR_SHOW(uniq);
 
-static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr,
-                              unsigned int min, unsigned int max)
+static int input_print_modalias_bits(char *buf, int size,
+                                    char name, unsigned long *bm,
+                                    unsigned int min_bit, unsigned int max_bit)
 {
-       int len, i;
+       int len = 0, i;
 
-       len = snprintf(buf, size, "%c", prefix);
-       for (i = min; i < max; i++)
-               if (arr[LONG(i)] & BIT(i))
-                       len += snprintf(buf + len, size - len, "%X,", i);
+       len += snprintf(buf, max(size, 0), "%c", name);
+       for (i = min_bit; i < max_bit; i++)
+               if (bm[LONG(i)] & BIT(i))
+                       len += snprintf(buf + len, max(size - len, 0), "%X,", i);
        return len;
 }
 
-static int print_modalias(char *buf, int size, struct input_dev *id)
+static int input_print_modalias(char *buf, int size, struct input_dev *id,
+                               int add_cr)
 {
        int len;
 
-       len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-",
-                      id->id.bustype,
-                      id->id.vendor,
-                      id->id.product,
-                      id->id.version);
-
-       len += print_modalias_bits(buf + len, size - len, 'e', id->evbit,
-                                  0, EV_MAX);
-       len += print_modalias_bits(buf + len, size - len, 'k', id->keybit,
-                                  KEY_MIN_INTERESTING, KEY_MAX);
-       len += print_modalias_bits(buf + len, size - len, 'r', id->relbit,
-                                  0, REL_MAX);
-       len += print_modalias_bits(buf + len, size - len, 'a', id->absbit,
-                                  0, ABS_MAX);
-       len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit,
-                                  0, MSC_MAX);
-       len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit,
-                                  0, LED_MAX);
-       len += print_modalias_bits(buf + len, size - len, 's', id->sndbit,
-                                  0, SND_MAX);
-       len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit,
-                                  0, FF_MAX);
-       len += print_modalias_bits(buf + len, size - len, 'w', id->swbit,
-                                  0, SW_MAX);
+       len = snprintf(buf, max(size, 0),
+                      "input:b%04Xv%04Xp%04Xe%04X-",
+                      id->id.bustype, id->id.vendor,
+                      id->id.product, id->id.version);
+
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'e', id->evbit, 0, EV_MAX);
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'r', id->relbit, 0, REL_MAX);
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'a', id->absbit, 0, ABS_MAX);
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'm', id->mscbit, 0, MSC_MAX);
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'l', id->ledbit, 0, LED_MAX);
+       len += input_print_modalias_bits(buf + len, size - len,
+                               's', id->sndbit, 0, SND_MAX);
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'f', id->ffbit, 0, FF_MAX);
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'w', id->swbit, 0, SW_MAX);
+
+       if (add_cr)
+               len += snprintf(buf + len, max(size - len, 0), "\n");
+
        return len;
 }
 
@@ -576,9 +624,9 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
        struct input_dev *id = to_input_dev(dev);
        ssize_t len;
 
-       len = print_modalias(buf, PAGE_SIZE, id);
-       len += snprintf(buf + len, PAGE_SIZE-len, "\n");
-       return len;
+       len = input_print_modalias(buf, PAGE_SIZE, id, 1);
+
+       return max_t(int, len, PAGE_SIZE);
 }
 static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
 
@@ -598,7 +646,7 @@ static struct attribute_group input_dev_attr_group = {
 static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf)   \
 {                                                                              \
        struct input_dev *input_dev = to_input_dev(dev);                        \
-       return sprintf(buf, "%04x\n", input_dev->id.name);                      \
+       return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name);         \
 }                                                                              \
 static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
 
@@ -620,11 +668,33 @@ static struct attribute_group input_dev_id_attr_group = {
        .attrs  = input_dev_id_attrs,
 };
 
+static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
+                             int max, int add_cr)
+{
+       int i;
+       int len = 0;
+
+       for (i = NBITS(max) - 1; i > 0; i--)
+               if (bitmap[i])
+                       break;
+
+       for (; i >= 0; i--)
+               len += snprintf(buf + len, max(buf_size - len, 0),
+                               "%lx%s", bitmap[i], i > 0 ? " " : "");
+
+       if (add_cr)
+               len += snprintf(buf + len, max(buf_size - len, 0), "\n");
+
+       return len;
+}
+
 #define INPUT_DEV_CAP_ATTR(ev, bm)                                             \
 static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf)    \
 {                                                                              \
        struct input_dev *input_dev = to_input_dev(dev);                        \
-       return input_print_bitmap(buf, PAGE_SIZE, input_dev->bm##bit, ev##_MAX);\
+       int len = input_print_bitmap(buf, PAGE_SIZE,                            \
+                                    input_dev->bm##bit, ev##_MAX, 1);          \
+       return min_t(int, len, PAGE_SIZE);                                      \
 }                                                                              \
 static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
 
@@ -669,8 +739,8 @@ static void input_dev_release(struct class_device *class_dev)
  * device bitfields.
  */
 static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
-                                   char *buffer, int buffer_size, int *cur_len,
-                                   const char *name, unsigned long *bitmap, int max)
+                                  char *buffer, int buffer_size, int *cur_len,
+                                  const char *name, unsigned long *bitmap, int max)
 {
        if (*cur_index >= num_envp - 1)
                return -ENOMEM;
@@ -678,12 +748,36 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
        envp[*cur_index] = buffer + *cur_len;
 
        *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
-       if (*cur_len > buffer_size)
+       if (*cur_len >= buffer_size)
                return -ENOMEM;
 
        *cur_len += input_print_bitmap(buffer + *cur_len,
                                        max(buffer_size - *cur_len, 0),
-                                       bitmap, max) + 1;
+                                       bitmap, max, 0) + 1;
+       if (*cur_len > buffer_size)
+               return -ENOMEM;
+
+       (*cur_index)++;
+       return 0;
+}
+
+static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index,
+                                        char *buffer, int buffer_size, int *cur_len,
+                                        struct input_dev *dev)
+{
+       if (*cur_index >= num_envp - 1)
+               return -ENOMEM;
+
+       envp[*cur_index] = buffer + *cur_len;
+
+       *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0),
+                            "MODALIAS=");
+       if (*cur_len >= buffer_size)
+               return -ENOMEM;
+
+       *cur_len += input_print_modalias(buffer + *cur_len,
+                                        max(buffer_size - *cur_len, 0),
+                                        dev, 0) + 1;
        if (*cur_len > buffer_size)
                return -ENOMEM;
 
@@ -693,7 +787,7 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
 
 #define INPUT_ADD_HOTPLUG_VAR(fmt, val...)                             \
        do {                                                            \
-               int err = add_uevent_var(envp, num_envp, &i,    \
+               int err = add_uevent_var(envp, num_envp, &i,            \
                                        buffer, buffer_size, &len,      \
                                        fmt, val);                      \
                if (err)                                                \
@@ -709,6 +803,16 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
                        return err;                                     \
        } while (0)
 
+#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev)                            \
+       do {                                                            \
+               int err = input_add_uevent_modalias_var(envp,           \
+                                       num_envp, &i,                   \
+                                       buffer, buffer_size, &len,      \
+                                       dev);                           \
+               if (err)                                                \
+                       return err;                                     \
+       } while (0)
+
 static int input_dev_uevent(struct class_device *cdev, char **envp,
                            int num_envp, char *buffer, int buffer_size)
 {
@@ -744,9 +848,7 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
        if (test_bit(EV_SW, dev->evbit))
                INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
 
-       envp[i++] = buffer + len;
-       len += snprintf(buffer + len, buffer_size - len, "MODALIAS=");
-       len += print_modalias(buffer + len, buffer_size - len, dev) + 1;
+       INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
 
        envp[i] = NULL;
        return 0;
@@ -790,7 +892,7 @@ int input_register_device(struct input_dev *dev)
                return -EINVAL;
        }
 
-       init_MUTEX(&dev->sem);
+       mutex_init(&dev->mutex);
        set_bit(EV_SYN, dev->evbit);
 
        /*
index 20e2972..949bdce 100644 (file)
@@ -171,9 +171,8 @@ static int joydev_open(struct inode *inode, struct file *file)
        if (i >= JOYDEV_MINORS || !joydev_table[i])
                return -ENODEV;
 
-       if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
+       if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL)))
                return -ENOMEM;
-       memset(list, 0, sizeof(struct joydev_list));
 
        list->joydev = joydev_table[i];
        list_add_tail(&list->node, &joydev_table[i]->list);
@@ -457,9 +456,8 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
                return NULL;
        }
 
-       if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL)))
+       if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL)))
                return NULL;
-       memset(joydev, 0, sizeof(struct joydev));
 
        INIT_LIST_HEAD(&joydev->list);
        init_waitqueue_head(&joydev->wait);
index ec55a29..7249d32 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/mutex.h>
 
 #include <asm/system.h>
 #include <asm/amigahw.h>
@@ -52,7 +53,7 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is
 __obsolete_setup("amijoy=");
 
 static int amijoy_used;
-static DECLARE_MUTEX(amijoy_sem);
+static DEFINE_MUTEX(amijoy_mutex);
 static struct input_dev *amijoy_dev[2];
 static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
 
@@ -85,7 +86,7 @@ static int amijoy_open(struct input_dev *dev)
 {
        int err;
 
-       err = down_interruptible(&amijoy_sem);
+       err = mutex_lock_interruptible(&amijoy_mutex);
        if (err)
                return err;
 
@@ -97,16 +98,16 @@ static int amijoy_open(struct input_dev *dev)
 
        amijoy_used++;
 out:
-       up(&amijoy_sem);
+       mutex_unlock(&amijoy_mutex);
        return err;
 }
 
 static void amijoy_close(struct input_dev *dev)
 {
-       down(&amijoy_sem);
+       mutex_lock(&amijoy_mutex);
        if (!--amijoy_used)
                free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
-       up(&amijoy_sem);
+       mutex_unlock(&amijoy_mutex);
 }
 
 static int __init amijoy_init(void)
index dcffc34..e618946 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/init.h>
 #include <linux/parport.h>
 #include <linux/input.h>
+#include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
@@ -111,7 +112,7 @@ struct db9 {
        struct pardevice *pd;
        int mode;
        int used;
-       struct semaphore sem;
+       struct mutex mutex;
        char phys[DB9_MAX_DEVICES][32];
 };
 
@@ -525,7 +526,7 @@ static int db9_open(struct input_dev *dev)
        struct parport *port = db9->pd->port;
        int err;
 
-       err = down_interruptible(&db9->sem);
+       err = mutex_lock_interruptible(&db9->mutex);
        if (err)
                return err;
 
@@ -539,7 +540,7 @@ static int db9_open(struct input_dev *dev)
                mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
        }
 
-       up(&db9->sem);
+       mutex_unlock(&db9->mutex);
        return 0;
 }
 
@@ -548,14 +549,14 @@ static void db9_close(struct input_dev *dev)
        struct db9 *db9 = dev->private;
        struct parport *port = db9->pd->port;
 
-       down(&db9->sem);
+       mutex_lock(&db9->mutex);
        if (!--db9->used) {
                del_timer_sync(&db9->timer);
                parport_write_control(port, 0x00);
                parport_data_forward(port);
                parport_release(db9->pd);
        }
-       up(&db9->sem);
+       mutex_unlock(&db9->mutex);
 }
 
 static struct db9 __init *db9_probe(int parport, int mode)
@@ -603,7 +604,7 @@ static struct db9 __init *db9_probe(int parport, int mode)
                goto err_unreg_pardev;
        }
 
-       init_MUTEX(&db9->sem);
+       mutex_init(&db9->mutex);
        db9->pd = pd;
        db9->mode = mode;
        init_timer(&db9->timer);
index 900587a..ecbdb6b 100644 (file)
@@ -7,6 +7,7 @@
  *  Based on the work of:
  *     Andree Borrmann         John Dahlstrom
  *     David Kuder             Nathan Hand
+ *     Raphael Assenat
  */
 
 /*
@@ -36,6 +37,7 @@
 #include <linux/init.h>
 #include <linux/parport.h>
 #include <linux/input.h>
+#include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
@@ -72,8 +74,9 @@ __obsolete_setup("gc_3=");
 #define GC_N64         6
 #define GC_PSX         7
 #define GC_DDR         8
+#define GC_SNESMOUSE   9
 
-#define GC_MAX         8
+#define GC_MAX         9
 
 #define GC_REFRESH_TIME        HZ/100
 
@@ -83,7 +86,7 @@ struct gc {
        struct timer_list timer;
        unsigned char pads[GC_MAX + 1];
        int used;
-       struct semaphore sem;
+       struct mutex mutex;
        char phys[GC_MAX_DEVICES][32];
 };
 
@@ -93,7 +96,7 @@ static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
 
 static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
                                "Multisystem 2-button joystick", "N64 controller", "PSX controller",
-                               "PSX DDR controller" };
+                               "PSX DDR controller", "SNES mouse" };
 /*
  * N64 support.
  */
@@ -205,9 +208,12 @@ static void gc_n64_process_packet(struct gc *gc)
  * NES/SNES support.
  */
 
-#define GC_NES_DELAY   6       /* Delay between bits - 6us */
-#define GC_NES_LENGTH  8       /* The NES pads use 8 bits of data */
-#define GC_SNES_LENGTH 12      /* The SNES true length is 16, but the last 4 bits are unused */
+#define GC_NES_DELAY           6       /* Delay between bits - 6us */
+#define GC_NES_LENGTH          8       /* The NES pads use 8 bits of data */
+#define GC_SNES_LENGTH         12      /* The SNES true length is 16, but the
+                                          last 4 bits are unused */
+#define GC_SNESMOUSE_LENGTH    32      /* The SNES mouse uses 32 bits, the first
+                                          16 bits are equivalent to a gamepad */
 
 #define GC_NES_POWER   0xfc
 #define GC_NES_CLOCK   0x01
@@ -242,11 +248,15 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
 
 static void gc_nes_process_packet(struct gc *gc)
 {
-       unsigned char data[GC_SNES_LENGTH];
+       unsigned char data[GC_SNESMOUSE_LENGTH];
        struct input_dev *dev;
-       int i, j, s;
+       int i, j, s, len;
+       char x_rel, y_rel;
+
+       len = gc->pads[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH :
+                       (gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH);
 
-       gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
+       gc_nes_read_packet(gc, len, data);
 
        for (i = 0; i < GC_MAX_DEVICES; i++) {
 
@@ -269,6 +279,44 @@ static void gc_nes_process_packet(struct gc *gc)
                        for (j = 0; j < 8; j++)
                                input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
 
+               if (s & gc->pads[GC_SNESMOUSE]) {
+                       /*
+                        * The 4 unused bits from SNES controllers appear to be ID bits
+                        * so use them to make sure iwe are dealing with a mouse.
+                        * gamepad is connected. This is important since
+                        * my SNES gamepad sends 1's for bits 16-31, which
+                        * cause the mouse pointer to quickly move to the
+                        * upper left corner of the screen.
+                        */
+                       if (!(s & data[12]) && !(s & data[13]) &&
+                           !(s & data[14]) && (s & data[15])) {
+                               input_report_key(dev, BTN_LEFT, s & data[9]);
+                               input_report_key(dev, BTN_RIGHT, s & data[8]);
+
+                               x_rel = y_rel = 0;
+                               for (j = 0; j < 7; j++) {
+                                       x_rel <<= 1;
+                                       if (data[25 + j] & s)
+                                               x_rel |= 1;
+
+                                       y_rel <<= 1;
+                                       if (data[17 + j] & s)
+                                               y_rel |= 1;
+                               }
+
+                               if (x_rel) {
+                                       if (data[24] & s)
+                                               x_rel = -x_rel;
+                                       input_report_rel(dev, REL_X, x_rel);
+                               }
+
+                               if (y_rel) {
+                                       if (data[16] & s)
+                                               y_rel = -y_rel;
+                                       input_report_rel(dev, REL_Y, y_rel);
+                               }
+                       }
+               }
                input_sync(dev);
        }
 }
@@ -524,10 +572,10 @@ static void gc_timer(unsigned long private)
                gc_n64_process_packet(gc);
 
 /*
- * NES and SNES pads
+ * NES and SNES pads or mouse
  */
 
-       if (gc->pads[GC_NES] || gc->pads[GC_SNES])
+       if (gc->pads[GC_NES] || gc->pads[GC_SNES] || gc->pads[GC_SNESMOUSE])
                gc_nes_process_packet(gc);
 
 /*
@@ -552,7 +600,7 @@ static int gc_open(struct input_dev *dev)
        struct gc *gc = dev->private;
        int err;
 
-       err = down_interruptible(&gc->sem);
+       err = mutex_lock_interruptible(&gc->mutex);
        if (err)
                return err;
 
@@ -562,7 +610,7 @@ static int gc_open(struct input_dev *dev)
                mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
        }
 
-       up(&gc->sem);
+       mutex_unlock(&gc->mutex);
        return 0;
 }
 
@@ -570,13 +618,13 @@ static void gc_close(struct input_dev *dev)
 {
        struct gc *gc = dev->private;
 
-       down(&gc->sem);
+       mutex_lock(&gc->mutex);
        if (!--gc->used) {
                del_timer_sync(&gc->timer);
                parport_write_control(gc->pd->port, 0x00);
                parport_release(gc->pd);
        }
-       up(&gc->sem);
+       mutex_unlock(&gc->mutex);
 }
 
 static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
@@ -609,10 +657,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
        input_dev->open = gc_open;
        input_dev->close = gc_close;
 
-       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+       if (pad_type != GC_SNESMOUSE) {
+               input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
-       for (i = 0; i < 2; i++)
-               input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
+               for (i = 0; i < 2; i++)
+                       input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
+       } else
+               input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 
        gc->pads[0] |= gc_status_bit[idx];
        gc->pads[pad_type] |= gc_status_bit[idx];
@@ -630,6 +681,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
 
                        break;
 
+               case GC_SNESMOUSE:
+                       set_bit(BTN_LEFT, input_dev->keybit);
+                       set_bit(BTN_RIGHT, input_dev->keybit);
+                       set_bit(REL_X, input_dev->relbit);
+                       set_bit(REL_Y, input_dev->relbit);
+                       break;
+
                case GC_SNES:
                        for (i = 4; i < 8; i++)
                                set_bit(gc_snes_btn[i], input_dev->keybit);
@@ -693,7 +751,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
                goto err_unreg_pardev;
        }
 
-       init_MUTEX(&gc->sem);
+       mutex_init(&gc->mutex);
        gc->pd = pd;
        init_timer(&gc->timer);
        gc->timer.data = (long) gc;
index 4678b6d..2b8e845 100644 (file)
@@ -42,14 +42,14 @@ static int make_magnitude_modifier(struct iforce* iforce,
        unsigned char data[3];
 
        if (!no_alloc) {
-               down(&iforce->mem_mutex);
+               mutex_lock(&iforce->mem_mutex);
                if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
                        iforce->device_memory.start, iforce->device_memory.end, 2L,
                        NULL, NULL)) {
-                       up(&iforce->mem_mutex);
+                       mutex_unlock(&iforce->mem_mutex);
                        return -ENOMEM;
                }
-               up(&iforce->mem_mutex);
+               mutex_unlock(&iforce->mem_mutex);
        }
 
        data[0] = LO(mod_chunk->start);
@@ -75,14 +75,14 @@ static int make_period_modifier(struct iforce* iforce,
        period = TIME_SCALE(period);
 
        if (!no_alloc) {
-               down(&iforce->mem_mutex);
+               mutex_lock(&iforce->mem_mutex);
                if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
                        iforce->device_memory.start, iforce->device_memory.end, 2L,
                        NULL, NULL)) {
-                       up(&iforce->mem_mutex);
+                       mutex_unlock(&iforce->mem_mutex);
                        return -ENOMEM;
                }
-               up(&iforce->mem_mutex);
+               mutex_unlock(&iforce->mem_mutex);
        }
 
        data[0] = LO(mod_chunk->start);
@@ -115,14 +115,14 @@ static int make_envelope_modifier(struct iforce* iforce,
        fade_duration = TIME_SCALE(fade_duration);
 
        if (!no_alloc) {
-               down(&iforce->mem_mutex);
+               mutex_lock(&iforce->mem_mutex);
                if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
                        iforce->device_memory.start, iforce->device_memory.end, 2L,
                        NULL, NULL)) {
-                       up(&iforce->mem_mutex);
+                       mutex_unlock(&iforce->mem_mutex);
                        return -ENOMEM;
                }
-               up(&iforce->mem_mutex);
+               mutex_unlock(&iforce->mem_mutex);
        }
 
        data[0] = LO(mod_chunk->start);
@@ -152,14 +152,14 @@ static int make_condition_modifier(struct iforce* iforce,
        unsigned char data[10];
 
        if (!no_alloc) {
-               down(&iforce->mem_mutex);
+               mutex_lock(&iforce->mem_mutex);
                if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
                        iforce->device_memory.start, iforce->device_memory.end, 2L,
                        NULL, NULL)) {
-                       up(&iforce->mem_mutex);
+                       mutex_unlock(&iforce->mem_mutex);
                        return -ENOMEM;
                }
-               up(&iforce->mem_mutex);
+               mutex_unlock(&iforce->mem_mutex);
        }
 
        data[0] = LO(mod_chunk->start);
index b6bc049..ab0a26b 100644 (file)
@@ -350,7 +350,7 @@ int iforce_init_device(struct iforce *iforce)
 
        init_waitqueue_head(&iforce->wait);
        spin_lock_init(&iforce->xmit_lock);
-       init_MUTEX(&iforce->mem_mutex);
+       mutex_init(&iforce->mem_mutex);
        iforce->xmit.buf = iforce->xmit_data;
        iforce->dev = input_dev;
 
index 146f406..668f245 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/serio.h>
 #include <linux/config.h>
 #include <linux/circ_buf.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 /* This module provides arbitrary resource management routines.
  * I use it to manage the device's memory.
@@ -45,6 +45,7 @@
  */
 #include <linux/ioport.h>
 
+
 #define IFORCE_MAX_LENGTH      16
 
 /* iforce::bus */
@@ -146,7 +147,7 @@ struct iforce {
        wait_queue_head_t wait;
        struct resource device_memory;
        struct iforce_core_effect core_effects[FF_EFFECTS_MAX];
-       struct semaphore mem_mutex;
+       struct mutex mem_mutex;
 };
 
 /* Get hi and low bytes of a 16-bits int */
index b154938..5570fd5 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
@@ -86,7 +87,7 @@ static struct tgfx {
        char phys[TGFX_MAX_DEVICES][32];
        int sticks;
        int used;
-       struct semaphore sem;
+       struct mutex sem;
 } *tgfx_base[TGFX_MAX_PORTS];
 
 /*
@@ -128,7 +129,7 @@ static int tgfx_open(struct input_dev *dev)
        struct tgfx *tgfx = dev->private;
        int err;
 
-       err = down_interruptible(&tgfx->sem);
+       err = mutex_lock_interruptible(&tgfx->sem);
        if (err)
                return err;
 
@@ -138,7 +139,7 @@ static int tgfx_open(struct input_dev *dev)
                mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
        }
 
-       up(&tgfx->sem);
+       mutex_unlock(&tgfx->sem);
        return 0;
 }
 
@@ -146,13 +147,13 @@ static void tgfx_close(struct input_dev *dev)
 {
        struct tgfx *tgfx = dev->private;
 
-       down(&tgfx->sem);
+       mutex_lock(&tgfx->sem);
        if (!--tgfx->used) {
                del_timer_sync(&tgfx->timer);
                parport_write_control(tgfx->pd->port, 0x00);
                parport_release(tgfx->pd);
        }
-       up(&tgfx->sem);
+       mutex_unlock(&tgfx->sem);
 }
 
 
@@ -191,7 +192,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
                goto err_unreg_pardev;
        }
 
-       init_MUTEX(&tgfx->sem);
+       mutex_init(&tgfx->sem);
        tgfx->pd = pd;
        init_timer(&tgfx->timer);
        tgfx->timer.data = (long) tgfx;
index 3b0ac3b..a9dda56 100644 (file)
@@ -13,7 +13,7 @@ menuconfig INPUT_KEYBOARD
 if INPUT_KEYBOARD
 
 config KEYBOARD_ATKBD
-       tristate "AT keyboard" if !X86_PC
+       tristate "AT keyboard" if EMBEDDED || !X86_PC
        default y
        select SERIO
        select SERIO_LIBPS2
index ffacf6e..fad04b6 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/serio.h>
 #include <linux/workqueue.h>
 #include <linux/libps2.h>
+#include <linux/mutex.h>
 
 #define DRIVER_DESC    "AT and PS/2 keyboard driver"
 
@@ -216,7 +217,7 @@ struct atkbd {
        unsigned long time;
 
        struct work_struct event_work;
-       struct semaphore event_sem;
+       struct mutex event_mutex;
        unsigned long event_mask;
 };
 
@@ -302,19 +303,19 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
        if (atkbd->translated) {
 
                if (atkbd->emul ||
-                   !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
-                     code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
-                    (code == ATKBD_RET_ERR && !atkbd->err_xl) ||
-                    (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
+                   (code != ATKBD_RET_EMUL0 && code != ATKBD_RET_EMUL1 &&
+                    code != ATKBD_RET_HANGUEL && code != ATKBD_RET_HANJA &&
+                    (code != ATKBD_RET_ERR || atkbd->err_xl) &&
+                    (code != ATKBD_RET_BAT || atkbd->bat_xl))) {
                        atkbd->release = code >> 7;
                        code &= 0x7f;
                }
 
                if (!atkbd->emul) {
                     if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
-                       atkbd->bat_xl = !atkbd->release;
+                       atkbd->bat_xl = !(data >> 7);
                     if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
-                       atkbd->err_xl = !atkbd->release;
+                       atkbd->err_xl = !(data >> 7);
                }
        }
 
@@ -449,7 +450,7 @@ static void atkbd_event_work(void *data)
        unsigned char param[2];
        int i, j;
 
-       down(&atkbd->event_sem);
+       mutex_lock(&atkbd->event_mutex);
 
        if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) {
                param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
@@ -480,7 +481,7 @@ static void atkbd_event_work(void *data)
                ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
        }
 
-       up(&atkbd->event_sem);
+       mutex_unlock(&atkbd->event_mutex);
 }
 
 /*
@@ -846,7 +847,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
        atkbd->dev = dev;
        ps2_init(&atkbd->ps2dev, serio);
        INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd);
-       init_MUTEX(&atkbd->event_sem);
+       mutex_init(&atkbd->event_mutex);
 
        switch (serio->id.type) {
 
@@ -862,9 +863,6 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
        atkbd->softrepeat = atkbd_softrepeat;
        atkbd->scroll = atkbd_scroll;
 
-       if (!atkbd->write)
-               atkbd->softrepeat = 1;
-
        if (atkbd->softrepeat)
                atkbd->softraw = 1;
 
index e301ee4..96c6bf7 100644 (file)
 #define KB_COLS                                12
 #define KB_ROWMASK(r)          (1 << (r))
 #define SCANCODE(r,c)          ( ((r)<<4) + (c) + 1 )
-/* zero code, 124 scancodes + 3 hinge combinations */
-#define        NR_SCANCODES            ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 )
-#define SCAN_INTERVAL          (HZ/10)
+/* zero code, 124 scancodes */
+#define        NR_SCANCODES            ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 )
 
-#define HINGE_SCAN_INTERVAL            (HZ/4)
+#define SCAN_INTERVAL          (50) /* ms */
+#define HINGE_SCAN_INTERVAL    (250) /* ms */
 
 #define CORGI_KEY_CALENDER     KEY_F1
 #define CORGI_KEY_ADDRESS      KEY_F2
@@ -49,9 +49,6 @@
 #define CORGI_KEY_MAIL         KEY_F10
 #define CORGI_KEY_OK           KEY_F11
 #define CORGI_KEY_MENU         KEY_F12
-#define CORGI_HINGE_0          KEY_KP0
-#define CORGI_HINGE_1          KEY_KP1
-#define CORGI_HINGE_2          KEY_KP2
 
 static unsigned char corgikbd_keycode[NR_SCANCODES] = {
        0,                                                                                                                /* 0 */
@@ -63,7 +60,6 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = {
        CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0,            /* 81-96 */
        KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0,  /* 97-112 */
        CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0,   /* 113-124 */
-       CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2       /* 125-127 */
 };
 
 
@@ -187,7 +183,7 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
 
        /* if any keys are pressed, enable the timer */
        if (num_pressed)
-               mod_timer(&corgikbd_data->timer, jiffies + SCAN_INTERVAL);
+               mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL));
 
        spin_unlock_irqrestore(&corgikbd_data->lock, flags);
 }
@@ -228,6 +224,7 @@ static void corgikbd_timer_callback(unsigned long data)
  *          0x0c - Keyboard and Screen Closed
  */
 
+#define READ_GPIO_BIT(x)    (GPLR(x) & GPIO_bit(x))
 #define HINGE_STABLE_COUNT 2
 static int sharpsl_hinge_state;
 static int hinge_count;
@@ -239,6 +236,7 @@ static void corgikbd_hinge_timer(unsigned long data)
        unsigned long flags;
 
        gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
+       gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0);
        if (gprr != sharpsl_hinge_state) {
                hinge_count = 0;
                sharpsl_hinge_state = gprr;
@@ -249,27 +247,38 @@ static void corgikbd_hinge_timer(unsigned long data)
 
                        input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
                        input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
+                       input_report_switch(corgikbd_data->input, SW_2, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0));
                        input_sync(corgikbd_data->input);
 
                        spin_unlock_irqrestore(&corgikbd_data->lock, flags);
                }
        }
-       mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
+       mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
 }
 
 #ifdef CONFIG_PM
 static int corgikbd_suspend(struct platform_device *dev, pm_message_t state)
 {
+       int i;
        struct corgikbd *corgikbd = platform_get_drvdata(dev);
+
        corgikbd->suspended = 1;
+       /* strobe 0 is the power key so this can't be made an input for
+          powersaving therefore i = 1 */
+       for (i = 1; i < CORGI_KEY_STROBE_NUM; i++)
+               pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN);
 
        return 0;
 }
 
 static int corgikbd_resume(struct platform_device *dev)
 {
+       int i;
        struct corgikbd *corgikbd = platform_get_drvdata(dev);
 
+       for (i = 1; i < CORGI_KEY_STROBE_NUM; i++)
+               pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
+
        /* Upon resume, ignore the suspend key for a short while */
        corgikbd->suspend_jiffies=jiffies;
        corgikbd->suspended = 0;
@@ -333,10 +342,11 @@ static int __init corgikbd_probe(struct platform_device *pdev)
        clear_bit(0, input_dev->keybit);
        set_bit(SW_0, input_dev->swbit);
        set_bit(SW_1, input_dev->swbit);
+       set_bit(SW_2, input_dev->swbit);
 
        input_register_device(corgikbd->input);
 
-       mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
+       mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
 
        /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
        for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
@@ -351,6 +361,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
        for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
                pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
 
+       /* Setup the headphone jack as an input */
+       pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
+
        return 0;
 }
 
index 0a90962..1dca3cf 100644 (file)
@@ -66,7 +66,7 @@ static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] =
 static char hil_language[][16] = { HIL_LOCALE_MAP };
 
 struct hil_kbd {
-       struct input_dev dev;
+       struct input_dev *dev;
        struct serio *serio;
 
        /* Input buffer and index for packets from HIL bus. */
@@ -86,7 +86,7 @@ struct hil_kbd {
 /* Process a complete packet after transfer from the HIL */
 static void hil_kbd_process_record(struct hil_kbd *kbd)
 {
-       struct input_dev *dev = &kbd->dev;
+       struct input_dev *dev = kbd->dev;
        hil_packet *data = kbd->data;
        hil_packet p;
        int idx, i, cnt;
@@ -240,8 +240,8 @@ static void hil_kbd_disconnect(struct serio *serio)
                return;
        }
 
-       input_unregister_device(&kbd->dev);
        serio_close(serio);
+       input_unregister_device(kbd->dev);
        kfree(kbd);
 }
 
@@ -250,17 +250,22 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
        struct hil_kbd  *kbd;
        uint8_t         did, *idd;
        int             i;
-       
-       kbd = kmalloc(sizeof(*kbd), GFP_KERNEL);
+
+       kbd = kzalloc(sizeof(*kbd), GFP_KERNEL);
        if (!kbd)
                return -ENOMEM;
-       memset(kbd, 0, sizeof(struct hil_kbd));
 
-       if (serio_open(serio, drv)) goto bail0;
+       kbd->dev = input_allocate_device();
+       if (!kbd->dev)
+               goto bail0;
+
+       kbd->dev->private = kbd;
+
+       if (serio_open(serio, drv))
+               goto bail1;
 
        serio_set_drvdata(serio, kbd);
        kbd->serio = serio;
-       kbd->dev.private = kbd;
 
        init_MUTEX_LOCKED(&(kbd->sem));
 
@@ -302,38 +307,38 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
                        did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
                break;
        default:
-               goto bail1;
+               goto bail2;
        }
 
        if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
                printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
-               goto bail1;
+               goto bail2;
        }
 
 
-       kbd->dev.evbit[0]       = BIT(EV_KEY) | BIT(EV_REP);
-       kbd->dev.ledbit[0]      = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
-       kbd->dev.keycodemax     = HIL_KEYCODES_SET1_TBLSIZE;
-       kbd->dev.keycodesize    = sizeof(hil_kbd_set1[0]);
-       kbd->dev.keycode        = hil_kbd_set1;
-       kbd->dev.name           = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
-       kbd->dev.phys           = "hpkbd/input0";       /* XXX */
+       kbd->dev->evbit[0]      = BIT(EV_KEY) | BIT(EV_REP);
+       kbd->dev->ledbit[0]     = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+       kbd->dev->keycodemax    = HIL_KEYCODES_SET1_TBLSIZE;
+       kbd->dev->keycodesize   = sizeof(hil_kbd_set1[0]);
+       kbd->dev->keycode       = hil_kbd_set1;
+       kbd->dev->name          = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
+       kbd->dev->phys          = "hpkbd/input0";       /* XXX */
 
-       kbd->dev.id.bustype     = BUS_HIL;
-       kbd->dev.id.vendor      = PCI_VENDOR_ID_HP;
-       kbd->dev.id.product     = 0x0001; /* TODO: get from kbd->rsc */
-       kbd->dev.id.version     = 0x0100; /* TODO: get from kbd->rsc */
-       kbd->dev.dev            = &serio->dev;
+       kbd->dev->id.bustype    = BUS_HIL;
+       kbd->dev->id.vendor     = PCI_VENDOR_ID_HP;
+       kbd->dev->id.product    = 0x0001; /* TODO: get from kbd->rsc */
+       kbd->dev->id.version    = 0x0100; /* TODO: get from kbd->rsc */
+       kbd->dev->dev           = &serio->dev;
 
        for (i = 0; i < 128; i++) {
-               set_bit(hil_kbd_set1[i], kbd->dev.keybit);
-               set_bit(hil_kbd_set3[i], kbd->dev.keybit);
+               set_bit(hil_kbd_set1[i], kbd->dev->keybit);
+               set_bit(hil_kbd_set3[i], kbd->dev->keybit);
        }
-       clear_bit(0, kbd->dev.keybit);
+       clear_bit(0, kbd->dev->keybit);
 
-       input_register_device(&kbd->dev);
+       input_register_device(kbd->dev);
        printk(KERN_INFO "input: %s, ID: %d\n",
-               kbd->dev.name, did);
+               kbd->dev->name, did);
 
        serio->write(serio, 0);
        serio->write(serio, 0);
@@ -343,8 +348,10 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
        up(&(kbd->sem));
 
        return 0;
- bail1:
+ bail2:
        serio_close(serio);
+ bail1:
+       input_free_device(kbd->dev);
  bail0:
        kfree(kbd);
        serio_set_drvdata(serio, NULL);
index e95bc05..33edd03 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
  *  Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
- *  Copyright (C) 1999-2003 Helge Deller <deller@gmx.de>
+ *  Copyright (C) 1999-2006 Helge Deller <deller@gmx.de>
  *
  *  Very basic HP Human Interface Loop (HIL) driver.
  *  This driver handles the keyboard on HP300 (m68k) and on some 
@@ -90,7 +90,7 @@ static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
 
 /* HIL structure */
 static struct {
-       struct input_dev dev;
+       struct input_dev *dev;
 
        unsigned int curdev;
        
@@ -117,7 +117,7 @@ static void poll_finished(void)
                down = (hil_dev.data[1] & 1) == 0;
                scode = hil_dev.data[1] >> 1;
                key = hphilkeyb_keycode[scode];
-               input_report_key(&hil_dev.dev, key, down);
+               input_report_key(hil_dev.dev, key, down);
                break;
        }
        hil_dev.curdev = 0;
@@ -207,9 +207,14 @@ hil_keyb_init(void)
        unsigned int i, kbid;
        wait_queue_head_t hil_wait;
 
-       if (hil_dev.dev.id.bustype) {
+       if (hil_dev.dev) {
                return -ENODEV; /* already initialized */
        }
+
+       hil_dev.dev = input_allocate_device();
+       if (!hil_dev.dev)
+               return -ENOMEM;
+       hil_dev.dev->private = &hil_dev;
        
 #if defined(CONFIG_HP300)
        if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
@@ -247,28 +252,26 @@ hil_keyb_init(void)
        c = 0;
        hil_do(HIL_WRITEKBDSADR, &c, 1);
        
-       init_input_dev(&hil_dev.dev);
-
        for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
                if (hphilkeyb_keycode[i] != KEY_RESERVED)
-                       set_bit(hphilkeyb_keycode[i], hil_dev.dev.keybit);
-
-       hil_dev.dev.evbit[0]    = BIT(EV_KEY) | BIT(EV_REP);
-       hil_dev.dev.ledbit[0]   = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
-       hil_dev.dev.keycodemax  = HIL_KEYCODES_SET1_TBLSIZE;
-        hil_dev.dev.keycodesize = sizeof(hphilkeyb_keycode[0]);
-       hil_dev.dev.keycode     = hphilkeyb_keycode;
-       hil_dev.dev.name        = "HIL keyboard";
-       hil_dev.dev.phys        = "hpkbd/input0";
-
-       hil_dev.dev.id.bustype  = BUS_HIL;
-       hil_dev.dev.id.vendor   = PCI_VENDOR_ID_HP;
-       hil_dev.dev.id.product  = 0x0001;
-       hil_dev.dev.id.version  = 0x0010;
-
-       input_register_device(&hil_dev.dev);
+                       set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit);
+
+       hil_dev.dev->evbit[0]    = BIT(EV_KEY) | BIT(EV_REP);
+       hil_dev.dev->ledbit[0]   = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+       hil_dev.dev->keycodemax  = HIL_KEYCODES_SET1_TBLSIZE;
+       hil_dev.dev->keycodesize = sizeof(hphilkeyb_keycode[0]);
+       hil_dev.dev->keycode     = hphilkeyb_keycode;
+       hil_dev.dev->name       = "HIL keyboard";
+       hil_dev.dev->phys       = "hpkbd/input0";
+
+       hil_dev.dev->id.bustype = BUS_HIL;
+       hil_dev.dev->id.vendor  = PCI_VENDOR_ID_HP;
+       hil_dev.dev->id.product = 0x0001;
+       hil_dev.dev->id.version = 0x0010;
+
+       input_register_device(hil_dev.dev);
        printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
-               hil_dev.dev.name, kbid, HILBASE, HIL_IRQ);
+               hil_dev.dev->name, kbid, HILBASE, HIL_IRQ);
 
        return 0;
 }
@@ -329,7 +332,9 @@ static void __exit hil_exit(void)
        /* Turn off interrupts */
        hil_do(HIL_INTOFF, NULL, 0);
 
-       input_unregister_device(&hil_dev.dev);
+       input_unregister_device(hil_dev.dev);
+
+       hil_dev.dev = NULL;
 
 #if defined(CONFIG_PARISC)
        unregister_parisc_driver(&hil_driver);
index 83999d5..bc61cf8 100644 (file)
@@ -30,6 +30,7 @@
 #define SCANCODE(r,c)          (((r)<<4) + (c) + 1)
 #define        NR_SCANCODES            ((KB_ROWS<<4) + 1)
 
+#define SCAN_INTERVAL          (50) /* ms */
 #define HINGE_SCAN_INTERVAL    (150) /* ms */
 
 #define SPITZ_KEY_CALENDER     KEY_F1
@@ -230,7 +231,7 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs
 
        /* if any keys are pressed, enable the timer */
        if (num_pressed)
-               mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100));
+               mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL));
 
        spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
 }
@@ -287,6 +288,7 @@ static void spitzkbd_hinge_timer(unsigned long data)
        unsigned long flags;
 
        state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
+       state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT));
        if (state != sharpsl_hinge_state) {
                hinge_count = 0;
                sharpsl_hinge_state = state;
@@ -299,6 +301,7 @@ static void spitzkbd_hinge_timer(unsigned long data)
 
                input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
                input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+               input_report_switch(spitzkbd_data->input, SW_2, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0));
                input_sync(spitzkbd_data->input);
 
                spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
@@ -397,6 +400,7 @@ static int __init spitzkbd_probe(struct platform_device *dev)
        clear_bit(0, input_dev->keybit);
        set_bit(SW_0, input_dev->swbit);
        set_bit(SW_1, input_dev->swbit);
+       set_bit(SW_2, input_dev->swbit);
 
        input_register_device(input_dev);
 
@@ -432,6 +436,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
        request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
                    SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
                    "Spitzkbd SWB", spitzkbd);
+       request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
+                   SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+                   "Spitzkbd HP", spitzkbd);
 
        printk(KERN_INFO "input: Spitz Keyboard Registered\n");
 
@@ -450,6 +457,7 @@ static int spitzkbd_remove(struct platform_device *dev)
        free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
        free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
        free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
+       free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd);
 
        del_timer_sync(&spitzkbd->htimer);
        del_timer_sync(&spitzkbd->timer);
index 1ef477f..afd3221 100644 (file)
@@ -24,7 +24,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("PC Speaker beeper driver");
 MODULE_LICENSE("GPL");
 
-static struct platform_device *pcspkr_platform_device;
 static DEFINE_SPINLOCK(i8253_beep_lock);
 
 static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -135,35 +134,11 @@ static struct platform_driver pcspkr_platform_driver = {
 
 static int __init pcspkr_init(void)
 {
-       int err;
-
-       err = platform_driver_register(&pcspkr_platform_driver);
-       if (err)
-               return err;
-
-       pcspkr_platform_device = platform_device_alloc("pcspkr", -1);
-       if (!pcspkr_platform_device) {
-               err = -ENOMEM;
-               goto err_unregister_driver;
-       }
-
-       err = platform_device_add(pcspkr_platform_device);
-       if (err)
-               goto err_free_device;
-
-       return 0;
-
- err_free_device:
-       platform_device_put(pcspkr_platform_device);
- err_unregister_driver:
-       platform_driver_unregister(&pcspkr_platform_driver);
-
-       return err;
+       return platform_driver_register(&pcspkr_platform_driver);
 }
 
 static void __exit pcspkr_exit(void)
 {
-       platform_device_unregister(pcspkr_platform_device);
        platform_driver_unregister(&pcspkr_platform_driver);
 }
 
index 546ed9b..d723e9a 100644 (file)
@@ -194,7 +194,7 @@ static int uinput_open(struct inode *inode, struct file *file)
        if (!newdev)
                return -ENOMEM;
 
-       init_MUTEX(&newdev->sem);
+       mutex_init(&newdev->mutex);
        spin_lock_init(&newdev->requests_lock);
        init_waitqueue_head(&newdev->requests_waitq);
        init_waitqueue_head(&newdev->waitq);
@@ -340,7 +340,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t
        struct uinput_device *udev = file->private_data;
        int retval;
 
-       retval = down_interruptible(&udev->sem);
+       retval = mutex_lock_interruptible(&udev->mutex);
        if (retval)
                return retval;
 
@@ -348,7 +348,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t
                        uinput_inject_event(udev, buffer, count) :
                        uinput_setup_device(udev, buffer, count);
 
-       up(&udev->sem);
+       mutex_unlock(&udev->mutex);
 
        return retval;
 }
@@ -369,7 +369,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
        if (retval)
                return retval;
 
-       retval = down_interruptible(&udev->sem);
+       retval = mutex_lock_interruptible(&udev->mutex);
        if (retval)
                return retval;
 
@@ -388,7 +388,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
        }
 
  out:
-       up(&udev->sem);
+       mutex_unlock(&udev->mutex);
 
        return retval;
 }
@@ -439,7 +439,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
        udev = file->private_data;
 
-       retval = down_interruptible(&udev->sem);
+       retval = mutex_lock_interruptible(&udev->mutex);
        if (retval)
                return retval;
 
@@ -589,7 +589,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        }
 
  out:
-       up(&udev->sem);
+       mutex_unlock(&udev->mutex);
        return retval;
 }
 
index c2bf2ed..69f0217 100644 (file)
@@ -55,7 +55,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 #define HIL_PTR_MAX_LENGTH 16
 
 struct hil_ptr {
-       struct input_dev dev;
+       struct input_dev *dev;
        struct serio *serio;
 
        /* Input buffer and index for packets from HIL bus. */
@@ -79,7 +79,7 @@ struct hil_ptr {
 /* Process a complete packet after transfer from the HIL */
 static void hil_ptr_process_record(struct hil_ptr *ptr)
 {
-       struct input_dev *dev = &ptr->dev;
+       struct input_dev *dev = ptr->dev;
        hil_packet *data = ptr->data;
        hil_packet p;
        int idx, i, cnt, laxis;
@@ -148,12 +148,12 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
                if (absdev) {
                        val = lo + (hi<<8);
 #ifdef TABLET_AUTOADJUST
-                       if (val < ptr->dev.absmin[ABS_X + i])
-                               ptr->dev.absmin[ABS_X + i] = val;
-                       if (val > ptr->dev.absmax[ABS_X + i])
-                               ptr->dev.absmax[ABS_X + i] = val;
+                       if (val < dev->absmin[ABS_X + i])
+                               dev->absmin[ABS_X + i] = val;
+                       if (val > dev->absmax[ABS_X + i])
+                               dev->absmax[ABS_X + i] = val;
 #endif
-                       if (i%3) val = ptr->dev.absmax[ABS_X + i] - val;
+                       if (i%3) val = dev->absmax[ABS_X + i] - val;
                        input_report_abs(dev, ABS_X + i, val);
                } else {
                        val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
@@ -233,26 +233,32 @@ static void hil_ptr_disconnect(struct serio *serio)
                return;
        }
 
-       input_unregister_device(&ptr->dev);
        serio_close(serio);
+       input_unregister_device(ptr->dev);
        kfree(ptr);
 }
 
 static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 {
-       struct hil_ptr  *ptr;
-       char            *txt;
-       unsigned int    i, naxsets, btntype;
-       uint8_t         did, *idd;
+       struct hil_ptr   *ptr;
+       char             *txt;
+       unsigned int     i, naxsets, btntype;
+       uint8_t          did, *idd;
 
-       if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return -ENOMEM;
-       memset(ptr, 0, sizeof(struct hil_ptr));
+       if (!(ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL)))
+               return -ENOMEM;
 
-       if (serio_open(serio, driver)) goto bail0;
+       ptr->dev = input_allocate_device();
+       if (!ptr->dev)
+               goto bail0;
+
+       ptr->dev->private = ptr;
+
+       if (serio_open(serio, driver))
+               goto bail1;
 
        serio_set_drvdata(serio, ptr);
        ptr->serio = serio;
-       ptr->dev.private = ptr;
 
        init_MUTEX_LOCKED(&(ptr->sem));
 
@@ -283,25 +289,24 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 
        up(&(ptr->sem));
 
-       init_input_dev(&ptr->dev);
        did = ptr->idd[0];
        idd = ptr->idd + 1;
        txt = "unknown";
        if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
-               ptr->dev.evbit[0] = BIT(EV_REL);
+               ptr->dev->evbit[0] = BIT(EV_REL);
                txt = "relative";
        }
 
        if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) {
-               ptr->dev.evbit[0] = BIT(EV_ABS);
+               ptr->dev->evbit[0] = BIT(EV_ABS);
                txt = "absolute";
        }
-       if (!ptr->dev.evbit[0]) {
-               goto bail1;
+       if (!ptr->dev->evbit[0]) {
+               goto bail2;
        }
 
        ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
-       if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY);
+       if (ptr->nbtn) ptr->dev->evbit[0] |= BIT(EV_KEY);
 
        naxsets = HIL_IDD_NUM_AXSETS(*idd);
        ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
@@ -325,7 +330,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
                btntype = BTN_MOUSE;
 
        for (i = 0; i < ptr->nbtn; i++) {
-               set_bit(btntype | i, ptr->dev.keybit);
+               set_bit(btntype | i, ptr->dev->keybit);
                ptr->btnmap[i] = btntype | i;
        }
 
@@ -337,50 +342,52 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 
        if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
                for (i = 0; i < ptr->naxes; i++) {
-                       set_bit(REL_X + i, ptr->dev.relbit);
+                       set_bit(REL_X + i, ptr->dev->relbit);
                }
                for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
-                       set_bit(REL_X + i, ptr->dev.relbit);
+                       set_bit(REL_X + i, ptr->dev->relbit);
                }
        } else {
                for (i = 0; i < ptr->naxes; i++) {
-                       set_bit(ABS_X + i, ptr->dev.absbit);
-                       ptr->dev.absmin[ABS_X + i] = 0;
-                       ptr->dev.absmax[ABS_X + i] = 
+                       set_bit(ABS_X + i, ptr->dev->absbit);
+                       ptr->dev->absmin[ABS_X + i] = 0;
+                       ptr->dev->absmax[ABS_X + i] =
                                HIL_IDD_AXIS_MAX((ptr->idd + 1), i);
                }
                for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
-                       set_bit(ABS_X + i, ptr->dev.absbit);
-                       ptr->dev.absmin[ABS_X + i] = 0;
-                       ptr->dev.absmax[ABS_X + i] = 
+                       set_bit(ABS_X + i, ptr->dev->absbit);
+                       ptr->dev->absmin[ABS_X + i] = 0;
+                       ptr->dev->absmax[ABS_X + i] =
                                HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3));
                }
 #ifdef TABLET_AUTOADJUST
                for (i = 0; i < ABS_MAX; i++) {
-                       int diff = ptr->dev.absmax[ABS_X + i] / 10;
-                       ptr->dev.absmin[ABS_X + i] += diff;
-                       ptr->dev.absmax[ABS_X + i] -= diff;
+                       int diff = ptr->dev->absmax[ABS_X + i] / 10;
+                       ptr->dev->absmin[ABS_X + i] += diff;
+                       ptr->dev->absmax[ABS_X + i] -= diff;
                }
 #endif
        }
 
-       ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME;
+       ptr->dev->name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME;
 
-       ptr->dev.id.bustype     = BUS_HIL;
-       ptr->dev.id.vendor      = PCI_VENDOR_ID_HP;
-       ptr->dev.id.product     = 0x0001; /* TODO: get from ptr->rsc */
-       ptr->dev.id.version     = 0x0100; /* TODO: get from ptr->rsc */
-       ptr->dev.dev            = &serio->dev;
+       ptr->dev->id.bustype    = BUS_HIL;
+       ptr->dev->id.vendor     = PCI_VENDOR_ID_HP;
+       ptr->dev->id.product    = 0x0001; /* TODO: get from ptr->rsc */
+       ptr->dev->id.version    = 0x0100; /* TODO: get from ptr->rsc */
+       ptr->dev->dev           = &serio->dev;
 
-       input_register_device(&ptr->dev);
+       input_register_device(ptr->dev);
        printk(KERN_INFO "input: %s (%s), ID: %d\n",
-                ptr->dev.name, 
+               ptr->dev->name,
                (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
                did);
 
        return 0;
- bail1:
+ bail2:
        serio_close(serio);
+ bail1:
+       input_free_device(ptr->dev);
  bail0:
        kfree(ptr);
        serio_set_drvdata(serio, NULL);
index ad62174..32d70ed 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 #include <linux/libps2.h>
+#include <linux/mutex.h>
+
 #include "psmouse.h"
 #include "synaptics.h"
 #include "logips2pp.h"
@@ -98,13 +100,13 @@ __obsolete_setup("psmouse_resetafter=");
 __obsolete_setup("psmouse_rate=");
 
 /*
- * psmouse_sem protects all operations changing state of mouse
+ * psmouse_mutex protects all operations changing state of mouse
  * (connecting, disconnecting, changing rate or resolution via
  * sysfs). We could use a per-device semaphore but since there
  * rarely more than one PS/2 mouse connected and since semaphore
  * is taken in "slow" paths it is not worth it.
  */
-static DECLARE_MUTEX(psmouse_sem);
+static DEFINE_MUTEX(psmouse_mutex);
 
 static struct workqueue_struct *kpsmoused_wq;
 
@@ -868,7 +870,7 @@ static void psmouse_resync(void *p)
        int failed = 0, enabled = 0;
        int i;
 
-       down(&psmouse_sem);
+       mutex_lock(&psmouse_mutex);
 
        if (psmouse->state != PSMOUSE_RESYNCING)
                goto out;
@@ -948,7 +950,7 @@ static void psmouse_resync(void *p)
        if (parent)
                psmouse_activate(parent);
  out:
-       up(&psmouse_sem);
+       mutex_unlock(&psmouse_mutex);
 }
 
 /*
@@ -974,14 +976,14 @@ static void psmouse_disconnect(struct serio *serio)
 
        sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
 
-       down(&psmouse_sem);
+       mutex_lock(&psmouse_mutex);
 
        psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 
        /* make sure we don't have a resync in progress */
-       up(&psmouse_sem);
+       mutex_unlock(&psmouse_mutex);
        flush_workqueue(kpsmoused_wq);
-       down(&psmouse_sem);
+       mutex_lock(&psmouse_mutex);
 
        if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
                parent = serio_get_drvdata(serio->parent);
@@ -1004,7 +1006,7 @@ static void psmouse_disconnect(struct serio *serio)
        if (parent)
                psmouse_activate(parent);
 
-       up(&psmouse_sem);
+       mutex_unlock(&psmouse_mutex);
 }
 
 static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)
@@ -1076,7 +1078,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
        struct input_dev *input_dev;
        int retval = -ENOMEM;
 
-       down(&psmouse_sem);
+       mutex_lock(&psmouse_mutex);
 
        /*
         * If this is a pass-through port deactivate parent so the device
@@ -1144,7 +1146,7 @@ out:
        if (parent)
                psmouse_activate(parent);
 
-       up(&psmouse_sem);
+       mutex_unlock(&psmouse_mutex);
        return retval;
 }
 
@@ -1161,7 +1163,7 @@ static int psmouse_reconnect(struct serio *serio)
                return -1;
        }
 
-       down(&psmouse_sem);
+       mutex_lock(&psmouse_mutex);
 
        if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
                parent = serio_get_drvdata(serio->parent);
@@ -1195,7 +1197,7 @@ out:
        if (parent)
                psmouse_activate(parent);
 
-       up(&psmouse_sem);
+       mutex_unlock(&psmouse_mutex);
        return rc;
 }
 
@@ -1273,7 +1275,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
                goto out_unpin;
        }
 
-       retval = down_interruptible(&psmouse_sem);
+       retval = mutex_lock_interruptible(&psmouse_mutex);
        if (retval)
                goto out_unpin;
 
@@ -1281,7 +1283,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
 
        if (psmouse->state == PSMOUSE_IGNORE) {
                retval = -ENODEV;
-               goto out_up;
+               goto out_unlock;
        }
 
        if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
@@ -1299,8 +1301,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
        if (parent)
                psmouse_activate(parent);
 
- out_up:
-       up(&psmouse_sem);
+ out_unlock:
+       mutex_unlock(&psmouse_mutex);
  out_unpin:
        serio_unpin_driver(serio);
        return retval;
@@ -1357,11 +1359,11 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
                        return -EIO;
                }
 
-               up(&psmouse_sem);
+               mutex_unlock(&psmouse_mutex);
                serio_unpin_driver(serio);
                serio_unregister_child_port(serio);
                serio_pin_driver_uninterruptible(serio);
-               down(&psmouse_sem);
+               mutex_lock(&psmouse_mutex);
 
                if (serio->drv != &psmouse_drv) {
                        input_free_device(new_dev);
index 2051bec..ad5d0a8 100644 (file)
@@ -247,14 +247,12 @@ static void synaptics_pt_create(struct psmouse *psmouse)
 {
        struct serio *serio;
 
-       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
        if (!serio) {
                printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
                return;
        }
 
-       memset(serio, 0, sizeof(struct serio));
-
        serio->id.type = SERIO_PS_PSTHRU;
        strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
        strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
@@ -605,14 +603,21 @@ static struct dmi_system_id toshiba_dmi_table[] = {
                .ident = "Toshiba Satellite",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-                       DMI_MATCH(DMI_PRODUCT_NAME , "Satellite"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
                },
        },
        {
                .ident = "Toshiba Dynabook",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-                       DMI_MATCH(DMI_PRODUCT_NAME , "dynabook"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"),
+               },
+       },
+       {
+               .ident = "Toshiba Portege M300",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
                },
        },
        { }
@@ -623,10 +628,9 @@ int synaptics_init(struct psmouse *psmouse)
 {
        struct synaptics_data *priv;
 
-       psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL);
+       psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
        if (!priv)
                return -1;
-       memset(priv, 0, sizeof(struct synaptics_data));
 
        if (synaptics_query_hardware(psmouse)) {
                printk(KERN_ERR "Unable to query Synaptics hardware.\n");
index 9abed18..b685a50 100644 (file)
@@ -412,9 +412,8 @@ static int mousedev_open(struct inode * inode, struct file * file)
        if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
                return -ENODEV;
 
-       if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
+       if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
                return -ENOMEM;
-       memset(list, 0, sizeof(struct mousedev_list));
 
        spin_lock_init(&list->packet_lock);
        list->pos_x = xres / 2;
@@ -626,9 +625,8 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
                return NULL;
        }
 
-       if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
+       if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL)))
                return NULL;
-       memset(mousedev, 0, sizeof(struct mousedev));
 
        INIT_LIST_HEAD(&mousedev->list);
        init_waitqueue_head(&mousedev->wait);
index bfc5c63..526e607 100644 (file)
@@ -103,9 +103,8 @@ static struct input_handle *power_connect(struct input_handler *handler,
 {
        struct input_handle *handle;
 
-       if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+       if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
                return NULL;
-       memset(handle, 0, sizeof(struct input_handle));
 
        handle->dev = dev;
        handle->handler = handler;
index a7b0de0..c0b1e4b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/input/serio/gscps2.c
  *
- * Copyright (c) 2004 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2004-2006 Helge Deller <deller@gmx.de>
  * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
  * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org>
  *
@@ -354,7 +354,7 @@ static int __init gscps2_probe(struct parisc_device *dev)
        memset(serio, 0, sizeof(struct serio));
        ps2port->port = serio;
        ps2port->padev = dev;
-       ps2port->addr = ioremap(hpa, GSC_STATUS + 4);
+       ps2port->addr = ioremap_nocache(hpa, GSC_STATUS + 4);
        spin_lock_init(&ps2port->lock);
 
        gscps2_reset(ps2port);
index ea49978..bbbe15e 100644 (file)
@@ -872,9 +872,8 @@ int hil_mlc_register(hil_mlc *mlc) {
        for (i = 0; i < HIL_MLC_DEVMEM; i++) {
                struct serio *mlc_serio;
                hil_mlc_copy_di_scratch(mlc, i);
-               mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);
+               mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL);
                mlc->serio[i] = mlc_serio;
-               memset(mlc_serio, 0, sizeof(*mlc_serio));
                mlc_serio->id                   = hil_mlc_serio_id;
                mlc_serio->write                = hil_mlc_serio_write;
                mlc_serio->open                 = hil_mlc_serio_open;
index a4c6f35..f606e96 100644 (file)
@@ -192,7 +192,9 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
 #include <linux/pnp.h>
 
 static int i8042_pnp_kbd_registered;
+static unsigned int i8042_pnp_kbd_devices;
 static int i8042_pnp_aux_registered;
+static unsigned int i8042_pnp_aux_devices;
 
 static int i8042_pnp_command_reg;
 static int i8042_pnp_data_reg;
@@ -219,6 +221,7 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
                strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
        }
 
+       i8042_pnp_kbd_devices++;
        return 0;
 }
 
@@ -239,6 +242,7 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
                strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
        }
 
+       i8042_pnp_aux_devices++;
        return 0;
 }
 
@@ -287,21 +291,23 @@ static void i8042_pnp_exit(void)
 
 static int __init i8042_pnp_init(void)
 {
-       int result_kbd = 0, result_aux = 0;
        char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
+       int err;
 
        if (i8042_nopnp) {
                printk(KERN_INFO "i8042: PNP detection disabled\n");
                return 0;
        }
 
-       if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
+       err = pnp_register_driver(&i8042_pnp_kbd_driver);
+       if (!err)
                i8042_pnp_kbd_registered = 1;
 
-       if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
+       err = pnp_register_driver(&i8042_pnp_aux_driver);
+       if (!err)
                i8042_pnp_aux_registered = 1;
 
-       if (result_kbd <= 0 && result_aux <= 0) {
+       if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) {
                i8042_pnp_exit();
 #if defined(__ia64__)
                return -ENODEV;
@@ -311,24 +317,24 @@ static int __init i8042_pnp_init(void)
 #endif
        }
 
-       if (result_kbd > 0)
+       if (i8042_pnp_kbd_devices)
                snprintf(kbd_irq_str, sizeof(kbd_irq_str),
                        "%d", i8042_pnp_kbd_irq);
-       if (result_aux > 0)
+       if (i8042_pnp_aux_devices)
                snprintf(aux_irq_str, sizeof(aux_irq_str),
                        "%d", i8042_pnp_aux_irq);
 
        printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n",
-               i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "",
+               i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "",
                i8042_pnp_aux_name,
                i8042_pnp_data_reg, i8042_pnp_command_reg,
-               kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "",
+               kbd_irq_str, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "",
                aux_irq_str);
 
 #if defined(__ia64__)
-       if (result_kbd <= 0)
+       if (!i8042_pnp_kbd_devices)
                i8042_nokbd = 1;
-       if (result_aux <= 0)
+       if (!i8042_pnp_aux_devices)
                i8042_noaux = 1;
 #endif
 
index d4c990f..79c97f9 100644 (file)
@@ -84,7 +84,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
                maxbytes = sizeof(ps2dev->cmdbuf);
        }
 
-       down(&ps2dev->cmd_sem);
+       mutex_lock(&ps2dev->cmd_mutex);
 
        serio_pause_rx(ps2dev->serio);
        ps2dev->flags = PS2_FLAG_CMD;
@@ -94,7 +94,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
        wait_event_timeout(ps2dev->wait,
                           !(ps2dev->flags & PS2_FLAG_CMD),
                           msecs_to_jiffies(timeout));
-       up(&ps2dev->cmd_sem);
+       mutex_unlock(&ps2dev->cmd_mutex);
 }
 
 /*
@@ -177,7 +177,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
                return -1;
        }
 
-       down(&ps2dev->cmd_sem);
+       mutex_lock(&ps2dev->cmd_mutex);
 
        serio_pause_rx(ps2dev->serio);
        ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
@@ -229,7 +229,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
        ps2dev->flags = 0;
        serio_continue_rx(ps2dev->serio);
 
-       up(&ps2dev->cmd_sem);
+       mutex_unlock(&ps2dev->cmd_mutex);
        return rc;
 }
 
@@ -281,7 +281,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman
 
 void ps2_init(struct ps2dev *ps2dev, struct serio *serio)
 {
-       init_MUTEX(&ps2dev->cmd_sem);
+       mutex_init(&ps2dev->cmd_mutex);
        init_waitqueue_head(&ps2dev->wait);
        ps2dev->serio = serio;
 }
index 1d15c28..a5c1fb3 100644 (file)
@@ -171,9 +171,8 @@ static struct serio * __init parkbd_allocate_serio(void)
 {
        struct serio *serio;
 
-       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
        if (serio) {
-               memset(serio, 0, sizeof(struct serio));
                serio->id.type = parkbd_mode;
                serio->write = parkbd_write,
                strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
index a3bd115..513d37f 100644 (file)
@@ -111,11 +111,10 @@ static int __devinit rpckbd_probe(struct platform_device *dev)
 {
        struct serio *serio;
 
-       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
        if (!serio)
                return -ENOMEM;
 
-       memset(serio, 0, sizeof(struct serio));
        serio->id.type          = SERIO_8042;
        serio->write            = rpckbd_write;
        serio->open             = rpckbd_open;
index 2f76813..6521034 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/kthread.h>
+#include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Serio abstraction core");
@@ -52,10 +53,10 @@ EXPORT_SYMBOL(serio_rescan);
 EXPORT_SYMBOL(serio_reconnect);
 
 /*
- * serio_sem protects entire serio subsystem and is taken every time
+ * serio_mutex protects entire serio subsystem and is taken every time
  * serio port or driver registrered or unregistered.
  */
-static DECLARE_MUTEX(serio_sem);
+static DEFINE_MUTEX(serio_mutex);
 
 static LIST_HEAD(serio_list);
 
@@ -70,9 +71,9 @@ static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
 {
        int retval;
 
-       down(&serio->drv_sem);
+       mutex_lock(&serio->drv_mutex);
        retval = drv->connect(serio, drv);
-       up(&serio->drv_sem);
+       mutex_unlock(&serio->drv_mutex);
 
        return retval;
 }
@@ -81,20 +82,20 @@ static int serio_reconnect_driver(struct serio *serio)
 {
        int retval = -1;
 
-       down(&serio->drv_sem);
+       mutex_lock(&serio->drv_mutex);
        if (serio->drv && serio->drv->reconnect)
                retval = serio->drv->reconnect(serio);
-       up(&serio->drv_sem);
+       mutex_unlock(&serio->drv_mutex);
 
        return retval;
 }
 
 static void serio_disconnect_driver(struct serio *serio)
 {
-       down(&serio->drv_sem);
+       mutex_lock(&serio->drv_mutex);
        if (serio->drv)
                serio->drv->disconnect(serio);
-       up(&serio->drv_sem);
+       mutex_unlock(&serio->drv_mutex);
 }
 
 static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
@@ -195,6 +196,7 @@ static void serio_queue_event(void *object, struct module *owner,
        if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
                if (!try_module_get(owner)) {
                        printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
+                       kfree(event);
                        goto out;
                }
 
@@ -272,7 +274,7 @@ static void serio_handle_event(void)
        struct serio_event *event;
        struct serio_driver *serio_drv;
 
-       down(&serio_sem);
+       mutex_lock(&serio_mutex);
 
        /*
         * Note that we handle only one event here to give swsusp
@@ -314,7 +316,7 @@ static void serio_handle_event(void)
                serio_free_event(event);
        }
 
-       up(&serio_sem);
+       mutex_unlock(&serio_mutex);
 }
 
 /*
@@ -449,7 +451,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
        struct device_driver *drv;
        int retval;
 
-       retval = down_interruptible(&serio_sem);
+       retval = mutex_lock_interruptible(&serio_mutex);
        if (retval)
                return retval;
 
@@ -469,7 +471,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
                retval = -EINVAL;
        }
 
-       up(&serio_sem);
+       mutex_unlock(&serio_mutex);
 
        return retval;
 }
@@ -524,7 +526,7 @@ static void serio_init_port(struct serio *serio)
        __module_get(THIS_MODULE);
 
        spin_lock_init(&serio->lock);
-       init_MUTEX(&serio->drv_sem);
+       mutex_init(&serio->drv_mutex);
        device_initialize(&serio->dev);
        snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id),
                 "serio%ld", (long)atomic_inc_return(&serio_no) - 1);
@@ -661,10 +663,10 @@ void __serio_register_port(struct serio *serio, struct module *owner)
  */
 void serio_unregister_port(struct serio *serio)
 {
-       down(&serio_sem);
+       mutex_lock(&serio_mutex);
        serio_disconnect_port(serio);
        serio_destroy_port(serio);
-       up(&serio_sem);
+       mutex_unlock(&serio_mutex);
 }
 
 /*
@@ -672,17 +674,17 @@ void serio_unregister_port(struct serio *serio)
  */
 void serio_unregister_child_port(struct serio *serio)
 {
-       down(&serio_sem);
+       mutex_lock(&serio_mutex);
        if (serio->child) {
                serio_disconnect_port(serio->child);
                serio_destroy_port(serio->child);
        }
-       up(&serio_sem);
+       mutex_unlock(&serio_mutex);
 }
 
 /*
  * Submits register request to kseriod for subsequent execution.
- * Can be used when it is not obvious whether the serio_sem is
+ * Can be used when it is not obvious whether the serio_mutex is
  * taken or not and when delayed execution is feasible.
  */
 void __serio_unregister_port_delayed(struct serio *serio, struct module *owner)
@@ -765,7 +767,7 @@ void serio_unregister_driver(struct serio_driver *drv)
 {
        struct serio *serio;
 
-       down(&serio_sem);
+       mutex_lock(&serio_mutex);
        drv->manual_bind = 1;   /* so serio_find_driver ignores it */
 
 start_over:
@@ -779,7 +781,7 @@ start_over:
        }
 
        driver_unregister(&drv->driver);
-       up(&serio_sem);
+       mutex_unlock(&serio_mutex);
 }
 
 static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
@@ -858,7 +860,7 @@ static int serio_resume(struct device *dev)
        return 0;
 }
 
-/* called from serio_driver->connect/disconnect methods under serio_sem */
+/* called from serio_driver->connect/disconnect methods under serio_mutex */
 int serio_open(struct serio *serio, struct serio_driver *drv)
 {
        serio_set_drv(serio, drv);
@@ -870,7 +872,7 @@ int serio_open(struct serio *serio, struct serio_driver *drv)
        return 0;
 }
 
-/* called from serio_driver->connect/disconnect methods under serio_sem */
+/* called from serio_driver->connect/disconnect methods under serio_mutex */
 void serio_close(struct serio *serio)
 {
        if (serio->close)
@@ -923,5 +925,5 @@ static void __exit serio_exit(void)
        kthread_stop(serio_task);
 }
 
-module_init(serio_init);
+subsys_initcall(serio_init);
 module_exit(serio_exit);
index 47e08de..5a2703b 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/miscdevice.h>
 #include <linux/wait.h>
+#include <linux/mutex.h>
 
 #define DRIVER_DESC    "Raw serio driver"
 
@@ -46,7 +47,7 @@ struct serio_raw_list {
        struct list_head node;
 };
 
-static DECLARE_MUTEX(serio_raw_sem);
+static DEFINE_MUTEX(serio_raw_mutex);
 static LIST_HEAD(serio_raw_list);
 static unsigned int serio_raw_no;
 
@@ -81,7 +82,7 @@ static int serio_raw_open(struct inode *inode, struct file *file)
        struct serio_raw_list *list;
        int retval = 0;
 
-       retval = down_interruptible(&serio_raw_sem);
+       retval = mutex_lock_interruptible(&serio_raw_mutex);
        if (retval)
                return retval;
 
@@ -95,12 +96,11 @@ static int serio_raw_open(struct inode *inode, struct file *file)
                goto out;
        }
 
-       if (!(list = kmalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
+       if (!(list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
                retval = -ENOMEM;
                goto out;
        }
 
-       memset(list, 0, sizeof(struct serio_raw_list));
        list->serio_raw = serio_raw;
        file->private_data = list;
 
@@ -108,7 +108,7 @@ static int serio_raw_open(struct inode *inode, struct file *file)
        list_add_tail(&list->node, &serio_raw->list);
 
 out:
-       up(&serio_raw_sem);
+       mutex_unlock(&serio_raw_mutex);
        return retval;
 }
 
@@ -130,12 +130,12 @@ static int serio_raw_release(struct inode *inode, struct file *file)
        struct serio_raw_list *list = file->private_data;
        struct serio_raw *serio_raw = list->serio_raw;
 
-       down(&serio_raw_sem);
+       mutex_lock(&serio_raw_mutex);
 
        serio_raw_fasync(-1, file, 0);
        serio_raw_cleanup(serio_raw);
 
-       up(&serio_raw_sem);
+       mutex_unlock(&serio_raw_mutex);
        return 0;
 }
 
@@ -194,7 +194,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
        int retval;
        unsigned char c;
 
-       retval = down_interruptible(&serio_raw_sem);
+       retval = mutex_lock_interruptible(&serio_raw_mutex);
        if (retval)
                return retval;
 
@@ -219,7 +219,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
        };
 
 out:
-       up(&serio_raw_sem);
+       mutex_unlock(&serio_raw_mutex);
        return written;
 }
 
@@ -275,14 +275,13 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
        struct serio_raw *serio_raw;
        int err;
 
-       if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
+       if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
                printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
                return -ENOMEM;
        }
 
-       down(&serio_raw_sem);
+       mutex_lock(&serio_raw_mutex);
 
-       memset(serio_raw, 0, sizeof(struct serio_raw));
        snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
        serio_raw->refcnt = 1;
        serio_raw->serio = serio;
@@ -325,7 +324,7 @@ out_free:
        serio_set_drvdata(serio, NULL);
        kfree(serio_raw);
 out:
-       up(&serio_raw_sem);
+       mutex_unlock(&serio_raw_mutex);
        return err;
 }
 
@@ -350,7 +349,7 @@ static void serio_raw_disconnect(struct serio *serio)
 {
        struct serio_raw *serio_raw;
 
-       down(&serio_raw_sem);
+       mutex_lock(&serio_raw_mutex);
 
        serio_raw = serio_get_drvdata(serio);
 
@@ -361,7 +360,7 @@ static void serio_raw_disconnect(struct serio *serio)
        if (!serio_raw_cleanup(serio_raw))
                wake_up_interruptible(&serio_raw->wait);
 
-       up(&serio_raw_sem);
+       mutex_unlock(&serio_raw_mutex);
 }
 
 static struct serio_device_id serio_raw_serio_ids[] = {
index ca15479..d678d14 100644 (file)
@@ -157,9 +157,8 @@ static int tsdev_open(struct inode *inode, struct file *file)
        if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
                return -ENODEV;
 
-       if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
+       if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
                return -ENOMEM;
-       memset(list, 0, sizeof(struct tsdev_list));
 
        list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
 
@@ -379,9 +378,8 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
                return NULL;
        }
 
-       if (!(tsdev = kmalloc(sizeof(struct tsdev), GFP_KERNEL)))
+       if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL)))
                return NULL;
-       memset(tsdev, 0, sizeof(struct tsdev));
 
        INIT_LIST_HEAD(&tsdev->list);
        init_waitqueue_head(&tsdev->wait);
index 2a2b03f..7bbfd85 100644 (file)
@@ -51,8 +51,8 @@ MODULE_LICENSE("GPL");
    handler.
 */
 
-static void avmcs_config(dev_link_t *link);
-static void avmcs_release(dev_link_t *link);
+static int avmcs_config(struct pcmcia_device *link);
+static void avmcs_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -65,10 +65,10 @@ static void avmcs_detach(struct pcmcia_device *p_dev);
 /*
    A linked list of "instances" of the skeleton device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
+   by one struct pcmcia_device structure (defined in ds.h).
 
    You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
+   memory card driver uses an array of struct pcmcia_device pointers, where minor
    device numbers are used to derive the corresponding array index.
 */
 
@@ -78,7 +78,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev);
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally can't be allocated dynamically.
 */
@@ -99,54 +99,38 @@ typedef struct local_info_t {
     
 ======================================================================*/
 
-static int avmcs_attach(struct pcmcia_device *p_dev)
+static int avmcs_probe(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link;
     local_info_t *local;
 
-    /* Initialize the dev_link_t structure */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    if (!link)
-        goto err;
-    memset(link, 0, sizeof(struct dev_link_t));
-
     /* The io structure describes IO port mapping */
-    link->io.NumPorts1 = 16;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.NumPorts2 = 0;
+    p_dev->io.NumPorts1 = 16;
+    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+    p_dev->io.NumPorts2 = 0;
 
     /* Interrupt setup */
-    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+    p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+    p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+
+    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
 
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-    
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
+    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->conf.IntType = INT_MEMORY_AND_IO;
+    p_dev->conf.ConfigIndex = 1;
+    p_dev->conf.Present = PRESENT_OPTION;
 
     /* Allocate space for private device-specific data */
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local)
-        goto err_kfree;
+        goto err;
     memset(local, 0, sizeof(local_info_t));
-    link->priv = local;
+    p_dev->priv = local;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
+    return avmcs_config(p_dev);
 
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    avmcs_config(link);
-
-    return 0;
-
- err_kfree:
-    kfree(link);
  err:
-    return -EINVAL;
+    return -ENOMEM;
 } /* avmcs_attach */
 
 /*======================================================================
@@ -158,15 +142,10 @@ static int avmcs_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void avmcs_detach(struct pcmcia_device *p_dev)
+static void avmcs_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-
-    if (link->state & DEV_CONFIG)
        avmcs_release(link);
-
-    kfree(link->priv);
-    kfree(link);
+       kfree(link->priv);
 } /* avmcs_detach */
 
 /*======================================================================
@@ -177,7 +156,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev)
     
 ======================================================================*/
 
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                     cisparse_t *parse)
 {
     int i = pcmcia_get_tuple_data(handle, tuple);
@@ -185,7 +164,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
     return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                     cisparse_t *parse)
 {
     int i = pcmcia_get_first_tuple(handle, tuple);
@@ -193,7 +172,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
     return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                     cisparse_t *parse)
 {
     int i = pcmcia_get_next_tuple(handle, tuple);
@@ -201,9 +180,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
     return get_tuple(handle, tuple, parse);
 }
 
-static void avmcs_config(dev_link_t *link)
+static int avmcs_config(struct pcmcia_device *link)
 {
-    client_handle_t handle;
     tuple_t tuple;
     cisparse_t parse;
     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
@@ -213,8 +191,7 @@ static void avmcs_config(dev_link_t *link)
     char devname[128];
     int cardtype;
     int (*addcard)(unsigned int port, unsigned irq);
-    
-    handle = link->handle;
+
     dev = link->priv;
 
     /*
@@ -223,25 +200,21 @@ static void avmcs_config(dev_link_t *link)
     */
     do {
        tuple.DesiredTuple = CISTPL_CONFIG;
-       i = pcmcia_get_first_tuple(handle, &tuple);
+       i = pcmcia_get_first_tuple(link, &tuple);
        if (i != CS_SUCCESS) break;
        tuple.TupleData = buf;
        tuple.TupleDataMax = 64;
        tuple.TupleOffset = 0;
-       i = pcmcia_get_tuple_data(handle, &tuple);
+       i = pcmcia_get_tuple_data(link, &tuple);
        if (i != CS_SUCCESS) break;
-       i = pcmcia_parse_tuple(handle, &tuple, &parse);
+       i = pcmcia_parse_tuple(link, &tuple, &parse);
        if (i != CS_SUCCESS) break;
        link->conf.ConfigBase = parse.config.base;
     } while (0);
     if (i != CS_SUCCESS) {
-       cs_error(link->handle, ParseTuple, i);
-       link->state &= ~DEV_CONFIG_PENDING;
-       return;
+       cs_error(link, ParseTuple, i);
+       return -ENODEV;
     }
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
 
     do {
 
@@ -252,7 +225,7 @@ static void avmcs_config(dev_link_t *link)
        tuple.DesiredTuple = CISTPL_VERS_1;
 
        devname[0] = 0;
-       if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
+       if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
            strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], 
                        sizeof(devname));
        }
@@ -263,7 +236,7 @@ static void avmcs_config(dev_link_t *link)
        tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
        tuple.Attributes = 0;
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       i = first_tuple(handle, &tuple, &parse);
+       i = first_tuple(link, &tuple, &parse);
        while (i == CS_SUCCESS) {
            if (cf->io.nwin > 0) {
                link->conf.ConfigIndex = cf->index;
@@ -273,36 +246,36 @@ static void avmcs_config(dev_link_t *link)
                 printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
                        link->io.BasePort1,
                        link->io.BasePort1+link->io.NumPorts1-1);
-               i = pcmcia_request_io(link->handle, &link->io);
+               i = pcmcia_request_io(link, &link->io);
                if (i == CS_SUCCESS) goto found_port;
            }
-           i = next_tuple(handle, &tuple, &parse);
+           i = next_tuple(link, &tuple, &parse);
        }
 
 found_port:
        if (i != CS_SUCCESS) {
-           cs_error(link->handle, RequestIO, i);
+           cs_error(link, RequestIO, i);
            break;
        }
-       
+
        /*
         * allocate an interrupt line
         */
-       i = pcmcia_request_irq(link->handle, &link->irq);
+       i = pcmcia_request_irq(link, &link->irq);
        if (i != CS_SUCCESS) {
-           cs_error(link->handle, RequestIRQ, i);
-           pcmcia_release_io(link->handle, &link->io);
+           cs_error(link, RequestIRQ, i);
+           /* undo */
+           pcmcia_disable_device(link);
            break;
        }
-       
+
        /*
          * configure the PCMCIA socket
          */
-       i = pcmcia_request_configuration(link->handle, &link->conf);
+       i = pcmcia_request_configuration(link, &link->conf);
        if (i != CS_SUCCESS) {
-           cs_error(link->handle, RequestConfiguration, i);
-           pcmcia_release_io(link->handle, &link->io);
-           pcmcia_release_irq(link->handle, &link->irq);
+           cs_error(link, RequestConfiguration, i);
+           pcmcia_disable_device(link);
            break;
        }
 
@@ -331,13 +304,12 @@ found_port:
 
     dev->node.major = 64;
     dev->node.minor = 0;
-    link->dev = &dev->node;
-    
-    link->state &= ~DEV_CONFIG_PENDING;
+    link->dev_node = &dev->node;
+
     /* If any step failed, release any partially configured state */
     if (i != 0) {
        avmcs_release(link);
-       return;
+       return -ENODEV;
     }
 
 
@@ -351,9 +323,10 @@ found_port:
         printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
                dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
        avmcs_release(link);
-       return;
+       return -ENODEV;
     }
     dev->node.minor = i;
+    return 0;
 
 } /* avmcs_config */
 
@@ -365,56 +338,12 @@ found_port:
     
 ======================================================================*/
 
-static void avmcs_release(dev_link_t *link)
+static void avmcs_release(struct pcmcia_device *link)
 {
-    b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
-
-    /* Unlink the device chain */
-    link->dev = NULL;
-    
-    /* Don't bother checking to see if these succeed or not */
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
+       b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
+       pcmcia_disable_device(link);
 } /* avmcs_release */
 
-static int avmcs_suspend(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int avmcs_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-       return 0;
-}
-
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
-
-    When a CARD_REMOVAL event is received, we immediately set a flag
-    to block future accesses to this device.  All the functions that
-    actually access the device should check this flag to make sure
-    the card is still present.
-    
-======================================================================*/
-
 
 static struct pcmcia_device_id avmcs_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
@@ -429,11 +358,9 @@ static struct pcmcia_driver avmcs_driver = {
        .drv    = {
                .name   = "avm_cs",
        },
-       .probe = avmcs_attach,
+       .probe = avmcs_probe,
        .remove = avmcs_detach,
        .id_table = avmcs_ids,
-       .suspend= avmcs_suspend,
-       .resume = avmcs_resume,
 };
 
 static int __init avmcs_init(void)
index 969da40..ac28e32 100644 (file)
@@ -67,8 +67,8 @@ module_param(isdnprot, int, 0);
    handler.
 */
 
-static void avma1cs_config(dev_link_t *link);
-static void avma1cs_release(dev_link_t *link);
+static int avma1cs_config(struct pcmcia_device *link);
+static void avma1cs_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -82,10 +82,10 @@ static void avma1cs_detach(struct pcmcia_device *p_dev);
 /*
    A linked list of "instances" of the skeleton device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
+   by one struct pcmcia_device structure (defined in ds.h).
 
    You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
+   memory card driver uses an array of struct pcmcia_device pointers, where minor
    device numbers are used to derive the corresponding array index.
 */
 
@@ -95,7 +95,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev);
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally can't be allocated dynamically.
 */
@@ -116,55 +116,40 @@ typedef struct local_info_t {
     
 ======================================================================*/
 
-static int avma1cs_attach(struct pcmcia_device *p_dev)
+static int avma1cs_probe(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link;
     local_info_t *local;
 
     DEBUG(0, "avma1cs_attach()\n");
 
-    /* Initialize the dev_link_t structure */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    if (!link)
-       return -ENOMEM;
-    memset(link, 0, sizeof(struct dev_link_t));
-
     /* Allocate space for private device-specific data */
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
-    if (!local) {
-       kfree(link);
+    if (!local)
        return -ENOMEM;
-    }
+
     memset(local, 0, sizeof(local_info_t));
-    link->priv = local;
+    p_dev->priv = local;
 
     /* The io structure describes IO port mapping */
-    link->io.NumPorts1 = 16;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.NumPorts2 = 16;
-    link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
-    link->io.IOAddrLines = 5;
+    p_dev->io.NumPorts1 = 16;
+    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+    p_dev->io.NumPorts2 = 16;
+    p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
+    p_dev->io.IOAddrLines = 5;
 
     /* Interrupt setup */
-    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+    p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+    p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
 
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
 
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
+    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->conf.IntType = INT_MEMORY_AND_IO;
+    p_dev->conf.ConfigIndex = 1;
+    p_dev->conf.Present = PRESENT_OPTION;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    avma1cs_config(link);
-
-    return 0;
+    return avma1cs_config(p_dev);
 } /* avma1cs_attach */
 
 /*======================================================================
@@ -176,17 +161,11 @@ static int avma1cs_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void avma1cs_detach(struct pcmcia_device *p_dev)
+static void avma1cs_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-
-    DEBUG(0, "avma1cs_detach(0x%p)\n", link);
-
-    if (link->state & DEV_CONFIG)
-           avma1cs_release(link);
-
-    kfree(link->priv);
-    kfree(link);
+       DEBUG(0, "avma1cs_detach(0x%p)\n", link);
+       avma1cs_release(link);
+       kfree(link->priv);
 } /* avma1cs_detach */
 
 /*======================================================================
@@ -197,7 +176,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev)
     
 ======================================================================*/
 
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                     cisparse_t *parse)
 {
     int i = pcmcia_get_tuple_data(handle, tuple);
@@ -205,7 +184,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
     return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                     cisparse_t *parse)
 {
     int i = pcmcia_get_first_tuple(handle, tuple);
@@ -213,7 +192,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
     return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                     cisparse_t *parse)
 {
     int i = pcmcia_get_next_tuple(handle, tuple);
@@ -221,9 +200,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
     return get_tuple(handle, tuple, parse);
 }
 
-static void avma1cs_config(dev_link_t *link)
+static int avma1cs_config(struct pcmcia_device *link)
 {
-    client_handle_t handle;
     tuple_t tuple;
     cisparse_t parse;
     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
@@ -233,8 +211,7 @@ static void avma1cs_config(dev_link_t *link)
     char devname[128];
     IsdnCard_t icard;
     int busy = 0;
-    
-    handle = link->handle;
+
     dev = link->priv;
 
     DEBUG(0, "avma1cs_config(0x%p)\n", link);
@@ -245,25 +222,21 @@ static void avma1cs_config(dev_link_t *link)
     */
     do {
        tuple.DesiredTuple = CISTPL_CONFIG;
-       i = pcmcia_get_first_tuple(handle, &tuple);
+       i = pcmcia_get_first_tuple(link, &tuple);
        if (i != CS_SUCCESS) break;
        tuple.TupleData = buf;
        tuple.TupleDataMax = 64;
        tuple.TupleOffset = 0;
-       i = pcmcia_get_tuple_data(handle, &tuple);
+       i = pcmcia_get_tuple_data(link, &tuple);
        if (i != CS_SUCCESS) break;
-       i = pcmcia_parse_tuple(handle, &tuple, &parse);
+       i = pcmcia_parse_tuple(link, &tuple, &parse);
        if (i != CS_SUCCESS) break;
        link->conf.ConfigBase = parse.config.base;
     } while (0);
     if (i != CS_SUCCESS) {
-       cs_error(link->handle, ParseTuple, i);
-       link->state &= ~DEV_CONFIG_PENDING;
-       return;
+       cs_error(link, ParseTuple, i);
+       return -ENODEV;
     }
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
 
     do {
 
@@ -274,7 +247,7 @@ static void avma1cs_config(dev_link_t *link)
        tuple.DesiredTuple = CISTPL_VERS_1;
 
        devname[0] = 0;
-       if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
+       if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
            strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], 
                        sizeof(devname));
        }
@@ -285,7 +258,7 @@ static void avma1cs_config(dev_link_t *link)
        tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
        tuple.Attributes = 0;
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       i = first_tuple(handle, &tuple, &parse);
+       i = first_tuple(link, &tuple, &parse);
        while (i == CS_SUCCESS) {
            if (cf->io.nwin > 0) {
                link->conf.ConfigIndex = cf->index;
@@ -295,36 +268,36 @@ static void avma1cs_config(dev_link_t *link)
                printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
                        link->io.BasePort1,
                        link->io.BasePort1+link->io.NumPorts1 - 1);
-               i = pcmcia_request_io(link->handle, &link->io);
+               i = pcmcia_request_io(link, &link->io);
                if (i == CS_SUCCESS) goto found_port;
            }
-           i = next_tuple(handle, &tuple, &parse);
+           i = next_tuple(link, &tuple, &parse);
        }
 
 found_port:
        if (i != CS_SUCCESS) {
-           cs_error(link->handle, RequestIO, i);
+           cs_error(link, RequestIO, i);
            break;
        }
        
        /*
         * allocate an interrupt line
         */
-       i = pcmcia_request_irq(link->handle, &link->irq);
+       i = pcmcia_request_irq(link, &link->irq);
        if (i != CS_SUCCESS) {
-           cs_error(link->handle, RequestIRQ, i);
-           pcmcia_release_io(link->handle, &link->io);
+           cs_error(link, RequestIRQ, i);
+           /* undo */
+           pcmcia_disable_device(link);
            break;
        }
-       
+
        /*
         * configure the PCMCIA socket
         */
-       i = pcmcia_request_configuration(link->handle, &link->conf);
+       i = pcmcia_request_configuration(link, &link->conf);
        if (i != CS_SUCCESS) {
-           cs_error(link->handle, RequestConfiguration, i);
-           pcmcia_release_io(link->handle, &link->io);
-           pcmcia_release_irq(link->handle, &link->irq);
+           cs_error(link, RequestConfiguration, i);
+           pcmcia_disable_device(link);
            break;
        }
 
@@ -336,13 +309,12 @@ found_port:
     strcpy(dev->node.dev_name, "A1");
     dev->node.major = 45;
     dev->node.minor = 0;
-    link->dev = &dev->node;
-    
-    link->state &= ~DEV_CONFIG_PENDING;
+    link->dev_node = &dev->node;
+
     /* If any step failed, release any partially configured state */
     if (i != 0) {
        avma1cs_release(link);
-       return;
+       return -ENODEV;
     }
 
     printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
@@ -357,10 +329,11 @@ found_port:
     if (i < 0) {
        printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
        avma1cs_release(link);
-       return;
+       return -ENODEV;
     }
     dev->node.minor = i;
 
+    return 0;
 } /* avma1cs_config */
 
 /*======================================================================
@@ -371,47 +344,18 @@ found_port:
     
 ======================================================================*/
 
-static void avma1cs_release(dev_link_t *link)
+static void avma1cs_release(struct pcmcia_device *link)
 {
-    local_info_t *local = link->priv;
+       local_info_t *local = link->priv;
 
-    DEBUG(0, "avma1cs_release(0x%p)\n", link);
+       DEBUG(0, "avma1cs_release(0x%p)\n", link);
 
-    /* no unregister function with hisax */
-    HiSax_closecard(local->node.minor);
+       /* now unregister function with hisax */
+       HiSax_closecard(local->node.minor);
 
-    /* Unlink the device chain */
-    link->dev = NULL;
-    
-    /* Don't bother checking to see if these succeed or not */
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
 } /* avma1cs_release */
 
-static int avma1cs_suspend(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int avma1cs_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-       return 0;
-}
-
 
 static struct pcmcia_device_id avma1cs_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
@@ -425,13 +369,11 @@ static struct pcmcia_driver avma1cs_driver = {
        .drv            = {
                .name   = "avma1_cs",
        },
-       .probe          = avma1cs_attach,
+       .probe          = avma1cs_probe,
        .remove         = avma1cs_detach,
        .id_table       = avma1cs_ids,
-       .suspend        = avma1cs_suspend,
-       .resume         = avma1cs_resume,
 };
+
 /*====================================================================*/
 
 static int __init init_avma1_cs(void)
index 062fb8f..e18e75b 100644 (file)
@@ -94,8 +94,8 @@ module_param(protocol, int, 0);
    handler.
 */
 
-static void elsa_cs_config(dev_link_t *link);
-static void elsa_cs_release(dev_link_t *link);
+static int elsa_cs_config(struct pcmcia_device *link);
+static void elsa_cs_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -111,7 +111,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev);
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally shouldn't be allocated dynamically.
    In this case, we also provide a flag to indicate if a device is
@@ -121,7 +121,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev);
 */
 
 typedef struct local_info_t {
-    dev_link_t          link;
+       struct pcmcia_device    *p_dev;
     dev_node_t          node;
     int                 busy;
     int                        cardnr;
@@ -139,9 +139,8 @@ typedef struct local_info_t {
 
 ======================================================================*/
 
-static int elsa_cs_attach(struct pcmcia_device *p_dev)
+static int elsa_cs_probe(struct pcmcia_device *link)
 {
-    dev_link_t *link;
     local_info_t *local;
 
     DEBUG(0, "elsa_cs_attach()\n");
@@ -150,8 +149,11 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local) return -ENOMEM;
     memset(local, 0, sizeof(local_info_t));
+
+    local->p_dev = link;
+    link->priv = local;
+
     local->cardnr = -1;
-    link = &local->link; link->priv = local;
 
     /* Interrupt setup */
     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
@@ -170,16 +172,9 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
     link->io.IOAddrLines = 3;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    elsa_cs_config(link);
-
-    return 0;
+    return elsa_cs_config(link);
 } /* elsa_cs_attach */
 
 /*======================================================================
@@ -191,20 +186,16 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void elsa_cs_detach(struct pcmcia_device *p_dev)
+static void elsa_cs_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-    local_info_t *info = link->priv;
+       local_info_t *info = link->priv;
 
-    DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
+       DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
 
-    if (link->state & DEV_CONFIG) {
-           info->busy = 1;
-           elsa_cs_release(link);
-    }
-
-    kfree(info);
+       info->busy = 1;
+       elsa_cs_release(link);
 
+       kfree(info);
 } /* elsa_cs_detach */
 
 /*======================================================================
@@ -214,7 +205,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev)
     device available to the system.
 
 ======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_tuple_data(handle, tuple);
@@ -222,7 +213,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
     return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_first_tuple(handle, tuple);
@@ -230,7 +221,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
     return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_next_tuple(handle, tuple);
@@ -238,9 +229,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
     return get_tuple(handle, tuple, parse);
 }
 
-static void elsa_cs_config(dev_link_t *link)
+static int elsa_cs_config(struct pcmcia_device *link)
 {
-    client_handle_t handle;
     tuple_t tuple;
     cisparse_t parse;
     local_info_t *dev;
@@ -250,7 +240,6 @@ static void elsa_cs_config(dev_link_t *link)
     IsdnCard_t icard;
 
     DEBUG(0, "elsa_config(0x%p)\n", link);
-    handle = link->handle;
     dev = link->priv;
 
     /*
@@ -262,7 +251,7 @@ static void elsa_cs_config(dev_link_t *link)
     tuple.TupleDataMax = 255;
     tuple.TupleOffset = 0;
     tuple.Attributes = 0;
-    i = first_tuple(handle, &tuple, &parse);
+    i = first_tuple(link, &tuple, &parse);
     if (i != CS_SUCCESS) {
         last_fn = ParseTuple;
        goto cs_failed;
@@ -270,32 +259,29 @@ static void elsa_cs_config(dev_link_t *link)
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     tuple.TupleData = (cisdata_t *)buf;
     tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    i = first_tuple(handle, &tuple, &parse);
+    i = first_tuple(link, &tuple, &parse);
     while (i == CS_SUCCESS) {
         if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
             printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
             link->conf.ConfigIndex = cf->index;
             link->io.BasePort1 = cf->io.win[0].base;
-            i = pcmcia_request_io(link->handle, &link->io);
+            i = pcmcia_request_io(link, &link->io);
             if (i == CS_SUCCESS) break;
         } else {
           printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
           link->conf.ConfigIndex = cf->index;
           for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
             link->io.BasePort1 = j;
-            i = pcmcia_request_io(link->handle, &link->io);
+            i = pcmcia_request_io(link, &link->io);
             if (i == CS_SUCCESS) break;
           }
           break;
         }
-        i = next_tuple(handle, &tuple, &parse);
+        i = next_tuple(link, &tuple, &parse);
     }
 
     if (i != CS_SUCCESS) {
@@ -303,14 +289,14 @@ static void elsa_cs_config(dev_link_t *link)
        goto cs_failed;
     }
 
-    i = pcmcia_request_irq(link->handle, &link->irq);
+    i = pcmcia_request_irq(link, &link->irq);
     if (i != CS_SUCCESS) {
         link->irq.AssignedIRQ = 0;
        last_fn = RequestIRQ;
         goto cs_failed;
     }
 
-    i = pcmcia_request_configuration(link->handle, &link->conf);
+    i = pcmcia_request_configuration(link, &link->conf);
     if (i != CS_SUCCESS) {
       last_fn = RequestConfiguration;
       goto cs_failed;
@@ -321,14 +307,11 @@ static void elsa_cs_config(dev_link_t *link)
     sprintf(dev->node.dev_name, "elsa");
     dev->node.major = dev->node.minor = 0x0;
 
-    link->dev = &dev->node;
+    link->dev_node = &dev->node;
 
     /* Finally, report what we've done */
-    printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-           dev->node.dev_name, link->conf.ConfigIndex,
-           link->conf.Vcc/10, link->conf.Vcc%10);
-    if (link->conf.Vpp1)
-        printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+    printk(KERN_INFO "%s: index 0x%02x: ",
+           dev->node.dev_name, link->conf.ConfigIndex);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
         printk(", irq %d", link->irq.AssignedIRQ);
     if (link->io.NumPorts1)
@@ -339,8 +322,6 @@ static void elsa_cs_config(dev_link_t *link)
                link->io.BasePort2+link->io.NumPorts2-1);
     printk("\n");
 
-    link->state &= ~DEV_CONFIG_PENDING;
-
     icard.para[0] = link->irq.AssignedIRQ;
     icard.para[1] = link->io.BasePort1;
     icard.protocol = protocol;
@@ -354,10 +335,11 @@ static void elsa_cs_config(dev_link_t *link)
     } else
        ((local_info_t*)link->priv)->cardnr = i;
 
-    return;
+    return 0;
 cs_failed:
-    cs_error(link->handle, last_fn, i);
+    cs_error(link, last_fn, i);
     elsa_cs_release(link);
+    return -ENODEV;
 } /* elsa_cs_config */
 
 /*======================================================================
@@ -368,7 +350,7 @@ cs_failed:
 
 ======================================================================*/
 
-static void elsa_cs_release(dev_link_t *link)
+static void elsa_cs_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
 
@@ -380,39 +362,23 @@ static void elsa_cs_release(dev_link_t *link)
            HiSax_closecard(local->cardnr);
        }
     }
-    /* Unlink the device chain */
-    link->dev = NULL;
-
-    /* Don't bother checking to see if these succeed or not */
-    if (link->win)
-        pcmcia_release_window(link->win);
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
+
+    pcmcia_disable_device(link);
 } /* elsa_cs_release */
 
-static int elsa_suspend(struct pcmcia_device *p_dev)
+static int elsa_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        local_info_t *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
         dev->busy = 1;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
 
        return 0;
 }
 
-static int elsa_resume(struct pcmcia_device *p_dev)
+static int elsa_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        local_info_t *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
         dev->busy = 0;
 
        return 0;
@@ -430,7 +396,7 @@ static struct pcmcia_driver elsa_cs_driver = {
        .drv            = {
                .name   = "elsa_cs",
        },
-       .probe          = elsa_cs_attach,
+       .probe          = elsa_cs_probe,
        .remove         = elsa_cs_detach,
        .id_table       = elsa_ids,
        .suspend        = elsa_suspend,
index 6f5213a..9bb18f3 100644 (file)
@@ -95,8 +95,8 @@ module_param(protocol, int, 0);
    event handler. 
 */
 
-static void sedlbauer_config(dev_link_t *link);
-static void sedlbauer_release(dev_link_t *link);
+static int sedlbauer_config(struct pcmcia_device *link);
+static void sedlbauer_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -119,7 +119,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev);
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally shouldn't be allocated dynamically.
 
@@ -130,7 +130,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev);
 */
    
 typedef struct local_info_t {
-    dev_link_t         link;
+       struct pcmcia_device    *p_dev;
     dev_node_t         node;
     int                        stop;
     int                        cardnr;
@@ -148,11 +148,10 @@ typedef struct local_info_t {
     
 ======================================================================*/
 
-static int sedlbauer_attach(struct pcmcia_device *p_dev)
+static int sedlbauer_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
-    dev_link_t *link;
-    
+
     DEBUG(0, "sedlbauer_attach()\n");
 
     /* Allocate space for private device-specific data */
@@ -160,8 +159,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev)
     if (!local) return -ENOMEM;
     memset(local, 0, sizeof(local_info_t));
     local->cardnr = -1;
-    link = &local->link; link->priv = local;
-    
+
+    local->p_dev = link;
+    link->priv = local;
+
     /* Interrupt setup */
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
@@ -182,18 +183,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev)
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
     link->io.IOAddrLines = 3;
 
-
     link->conf.Attributes = 0;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    sedlbauer_config(link);
-
-    return 0;
+    return sedlbauer_config(link);
 } /* sedlbauer_attach */
 
 /*======================================================================
@@ -205,19 +198,15 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void sedlbauer_detach(struct pcmcia_device *p_dev)
+static void sedlbauer_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-
-    DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
+       DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
 
-    if (link->state & DEV_CONFIG) {
-           ((local_info_t *)link->priv)->stop = 1;
-           sedlbauer_release(link);
-    }
+       ((local_info_t *)link->priv)->stop = 1;
+       sedlbauer_release(link);
 
-    /* This points to the parent local_info_t struct */
-    kfree(link->priv);
+       /* This points to the parent local_info_t struct */
+       kfree(link->priv);
 } /* sedlbauer_detach */
 
 /*======================================================================
@@ -230,9 +219,8 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void sedlbauer_config(dev_link_t *link)
+static int sedlbauer_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     local_info_t *dev = link->priv;
     tuple_t tuple;
     cisparse_t parse;
@@ -254,18 +242,13 @@ static void sedlbauer_config(dev_link_t *link)
     tuple.TupleData = buf;
     tuple.TupleDataMax = sizeof(buf);
     tuple.TupleOffset = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
 
-    /* Look up the current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-    link->conf.Vcc = conf.Vcc;
+    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
 
     /*
       In this loop, we scan the CIS for configuration table entries,
@@ -280,12 +263,12 @@ static void sedlbauer_config(dev_link_t *link)
       will only use the CIS to fill in implementation-defined details.
     */
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (1) {
        cistpl_cftable_entry_t dflt = { 0 };
        cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-       if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-               pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
            goto next_entry;
 
        if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -309,10 +292,10 @@ static void sedlbauer_config(dev_link_t *link)
        }
            
        if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-           link->conf.Vpp1 = link->conf.Vpp2 =
+           link->conf.Vpp =
                cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
        else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-           link->conf.Vpp1 = link->conf.Vpp2 =
+           link->conf.Vpp =
                dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
        
        /* Do we need to allocate an interrupt? */
@@ -339,13 +322,13 @@ static void sedlbauer_config(dev_link_t *link)
                link->io.NumPorts2 = io->win[1].len;
            }
            /* This reserves IO space but doesn't actually enable it */
-           if (pcmcia_request_io(link->handle, &link->io) != 0)
+           if (pcmcia_request_io(link, &link->io) != 0)
                goto next_entry;
        }
 
        /*
          Now set up a common memory window, if needed.  There is room
-         in the dev_link_t structure for one memory window handle,
+         in the struct pcmcia_device structure for one memory window handle,
          but if the base addresses need to be saved, or if multiple
          windows are needed, the info should go in the private data
          structure for this device.
@@ -366,7 +349,7 @@ static void sedlbauer_config(dev_link_t *link)
                 req.Size = 0x1000;
 */
            req.AccessSpeed = 0;
-           if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+           if (pcmcia_request_window(&link, &req, &link->win) != 0)
                goto next_entry;
            map.Page = 0; map.CardOffset = mem->win[0].card_addr;
            if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -374,29 +357,25 @@ static void sedlbauer_config(dev_link_t *link)
        }
        /* If we got this far, we're cool! */
        break;
-       
+
     next_entry:
-/* new in dummy.cs 2001/01/28 MN 
-        if (link->io.NumPorts1)
-           pcmcia_release_io(link->handle, &link->io);
-*/
-       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
     }
-    
+
     /*
        Allocate an interrupt line.  Note that this does not assign a
        handler to the interrupt, unless the 'Handler' member of the
        irq structure is initialized.
     */
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
-       CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+       CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
        
     /*
        This actually configures the PCMCIA socket -- setting up
        the I/O windows and the interrupt mapping, and putting the
        card and host interface into "Memory and IO" mode.
     */
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     /*
       At this point, the dev_node_t structure(s) need to be
@@ -404,14 +383,13 @@ static void sedlbauer_config(dev_link_t *link)
     */
     sprintf(dev->node.dev_name, "sedlbauer");
     dev->node.major = dev->node.minor = 0;
-    link->dev = &dev->node;
+    link->dev_node = &dev->node;
 
     /* Finally, report what we've done */
-    printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-          dev->node.dev_name, link->conf.ConfigIndex,
-          link->conf.Vcc/10, link->conf.Vcc%10);
-    if (link->conf.Vpp1)
-       printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+    printk(KERN_INFO "%s: index 0x%02x:",
+          dev->node.dev_name, link->conf.ConfigIndex);
+    if (link->conf.Vpp)
+       printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
        printk(", irq %d", link->irq.AssignedIRQ);
     if (link->io.NumPorts1)
@@ -424,8 +402,6 @@ static void sedlbauer_config(dev_link_t *link)
        printk(", mem 0x%06lx-0x%06lx", req.Base,
               req.Base+req.Size-1);
     printk("\n");
-    
-    link->state &= ~DEV_CONFIG_PENDING;
 
     icard.para[0] = link->irq.AssignedIRQ;
     icard.para[1] = link->io.BasePort1;
@@ -437,14 +413,16 @@ static void sedlbauer_config(dev_link_t *link)
        printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
                last_ret, link->io.BasePort1);
        sedlbauer_release(link);
+       return -ENODEV;
     } else
        ((local_info_t*)link->priv)->cardnr = last_ret;
 
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
     sedlbauer_release(link);
+    return -ENODEV;
 
 } /* sedlbauer_config */
 
@@ -456,7 +434,7 @@ cs_failed:
     
 ======================================================================*/
 
-static void sedlbauer_release(dev_link_t *link)
+static void sedlbauer_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
     DEBUG(0, "sedlbauer_release(0x%p)\n", link);
@@ -467,46 +445,23 @@ static void sedlbauer_release(dev_link_t *link)
            HiSax_closecard(local->cardnr);
        }
     }
-    /* Unlink the device chain */
-    link->dev = NULL;
 
-    /*
-      In a normal driver, additional code may be needed to release
-      other kernel data structures associated with this device. 
-    */
-    
-    /* Don't bother checking to see if these succeed or not */
-    if (link->win)
-       pcmcia_release_window(link->win);
-    pcmcia_release_configuration(link->handle);
-    if (link->io.NumPorts1)
-       pcmcia_release_io(link->handle, &link->io);
-    if (link->irq.AssignedIRQ)
-       pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
+    pcmcia_disable_device(link);
 } /* sedlbauer_release */
 
-static int sedlbauer_suspend(struct pcmcia_device *p_dev)
+static int sedlbauer_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        local_info_t *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
        dev->stop = 1;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
 
        return 0;
 }
 
-static int sedlbauer_resume(struct pcmcia_device *p_dev)
+static int sedlbauer_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        local_info_t *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
        dev->stop = 0;
 
        return 0;
@@ -530,7 +485,7 @@ static struct pcmcia_driver sedlbauer_driver = {
        .drv            = {
                .name   = "sedlbauer_cs",
        },
-       .probe          = sedlbauer_attach,
+       .probe          = sedlbauer_probe,
        .remove         = sedlbauer_detach,
        .id_table       = sedlbauer_ids,
        .suspend        = sedlbauer_suspend,
index 4e5c14c..afcc2ae 100644 (file)
@@ -75,8 +75,8 @@ module_param(protocol, int, 0);
    handler.
 */
 
-static void teles_cs_config(dev_link_t *link);
-static void teles_cs_release(dev_link_t *link);
+static int teles_cs_config(struct pcmcia_device *link);
+static void teles_cs_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -89,10 +89,10 @@ static void teles_detach(struct pcmcia_device *p_dev);
 /*
    A linked list of "instances" of the teles_cs device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
+   by one struct pcmcia_device structure (defined in ds.h).
 
    You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
+   memory card driver uses an array of struct pcmcia_device pointers, where minor
    device numbers are used to derive the corresponding array index.
 */
 
@@ -102,7 +102,7 @@ static void teles_detach(struct pcmcia_device *p_dev);
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally shouldn't be allocated dynamically.
    In this case, we also provide a flag to indicate if a device is
@@ -112,7 +112,7 @@ static void teles_detach(struct pcmcia_device *p_dev);
 */
 
 typedef struct local_info_t {
-    dev_link_t          link;
+       struct pcmcia_device    *p_dev;
     dev_node_t          node;
     int                 busy;
     int                        cardnr;
@@ -130,9 +130,8 @@ typedef struct local_info_t {
 
 ======================================================================*/
 
-static int teles_attach(struct pcmcia_device *p_dev)
+static int teles_probe(struct pcmcia_device *link)
 {
-    dev_link_t *link;
     local_info_t *local;
 
     DEBUG(0, "teles_attach()\n");
@@ -142,7 +141,9 @@ static int teles_attach(struct pcmcia_device *p_dev)
     if (!local) return -ENOMEM;
     memset(local, 0, sizeof(local_info_t));
     local->cardnr = -1;
-    link = &local->link; link->priv = local;
+
+    local->p_dev = link;
+    link->priv = local;
 
     /* Interrupt setup */
     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
@@ -161,16 +162,9 @@ static int teles_attach(struct pcmcia_device *p_dev)
     link->io.IOAddrLines = 5;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    teles_cs_config(link);
-
-    return 0;
+    return teles_cs_config(link);
 } /* teles_attach */
 
 /*======================================================================
@@ -182,20 +176,16 @@ static int teles_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void teles_detach(struct pcmcia_device *p_dev)
+static void teles_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-    local_info_t *info = link->priv;
-
-    DEBUG(0, "teles_detach(0x%p)\n", link);
+       local_info_t *info = link->priv;
 
-    if (link->state & DEV_CONFIG) {
-           info->busy = 1;
-           teles_cs_release(link);
-    }
+       DEBUG(0, "teles_detach(0x%p)\n", link);
 
-    kfree(info);
+       info->busy = 1;
+       teles_cs_release(link);
 
+       kfree(info);
 } /* teles_detach */
 
 /*======================================================================
@@ -205,7 +195,7 @@ static void teles_detach(struct pcmcia_device *p_dev)
     device available to the system.
 
 ======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_tuple_data(handle, tuple);
@@ -213,7 +203,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
     return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_first_tuple(handle, tuple);
@@ -221,7 +211,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
     return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_next_tuple(handle, tuple);
@@ -229,9 +219,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
     return get_tuple(handle, tuple, parse);
 }
 
-static void teles_cs_config(dev_link_t *link)
+static int teles_cs_config(struct pcmcia_device *link)
 {
-    client_handle_t handle;
     tuple_t tuple;
     cisparse_t parse;
     local_info_t *dev;
@@ -241,7 +230,6 @@ static void teles_cs_config(dev_link_t *link)
     IsdnCard_t icard;
 
     DEBUG(0, "teles_config(0x%p)\n", link);
-    handle = link->handle;
     dev = link->priv;
 
     /*
@@ -253,7 +241,7 @@ static void teles_cs_config(dev_link_t *link)
     tuple.TupleDataMax = 255;
     tuple.TupleOffset = 0;
     tuple.Attributes = 0;
-    i = first_tuple(handle, &tuple, &parse);
+    i = first_tuple(link, &tuple, &parse);
     if (i != CS_SUCCESS) {
         last_fn = ParseTuple;
        goto cs_failed;
@@ -261,32 +249,29 @@ static void teles_cs_config(dev_link_t *link)
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     tuple.TupleData = (cisdata_t *)buf;
     tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    i = first_tuple(handle, &tuple, &parse);
+    i = first_tuple(link, &tuple, &parse);
     while (i == CS_SUCCESS) {
         if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
             printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
             link->conf.ConfigIndex = cf->index;
             link->io.BasePort1 = cf->io.win[0].base;
-            i = pcmcia_request_io(link->handle, &link->io);
+            i = pcmcia_request_io(link, &link->io);
             if (i == CS_SUCCESS) break;
         } else {
           printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
           link->conf.ConfigIndex = cf->index;
           for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
             link->io.BasePort1 = j;
-            i = pcmcia_request_io(link->handle, &link->io);
+            i = pcmcia_request_io(link, &link->io);
             if (i == CS_SUCCESS) break;
           }
           break;
         }
-        i = next_tuple(handle, &tuple, &parse);
+        i = next_tuple(link, &tuple, &parse);
     }
 
     if (i != CS_SUCCESS) {
@@ -294,14 +279,14 @@ static void teles_cs_config(dev_link_t *link)
        goto cs_failed;
     }
 
-    i = pcmcia_request_irq(link->handle, &link->irq);
+    i = pcmcia_request_irq(link, &link->irq);
     if (i != CS_SUCCESS) {
         link->irq.AssignedIRQ = 0;
        last_fn = RequestIRQ;
         goto cs_failed;
     }
 
-    i = pcmcia_request_configuration(link->handle, &link->conf);
+    i = pcmcia_request_configuration(link, &link->conf);
     if (i != CS_SUCCESS) {
       last_fn = RequestConfiguration;
       goto cs_failed;
@@ -312,14 +297,11 @@ static void teles_cs_config(dev_link_t *link)
     sprintf(dev->node.dev_name, "teles");
     dev->node.major = dev->node.minor = 0x0;
 
-    link->dev = &dev->node;
+    link->dev_node = &dev->node;
 
     /* Finally, report what we've done */
-    printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-           dev->node.dev_name, link->conf.ConfigIndex,
-           link->conf.Vcc/10, link->conf.Vcc%10);
-    if (link->conf.Vpp1)
-        printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+    printk(KERN_INFO "%s: index 0x%02x:",
+           dev->node.dev_name, link->conf.ConfigIndex);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
         printk(", irq %d", link->irq.AssignedIRQ);
     if (link->io.NumPorts1)
@@ -330,8 +312,6 @@ static void teles_cs_config(dev_link_t *link)
                link->io.BasePort2+link->io.NumPorts2-1);
     printk("\n");
 
-    link->state &= ~DEV_CONFIG_PENDING;
-
     icard.para[0] = link->irq.AssignedIRQ;
     icard.para[1] = link->io.BasePort1;
     icard.protocol = protocol;
@@ -342,13 +322,16 @@ static void teles_cs_config(dev_link_t *link)
        printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
                i, link->io.BasePort1);
        teles_cs_release(link);
-    } else
-       ((local_info_t*)link->priv)->cardnr = i;
+       return -ENODEV;
+    }
+
+    ((local_info_t*)link->priv)->cardnr = i;
+    return 0;
 
-    return;
 cs_failed:
-    cs_error(link->handle, last_fn, i);
+    cs_error(link, last_fn, i);
     teles_cs_release(link);
+    return -ENODEV;
 } /* teles_cs_config */
 
 /*======================================================================
@@ -359,7 +342,7 @@ cs_failed:
 
 ======================================================================*/
 
-static void teles_cs_release(dev_link_t *link)
+static void teles_cs_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
 
@@ -371,39 +354,23 @@ static void teles_cs_release(dev_link_t *link)
            HiSax_closecard(local->cardnr);
        }
     }
-    /* Unlink the device chain */
-    link->dev = NULL;
-
-    /* Don't bother checking to see if these succeed or not */
-    if (link->win)
-        pcmcia_release_window(link->win);
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
+
+    pcmcia_disable_device(link);
 } /* teles_cs_release */
 
-static int teles_suspend(struct pcmcia_device *p_dev)
+static int teles_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        local_info_t *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
         dev->busy = 1;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
 
        return 0;
 }
 
-static int teles_resume(struct pcmcia_device *p_dev)
+static int teles_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        local_info_t *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
         dev->busy = 0;
 
        return 0;
@@ -421,7 +388,7 @@ static struct pcmcia_driver teles_cs_driver = {
        .drv            = {
                .name   = "teles_cs",
        },
-       .probe          = teles_attach,
+       .probe          = teles_probe,
        .remove         = teles_detach,
        .id_table       = teles_ids,
        .suspend        = teles_suspend,
index 94c9afb..f4f7122 100644 (file)
@@ -46,7 +46,8 @@ int sc_ioctl(int card, scs_ioctl *data)
                pr_debug("%s: SCIOCRESET: ioctl received\n",
                        sc_adapter[card]->devicename);
                sc_adapter[card]->StartOnReset = 0;
-               return (reset(card));
+               kfree(rcvmsg);
+               return reset(card);
        }
 
        case SCIOCLOAD:
@@ -183,7 +184,7 @@ int sc_ioctl(int card, scs_ioctl *data)
                                sc_adapter[card]->devicename);
 
                spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
-               if(!spid) {
+               if (!spid) {
                        kfree(rcvmsg);
                        return -ENOMEM;
                }
@@ -195,10 +196,10 @@ int sc_ioctl(int card, scs_ioctl *data)
                if (!status) {
                        pr_debug("%s: SCIOCGETSPID: command successful\n",
                                        sc_adapter[card]->devicename);
-               }
-               else {
+               } else {
                        pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n",
                                sc_adapter[card]->devicename, status);
+                       kfree(spid);
                        kfree(rcvmsg);
                        return status;
                }
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
new file mode 100644 (file)
index 0000000..2c4f20b
--- /dev/null
@@ -0,0 +1,77 @@
+
+menu "LED devices"
+
+config NEW_LEDS
+       bool "LED Support"
+       help
+         Say Y to enable Linux LED support.  This is not related to standard
+         keyboard LEDs which are controlled via the input system.
+
+config LEDS_CLASS
+       tristate "LED Class Support"
+       depends NEW_LEDS
+       help
+         This option enables the led sysfs class in /sys/class/leds.  You'll
+         need this to do anything useful with LEDs.  If unsure, say N.
+
+config LEDS_TRIGGERS
+       bool "LED Trigger support"
+       depends NEW_LEDS
+       help
+         This option enables trigger support for the leds class.
+         These triggers allow kernel events to drive the LEDs and can
+         be configured via sysfs. If unsure, say Y.
+
+config LEDS_CORGI
+       tristate "LED Support for the Sharp SL-C7x0 series"
+       depends LEDS_CLASS && PXA_SHARP_C7xx
+       help
+         This option enables support for the LEDs on Sharp Zaurus
+         SL-C7x0 series (C700, C750, C760, C860).
+
+config LEDS_LOCOMO
+       tristate "LED Support for Locomo device"
+       depends LEDS_CLASS && SHARP_LOCOMO
+       help
+         This option enables support for the LEDs on Sharp Locomo.
+         Zaurus models SL-5500 and SL-5600.
+
+config LEDS_SPITZ
+       tristate "LED Support for the Sharp SL-Cxx00 series"
+       depends LEDS_CLASS && PXA_SHARP_Cxx00
+       help
+         This option enables support for the LEDs on Sharp Zaurus
+         SL-Cxx00 series (C1000, C3000, C3100).
+
+config LEDS_IXP4XX
+       tristate "LED Support for GPIO connected LEDs on IXP4XX processors"
+       depends LEDS_CLASS && ARCH_IXP4XX
+       help
+         This option enables support for the LEDs connected to GPIO
+         outputs of the Intel IXP4XX processors.  To be useful the
+         particular board must have LEDs and they must be connected
+         to the GPIO lines.  If unsure, say Y.
+
+config LEDS_TOSA
+       tristate "LED Support for the Sharp SL-6000 series"
+       depends LEDS_CLASS && PXA_SHARPSL
+       help
+         This option enables support for the LEDs on Sharp Zaurus
+         SL-6000 series.
+
+config LEDS_TRIGGER_TIMER
+       tristate "LED Timer Trigger"
+       depends LEDS_TRIGGERS
+       help
+         This allows LEDs to be controlled by a programmable timer
+         via sysfs. If unsure, say Y.
+
+config LEDS_TRIGGER_IDE_DISK
+       bool "LED Timer Trigger"
+       depends LEDS_TRIGGERS && BLK_DEV_IDEDISK
+       help
+         This allows LEDs to be controlled by IDE disk activity.
+         If unsure, say Y.
+
+endmenu
+
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
new file mode 100644 (file)
index 0000000..40699d3
--- /dev/null
@@ -0,0 +1,16 @@
+
+# LED Core
+obj-$(CONFIG_NEW_LEDS)                 += led-core.o
+obj-$(CONFIG_LEDS_CLASS)               += led-class.o
+obj-$(CONFIG_LEDS_TRIGGERS)            += led-triggers.o
+
+# LED Platform Drivers
+obj-$(CONFIG_LEDS_CORGI)               += leds-corgi.o
+obj-$(CONFIG_LEDS_LOCOMO)              += leds-locomo.o
+obj-$(CONFIG_LEDS_SPITZ)               += leds-spitz.o
+obj-$(CONFIG_LEDS_IXP4XX)              += leds-ixp4xx-gpio.o
+obj-$(CONFIG_LEDS_TOSA)                        += leds-tosa.o
+
+# LED Triggers
+obj-$(CONFIG_LEDS_TRIGGER_TIMER)       += ledtrig-timer.o
+obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)    += ledtrig-ide-disk.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
new file mode 100644 (file)
index 0000000..b0b5d05
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * LED Class Core
+ *
+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu>
+ * Copyright (C) 2005-2006 Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/timer.h>
+#include <linux/err.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+static struct class *leds_class;
+
+static ssize_t led_brightness_show(struct class_device *dev, char *buf)
+{
+       struct led_classdev *led_cdev = class_get_devdata(dev);
+       ssize_t ret = 0;
+
+       /* no lock needed for this */
+       sprintf(buf, "%u\n", led_cdev->brightness);
+       ret = strlen(buf) + 1;
+
+       return ret;
+}
+
+static ssize_t led_brightness_store(struct class_device *dev,
+                               const char *buf, size_t size)
+{
+       struct led_classdev *led_cdev = class_get_devdata(dev);
+       ssize_t ret = -EINVAL;
+       char *after;
+       unsigned long state = simple_strtoul(buf, &after, 10);
+
+       if (after - buf > 0) {
+               ret = after - buf;
+               led_set_brightness(led_cdev, state);
+       }
+
+       return ret;
+}
+
+static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show,
+                       led_brightness_store);
+#ifdef CONFIG_LEDS_TRIGGERS
+static CLASS_DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
+#endif
+
+/**
+ * led_classdev_suspend - suspend an led_classdev.
+ * @led_cdev: the led_classdev to suspend.
+ */
+void led_classdev_suspend(struct led_classdev *led_cdev)
+{
+       led_cdev->flags |= LED_SUSPENDED;
+       led_cdev->brightness_set(led_cdev, 0);
+}
+EXPORT_SYMBOL_GPL(led_classdev_suspend);
+
+/**
+ * led_classdev_resume - resume an led_classdev.
+ * @led_cdev: the led_classdev to resume.
+ */
+void led_classdev_resume(struct led_classdev *led_cdev)
+{
+       led_cdev->brightness_set(led_cdev, led_cdev->brightness);
+       led_cdev->flags &= ~LED_SUSPENDED;
+}
+EXPORT_SYMBOL_GPL(led_classdev_resume);
+
+/**
+ * led_classdev_register - register a new object of led_classdev class.
+ * @dev: The device to register.
+ * @led_cdev: the led_classdev structure for this device.
+ */
+int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
+{
+       led_cdev->class_dev = class_device_create(leds_class, NULL, 0,
+                                               parent, "%s", led_cdev->name);
+       if (unlikely(IS_ERR(led_cdev->class_dev)))
+               return PTR_ERR(led_cdev->class_dev);
+
+       class_set_devdata(led_cdev->class_dev, led_cdev);
+
+       /* register the attributes */
+       class_device_create_file(led_cdev->class_dev,
+                               &class_device_attr_brightness);
+
+       /* add to the list of leds */
+       write_lock(&leds_list_lock);
+       list_add_tail(&led_cdev->node, &leds_list);
+       write_unlock(&leds_list_lock);
+
+#ifdef CONFIG_LEDS_TRIGGERS
+       rwlock_init(&led_cdev->trigger_lock);
+
+       led_trigger_set_default(led_cdev);
+
+       class_device_create_file(led_cdev->class_dev,
+                               &class_device_attr_trigger);
+#endif
+
+       printk(KERN_INFO "Registered led device: %s\n",
+                       led_cdev->class_dev->class_id);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(led_classdev_register);
+
+/**
+ * led_classdev_unregister - unregisters a object of led_properties class.
+ * @led_cdev: the led device to unreigister
+ *
+ * Unregisters a previously registered via led_classdev_register object.
+ */
+void led_classdev_unregister(struct led_classdev *led_cdev)
+{
+       class_device_remove_file(led_cdev->class_dev,
+                               &class_device_attr_brightness);
+#ifdef CONFIG_LEDS_TRIGGERS
+       class_device_remove_file(led_cdev->class_dev,
+                               &class_device_attr_trigger);
+       write_lock(&led_cdev->trigger_lock);
+       if (led_cdev->trigger)
+               led_trigger_set(led_cdev, NULL);
+       write_unlock(&led_cdev->trigger_lock);
+#endif
+
+       class_device_unregister(led_cdev->class_dev);
+
+       write_lock(&leds_list_lock);
+       list_del(&led_cdev->node);
+       write_unlock(&leds_list_lock);
+}
+EXPORT_SYMBOL_GPL(led_classdev_unregister);
+
+static int __init leds_init(void)
+{
+       leds_class = class_create(THIS_MODULE, "leds");
+       if (IS_ERR(leds_class))
+               return PTR_ERR(leds_class);
+       return 0;
+}
+
+static void __exit leds_exit(void)
+{
+       class_destroy(leds_class);
+}
+
+subsys_initcall(leds_init);
+module_exit(leds_exit);
+
+MODULE_AUTHOR("John Lenz, Richard Purdie");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LED Class Interface");
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
new file mode 100644 (file)
index 0000000..fe65413
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * LED Class Core
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+rwlock_t leds_list_lock = RW_LOCK_UNLOCKED;
+LIST_HEAD(leds_list);
+
+EXPORT_SYMBOL_GPL(leds_list);
+EXPORT_SYMBOL_GPL(leds_list_lock);
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
new file mode 100644 (file)
index 0000000..5e2cd8b
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * LED Triggers Core
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/timer.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+/*
+ * Nests outside led_cdev->trigger_lock
+ */
+static rwlock_t triggers_list_lock = RW_LOCK_UNLOCKED;
+static LIST_HEAD(trigger_list);
+
+ssize_t led_trigger_store(struct class_device *dev, const char *buf,
+                       size_t count)
+{
+       struct led_classdev *led_cdev = class_get_devdata(dev);
+       char trigger_name[TRIG_NAME_MAX];
+       struct led_trigger *trig;
+       size_t len;
+
+       trigger_name[sizeof(trigger_name) - 1] = '\0';
+       strncpy(trigger_name, buf, sizeof(trigger_name) - 1);
+       len = strlen(trigger_name);
+
+       if (len && trigger_name[len - 1] == '\n')
+               trigger_name[len - 1] = '\0';
+
+       if (!strcmp(trigger_name, "none")) {
+               write_lock(&led_cdev->trigger_lock);
+               led_trigger_set(led_cdev, NULL);
+               write_unlock(&led_cdev->trigger_lock);
+               return count;
+       }
+
+       read_lock(&triggers_list_lock);
+       list_for_each_entry(trig, &trigger_list, next_trig) {
+               if (!strcmp(trigger_name, trig->name)) {
+                       write_lock(&led_cdev->trigger_lock);
+                       led_trigger_set(led_cdev, trig);
+                       write_unlock(&led_cdev->trigger_lock);
+
+                       read_unlock(&triggers_list_lock);
+                       return count;
+               }
+       }
+       read_unlock(&triggers_list_lock);
+
+       return -EINVAL;
+}
+
+
+ssize_t led_trigger_show(struct class_device *dev, char *buf)
+{
+       struct led_classdev *led_cdev = class_get_devdata(dev);
+       struct led_trigger *trig;
+       int len = 0;
+
+       read_lock(&triggers_list_lock);
+       read_lock(&led_cdev->trigger_lock);
+
+       if (!led_cdev->trigger)
+               len += sprintf(buf+len, "[none] ");
+       else
+               len += sprintf(buf+len, "none ");
+
+       list_for_each_entry(trig, &trigger_list, next_trig) {
+               if (led_cdev->trigger && !strcmp(led_cdev->trigger->name,
+                                                       trig->name))
+                       len += sprintf(buf+len, "[%s] ", trig->name);
+               else
+                       len += sprintf(buf+len, "%s ", trig->name);
+       }
+       read_unlock(&led_cdev->trigger_lock);
+       read_unlock(&triggers_list_lock);
+
+       len += sprintf(len+buf, "\n");
+       return len;
+}
+
+void led_trigger_event(struct led_trigger *trigger,
+                       enum led_brightness brightness)
+{
+       struct list_head *entry;
+
+       if (!trigger)
+               return;
+
+       read_lock(&trigger->leddev_list_lock);
+       list_for_each(entry, &trigger->led_cdevs) {
+               struct led_classdev *led_cdev;
+
+               led_cdev = list_entry(entry, struct led_classdev, trig_list);
+               led_set_brightness(led_cdev, brightness);
+       }
+       read_unlock(&trigger->leddev_list_lock);
+}
+
+/* Caller must ensure led_cdev->trigger_lock held */
+void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
+{
+       unsigned long flags;
+
+       /* Remove any existing trigger */
+       if (led_cdev->trigger) {
+               write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags);
+               list_del(&led_cdev->trig_list);
+               write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags);
+               if (led_cdev->trigger->deactivate)
+                       led_cdev->trigger->deactivate(led_cdev);
+       }
+       if (trigger) {
+               write_lock_irqsave(&trigger->leddev_list_lock, flags);
+               list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs);
+               write_unlock_irqrestore(&trigger->leddev_list_lock, flags);
+               if (trigger->activate)
+                       trigger->activate(led_cdev);
+       }
+       led_cdev->trigger = trigger;
+}
+
+void led_trigger_set_default(struct led_classdev *led_cdev)
+{
+       struct led_trigger *trig;
+
+       if (!led_cdev->default_trigger)
+               return;
+
+       read_lock(&triggers_list_lock);
+       write_lock(&led_cdev->trigger_lock);
+       list_for_each_entry(trig, &trigger_list, next_trig) {
+               if (!strcmp(led_cdev->default_trigger, trig->name))
+                       led_trigger_set(led_cdev, trig);
+       }
+       write_unlock(&led_cdev->trigger_lock);
+       read_unlock(&triggers_list_lock);
+}
+
+int led_trigger_register(struct led_trigger *trigger)
+{
+       struct led_classdev *led_cdev;
+
+       rwlock_init(&trigger->leddev_list_lock);
+       INIT_LIST_HEAD(&trigger->led_cdevs);
+
+       /* Add to the list of led triggers */
+       write_lock(&triggers_list_lock);
+       list_add_tail(&trigger->next_trig, &trigger_list);
+       write_unlock(&triggers_list_lock);
+
+       /* Register with any LEDs that have this as a default trigger */
+       read_lock(&leds_list_lock);
+       list_for_each_entry(led_cdev, &leds_list, node) {
+               write_lock(&led_cdev->trigger_lock);
+               if (!led_cdev->trigger && led_cdev->default_trigger &&
+                           !strcmp(led_cdev->default_trigger, trigger->name))
+                       led_trigger_set(led_cdev, trigger);
+               write_unlock(&led_cdev->trigger_lock);
+       }
+       read_unlock(&leds_list_lock);
+
+       return 0;
+}
+
+void led_trigger_register_simple(const char *name, struct led_trigger **tp)
+{
+       struct led_trigger *trigger;
+
+       trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+
+       if (trigger) {
+               trigger->name = name;
+               led_trigger_register(trigger);
+       }
+       *tp = trigger;
+}
+
+void led_trigger_unregister(struct led_trigger *trigger)
+{
+       struct led_classdev *led_cdev;
+
+       /* Remove from the list of led triggers */
+       write_lock(&triggers_list_lock);
+       list_del(&trigger->next_trig);
+       write_unlock(&triggers_list_lock);
+
+       /* Remove anyone actively using this trigger */
+       read_lock(&leds_list_lock);
+       list_for_each_entry(led_cdev, &leds_list, node) {
+               write_lock(&led_cdev->trigger_lock);
+               if (led_cdev->trigger == trigger)
+                       led_trigger_set(led_cdev, NULL);
+               write_unlock(&led_cdev->trigger_lock);
+       }
+       read_unlock(&leds_list_lock);
+}
+
+void led_trigger_unregister_simple(struct led_trigger *trigger)
+{
+       led_trigger_unregister(trigger);
+       kfree(trigger);
+}
+
+/* Used by LED Class */
+EXPORT_SYMBOL_GPL(led_trigger_set);
+EXPORT_SYMBOL_GPL(led_trigger_set_default);
+EXPORT_SYMBOL_GPL(led_trigger_show);
+EXPORT_SYMBOL_GPL(led_trigger_store);
+
+/* LED Trigger Interface */
+EXPORT_SYMBOL_GPL(led_trigger_register);
+EXPORT_SYMBOL_GPL(led_trigger_unregister);
+
+/* Simple LED Tigger Interface */
+EXPORT_SYMBOL_GPL(led_trigger_register_simple);
+EXPORT_SYMBOL_GPL(led_trigger_unregister_simple);
+EXPORT_SYMBOL_GPL(led_trigger_event);
+
+MODULE_AUTHOR("Richard Purdie");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LED Triggers Core");
diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c
new file mode 100644 (file)
index 0000000..bb7d84d
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * LED Triggers Core
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/arch/corgi.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/hardware/scoop.h>
+
+static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+       if (value)
+               GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
+       else
+               GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
+}
+
+static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+       if (value)
+               set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
+       else
+               reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
+}
+
+static struct led_classdev corgi_amber_led = {
+       .name                   = "corgi:amber",
+       .default_trigger        = "sharpsl-charge",
+       .brightness_set         = corgiled_amber_set,
+};
+
+static struct led_classdev corgi_green_led = {
+       .name                   = "corgi:green",
+       .default_trigger        = "nand-disk",
+       .brightness_set         = corgiled_green_set,
+};
+
+#ifdef CONFIG_PM
+static int corgiled_suspend(struct platform_device *dev, pm_message_t state)
+{
+#ifdef CONFIG_LEDS_TRIGGERS
+       if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
+#endif
+               led_classdev_suspend(&corgi_amber_led);
+       led_classdev_suspend(&corgi_green_led);
+       return 0;
+}
+
+static int corgiled_resume(struct platform_device *dev)
+{
+       led_classdev_resume(&corgi_amber_led);
+       led_classdev_resume(&corgi_green_led);
+       return 0;
+}
+#endif
+
+static int corgiled_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       ret = led_classdev_register(&pdev->dev, &corgi_amber_led);
+       if (ret < 0)
+               return ret;
+
+       ret = led_classdev_register(&pdev->dev, &corgi_green_led);
+       if (ret < 0)
+               led_classdev_unregister(&corgi_amber_led);
+
+       return ret;
+}
+
+static int corgiled_remove(struct platform_device *pdev)
+{
+       led_classdev_unregister(&corgi_amber_led);
+       led_classdev_unregister(&corgi_green_led);
+       return 0;
+}
+
+static struct platform_driver corgiled_driver = {
+       .probe          = corgiled_probe,
+       .remove         = corgiled_remove,
+#ifdef CONFIG_PM
+       .suspend        = corgiled_suspend,
+       .resume         = corgiled_resume,
+#endif
+       .driver         = {
+               .name           = "corgi-led",
+       },
+};
+
+static int __init corgiled_init(void)
+{
+       return platform_driver_register(&corgiled_driver);
+}
+
+static void __exit corgiled_exit(void)
+{
+       platform_driver_unregister(&corgiled_driver);
+}
+
+module_init(corgiled_init);
+module_exit(corgiled_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
+MODULE_DESCRIPTION("Corgi LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-ixp4xx-gpio.c b/drivers/leds/leds-ixp4xx-gpio.c
new file mode 100644 (file)
index 0000000..30ced15
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * IXP4XX GPIO driver LED driver
+ *
+ * Author: John Bowler <jbowler@acm.org>
+ *
+ * Copyright (c) 2006 John Bowler
+ *
+ * Permission is hereby granted, free of charge, to any
+ * person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the
+ * Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice
+ * shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/leds.h>
+#include <asm/arch/hardware.h>
+
+extern spinlock_t gpio_lock;
+
+/* Up to 16 gpio lines are possible. */
+#define GPIO_MAX 16
+static struct ixp4xxgpioled_device {
+       struct led_classdev ancestor;
+       int               flags;
+} ixp4xxgpioled_devices[GPIO_MAX];
+
+void ixp4xxgpioled_brightness_set(struct led_classdev *pled,
+                               enum led_brightness value)
+{
+       const struct ixp4xxgpioled_device *const ixp4xx_dev =
+               container_of(pled, struct ixp4xxgpioled_device, ancestor);
+       const u32 gpio_pin = ixp4xx_dev - ixp4xxgpioled_devices;
+
+       if (gpio_pin < GPIO_MAX && ixp4xx_dev->ancestor.name != 0) {
+               /* Set or clear the 'gpio_pin' bit according to the style
+                * and the required setting (value > 0 == on)
+                */
+               const int gpio_value =
+                       (value > 0) == (ixp4xx_dev->flags != IXP4XX_GPIO_LOW) ?
+                               IXP4XX_GPIO_HIGH : IXP4XX_GPIO_LOW;
+
+               {
+                       unsigned long flags;
+                       spin_lock_irqsave(&gpio_lock, flags);
+                       gpio_line_set(gpio_pin, gpio_value);
+                       spin_unlock_irqrestore(&gpio_lock, flags);
+               }
+       }
+}
+
+/* LEDs are described in resources, the following iterates over the valid
+ * LED resources.
+ */
+#define for_all_leds(i, pdev) \
+       for (i=0; i<pdev->num_resources; ++i) \
+               if (pdev->resource[i].start < GPIO_MAX && \
+                       pdev->resource[i].name != 0)
+
+/* The following applies 'operation' to each LED from the given platform,
+ * the function always returns 0 to allow tail call elimination.
+ */
+static int apply_to_all_leds(struct platform_device *pdev,
+       void (*operation)(struct led_classdev *pled))
+{
+       int i;
+
+       for_all_leds(i, pdev)
+               operation(&ixp4xxgpioled_devices[pdev->resource[i].start].ancestor);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int ixp4xxgpioled_suspend(struct platform_device *pdev,
+                               pm_message_t state)
+{
+       return apply_to_all_leds(pdev, led_classdev_suspend);
+}
+
+static int ixp4xxgpioled_resume(struct platform_device *pdev)
+{
+       return apply_to_all_leds(pdev, led_classdev_resume);
+}
+#endif
+
+static void ixp4xxgpioled_remove_one_led(struct led_classdev *pled)
+{
+       led_classdev_unregister(pled);
+       pled->name = 0;
+}
+
+static int ixp4xxgpioled_remove(struct platform_device *pdev)
+{
+       return apply_to_all_leds(pdev, ixp4xxgpioled_remove_one_led);
+}
+
+static int ixp4xxgpioled_probe(struct platform_device *pdev)
+{
+       /* The board level has to tell the driver where the
+        * LEDs are connected - there is no way to find out
+        * electrically.  It must also say whether the GPIO
+        * lines are active high or active low.
+        *
+        * To do this read the num_resources (the number of
+        * LEDs) and the struct resource (the data for each
+        * LED).  The name comes from the resource, and it
+        * isn't copied.
+        */
+       int i;
+
+       for_all_leds(i, pdev) {
+               const u8 gpio_pin = pdev->resource[i].start;
+               int      rc;
+
+               if (ixp4xxgpioled_devices[gpio_pin].ancestor.name == 0) {
+                       unsigned long flags;
+
+                       spin_lock_irqsave(&gpio_lock, flags);
+                       gpio_line_config(gpio_pin, IXP4XX_GPIO_OUT);
+                       /* The config can, apparently, reset the state,
+                        * I suspect the gpio line may be an input and
+                        * the config may cause the line to be latched,
+                        * so the setting depends on how the LED is
+                        * connected to the line (which affects how it
+                        * floats if not driven).
+                        */
+                       gpio_line_set(gpio_pin, IXP4XX_GPIO_HIGH);
+                       spin_unlock_irqrestore(&gpio_lock, flags);
+
+                       ixp4xxgpioled_devices[gpio_pin].flags =
+                               pdev->resource[i].flags & IORESOURCE_BITS;
+
+                       ixp4xxgpioled_devices[gpio_pin].ancestor.name =
+                               pdev->resource[i].name;
+
+                       /* This is how a board manufacturer makes the LED
+                        * come on on reset - the GPIO line will be high, so
+                        * make the LED light when the line is low...
+                        */
+                       if (ixp4xxgpioled_devices[gpio_pin].flags != IXP4XX_GPIO_LOW)
+                               ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 100;
+                       else
+                               ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 0;
+
+                       ixp4xxgpioled_devices[gpio_pin].ancestor.flags = 0;
+
+                       ixp4xxgpioled_devices[gpio_pin].ancestor.brightness_set =
+                               ixp4xxgpioled_brightness_set;
+
+                       ixp4xxgpioled_devices[gpio_pin].ancestor.default_trigger = 0;
+               }
+
+               rc = led_classdev_register(&pdev->dev,
+                               &ixp4xxgpioled_devices[gpio_pin].ancestor);
+               if (rc < 0) {
+                       ixp4xxgpioled_devices[gpio_pin].ancestor.name = 0;
+                       ixp4xxgpioled_remove(pdev);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
+static struct platform_driver ixp4xxgpioled_driver = {
+       .probe   = ixp4xxgpioled_probe,
+       .remove  = ixp4xxgpioled_remove,
+#ifdef CONFIG_PM
+       .suspend = ixp4xxgpioled_suspend,
+       .resume  = ixp4xxgpioled_resume,
+#endif
+       .driver  = {
+               .name = "IXP4XX-GPIO-LED",
+       },
+};
+
+static int __init ixp4xxgpioled_init(void)
+{
+       return platform_driver_register(&ixp4xxgpioled_driver);
+}
+
+static void __exit ixp4xxgpioled_exit(void)
+{
+       platform_driver_unregister(&ixp4xxgpioled_driver);
+}
+
+module_init(ixp4xxgpioled_init);
+module_exit(ixp4xxgpioled_exit);
+
+MODULE_AUTHOR("John Bowler <jbowler@acm.org>");
+MODULE_DESCRIPTION("IXP4XX GPIO LED driver");
+MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c
new file mode 100644 (file)
index 0000000..749a86c
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * linux/drivers/leds/locomo.c
+ *
+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/leds.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/locomo.h>
+
+static void locomoled_brightness_set(struct led_classdev *led_cdev,
+                               enum led_brightness value, int offset)
+{
+       struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->class_dev->dev);
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (value)
+               locomo_writel(LOCOMO_LPT_TOFH, locomo_dev->mapbase + offset);
+       else
+               locomo_writel(LOCOMO_LPT_TOFL, locomo_dev->mapbase + offset);
+       local_irq_restore(flags);
+}
+
+static void locomoled_brightness_set0(struct led_classdev *led_cdev,
+                               enum led_brightness value)
+{
+       locomoled_brightness_set(led_cdev, value, LOCOMO_LPT0);
+}
+
+static void locomoled_brightness_set1(struct led_classdev *led_cdev,
+                               enum led_brightness value)
+{
+       locomoled_brightness_set(led_cdev, value, LOCOMO_LPT1);
+}
+
+static struct led_classdev locomo_led0 = {
+       .name                   = "locomo:amber",
+       .brightness_set         = locomoled_brightness_set0,
+};
+
+static struct led_classdev locomo_led1 = {
+       .name                   = "locomo:green",
+       .brightness_set         = locomoled_brightness_set1,
+};
+
+static int locomoled_probe(struct locomo_dev *ldev)
+{
+       int ret;
+
+       ret = led_classdev_register(&ldev->dev, &locomo_led0);
+       if (ret < 0)
+               return ret;
+
+       ret = led_classdev_register(&ldev->dev, &locomo_led1);
+       if (ret < 0)
+               led_classdev_unregister(&locomo_led0);
+
+       return ret;
+}
+
+static int locomoled_remove(struct locomo_dev *dev)
+{
+       led_classdev_unregister(&locomo_led0);
+       led_classdev_unregister(&locomo_led1);
+       return 0;
+}
+
+static struct locomo_driver locomoled_driver = {
+       .drv = {
+               .name = "locomoled"
+       },
+       .devid  = LOCOMO_DEVID_LED,
+       .probe  = locomoled_probe,
+       .remove = locomoled_remove,
+};
+
+static int __init locomoled_init(void)
+{
+       return locomo_driver_register(&locomoled_driver);
+}
+module_init(locomoled_init);
+
+MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
+MODULE_DESCRIPTION("Locomo LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c
new file mode 100644 (file)
index 0000000..65bbef4
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * LED Triggers Core
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/hardware/scoop.h>
+#include <asm/mach-types.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/spitz.h>
+
+static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+       if (value)
+               set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
+       else
+               reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
+}
+
+static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+       if (value)
+               set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
+       else
+               reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
+}
+
+static struct led_classdev spitz_amber_led = {
+       .name                   = "spitz:amber",
+       .default_trigger        = "sharpsl-charge",
+       .brightness_set         = spitzled_amber_set,
+};
+
+static struct led_classdev spitz_green_led = {
+       .name                   = "spitz:green",
+       .default_trigger        = "ide-disk",
+       .brightness_set         = spitzled_green_set,
+};
+
+#ifdef CONFIG_PM
+static int spitzled_suspend(struct platform_device *dev, pm_message_t state)
+{
+#ifdef CONFIG_LEDS_TRIGGERS
+       if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
+#endif
+               led_classdev_suspend(&spitz_amber_led);
+       led_classdev_suspend(&spitz_green_led);
+       return 0;
+}
+
+static int spitzled_resume(struct platform_device *dev)
+{
+       led_classdev_resume(&spitz_amber_led);
+       led_classdev_resume(&spitz_green_led);
+       return 0;
+}
+#endif
+
+static int spitzled_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       if (machine_is_akita())
+               spitz_green_led.default_trigger = "nand-disk";
+
+       ret = led_classdev_register(&pdev->dev, &spitz_amber_led);
+       if (ret < 0)
+               return ret;
+
+       ret = led_classdev_register(&pdev->dev, &spitz_green_led);
+       if (ret < 0)
+               led_classdev_unregister(&spitz_amber_led);
+
+       return ret;
+}
+
+static int spitzled_remove(struct platform_device *pdev)
+{
+       led_classdev_unregister(&spitz_amber_led);
+       led_classdev_unregister(&spitz_green_led);
+
+       return 0;
+}
+
+static struct platform_driver spitzled_driver = {
+       .probe          = spitzled_probe,
+       .remove         = spitzled_remove,
+#ifdef CONFIG_PM
+       .suspend        = spitzled_suspend,
+       .resume         = spitzled_resume,
+#endif
+       .driver         = {
+               .name           = "spitz-led",
+       },
+};
+
+static int __init spitzled_init(void)
+{
+       return platform_driver_register(&spitzled_driver);
+}
+
+static void __exit spitzled_exit(void)
+{
+       platform_driver_unregister(&spitzled_driver);
+}
+
+module_init(spitzled_init);
+module_exit(spitzled_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
+MODULE_DESCRIPTION("Spitz LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-tosa.c b/drivers/leds/leds-tosa.c
new file mode 100644 (file)
index 0000000..c9e8cc1
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * LED Triggers Core
+ *
+ * Copyright 2005 Dirk Opfer
+ *
+ * Author: Dirk Opfer <Dirk@Opfer-Online.de>
+ *     based on spitz.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/hardware/scoop.h>
+#include <asm/mach-types.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/tosa.h>
+
+static void tosaled_amber_set(struct led_classdev *led_cdev,
+                               enum led_brightness value)
+{
+       if (value)
+               set_scoop_gpio(&tosascoop_jc_device.dev,
+                               TOSA_SCOOP_JC_CHRG_ERR_LED);
+       else
+               reset_scoop_gpio(&tosascoop_jc_device.dev,
+                               TOSA_SCOOP_JC_CHRG_ERR_LED);
+}
+
+static void tosaled_green_set(struct led_classdev *led_cdev,
+                               enum led_brightness value)
+{
+       if (value)
+               set_scoop_gpio(&tosascoop_jc_device.dev,
+                               TOSA_SCOOP_JC_NOTE_LED);
+       else
+               reset_scoop_gpio(&tosascoop_jc_device.dev,
+                               TOSA_SCOOP_JC_NOTE_LED);
+}
+
+static struct led_classdev tosa_amber_led = {
+       .name                   = "tosa:amber",
+       .default_trigger        = "sharpsl-charge",
+       .brightness_set         = tosaled_amber_set,
+};
+
+static struct led_classdev tosa_green_led = {
+       .name                   = "tosa:green",
+       .default_trigger        = "nand-disk",
+       .brightness_set         = tosaled_green_set,
+};
+
+#ifdef CONFIG_PM
+static int tosaled_suspend(struct platform_device *dev, pm_message_t state)
+{
+#ifdef CONFIG_LEDS_TRIGGERS
+       if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name,
+                                               "sharpsl-charge"))
+#endif
+               led_classdev_suspend(&tosa_amber_led);
+       led_classdev_suspend(&tosa_green_led);
+       return 0;
+}
+
+static int tosaled_resume(struct platform_device *dev)
+{
+       led_classdev_resume(&tosa_amber_led);
+       led_classdev_resume(&tosa_green_led);
+       return 0;
+}
+#else
+#define tosaled_suspend NULL
+#define tosaled_resume NULL
+#endif
+
+static int tosaled_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       ret = led_classdev_register(&pdev->dev, &tosa_amber_led);
+       if (ret < 0)
+               return ret;
+
+       ret = led_classdev_register(&pdev->dev, &tosa_green_led);
+       if (ret < 0)
+               led_classdev_unregister(&tosa_amber_led);
+
+       return ret;
+}
+
+static int tosaled_remove(struct platform_device *pdev)
+{
+       led_classdev_unregister(&tosa_amber_led);
+       led_classdev_unregister(&tosa_green_led);
+
+       return 0;
+}
+
+static struct platform_driver tosaled_driver = {
+       .probe          = tosaled_probe,
+       .remove         = tosaled_remove,
+       .suspend        = tosaled_suspend,
+       .resume         = tosaled_resume,
+       .driver         = {
+               .name           = "tosa-led",
+       },
+};
+
+static int __init tosaled_init(void)
+{
+       return platform_driver_register(&tosaled_driver);
+}
+
+static void __exit tosaled_exit(void)
+{
+       platform_driver_unregister(&tosaled_driver);
+}
+
+module_init(tosaled_init);
+module_exit(tosaled_exit);
+
+MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>");
+MODULE_DESCRIPTION("Tosa LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
new file mode 100644 (file)
index 0000000..a715c4e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * LED Core
+ *
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __LEDS_H_INCLUDED
+#define __LEDS_H_INCLUDED
+
+#include <linux/leds.h>
+
+static inline void led_set_brightness(struct led_classdev *led_cdev,
+                                       enum led_brightness value)
+{
+       if (value > LED_FULL)
+               value = LED_FULL;
+       led_cdev->brightness = value;
+       if (!(led_cdev->flags & LED_SUSPENDED))
+               led_cdev->brightness_set(led_cdev, value);
+}
+
+extern rwlock_t leds_list_lock;
+extern struct list_head leds_list;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+void led_trigger_set_default(struct led_classdev *led_cdev);
+void led_trigger_set(struct led_classdev *led_cdev,
+                       struct led_trigger *trigger);
+#else
+#define led_trigger_set_default(x) do {} while(0)
+#define led_trigger_set(x, y) do {} while(0)
+#endif
+
+ssize_t led_trigger_store(struct class_device *dev, const char *buf,
+                       size_t count);
+ssize_t led_trigger_show(struct class_device *dev, char *buf);
+
+#endif /* __LEDS_H_INCLUDED */
diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c
new file mode 100644 (file)
index 0000000..fa65188
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * LED IDE-Disk Activity Trigger
+ *
+ * Copyright 2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/leds.h>
+
+static void ledtrig_ide_timerfunc(unsigned long data);
+
+DEFINE_LED_TRIGGER(ledtrig_ide);
+static DEFINE_TIMER(ledtrig_ide_timer, ledtrig_ide_timerfunc, 0, 0);
+static int ide_activity;
+static int ide_lastactivity;
+
+void ledtrig_ide_activity(void)
+{
+       ide_activity++;
+       if (!timer_pending(&ledtrig_ide_timer))
+               mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
+}
+EXPORT_SYMBOL(ledtrig_ide_activity);
+
+static void ledtrig_ide_timerfunc(unsigned long data)
+{
+       if (ide_lastactivity != ide_activity) {
+               ide_lastactivity = ide_activity;
+               led_trigger_event(ledtrig_ide, LED_FULL);
+               mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
+       } else {
+               led_trigger_event(ledtrig_ide, LED_OFF);
+       }
+}
+
+static int __init ledtrig_ide_init(void)
+{
+       led_trigger_register_simple("ide-disk", &ledtrig_ide);
+       return 0;
+}
+
+static void __exit ledtrig_ide_exit(void)
+{
+       led_trigger_unregister_simple(ledtrig_ide);
+}
+
+module_init(ledtrig_ide_init);
+module_exit(ledtrig_ide_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
+MODULE_DESCRIPTION("LED IDE Disk Activity Trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
new file mode 100644 (file)
index 0000000..f484b5d
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * LED Kernel Timer Trigger
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/timer.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+struct timer_trig_data {
+       unsigned long delay_on;         /* milliseconds on */
+       unsigned long delay_off;        /* milliseconds off */
+       struct timer_list timer;
+};
+
+static void led_timer_function(unsigned long data)
+{
+       struct led_classdev *led_cdev = (struct led_classdev *) data;
+       struct timer_trig_data *timer_data = led_cdev->trigger_data;
+       unsigned long brightness = LED_OFF;
+       unsigned long delay = timer_data->delay_off;
+
+       if (!timer_data->delay_on || !timer_data->delay_off) {
+               led_set_brightness(led_cdev, LED_OFF);
+               return;
+       }
+
+       if (!led_cdev->brightness) {
+               brightness = LED_FULL;
+               delay = timer_data->delay_on;
+       }
+
+       led_set_brightness(led_cdev, brightness);
+
+       mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay));
+}
+
+static ssize_t led_delay_on_show(struct class_device *dev, char *buf)
+{
+       struct led_classdev *led_cdev = class_get_devdata(dev);
+       struct timer_trig_data *timer_data = led_cdev->trigger_data;
+
+       sprintf(buf, "%lu\n", timer_data->delay_on);
+
+       return strlen(buf) + 1;
+}
+
+static ssize_t led_delay_on_store(struct class_device *dev, const char *buf,
+                               size_t size)
+{
+       struct led_classdev *led_cdev = class_get_devdata(dev);
+       struct timer_trig_data *timer_data = led_cdev->trigger_data;
+       int ret = -EINVAL;
+       char *after;
+       unsigned long state = simple_strtoul(buf, &after, 10);
+
+       if (after - buf > 0) {
+               timer_data->delay_on = state;
+               mod_timer(&timer_data->timer, jiffies + 1);
+               ret = after - buf;
+       }
+
+       return ret;
+}
+
+static ssize_t led_delay_off_show(struct class_device *dev, char *buf)
+{
+       struct led_classdev *led_cdev = class_get_devdata(dev);
+       struct timer_trig_data *timer_data = led_cdev->trigger_data;
+
+       sprintf(buf, "%lu\n", timer_data->delay_off);
+
+       return strlen(buf) + 1;
+}
+
+static ssize_t led_delay_off_store(struct class_device *dev, const char *buf,
+                               size_t size)
+{
+       struct led_classdev *led_cdev = class_get_devdata(dev);
+       struct timer_trig_data *timer_data = led_cdev->trigger_data;
+       int ret = -EINVAL;
+       char *after;
+       unsigned long state = simple_strtoul(buf, &after, 10);
+
+       if (after - buf > 0) {
+               timer_data->delay_off = state;
+               mod_timer(&timer_data->timer, jiffies + 1);
+               ret = after - buf;
+       }
+
+       return ret;
+}
+
+static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show,
+                       led_delay_on_store);
+static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show,
+                       led_delay_off_store);
+
+static void timer_trig_activate(struct led_classdev *led_cdev)
+{
+       struct timer_trig_data *timer_data;
+
+       timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL);
+       if (!timer_data)
+               return;
+
+       led_cdev->trigger_data = timer_data;
+
+       init_timer(&timer_data->timer);
+       timer_data->timer.function = led_timer_function;
+       timer_data->timer.data = (unsigned long) led_cdev;
+
+       class_device_create_file(led_cdev->class_dev,
+                               &class_device_attr_delay_on);
+       class_device_create_file(led_cdev->class_dev,
+                               &class_device_attr_delay_off);
+}
+
+static void timer_trig_deactivate(struct led_classdev *led_cdev)
+{
+       struct timer_trig_data *timer_data = led_cdev->trigger_data;
+
+       if (timer_data) {
+               class_device_remove_file(led_cdev->class_dev,
+                                       &class_device_attr_delay_on);
+               class_device_remove_file(led_cdev->class_dev,
+                                       &class_device_attr_delay_off);
+               del_timer_sync(&timer_data->timer);
+               kfree(timer_data);
+       }
+}
+
+static struct led_trigger timer_led_trigger = {
+       .name     = "timer",
+       .activate = timer_trig_activate,
+       .deactivate = timer_trig_deactivate,
+};
+
+static int __init timer_trig_init(void)
+{
+       return led_trigger_register(&timer_led_trigger);
+}
+
+static void __exit timer_trig_exit(void)
+{
+       led_trigger_unregister(&timer_led_trigger);
+}
+
+module_init(timer_trig_init);
+module_exit(timer_trig_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
+MODULE_DESCRIPTION("Timer LED trigger");
+MODULE_LICENSE("GPL");
index 039e071..1ed5152 100644 (file)
@@ -215,13 +215,11 @@ static void mddev_put(mddev_t *mddev)
                return;
        if (!mddev->raid_disks && list_empty(&mddev->disks)) {
                list_del(&mddev->all_mddevs);
-               /* that blocks */
+               spin_unlock(&all_mddevs_lock);
                blk_cleanup_queue(mddev->queue);
-               /* that also blocks */
                kobject_unregister(&mddev->kobj);
-               /* result blows... */
-       }
-       spin_unlock(&all_mddevs_lock);
+       } else
+               spin_unlock(&all_mddevs_lock);
 }
 
 static mddev_t * mddev_find(dev_t unit)
index 3cb0872..9b374c9 100644 (file)
@@ -1135,8 +1135,19 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
                        mirror = i;
                        break;
                }
-       if (!uptodate)
+       if (!uptodate) {
+               int sync_blocks = 0;
+               sector_t s = r1_bio->sector;
+               long sectors_to_go = r1_bio->sectors;
+               /* make sure these bits doesn't get cleared. */
+               do {
+                       bitmap_end_sync(mddev->bitmap, r1_bio->sector,
+                                       &sync_blocks, 1);
+                       s += sync_blocks;
+                       sectors_to_go -= sync_blocks;
+               } while (sectors_to_go > 0);
                md_error(mddev, conf->mirrors[mirror].rdev);
+       }
 
        update_head_pos(mirror, r1_bio);
 
index 6df4930..ab64b37 100644 (file)
@@ -2151,6 +2151,8 @@ static int run(mddev_t *mddev)
        }
 
        /* Ok, everything is just fine now */
+       sysfs_create_group(&mddev->kobj, &raid6_attrs_group);
+
        mddev->array_size =  mddev->size * (mddev->raid_disks - 2);
 
        mddev->queue->unplug_fn = raid6_unplug_device;
index 3021f21..0b00e60 100644 (file)
@@ -873,7 +873,7 @@ static int __init cpia_pp_setup(char *str)
                parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE;
        }
 
-       return 0;
+       return 1;
 }
 
 __setup("cpia_pp=", cpia_pp_setup);
index 3f5d77f..7cc162e 100644 (file)
@@ -60,6 +60,17 @@ config MMC_SDHCI
 
          If unsure, say N.
 
+config MMC_OMAP
+       tristate "TI OMAP Multimedia Card Interface support"
+       depends on ARCH_OMAP && MMC
+       select TPS65010 if MACH_OMAP_H2
+       help
+         This selects the TI OMAP Multimedia card Interface.
+         If you have an OMAP board with a Multimedia Card slot,
+         say Y or M here.
+
+         If unsure, say N.
+
 config MMC_WBSD
        tristate "Winbond W83L51xD SD/MMC Card Interface support"
        depends on MMC && ISA_DMA_API
index 769d545..c7c34aa 100644 (file)
@@ -20,5 +20,10 @@ obj-$(CONFIG_MMC_PXA)                += pxamci.o
 obj-$(CONFIG_MMC_SDHCI)                += sdhci.o
 obj-$(CONFIG_MMC_WBSD)         += wbsd.o
 obj-$(CONFIG_MMC_AU1X)         += au1xmmc.o
+obj-$(CONFIG_MMC_OMAP)         += omap.o
 
 mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
index 85e89c7..c0326bb 100644 (file)
 #define DRIVER_NAME "au1xxx-mmc"
 
 /* Set this to enable special debugging macros */
-/* #define MMC_DEBUG */
 
-#ifdef MMC_DEBUG
-#define DEBUG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
+#ifdef DEBUG
+#define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
 #else
-#define DEBUG(fmt, idx, args...)
+#define DBG(fmt, idx, args...)
 #endif
 
 const struct {
@@ -424,18 +423,18 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
                        break;
 
                if (status & SD_STATUS_RC) {
-                       DEBUG("RX CRC Error [%d + %d].\n", host->id,
+                       DBG("RX CRC Error [%d + %d].\n", host->id,
                                        host->pio.len, count);
                        break;
                }
 
                if (status & SD_STATUS_RO) {
-                       DEBUG("RX Overrun [%d + %d]\n", host->id,
+                       DBG("RX Overrun [%d + %d]\n", host->id,
                                        host->pio.len, count);
                        break;
                }
                else if (status & SD_STATUS_RU) {
-                       DEBUG("RX Underrun [%d + %d]\n", host->id,
+                       DBG("RX Underrun [%d + %d]\n", host->id,
                                        host->pio.len,  count);
                        break;
                }
@@ -721,7 +720,7 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
 {
        struct au1xmmc_host *host = mmc_priv(mmc);
 
-       DEBUG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n",
+       DBG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n",
              host->id, ios->power_mode, ios->clock, ios->vdd,
              ios->bus_mode);
 
@@ -810,7 +809,7 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id, struct pt_regs *regs)
                                au1xmmc_receive_pio(host);
                }
                else if (status & 0x203FBC70) {
-                       DEBUG("Unhandled status %8.8x\n", host->id, status);
+                       DBG("Unhandled status %8.8x\n", host->id, status);
                        handled = 0;
                }
 
@@ -839,7 +838,7 @@ static void au1xmmc_poll_event(unsigned long arg)
 
        if (host->mrq != NULL) {
                u32 status = au_readl(HOST_STATUS(host));
-               DEBUG("PENDING - %8.8x\n", host->id, status);
+               DBG("PENDING - %8.8x\n", host->id, status);
        }
 
        mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
index 1888060..da6ddd9 100644 (file)
 
 #include "mmc.h"
 
-#ifdef CONFIG_MMC_DEBUG
-#define DBG(x...)      printk(KERN_DEBUG x)
-#else
-#define DBG(x...)      do { } while (0)
-#endif
-
 #define CMD_RETRIES    3
 
 /*
@@ -77,8 +71,9 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
 {
        struct mmc_command *cmd = mrq->cmd;
        int err = mrq->cmd->error;
-       DBG("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", cmd->opcode,
-           err, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+       pr_debug("MMC: req done (%02x): %d: %08x %08x %08x %08x\n",
+                cmd->opcode, err, cmd->resp[0], cmd->resp[1],
+                cmd->resp[2], cmd->resp[3]);
 
        if (err && cmd->retries) {
                cmd->retries--;
@@ -102,8 +97,8 @@ EXPORT_SYMBOL(mmc_request_done);
 void
 mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 {
-       DBG("MMC: starting cmd %02x arg %08x flags %08x\n",
-           mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags);
+       pr_debug("MMC: starting cmd %02x arg %08x flags %08x\n",
+                mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags);
 
        WARN_ON(host->card_busy == NULL);
 
@@ -976,8 +971,8 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host)
                if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr)
                        max_dtr = card->csd.max_dtr;
 
-       DBG("MMC: selected %d.%03dMHz transfer rate\n",
-           max_dtr / 1000000, (max_dtr / 1000) % 1000);
+       pr_debug("MMC: selected %d.%03dMHz transfer rate\n",
+                max_dtr / 1000000, (max_dtr / 1000) % 1000);
 
        return max_dtr;
 }
index 9fef29d..df7e861 100644 (file)
 
 #define DRIVER_NAME "mmci-pl18x"
 
-#ifdef CONFIG_MMC_DEBUG
 #define DBG(host,fmt,args...)  \
        pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args)
-#else
-#define DBG(host,fmt,args...)  do { } while (0)
-#endif
 
 static unsigned int fmax = 515633;
 
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
new file mode 100644 (file)
index 0000000..becb3c6
--- /dev/null
@@ -0,0 +1,1226 @@
+/*
+ *  linux/drivers/media/mmc/omap.c
+ *
+ *  Copyright (C) 2004 Nokia Corporation
+ *  Written by Tuukka Tikkanen and Juha Yrjölä<juha.yrjola@nokia.com>
+ *  Misc hacks here and there by Tony Lindgren <tony@atomide.com>
+ *  Other hacks (DMA, SD, etc) by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+#include <linux/mmc/card.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/scatterlist.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/fpga.h>
+#include <asm/arch/tps65010.h>
+
+#include "omap.h"
+
+#define DRIVER_NAME "mmci-omap"
+#define RSP_TYPE(x)    ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
+
+/* Specifies how often in millisecs to poll for card status changes
+ * when the cover switch is open */
+#define OMAP_MMC_SWITCH_POLL_DELAY     500
+
+static int mmc_omap_enable_poll = 1;
+
+struct mmc_omap_host {
+       int                     initialized;
+       int                     suspended;
+       struct mmc_request *    mrq;
+       struct mmc_command *    cmd;
+       struct mmc_data *       data;
+       struct mmc_host *       mmc;
+       struct device *         dev;
+       unsigned char           id; /* 16xx chips have 2 MMC blocks */
+       struct clk *            iclk;
+       struct clk *            fclk;
+       void __iomem            *base;
+       int                     irq;
+       unsigned char           bus_mode;
+       unsigned char           hw_bus_mode;
+
+       unsigned int            sg_len;
+       int                     sg_idx;
+       u16 *                   buffer;
+       u32                     buffer_bytes_left;
+       u32                     total_bytes_left;
+
+       unsigned                use_dma:1;
+       unsigned                brs_received:1, dma_done:1;
+       unsigned                dma_is_read:1;
+       unsigned                dma_in_use:1;
+       int                     dma_ch;
+       spinlock_t              dma_lock;
+       struct timer_list       dma_timer;
+       unsigned                dma_len;
+
+       short                   power_pin;
+       short                   wp_pin;
+
+       int                     switch_pin;
+       struct work_struct      switch_work;
+       struct timer_list       switch_timer;
+       int                     switch_last_state;
+};
+
+static inline int
+mmc_omap_cover_is_open(struct mmc_omap_host *host)
+{
+       if (host->switch_pin < 0)
+               return 0;
+       return omap_get_gpio_datain(host->switch_pin);
+}
+
+static ssize_t
+mmc_omap_show_cover_switch(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%s\n", mmc_omap_cover_is_open(host) ? "open" :
+                       "closed");
+}
+
+static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
+
+static ssize_t
+mmc_omap_show_enable_poll(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", mmc_omap_enable_poll);
+}
+
+static ssize_t
+mmc_omap_store_enable_poll(struct device *dev,
+       struct device_attribute *attr, const char *buf,
+       size_t size)
+{
+       int enable_poll;
+
+       if (sscanf(buf, "%10d", &enable_poll) != 1)
+               return -EINVAL;
+
+       if (enable_poll != mmc_omap_enable_poll) {
+               struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+               mmc_omap_enable_poll = enable_poll;
+               if (enable_poll && host->switch_pin >= 0)
+                       schedule_work(&host->switch_work);
+       }
+       return size;
+}
+
+static DEVICE_ATTR(enable_poll, 0664,
+                  mmc_omap_show_enable_poll, mmc_omap_store_enable_poll);
+
+static void
+mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+{
+       u32 cmdreg;
+       u32 resptype;
+       u32 cmdtype;
+
+       host->cmd = cmd;
+
+       resptype = 0;
+       cmdtype = 0;
+
+       /* Our hardware needs to know exact type */
+       switch (RSP_TYPE(mmc_resp_type(cmd))) {
+       case RSP_TYPE(MMC_RSP_R1):
+               /* resp 1, resp 1b */
+               resptype = 1;
+               break;
+       case RSP_TYPE(MMC_RSP_R2):
+               resptype = 2;
+               break;
+       case RSP_TYPE(MMC_RSP_R3):
+               resptype = 3;
+               break;
+       default:
+               break;
+       }
+
+       if (mmc_cmd_type(cmd) == MMC_CMD_ADTC) {
+               cmdtype = OMAP_MMC_CMDTYPE_ADTC;
+       } else if (mmc_cmd_type(cmd) == MMC_CMD_BC) {
+               cmdtype = OMAP_MMC_CMDTYPE_BC;
+       } else if (mmc_cmd_type(cmd) == MMC_CMD_BCR) {
+               cmdtype = OMAP_MMC_CMDTYPE_BCR;
+       } else {
+               cmdtype = OMAP_MMC_CMDTYPE_AC;
+       }
+
+       cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12);
+
+       if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+               cmdreg |= 1 << 6;
+
+       if (cmd->flags & MMC_RSP_BUSY)
+               cmdreg |= 1 << 11;
+
+       if (host->data && !(host->data->flags & MMC_DATA_WRITE))
+               cmdreg |= 1 << 15;
+
+       clk_enable(host->fclk);
+
+       OMAP_MMC_WRITE(host->base, CTO, 200);
+       OMAP_MMC_WRITE(host->base, ARGL, cmd->arg & 0xffff);
+       OMAP_MMC_WRITE(host->base, ARGH, cmd->arg >> 16);
+       OMAP_MMC_WRITE(host->base, IE,
+                      OMAP_MMC_STAT_A_EMPTY    | OMAP_MMC_STAT_A_FULL    |
+                      OMAP_MMC_STAT_CMD_CRC    | OMAP_MMC_STAT_CMD_TOUT  |
+                      OMAP_MMC_STAT_DATA_CRC   | OMAP_MMC_STAT_DATA_TOUT |
+                      OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR  |
+                      OMAP_MMC_STAT_END_OF_DATA);
+       OMAP_MMC_WRITE(host->base, CMD, cmdreg);
+}
+
+static void
+mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       if (host->dma_in_use) {
+               enum dma_data_direction dma_data_dir;
+
+               BUG_ON(host->dma_ch < 0);
+               if (data->error != MMC_ERR_NONE)
+                       omap_stop_dma(host->dma_ch);
+               /* Release DMA channel lazily */
+               mod_timer(&host->dma_timer, jiffies + HZ);
+               if (data->flags & MMC_DATA_WRITE)
+                       dma_data_dir = DMA_TO_DEVICE;
+               else
+                       dma_data_dir = DMA_FROM_DEVICE;
+               dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
+                            dma_data_dir);
+       }
+       host->data = NULL;
+       host->sg_len = 0;
+       clk_disable(host->fclk);
+
+       /* NOTE:  MMC layer will sometimes poll-wait CMD13 next, issuing
+        * dozens of requests until the card finishes writing data.
+        * It'd be cheaper to just wait till an EOFB interrupt arrives...
+        */
+
+       if (!data->stop) {
+               host->mrq = NULL;
+               mmc_request_done(host->mmc, data->mrq);
+               return;
+       }
+
+       mmc_omap_start_command(host, data->stop);
+}
+
+static void
+mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       unsigned long flags;
+       int done;
+
+       if (!host->dma_in_use) {
+               mmc_omap_xfer_done(host, data);
+               return;
+       }
+       done = 0;
+       spin_lock_irqsave(&host->dma_lock, flags);
+       if (host->dma_done)
+               done = 1;
+       else
+               host->brs_received = 1;
+       spin_unlock_irqrestore(&host->dma_lock, flags);
+       if (done)
+               mmc_omap_xfer_done(host, data);
+}
+
+static void
+mmc_omap_dma_timer(unsigned long data)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+
+       BUG_ON(host->dma_ch < 0);
+       omap_free_dma(host->dma_ch);
+       host->dma_ch = -1;
+}
+
+static void
+mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       unsigned long flags;
+       int done;
+
+       done = 0;
+       spin_lock_irqsave(&host->dma_lock, flags);
+       if (host->brs_received)
+               done = 1;
+       else
+               host->dma_done = 1;
+       spin_unlock_irqrestore(&host->dma_lock, flags);
+       if (done)
+               mmc_omap_xfer_done(host, data);
+}
+
+static void
+mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
+{
+       host->cmd = NULL;
+
+       if (cmd->flags & MMC_RSP_PRESENT) {
+               if (cmd->flags & MMC_RSP_136) {
+                       /* response type 2 */
+                       cmd->resp[3] =
+                               OMAP_MMC_READ(host->base, RSP0) |
+                               (OMAP_MMC_READ(host->base, RSP1) << 16);
+                       cmd->resp[2] =
+                               OMAP_MMC_READ(host->base, RSP2) |
+                               (OMAP_MMC_READ(host->base, RSP3) << 16);
+                       cmd->resp[1] =
+                               OMAP_MMC_READ(host->base, RSP4) |
+                               (OMAP_MMC_READ(host->base, RSP5) << 16);
+                       cmd->resp[0] =
+                               OMAP_MMC_READ(host->base, RSP6) |
+                               (OMAP_MMC_READ(host->base, RSP7) << 16);
+               } else {
+                       /* response types 1, 1b, 3, 4, 5, 6 */
+                       cmd->resp[0] =
+                               OMAP_MMC_READ(host->base, RSP6) |
+                               (OMAP_MMC_READ(host->base, RSP7) << 16);
+               }
+       }
+
+       if (host->data == NULL || cmd->error != MMC_ERR_NONE) {
+               host->mrq = NULL;
+               clk_disable(host->fclk);
+               mmc_request_done(host->mmc, cmd->mrq);
+       }
+}
+
+/* PIO only */
+static void
+mmc_omap_sg_to_buf(struct mmc_omap_host *host)
+{
+       struct scatterlist *sg;
+
+       sg = host->data->sg + host->sg_idx;
+       host->buffer_bytes_left = sg->length;
+       host->buffer = page_address(sg->page) + sg->offset;
+       if (host->buffer_bytes_left > host->total_bytes_left)
+               host->buffer_bytes_left = host->total_bytes_left;
+}
+
+/* PIO only */
+static void
+mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
+{
+       int n;
+       void __iomem *reg;
+       u16 *p;
+
+       if (host->buffer_bytes_left == 0) {
+               host->sg_idx++;
+               BUG_ON(host->sg_idx == host->sg_len);
+               mmc_omap_sg_to_buf(host);
+       }
+       n = 64;
+       if (n > host->buffer_bytes_left)
+               n = host->buffer_bytes_left;
+       host->buffer_bytes_left -= n;
+       host->total_bytes_left -= n;
+       host->data->bytes_xfered += n;
+
+       if (write) {
+               __raw_writesw(host->base + OMAP_MMC_REG_DATA, host->buffer, n);
+       } else {
+               __raw_readsw(host->base + OMAP_MMC_REG_DATA, host->buffer, n);
+       }
+}
+
+static inline void mmc_omap_report_irq(u16 status)
+{
+       static const char *mmc_omap_status_bits[] = {
+               "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO",
+               "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR"
+       };
+       int i, c = 0;
+
+       for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
+               if (status & (1 << i)) {
+                       if (c)
+                               printk(" ");
+                       printk("%s", mmc_omap_status_bits[i]);
+                       c++;
+               }
+}
+
+static irqreturn_t mmc_omap_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct mmc_omap_host * host = (struct mmc_omap_host *)dev_id;
+       u16 status;
+       int end_command;
+       int end_transfer;
+       int transfer_error;
+
+       if (host->cmd == NULL && host->data == NULL) {
+               status = OMAP_MMC_READ(host->base, STAT);
+               dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status);
+               if (status != 0) {
+                       OMAP_MMC_WRITE(host->base, STAT, status);
+                       OMAP_MMC_WRITE(host->base, IE, 0);
+               }
+               return IRQ_HANDLED;
+       }
+
+       end_command = 0;
+       end_transfer = 0;
+       transfer_error = 0;
+
+       while ((status = OMAP_MMC_READ(host->base, STAT)) != 0) {
+               OMAP_MMC_WRITE(host->base, STAT, status);
+#ifdef CONFIG_MMC_DEBUG
+               dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
+                       status, host->cmd != NULL ? host->cmd->opcode : -1);
+               mmc_omap_report_irq(status);
+               printk("\n");
+#endif
+               if (host->total_bytes_left) {
+                       if ((status & OMAP_MMC_STAT_A_FULL) ||
+                           (status & OMAP_MMC_STAT_END_OF_DATA))
+                               mmc_omap_xfer_data(host, 0);
+                       if (status & OMAP_MMC_STAT_A_EMPTY)
+                               mmc_omap_xfer_data(host, 1);
+               }
+
+               if (status & OMAP_MMC_STAT_END_OF_DATA) {
+                       end_transfer = 1;
+               }
+
+               if (status & OMAP_MMC_STAT_DATA_TOUT) {
+                       dev_dbg(mmc_dev(host->mmc), "data timeout\n");
+                       if (host->data) {
+                               host->data->error |= MMC_ERR_TIMEOUT;
+                               transfer_error = 1;
+                       }
+               }
+
+               if (status & OMAP_MMC_STAT_DATA_CRC) {
+                       if (host->data) {
+                               host->data->error |= MMC_ERR_BADCRC;
+                               dev_dbg(mmc_dev(host->mmc),
+                                        "data CRC error, bytes left %d\n",
+                                       host->total_bytes_left);
+                               transfer_error = 1;
+                       } else {
+                               dev_dbg(mmc_dev(host->mmc), "data CRC error\n");
+                       }
+               }
+
+               if (status & OMAP_MMC_STAT_CMD_TOUT) {
+                       /* Timeouts are routine with some commands */
+                       if (host->cmd) {
+                               if (host->cmd->opcode != MMC_ALL_SEND_CID &&
+                                               host->cmd->opcode !=
+                                               MMC_SEND_OP_COND &&
+                                               host->cmd->opcode !=
+                                               MMC_APP_CMD &&
+                                               !mmc_omap_cover_is_open(host))
+                                       dev_err(mmc_dev(host->mmc),
+                                               "command timeout, CMD %d\n",
+                                               host->cmd->opcode);
+                               host->cmd->error = MMC_ERR_TIMEOUT;
+                               end_command = 1;
+                       }
+               }
+
+               if (status & OMAP_MMC_STAT_CMD_CRC) {
+                       if (host->cmd) {
+                               dev_err(mmc_dev(host->mmc),
+                                       "command CRC error (CMD%d, arg 0x%08x)\n",
+                                       host->cmd->opcode, host->cmd->arg);
+                               host->cmd->error = MMC_ERR_BADCRC;
+                               end_command = 1;
+                       } else
+                               dev_err(mmc_dev(host->mmc),
+                                       "command CRC error without cmd?\n");
+               }
+
+               if (status & OMAP_MMC_STAT_CARD_ERR) {
+                       if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
+                               u32 response = OMAP_MMC_READ(host->base, RSP6)
+                                       | (OMAP_MMC_READ(host->base, RSP7) << 16);
+                               /* STOP sometimes sets must-ignore bits */
+                               if (!(response & (R1_CC_ERROR
+                                                               | R1_ILLEGAL_COMMAND
+                                                               | R1_COM_CRC_ERROR))) {
+                                       end_command = 1;
+                                       continue;
+                               }
+                       }
+
+                       dev_dbg(mmc_dev(host->mmc), "card status error (CMD%d)\n",
+                               host->cmd->opcode);
+                       if (host->cmd) {
+                               host->cmd->error = MMC_ERR_FAILED;
+                               end_command = 1;
+                       }
+                       if (host->data) {
+                               host->data->error = MMC_ERR_FAILED;
+                               transfer_error = 1;
+                       }
+               }
+
+               /*
+                * NOTE: On 1610 the END_OF_CMD may come too early when
+                * starting a write 
+                */
+               if ((status & OMAP_MMC_STAT_END_OF_CMD) &&
+                   (!(status & OMAP_MMC_STAT_A_EMPTY))) {
+                       end_command = 1;
+               }
+       }
+
+       if (end_command) {
+               mmc_omap_cmd_done(host, host->cmd);
+       }
+       if (transfer_error)
+               mmc_omap_xfer_done(host, host->data);
+       else if (end_transfer)
+               mmc_omap_end_of_data(host, host->data);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id;
+
+       schedule_work(&host->switch_work);
+
+       return IRQ_HANDLED;
+}
+
+static void mmc_omap_switch_timer(unsigned long arg)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) arg;
+
+       schedule_work(&host->switch_work);
+}
+
+/* FIXME: Handle card insertion and removal properly. Maybe use a mask
+ * for MMC state? */
+static void mmc_omap_switch_callback(unsigned long data, u8 mmc_mask)
+{
+}
+
+static void mmc_omap_switch_handler(void *data)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+       struct mmc_card *card;
+       static int complained = 0;
+       int cards = 0, cover_open;
+
+       if (host->switch_pin == -1)
+               return;
+       cover_open = mmc_omap_cover_is_open(host);
+       if (cover_open != host->switch_last_state) {
+               kobject_uevent(&host->dev->kobj, KOBJ_CHANGE);
+               host->switch_last_state = cover_open;
+       }
+       mmc_detect_change(host->mmc, 0);
+       list_for_each_entry(card, &host->mmc->cards, node) {
+               if (mmc_card_present(card))
+                       cards++;
+       }
+       if (mmc_omap_cover_is_open(host)) {
+               if (!complained) {
+                       dev_info(mmc_dev(host->mmc), "cover is open");
+                       complained = 1;
+               }
+               if (mmc_omap_enable_poll)
+                       mod_timer(&host->switch_timer, jiffies +
+                               msecs_to_jiffies(OMAP_MMC_SWITCH_POLL_DELAY));
+       } else {
+               complained = 0;
+       }
+}
+
+/* Prepare to transfer the next segment of a scatterlist */
+static void
+mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       int dma_ch = host->dma_ch;
+       unsigned long data_addr;
+       u16 buf, frame;
+       u32 count;
+       struct scatterlist *sg = &data->sg[host->sg_idx];
+       int src_port = 0;
+       int dst_port = 0;
+       int sync_dev = 0;
+
+       data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA;
+       frame = 1 << data->blksz_bits;
+       count = sg_dma_len(sg);
+
+       if ((data->blocks == 1) && (count > (1 << data->blksz_bits)))
+               count = frame;
+
+       host->dma_len = count;
+
+       /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx.
+        * Use 16 or 32 word frames when the blocksize is at least that large.
+        * Blocksize is usually 512 bytes; but not for some SD reads.
+        */
+       if (cpu_is_omap15xx() && frame > 32)
+               frame = 32;
+       else if (frame > 64)
+               frame = 64;
+       count /= frame;
+       frame >>= 1;
+
+       if (!(data->flags & MMC_DATA_WRITE)) {
+               buf = 0x800f | ((frame - 1) << 8);
+
+               if (cpu_class_is_omap1()) {
+                       src_port = OMAP_DMA_PORT_TIPB;
+                       dst_port = OMAP_DMA_PORT_EMIFF;
+               }
+               if (cpu_is_omap24xx())
+                       sync_dev = OMAP24XX_DMA_MMC1_RX;
+
+               omap_set_dma_src_params(dma_ch, src_port,
+                                       OMAP_DMA_AMODE_CONSTANT,
+                                       data_addr, 0, 0);
+               omap_set_dma_dest_params(dma_ch, dst_port,
+                                        OMAP_DMA_AMODE_POST_INC,
+                                        sg_dma_address(sg), 0, 0);
+               omap_set_dma_dest_data_pack(dma_ch, 1);
+               omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
+       } else {
+               buf = 0x0f80 | ((frame - 1) << 0);
+
+               if (cpu_class_is_omap1()) {
+                       src_port = OMAP_DMA_PORT_EMIFF;
+                       dst_port = OMAP_DMA_PORT_TIPB;
+               }
+               if (cpu_is_omap24xx())
+                       sync_dev = OMAP24XX_DMA_MMC1_TX;
+
+               omap_set_dma_dest_params(dma_ch, dst_port,
+                                        OMAP_DMA_AMODE_CONSTANT,
+                                        data_addr, 0, 0);
+               omap_set_dma_src_params(dma_ch, src_port,
+                                       OMAP_DMA_AMODE_POST_INC,
+                                       sg_dma_address(sg), 0, 0);
+               omap_set_dma_src_data_pack(dma_ch, 1);
+               omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
+       }
+
+       /* Max limit for DMA frame count is 0xffff */
+       if (unlikely(count > 0xffff))
+               BUG();
+
+       OMAP_MMC_WRITE(host->base, BUF, buf);
+       omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16,
+                                    frame, count, OMAP_DMA_SYNC_FRAME,
+                                    sync_dev, 0);
+}
+
+/* A scatterlist segment completed */
+static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+       struct mmc_data *mmcdat = host->data;
+
+       if (unlikely(host->dma_ch < 0)) {
+               dev_err(mmc_dev(host->mmc), "DMA callback while DMA not
+                               enabled\n");
+               return;
+       }
+       /* FIXME: We really should do something to _handle_ the errors */
+       if (ch_status & OMAP_DMA_TOUT_IRQ) {
+               dev_err(mmc_dev(host->mmc),"DMA timeout\n");
+               return;
+       }
+       if (ch_status & OMAP_DMA_DROP_IRQ) {
+               dev_err(mmc_dev(host->mmc), "DMA sync error\n");
+               return;
+       }
+       if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) {
+               return;
+       }
+       mmcdat->bytes_xfered += host->dma_len;
+       host->sg_idx++;
+       if (host->sg_idx < host->sg_len) {
+               mmc_omap_prepare_dma(host, host->data);
+               omap_start_dma(host->dma_ch);
+       } else
+               mmc_omap_dma_done(host, host->data);
+}
+
+static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       const char *dev_name;
+       int sync_dev, dma_ch, is_read, r;
+
+       is_read = !(data->flags & MMC_DATA_WRITE);
+       del_timer_sync(&host->dma_timer);
+       if (host->dma_ch >= 0) {
+               if (is_read == host->dma_is_read)
+                       return 0;
+               omap_free_dma(host->dma_ch);
+               host->dma_ch = -1;
+       }
+
+       if (is_read) {
+               if (host->id == 1) {
+                       sync_dev = OMAP_DMA_MMC_RX;
+                       dev_name = "MMC1 read";
+               } else {
+                       sync_dev = OMAP_DMA_MMC2_RX;
+                       dev_name = "MMC2 read";
+               }
+       } else {
+               if (host->id == 1) {
+                       sync_dev = OMAP_DMA_MMC_TX;
+                       dev_name = "MMC1 write";
+               } else {
+                       sync_dev = OMAP_DMA_MMC2_TX;
+                       dev_name = "MMC2 write";
+               }
+       }
+       r = omap_request_dma(sync_dev, dev_name, mmc_omap_dma_cb,
+                            host, &dma_ch);
+       if (r != 0) {
+               dev_dbg(mmc_dev(host->mmc), "omap_request_dma() failed with %d\n", r);
+               return r;
+       }
+       host->dma_ch = dma_ch;
+       host->dma_is_read = is_read;
+
+       return 0;
+}
+
+static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req)
+{
+       u16 reg;
+
+       reg = OMAP_MMC_READ(host->base, SDIO);
+       reg &= ~(1 << 5);
+       OMAP_MMC_WRITE(host->base, SDIO, reg);
+       /* Set maximum timeout */
+       OMAP_MMC_WRITE(host->base, CTO, 0xff);
+}
+
+static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
+{
+       int timeout;
+       u16 reg;
+
+       /* Convert ns to clock cycles by assuming 20MHz frequency
+        * 1 cycle at 20MHz = 500 ns
+        */
+       timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
+
+       /* Check if we need to use timeout multiplier register */
+       reg = OMAP_MMC_READ(host->base, SDIO);
+       if (timeout > 0xffff) {
+               reg |= (1 << 5);
+               timeout /= 1024;
+       } else
+               reg &= ~(1 << 5);
+       OMAP_MMC_WRITE(host->base, SDIO, reg);
+       OMAP_MMC_WRITE(host->base, DTO, timeout);
+}
+
+static void
+mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
+{
+       struct mmc_data *data = req->data;
+       int i, use_dma, block_size;
+       unsigned sg_len;
+
+       host->data = data;
+       if (data == NULL) {
+               OMAP_MMC_WRITE(host->base, BLEN, 0);
+               OMAP_MMC_WRITE(host->base, NBLK, 0);
+               OMAP_MMC_WRITE(host->base, BUF, 0);
+               host->dma_in_use = 0;
+               set_cmd_timeout(host, req);
+               return;
+       }
+
+
+       block_size = 1 << data->blksz_bits;
+
+       OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1);
+       OMAP_MMC_WRITE(host->base, BLEN, block_size - 1);
+       set_data_timeout(host, req);
+
+       /* cope with calling layer confusion; it issues "single
+        * block" writes using multi-block scatterlists.
+        */
+       sg_len = (data->blocks == 1) ? 1 : data->sg_len;
+
+       /* Only do DMA for entire blocks */
+       use_dma = host->use_dma;
+       if (use_dma) {
+               for (i = 0; i < sg_len; i++) {
+                       if ((data->sg[i].length % block_size) != 0) {
+                               use_dma = 0;
+                               break;
+                       }
+               }
+       }
+
+       host->sg_idx = 0;
+       if (use_dma) {
+               if (mmc_omap_get_dma_channel(host, data) == 0) {
+                       enum dma_data_direction dma_data_dir;
+
+                       if (data->flags & MMC_DATA_WRITE)
+                               dma_data_dir = DMA_TO_DEVICE;
+                       else
+                               dma_data_dir = DMA_FROM_DEVICE;
+
+                       host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+                                               sg_len, dma_data_dir);
+                       host->total_bytes_left = 0;
+                       mmc_omap_prepare_dma(host, req->data);
+                       host->brs_received = 0;
+                       host->dma_done = 0;
+                       host->dma_in_use = 1;
+               } else
+                       use_dma = 0;
+       }
+
+       /* Revert to PIO? */
+       if (!use_dma) {
+               OMAP_MMC_WRITE(host->base, BUF, 0x1f1f);
+               host->total_bytes_left = data->blocks * block_size;
+               host->sg_len = sg_len;
+               mmc_omap_sg_to_buf(host);
+               host->dma_in_use = 0;
+       }
+}
+
+static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+       struct mmc_omap_host *host = mmc_priv(mmc);
+
+       WARN_ON(host->mrq != NULL);
+
+       host->mrq = req;
+
+       /* only touch fifo AFTER the controller readies it */
+       mmc_omap_prepare_data(host, req);
+       mmc_omap_start_command(host, req->cmd);
+       if (host->dma_in_use)
+               omap_start_dma(host->dma_ch);
+}
+
+static void innovator_fpga_socket_power(int on)
+{
+#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
+
+       if (on) {
+               fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
+                    OMAP1510_FPGA_POWER);
+       } else {
+               fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
+                    OMAP1510_FPGA_POWER);
+       }
+#endif
+}
+
+/*
+ * Turn the socket power on/off. Innovator uses FPGA, most boards
+ * probably use GPIO.
+ */
+static void mmc_omap_power(struct mmc_omap_host *host, int on)
+{
+       if (on) {
+               if (machine_is_omap_innovator())
+                       innovator_fpga_socket_power(1);
+               else if (machine_is_omap_h2())
+                       tps65010_set_gpio_out_value(GPIO3, HIGH);
+               else if (machine_is_omap_h3())
+                       /* GPIO 4 of TPS65010 sends SD_EN signal */
+                       tps65010_set_gpio_out_value(GPIO4, HIGH);
+               else if (cpu_is_omap24xx()) {
+                       u16 reg = OMAP_MMC_READ(host->base, CON);
+                       OMAP_MMC_WRITE(host->base, CON, reg | (1 << 11));
+               } else
+                       if (host->power_pin >= 0)
+                               omap_set_gpio_dataout(host->power_pin, 1);
+       } else {
+               if (machine_is_omap_innovator())
+                       innovator_fpga_socket_power(0);
+               else if (machine_is_omap_h2())
+                       tps65010_set_gpio_out_value(GPIO3, LOW);
+               else if (machine_is_omap_h3())
+                       tps65010_set_gpio_out_value(GPIO4, LOW);
+               else if (cpu_is_omap24xx()) {
+                       u16 reg = OMAP_MMC_READ(host->base, CON);
+                       OMAP_MMC_WRITE(host->base, CON, reg & ~(1 << 11));
+               } else
+                       if (host->power_pin >= 0)
+                               omap_set_gpio_dataout(host->power_pin, 0);
+       }
+}
+
+static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct mmc_omap_host *host = mmc_priv(mmc);
+       int dsor;
+       int realclock, i;
+
+       realclock = ios->clock;
+
+       if (ios->clock == 0)
+               dsor = 0;
+       else {
+               int func_clk_rate = clk_get_rate(host->fclk);
+
+               dsor = func_clk_rate / realclock;
+               if (dsor < 1)
+                       dsor = 1;
+
+               if (func_clk_rate / dsor > realclock)
+                       dsor++;
+
+               if (dsor > 250)
+                       dsor = 250;
+               dsor++;
+
+               if (ios->bus_width == MMC_BUS_WIDTH_4)
+                       dsor |= 1 << 15;
+       }
+
+       switch (ios->power_mode) {
+       case MMC_POWER_OFF:
+               mmc_omap_power(host, 0);
+               break;
+       case MMC_POWER_UP:
+       case MMC_POWER_ON:
+               mmc_omap_power(host, 1);
+               dsor |= 1<<11;
+               break;
+       }
+
+       host->bus_mode = ios->bus_mode;
+       host->hw_bus_mode = host->bus_mode;
+
+       clk_enable(host->fclk);
+
+       /* On insanely high arm_per frequencies something sometimes
+        * goes somehow out of sync, and the POW bit is not being set,
+        * which results in the while loop below getting stuck.
+        * Writing to the CON register twice seems to do the trick. */
+       for (i = 0; i < 2; i++)
+               OMAP_MMC_WRITE(host->base, CON, dsor);
+       if (ios->power_mode == MMC_POWER_UP) {
+               /* Send clock cycles, poll completion */
+               OMAP_MMC_WRITE(host->base, IE, 0);
+               OMAP_MMC_WRITE(host->base, STAT, 0xffff);
+               OMAP_MMC_WRITE(host->base, CMD, 1<<7);
+               while (0 == (OMAP_MMC_READ(host->base, STAT) & 1));
+               OMAP_MMC_WRITE(host->base, STAT, 1);
+       }
+       clk_disable(host->fclk);
+}
+
+static int mmc_omap_get_ro(struct mmc_host *mmc)
+{
+       struct mmc_omap_host *host = mmc_priv(mmc);
+
+       return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
+}
+
+static struct mmc_host_ops mmc_omap_ops = {
+       .request        = mmc_omap_request,
+       .set_ios        = mmc_omap_set_ios,
+       .get_ro         = mmc_omap_get_ro,
+};
+
+static int __init mmc_omap_probe(struct platform_device *pdev)
+{
+       struct omap_mmc_conf *minfo = pdev->dev.platform_data;
+       struct mmc_host *mmc;
+       struct mmc_omap_host *host = NULL;
+       int ret = 0;
+       
+       if (platform_get_resource(pdev, IORESOURCE_MEM, 0) ||
+                       platform_get_irq(pdev, IORESOURCE_IRQ, 0)) {
+               dev_err(&pdev->dev, "mmc_omap_probe: invalid resource type\n");
+               return -ENODEV;
+       }
+
+       if (!request_mem_region(pdev->resource[0].start,
+                               pdev->resource[0].end - pdev->resource[0].start + 1,
+                               pdev->name)) {
+               dev_dbg(&pdev->dev, "request_mem_region failed\n");
+               return -EBUSY;
+       }
+
+       mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
+       if (!mmc) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       host = mmc_priv(mmc);
+       host->mmc = mmc;
+
+       spin_lock_init(&host->dma_lock);
+       init_timer(&host->dma_timer);
+       host->dma_timer.function = mmc_omap_dma_timer;
+       host->dma_timer.data = (unsigned long) host;
+
+       host->id = pdev->id;
+
+       if (cpu_is_omap24xx()) {
+               host->iclk = clk_get(&pdev->dev, "mmc_ick");
+               if (IS_ERR(host->iclk))
+                       goto out;
+               clk_enable(host->iclk);
+       }
+
+       if (!cpu_is_omap24xx())
+               host->fclk = clk_get(&pdev->dev, "mmc_ck");
+       else
+               host->fclk = clk_get(&pdev->dev, "mmc_fck");
+
+       if (IS_ERR(host->fclk)) {
+               ret = PTR_ERR(host->fclk);
+               goto out;
+       }
+
+       /* REVISIT:
+        * Also, use minfo->cover to decide how to manage
+        * the card detect sensing.
+        */
+       host->power_pin = minfo->power_pin;
+       host->switch_pin = minfo->switch_pin;
+       host->wp_pin = minfo->wp_pin;
+       host->use_dma = 1;
+       host->dma_ch = -1;
+
+       host->irq = pdev->resource[1].start;
+       host->base = ioremap(pdev->res.start, SZ_4K);
+       if (!host->base) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+        if (minfo->wire4)
+                mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+       mmc->ops = &mmc_omap_ops;
+       mmc->f_min = 400000;
+       mmc->f_max = 24000000;
+       mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+
+       /* Use scatterlist DMA to reduce per-transfer costs.
+        * NOTE max_seg_size assumption that small blocks aren't
+        * normally used (except e.g. for reading SD registers).
+        */
+       mmc->max_phys_segs = 32;
+       mmc->max_hw_segs = 32;
+       mmc->max_sectors = 256; /* NBLK max 11-bits, OMAP also limited by DMA */
+       mmc->max_seg_size = mmc->max_sectors * 512;
+
+       if (host->power_pin >= 0) {
+               if ((ret = omap_request_gpio(host->power_pin)) != 0) {
+                       dev_err(mmc_dev(host->mmc), "Unable to get GPIO
+                                       pin for MMC power\n");
+                       goto out;
+               }
+               omap_set_gpio_direction(host->power_pin, 0);
+       }
+
+       ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
+       if (ret)
+               goto out;
+
+       host->dev = &pdev->dev;
+       platform_set_drvdata(pdev, host);
+
+       mmc_add_host(mmc);
+
+       if (host->switch_pin >= 0) {
+               INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host);
+               init_timer(&host->switch_timer);
+               host->switch_timer.function = mmc_omap_switch_timer;
+               host->switch_timer.data = (unsigned long) host;
+               if (omap_request_gpio(host->switch_pin) != 0) {
+                       dev_warn(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC cover switch\n");
+                       host->switch_pin = -1;
+                       goto no_switch;
+               }
+
+               omap_set_gpio_direction(host->switch_pin, 1);
+               ret = request_irq(OMAP_GPIO_IRQ(host->switch_pin),
+                                 mmc_omap_switch_irq, SA_TRIGGER_RISING, DRIVER_NAME, host);
+               if (ret) {
+                       dev_warn(mmc_dev(host->mmc), "Unable to get IRQ for MMC cover switch\n");
+                       omap_free_gpio(host->switch_pin);
+                       host->switch_pin = -1;
+                       goto no_switch;
+               }
+               ret = device_create_file(&pdev->dev, &dev_attr_cover_switch);
+               if (ret == 0) {
+                       ret = device_create_file(&pdev->dev, &dev_attr_enable_poll);
+                       if (ret != 0)
+                               device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+               }
+               if (ret) {
+                       dev_wan(mmc_dev(host->mmc), "Unable to create sysfs attributes\n");
+                       free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+                       omap_free_gpio(host->switch_pin);
+                       host->switch_pin = -1;
+                       goto no_switch;
+               }
+               if (mmc_omap_enable_poll && mmc_omap_cover_is_open(host))
+                       schedule_work(&host->switch_work);
+       }
+
+no_switch:
+       return 0;
+
+out:
+       /* FIXME: Free other resources too. */
+       if (host) {
+               if (host->iclk && !IS_ERR(host->iclk))
+                       clk_put(host->iclk);
+               if (host->fclk && !IS_ERR(host->fclk))
+                       clk_put(host->fclk);
+               mmc_free_host(host->mmc);
+       }
+       return ret;
+}
+
+static int mmc_omap_remove(struct platform_device *pdev)
+{
+       struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       if (host) {
+               mmc_remove_host(host->mmc);
+               free_irq(host->irq, host);
+
+               if (host->power_pin >= 0)
+                       omap_free_gpio(host->power_pin);
+               if (host->switch_pin >= 0) {
+                       device_remove_file(&pdev->dev, &dev_attr_enable_poll);
+                       device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+                       free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+                       omap_free_gpio(host->switch_pin);
+                       host->switch_pin = -1;
+                       del_timer_sync(&host->switch_timer);
+                       flush_scheduled_work();
+               }
+               if (host->iclk && !IS_ERR(host->iclk))
+                       clk_put(host->iclk);
+               if (host->fclk && !IS_ERR(host->fclk))
+                       clk_put(host->fclk);
+               mmc_free_host(host->mmc);
+       }
+
+       release_mem_region(pdev->resource[0].start,
+                       pdev->resource[0].end - pdev->resource[0].start + 1);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+       int ret = 0;
+       struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+       if (host && host->suspended)
+               return 0;
+
+       if (host) {
+               ret = mmc_suspend_host(host->mmc, mesg);
+               if (ret == 0)
+                       host->suspended = 1;
+       }
+       return ret;
+}
+
+static int mmc_omap_resume(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+       if (host && !host->suspended)
+               return 0;
+
+       if (host) {
+               ret = mmc_resume_host(host->mmc);
+               if (ret == 0)
+                       host->suspended = 0;
+       }
+
+       return ret;
+}
+#else
+#define mmc_omap_suspend       NULL
+#define mmc_omap_resume                NULL
+#endif
+
+static struct platform_driver mmc_omap_driver = {
+       .probe          = mmc_omap_probe,
+       .remove         = mmc_omap_remove,
+       .suspend        = mmc_omap_suspend,
+       .resume         = mmc_omap_resume,
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+static int __init mmc_omap_init(void)
+{
+       return platform_driver_register(&mmc_omap_driver);
+}
+
+static void __exit mmc_omap_exit(void)
+{
+       platform_driver_unregister(&mmc_omap_driver);
+}
+
+module_init(mmc_omap_init);
+module_exit(mmc_omap_exit);
+
+MODULE_DESCRIPTION("OMAP Multimedia Card driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS(DRIVER_NAME);
+MODULE_AUTHOR("Juha Yrjölä");
diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h
new file mode 100644 (file)
index 0000000..c954d35
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef        DRIVERS_MEDIA_MMC_OMAP_H
+#define        DRIVERS_MEDIA_MMC_OMAP_H
+
+#define        OMAP_MMC_REG_CMD        0x00
+#define        OMAP_MMC_REG_ARGL       0x04
+#define        OMAP_MMC_REG_ARGH       0x08
+#define        OMAP_MMC_REG_CON        0x0c
+#define        OMAP_MMC_REG_STAT       0x10
+#define        OMAP_MMC_REG_IE         0x14
+#define        OMAP_MMC_REG_CTO        0x18
+#define        OMAP_MMC_REG_DTO        0x1c
+#define        OMAP_MMC_REG_DATA       0x20
+#define        OMAP_MMC_REG_BLEN       0x24
+#define        OMAP_MMC_REG_NBLK       0x28
+#define        OMAP_MMC_REG_BUF        0x2c
+#define OMAP_MMC_REG_SDIO      0x34
+#define        OMAP_MMC_REG_REV        0x3c
+#define        OMAP_MMC_REG_RSP0       0x40
+#define        OMAP_MMC_REG_RSP1       0x44
+#define        OMAP_MMC_REG_RSP2       0x48
+#define        OMAP_MMC_REG_RSP3       0x4c
+#define        OMAP_MMC_REG_RSP4       0x50
+#define        OMAP_MMC_REG_RSP5       0x54
+#define        OMAP_MMC_REG_RSP6       0x58
+#define        OMAP_MMC_REG_RSP7       0x5c
+#define        OMAP_MMC_REG_IOSR       0x60
+#define        OMAP_MMC_REG_SYSC       0x64
+#define        OMAP_MMC_REG_SYSS       0x68
+
+#define        OMAP_MMC_STAT_CARD_ERR          (1 << 14)
+#define        OMAP_MMC_STAT_CARD_IRQ          (1 << 13)
+#define        OMAP_MMC_STAT_OCR_BUSY          (1 << 12)
+#define        OMAP_MMC_STAT_A_EMPTY           (1 << 11)
+#define        OMAP_MMC_STAT_A_FULL            (1 << 10)
+#define        OMAP_MMC_STAT_CMD_CRC           (1 <<  8)
+#define        OMAP_MMC_STAT_CMD_TOUT          (1 <<  7)
+#define        OMAP_MMC_STAT_DATA_CRC          (1 <<  6)
+#define        OMAP_MMC_STAT_DATA_TOUT         (1 <<  5)
+#define        OMAP_MMC_STAT_END_BUSY          (1 <<  4)
+#define        OMAP_MMC_STAT_END_OF_DATA       (1 <<  3)
+#define        OMAP_MMC_STAT_CARD_BUSY         (1 <<  2)
+#define        OMAP_MMC_STAT_END_OF_CMD        (1 <<  0)
+
+#define OMAP_MMC_READ(base, reg)       __raw_readw((base) + OMAP_MMC_REG_##reg)
+#define OMAP_MMC_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MMC_REG_##reg)
+
+/*
+ * Command types
+ */
+#define OMAP_MMC_CMDTYPE_BC    0
+#define OMAP_MMC_CMDTYPE_BCR   1
+#define OMAP_MMC_CMDTYPE_AC    2
+#define OMAP_MMC_CMDTYPE_ADTC  3
+
+#endif
index c32fad1..eb9a882 100644 (file)
 
 #include "pxamci.h"
 
-#ifdef CONFIG_MMC_DEBUG
-#define DBG(x...)      printk(KERN_DEBUG x)
-#else
-#define DBG(x...)      do { } while (0)
-#endif
-
 #define DRIVER_NAME    "pxa2xx-mci"
 
 #define NR_SG  1
@@ -206,7 +200,7 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd,
 
 static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq)
 {
-       DBG("PXAMCI: request done\n");
+       pr_debug("PXAMCI: request done\n");
        host->mrq = NULL;
        host->cmd = NULL;
        host->data = NULL;
@@ -252,7 +246,7 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
                        if ((cmd->resp[0] & 0x80000000) == 0)
                                cmd->error = MMC_ERR_BADCRC;
                } else {
-                       DBG("ignoring CRC from command %d - *risky*\n",cmd->opcode);
+                       pr_debug("ignoring CRC from command %d - *risky*\n",cmd->opcode);
                }
 #else
                cmd->error = MMC_ERR_BADCRC;
@@ -317,12 +311,12 @@ static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs)
 
        ireg = readl(host->base + MMC_I_REG);
 
-       DBG("PXAMCI: irq %08x\n", ireg);
+       pr_debug("PXAMCI: irq %08x\n", ireg);
 
        if (ireg) {
                unsigned stat = readl(host->base + MMC_STAT);
 
-               DBG("PXAMCI: stat %08x\n", stat);
+               pr_debug("PXAMCI: stat %08x\n", stat);
 
                if (ireg & END_CMD_RES)
                        handled |= pxamci_cmd_done(host, stat);
@@ -376,9 +370,9 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct pxamci_host *host = mmc_priv(mmc);
 
-       DBG("pxamci_set_ios: clock %u power %u vdd %u.%02u\n",
-           ios->clock, ios->power_mode, ios->vdd / 100,
-           ios->vdd % 100);
+       pr_debug("pxamci_set_ios: clock %u power %u vdd %u.%02u\n",
+                ios->clock, ios->power_mode, ios->vdd / 100,
+                ios->vdd % 100);
 
        if (ios->clock) {
                unsigned int clk = CLOCKRATE / ios->clock;
@@ -405,8 +399,8 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                        host->cmdat |= CMDAT_INIT;
        }
 
-       DBG("pxamci_set_ios: clkrt = %x cmdat = %x\n",
-           host->clkrt, host->cmdat);
+       pr_debug("pxamci_set_ios: clkrt = %x cmdat = %x\n",
+                host->clkrt, host->cmdat);
 }
 
 static struct mmc_host_ops pxamci_ops = {
index 8b811d9..bdbfca0 100644 (file)
 
 #define BUGMAIL "<sdhci-devel@list.drzeus.cx>"
 
-#ifdef CONFIG_MMC_DEBUG
 #define DBG(f, x...) \
-       printk(KERN_DEBUG DRIVER_NAME " [%s()]: " f, __func__,## x)
-#else
-#define DBG(f, x...) do { } while (0)
-#endif
+       pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
 
 static const struct pci_device_id pci_ids[] __devinitdata = {
        /* handle any SD host controller */
index 3be397d..511f7b0 100644 (file)
 #define DRIVER_NAME "wbsd"
 #define DRIVER_VERSION "1.5"
 
-#ifdef CONFIG_MMC_DEBUG
 #define DBG(x...) \
-       printk(KERN_DEBUG DRIVER_NAME ": " x)
+       pr_debug(DRIVER_NAME ": " x)
 #define DBGF(f, x...) \
-       printk(KERN_DEBUG DRIVER_NAME " [%s()]: " f, __func__ , ##x)
-#else
-#define DBG(x...)      do { } while (0)
-#define DBGF(x...)     do { } while (0)
-#endif
+       pr_debug(DRIVER_NAME " [%s()]: " f, __func__ , ##x)
 
 /*
  * Device resources
index fdb91b6..5711561 100644 (file)
@@ -664,7 +664,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
        printk("%s: Probing for AMD compatible flash...\n", map->name);
 
        if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table,
-                                          sizeof(table)/sizeof(table[0])))
+                                          ARRAY_SIZE(table)))
            == -1) {
                printk(KERN_WARNING
                       "%s: Found no AMD compatible device at location zero\n",
@@ -696,7 +696,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
             base += (1 << temp.chipshift)) {
                int numchips = temp.numchips;
                table_pos[numchips] = probe_new_chip(mtd, base, chips,
-                       &temp, table, sizeof(table)/sizeof(table[0]));
+                       &temp, table, ARRAY_SIZE(table));
        }
 
        mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) *
index edb306c..517ea33 100644 (file)
@@ -34,6 +34,7 @@
 #define MANUFACTURER_MACRONIX  0x00C2
 #define MANUFACTURER_NEC       0x0010
 #define MANUFACTURER_PMC       0x009D
+#define MANUFACTURER_SHARP     0x00b0
 #define MANUFACTURER_SST       0x00BF
 #define MANUFACTURER_ST                0x0020
 #define MANUFACTURER_TOSHIBA   0x0098
 #define PM49FL004      0x006E
 #define PM49FL008      0x006A
 
+/* Sharp */
+#define LH28F640BF     0x00b0
+
 /* ST - www.st.com */
 #define M29W800DT      0x00D7
 #define M29W800DB      0x005B
@@ -1267,6 +1271,19 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO( 0x01000, 256 )
                }
+       }, {
+               .mfr_id         = MANUFACTURER_SHARP,
+               .dev_id         = LH28F640BF,
+               .name           = "LH28F640BF",
+               .uaddr          = {
+                       [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+               },
+               .DevSize        = SIZE_4MiB,
+               .CmdSet         = P_ID_INTEL_STD,
+               .NumEraseRegions= 1,
+               .regions        = {
+                       ERASEINFO(0x40000,16),
+               }
         }, {
                .mfr_id         = MANUFACTURER_SST,
                .dev_id         = SST39LF512,
@@ -2035,7 +2052,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
                DEBUG(MTD_DEBUG_LEVEL3,
                      "Search for id:(%02x %02x) interleave(%d) type(%d)\n",
                        cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
-               for (i=0; i<sizeof(jedec_table)/sizeof(jedec_table[0]); i++) {
+               for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
                        if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
                                DEBUG( MTD_DEBUG_LEVEL3,
                                       "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
index 36f61a6..3cc0b23 100644 (file)
@@ -64,7 +64,7 @@
 
 #undef AUTOUNLOCK  /* automatically unlocks blocks before erasing */
 
-struct mtd_info *sharp_probe(struct map_info *);
+static struct mtd_info *sharp_probe(struct map_info *);
 
 static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd);
 
@@ -96,7 +96,6 @@ struct sharp_info{
        struct flchip chips[1];
 };
 
-struct mtd_info *sharp_probe(struct map_info *map);
 static void sharp_destroy(struct mtd_info *mtd);
 
 static struct mtd_chip_driver sharp_chipdrv = {
@@ -107,7 +106,7 @@ static struct mtd_chip_driver sharp_chipdrv = {
 };
 
 
-struct mtd_info *sharp_probe(struct map_info *map)
+static struct mtd_info *sharp_probe(struct map_info *map)
 {
        struct mtd_info *mtd = NULL;
        struct sharp_info *sharp = NULL;
@@ -581,7 +580,7 @@ static void sharp_destroy(struct mtd_info *mtd)
 
 }
 
-int __init sharp_probe_init(void)
+static int __init sharp_probe_init(void)
 {
        printk("MTD Sharp chip driver <ds@lineo.com>\n");
 
index 6b8bb2e..a7a7bfe 100644 (file)
@@ -42,7 +42,8 @@
 
 
 /* special size referring to all the remaining space in a partition */
-#define SIZE_REMAINING 0xffffffff
+#define SIZE_REMAINING UINT_MAX
+#define OFFSET_CONTINUOUS UINT_MAX
 
 struct cmdline_mtd_partition {
        struct cmdline_mtd_partition *next;
@@ -75,7 +76,7 @@ static struct mtd_partition * newpart(char *s,
 {
        struct mtd_partition *parts;
        unsigned long size;
-       unsigned long offset = 0;
+       unsigned long offset = OFFSET_CONTINUOUS;
        char *name;
        int name_len;
        unsigned char *extra_mem;
@@ -314,7 +315,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
                {
                        for(i = 0, offset = 0; i < part->num_parts; i++)
                        {
-                               if (!part->parts[i].offset)
+                               if (part->parts[i].offset == OFFSET_CONTINUOUS)
                                  part->parts[i].offset = offset;
                                else
                                  offset = part->parts[i].offset;
index 04f864d..79f2e1f 100644 (file)
@@ -28,8 +28,9 @@
 #include <linux/pagemap.h>
 #include <linux/list.h>
 #include <linux/init.h>
+#include <linux/mount.h>
 #include <linux/mtd/mtd.h>
-
+#include <linux/mutex.h>
 
 #define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg)
 #define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg)
@@ -46,7 +47,7 @@ struct blkmtd_dev {
        struct list_head list;
        struct block_device *blkdev;
        struct mtd_info mtd_info;
-       struct semaphore wrbuf_mutex;
+       struct mutex wrbuf_mutex;
 };
 
 
@@ -268,7 +269,7 @@ static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to,
        if(end_len)
                pagecnt++;
 
-       down(&dev->wrbuf_mutex);
+       mutex_lock(&dev->wrbuf_mutex);
 
        DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n",
              start_len, len, end_len, pagecnt);
@@ -376,7 +377,7 @@ static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to,
                blkmtd_write_out(bio);
 
        DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err);
-       up(&dev->wrbuf_mutex);
+       mutex_unlock(&dev->wrbuf_mutex);
 
        if(retlen)
                *retlen = thislen;
@@ -614,8 +615,6 @@ static struct mtd_erase_region_info *calc_erase_regions(
 }
 
 
-extern dev_t __init name_to_dev_t(const char *line);
-
 static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size)
 {
        struct block_device *bdev;
@@ -659,7 +658,7 @@ static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size
        memset(dev, 0, sizeof(struct blkmtd_dev));
        dev->blkdev = bdev;
        if(!readonly) {
-               init_MUTEX(&dev->wrbuf_mutex);
+               mutex_init(&dev->wrbuf_mutex);
        }
 
        dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
index 7ff403b..4160b83 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/buffer_head.h>
+#include <linux/mutex.h>
 
 #define VERSION "$Revision: 1.30 $"
 
@@ -31,7 +32,7 @@ struct block2mtd_dev {
        struct list_head list;
        struct block_device *blkdev;
        struct mtd_info mtd;
-       struct semaphore write_mutex;
+       struct mutex write_mutex;
 };
 
 
@@ -134,9 +135,9 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
        int err;
 
        instr->state = MTD_ERASING;
-       down(&dev->write_mutex);
+       mutex_lock(&dev->write_mutex);
        err = _block2mtd_erase(dev, from, len);
-       up(&dev->write_mutex);
+       mutex_unlock(&dev->write_mutex);
        if (err) {
                ERROR("erase failed err = %d", err);
                instr->state = MTD_ERASE_FAILED;
@@ -249,9 +250,9 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
        if (to + len > mtd->size)
                len = mtd->size - to;
 
-       down(&dev->write_mutex);
+       mutex_lock(&dev->write_mutex);
        err = _block2mtd_write(dev, buf, to, len, retlen);
-       up(&dev->write_mutex);
+       mutex_unlock(&dev->write_mutex);
        if (err > 0)
                err = 0;
        return err;
@@ -310,7 +311,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
                goto devinit_err;
        }
 
-       init_MUTEX(&dev->write_mutex);
+       mutex_init(&dev->write_mutex);
 
        /* Setup the MTD structure */
        /* make the name contain the block device in */
index e4345cf..23e7a5c 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
+#include <linux/mutex.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -605,7 +606,7 @@ static void DoC2k_init(struct mtd_info *mtd)
 
        this->curfloor = -1;
        this->curchip = -1;
-       init_MUTEX(&this->lock);
+       mutex_init(&this->lock);
 
        /* Ident all the chips present. */
        DoC_ScanChips(this, maxchips);
@@ -645,7 +646,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
        if (from >= this->totlen)
                return -EINVAL;
 
-       down(&this->lock);
+       mutex_lock(&this->lock);
 
        *retlen = 0;
        while (left) {
@@ -774,7 +775,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
                buf += len;
        }
 
-       up(&this->lock);
+       mutex_unlock(&this->lock);
 
        return ret;
 }
@@ -803,7 +804,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
        if (to >= this->totlen)
                return -EINVAL;
 
-       down(&this->lock);
+       mutex_lock(&this->lock);
 
        *retlen = 0;
        while (left) {
@@ -873,7 +874,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
                                printk(KERN_ERR "Error programming flash\n");
                                /* Error in programming */
                                *retlen = 0;
-                               up(&this->lock);
+                               mutex_unlock(&this->lock);
                                return -EIO;
                        }
 
@@ -935,7 +936,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
                        printk(KERN_ERR "Error programming flash\n");
                        /* Error in programming */
                        *retlen = 0;
-                       up(&this->lock);
+                       mutex_unlock(&this->lock);
                        return -EIO;
                }
 
@@ -956,7 +957,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
 
                        ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x);
                        if (ret) {
-                               up(&this->lock);
+                               mutex_unlock(&this->lock);
                                return ret;
                        }
                }
@@ -966,7 +967,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
                buf += len;
        }
 
-       up(&this->lock);
+       mutex_unlock(&this->lock);
        return 0;
 }
 
@@ -975,13 +976,13 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
                          u_char *eccbuf, struct nand_oobinfo *oobsel)
 {
        static char static_buf[512];
-       static DECLARE_MUTEX(writev_buf_sem);
+       static DEFINE_MUTEX(writev_buf_mutex);
 
        size_t totretlen = 0;
        size_t thisvecofs = 0;
        int ret= 0;
 
-       down(&writev_buf_sem);
+       mutex_lock(&writev_buf_mutex);
 
        while(count) {
                size_t thislen, thisretlen;
@@ -1024,7 +1025,7 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
                to += thislen;
        }
 
-       up(&writev_buf_sem);
+       mutex_unlock(&writev_buf_mutex);
        *retlen = totretlen;
        return ret;
 }
@@ -1037,7 +1038,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
        int len256 = 0, ret;
        struct Nand *mychip;
 
-       down(&this->lock);
+       mutex_lock(&this->lock);
 
        mychip = &this->chips[ofs >> this->chipshift];
 
@@ -1083,7 +1084,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
 
        ret = DoC_WaitReady(this);
 
-       up(&this->lock);
+       mutex_unlock(&this->lock);
        return ret;
 
 }
@@ -1197,10 +1198,10 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
        struct DiskOnChip *this = mtd->priv;
        int ret;
 
-       down(&this->lock);
+       mutex_lock(&this->lock);
        ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf);
 
-       up(&this->lock);
+       mutex_unlock(&this->lock);
        return ret;
 }
 
@@ -1214,10 +1215,10 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
        struct Nand *mychip;
        int status;
 
-       down(&this->lock);
+       mutex_lock(&this->lock);
 
        if (ofs & (mtd->erasesize-1) || len & (mtd->erasesize-1)) {
-               up(&this->lock);
+               mutex_unlock(&this->lock);
                return -EINVAL;
        }
 
@@ -1265,7 +1266,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
  callback:
        mtd_erase_callback(instr);
 
-       up(&this->lock);
+       mutex_unlock(&this->lock);
        return 0;
 }
 
index 1e876fc..29b0dda 100644 (file)
@@ -581,8 +581,6 @@ static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen
 
 /***************************************************************************************************/
 
-#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
-
 static struct mtd_info mtd;
 
 static struct mtd_erase_region_info erase_regions[] = {
@@ -640,7 +638,7 @@ int __init lart_flash_init (void)
    mtd.flags = MTD_CAP_NORFLASH;
    mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
    mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
-   mtd.numeraseregions = NB_OF (erase_regions);
+   mtd.numeraseregions = ARRAY_SIZE(erase_regions);
    mtd.eraseregions = erase_regions;
    mtd.erase = flash_erase;
    mtd.read = flash_read;
@@ -670,9 +668,9 @@ int __init lart_flash_init (void)
                           result,mtd.eraseregions[result].numblocks);
 
 #ifdef HAVE_PARTITIONS
-   printk ("\npartitions = %d\n",NB_OF (lart_partitions));
+   printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
 
-   for (result = 0; result < NB_OF (lart_partitions); result++)
+   for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
         printk (KERN_DEBUG
                         "\n\n"
                         "lart_partitions[%d].name = %s\n"
@@ -687,7 +685,7 @@ int __init lart_flash_init (void)
 #ifndef HAVE_PARTITIONS
    result = add_mtd_device (&mtd);
 #else
-   result = add_mtd_partitions (&mtd,lart_partitions,NB_OF (lart_partitions));
+   result = add_mtd_partitions (&mtd,lart_partitions, ARRAY_SIZE(lart_partitions));
 #endif
 
    return (result);
index d5f2408..04e65d5 100644 (file)
@@ -186,7 +186,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
        struct m25p *flash = mtd_to_m25p(mtd);
        u32 addr,len;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
                        flash->spi->dev.bus_id, __FUNCTION__, "at",
                        (u32)instr->addr, instr->len);
 
index 0ff2e43..485f663 100644 (file)
@@ -308,7 +308,7 @@ static int __init ms02nv_init(void)
                break;
        }
 
-       for (i = 0; i < (sizeof(ms02nv_addrs) / sizeof(*ms02nv_addrs)); i++)
+       for (i = 0; i < ARRAY_SIZE(ms02nv_addrs); i++)
                if (!ms02nv_init_one(ms02nv_addrs[i] << stride))
                        count++;
 
index 8a54489..a3b9247 100644 (file)
@@ -47,9 +47,6 @@
  */
 #define MAX_LOOPS 10000
 
-extern void INFTL_dumptables(struct INFTLrecord *inftl);
-extern void INFTL_dumpVUchains(struct INFTLrecord *inftl);
-
 static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 {
        struct INFTLrecord *inftl;
@@ -132,7 +129,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
                return;
        }
 #ifdef PSYCHO_DEBUG
-       printk(KERN_INFO "INFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a');
+       printk(KERN_INFO "INFTL: Found new inftl%c\n", inftl->mbd.devnum + 'a');
 #endif
        return;
 }
@@ -885,8 +882,6 @@ static struct mtd_blktrans_ops inftl_tr = {
        .owner          = THIS_MODULE,
 };
 
-extern char inftlmountrev[];
-
 static int __init init_inftl(void)
 {
        printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, "
index a57791a..b933a2a 100644 (file)
@@ -126,8 +126,6 @@ static struct mtd_partition alchemy_partitions[] = {
         }
 };
 
-#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
-
 static struct mtd_info *mymtd;
 
 int __init alchemy_mtd_init(void)
@@ -154,7 +152,7 @@ int __init alchemy_mtd_init(void)
         * Static partition definition selection
         */
        parts = alchemy_partitions;
-       nb_parts = NB_OF(alchemy_partitions);
+       nb_parts = ARRAY_SIZE(alchemy_partitions);
        alchemy_map.size = window_size;
 
        /*
index 6a8c041..fd0f0d3 100644 (file)
@@ -86,7 +86,7 @@ struct mtd_partition flagadm_parts[] = {
        }
 };
 
-#define PARTITION_COUNT (sizeof(flagadm_parts)/sizeof(struct mtd_partition))
+#define PARTITION_COUNT ARRAY_SIZE(flagadm_parts)
 
 static struct mtd_info *mymtd;
 
index 49d9054..652813c 100644 (file)
@@ -57,7 +57,7 @@ static struct mtd_partition partition_info[]= {
        }
 };
 
-#define NUM_PARTITIONS (sizeof(partition_info) / sizeof(partition_info[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
 
 #define WINDOW_ADDR 0x10000000
 #define WINDOW_SIZE 0x800000
index efb2216..c299d10 100644 (file)
@@ -300,7 +300,7 @@ static struct mtd_partition partition_info[]=
        },
 };
 
-#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
 
 static struct mtd_info *mymtd;
 static struct mtd_info *lowlvl_parts[NUM_PARTITIONS];
@@ -345,7 +345,7 @@ static struct mtd_partition higlvl_partition_info[]=
        },
 };
 
-#define NUM_HIGHLVL_PARTITIONS (sizeof(higlvl_partition_info)/sizeof(partition_info[0]))
+#define NUM_HIGHLVL_PARTITIONS ARRAY_SIZE(higlvl_partition_info)
 
 
 static int dnp_adnp_probe(void)
index b993ac0..2bb3c0f 100644 (file)
@@ -99,7 +99,7 @@ static struct mtd_info *this_mtd;
 static int __init init_svme182(void)
 {
        struct mtd_partition *partitions;
-       int num_parts = sizeof(svme182_partitions) / sizeof(struct mtd_partition);
+       int num_parts = ARRAY_SIZE(svme182_partitions);
 
        partitions = svme182_partitions;
 
index 3190948..0667101 100644 (file)
@@ -59,7 +59,7 @@ static struct mtd_partition h720x_partitions[] = {
         }
 };
 
-#define NUM_PARTITIONS  (sizeof(h720x_partitions)/sizeof(h720x_partitions[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions)
 
 static int                   nr_mtd_parts;
 static struct mtd_partition *mtd_parts;
index 33060a3..ed21547 100644 (file)
@@ -76,7 +76,7 @@ static struct mtd_partition partition_info[]={
            .size = 0x80000
     },
 };
-#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
 
 #define WINDOW_SIZE    0x00100000
 #define WINDOW_ADDR    0x00200000
@@ -88,7 +88,7 @@ static struct map_info netsc520_map = {
        .phys = WINDOW_ADDR,
 };
 
-#define NUM_FLASH_BANKS        (sizeof(netsc520_map)/sizeof(struct map_info))
+#define NUM_FLASH_BANKS        ARRAY_SIZE(netsc520_map)
 
 static struct mtd_info *mymtd;
 
index 632eb2a..54a3102 100644 (file)
@@ -128,8 +128,7 @@ static struct mtd_partition nettel_amd_partitions[] = {
        }
 };
 
-#define NUM_AMD_PARTITIONS \
-       (sizeof(nettel_amd_partitions)/sizeof(nettel_amd_partitions[0]))
+#define NUM_AMD_PARTITIONS ARRAY_SIZE(nettel_amd_partitions)
 
 /****************************************************************************/
 
index c223514..a21fcd1 100644 (file)
@@ -58,8 +58,6 @@ static struct mtd_partition ocotea_large_partitions[] = {
        }
 };
 
-#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
-
 int __init init_ocotea(void)
 {
        u8 fpga0_reg;
@@ -97,7 +95,7 @@ int __init init_ocotea(void)
        if (flash) {
                flash->owner = THIS_MODULE;
                add_mtd_partitions(flash, ocotea_small_partitions,
-                                       NB_OF(ocotea_small_partitions));
+                                       ARRAY_SIZE(ocotea_small_partitions));
        } else {
                printk("map probe failed for flash\n");
                return -ENXIO;
@@ -118,7 +116,7 @@ int __init init_ocotea(void)
        if (flash) {
                flash->owner = THIS_MODULE;
                add_mtd_partitions(flash, ocotea_large_partitions,
-                                       NB_OF(ocotea_large_partitions));
+                                       ARRAY_SIZE(ocotea_large_partitions));
        } else {
                printk("map probe failed for flash\n");
                return -ENXIO;
index 21822c2..d2ab1ba 100644 (file)
@@ -334,9 +334,6 @@ mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        return 0;
 
 release:
-       if (mtd)
-               map_destroy(mtd);
-
        if (map) {
                map->exit(dev, map);
                kfree(map);
index f988c81..d27f412 100644 (file)
@@ -54,7 +54,7 @@ static const int debug = 0;
 #define MAX_PCMCIA_ADDR        0x4000000
 
 struct pcmciamtd_dev {
-       dev_link_t      link;           /* PCMCIA link */
+       struct pcmcia_device    *p_dev;
        dev_node_t      node;           /* device node */
        caddr_t         win_base;       /* ioremapped address of PCMCIA window */
        unsigned int    win_size;       /* size of window */
@@ -111,8 +111,8 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
        memreq_t mrq;
        int ret;
 
-       if(!(dev->link.state & DEV_PRESENT)) {
-               DEBUG(1, "device removed state = 0x%4.4X", dev->link.state);
+       if (!pcmcia_dev_present(dev->p_dev)) {
+               DEBUG(1, "device removed");
                return 0;
        }
 
@@ -122,7 +122,7 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
                      dev->offset, mrq.CardOffset);
                mrq.Page = 0;
                if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) {
-                       cs_error(dev->link.handle, MapMemPage, ret);
+                       cs_error(dev->p_dev, MapMemPage, ret);
                        return NULL;
                }
                dev->offset = mrq.CardOffset;
@@ -238,7 +238,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v
 
 /* read/write{8,16} copy_{from,to} routines with direct access */
 
-#define DEV_REMOVED(x)  (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))
+#define DEV_REMOVED(x)  (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev)))
 
 static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
 {
@@ -319,7 +319,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f
 static void pcmciamtd_set_vpp(struct map_info *map, int on)
 {
        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
-       dev_link_t *link = &dev->link;
+       struct pcmcia_device *link = dev->p_dev;
        modconf_t mod;
        int ret;
 
@@ -328,9 +328,9 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
        mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
 
        DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
-       ret = pcmcia_modify_configuration(link->handle, &mod);
+       ret = pcmcia_modify_configuration(link, &mod);
        if(ret != CS_SUCCESS) {
-               cs_error(link->handle, ModifyConfiguration, ret);
+               cs_error(link, ModifyConfiguration, ret);
        }
 }
 
@@ -340,7 +340,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
  * still open, this will be postponed until it is closed.
  */
 
-static void pcmciamtd_release(dev_link_t *link)
+static void pcmciamtd_release(struct pcmcia_device *link)
 {
        struct pcmciamtd_dev *dev = link->priv;
 
@@ -353,12 +353,11 @@ static void pcmciamtd_release(dev_link_t *link)
                }
                pcmcia_release_window(link->win);
        }
-       pcmcia_release_configuration(link->handle);
-       link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
 }
 
 
-static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name)
+static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name)
 {
        int rc;
        tuple_t tuple;
@@ -371,16 +370,16 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_
        tuple.TupleOffset = 0;
        tuple.DesiredTuple = RETURN_FIRST_TUPLE;
 
-       rc = pcmcia_get_first_tuple(link->handle, &tuple);
+       rc = pcmcia_get_first_tuple(link, &tuple);
        while(rc == CS_SUCCESS) {
-               rc = pcmcia_get_tuple_data(link->handle, &tuple);
+               rc = pcmcia_get_tuple_data(link, &tuple);
                if(rc != CS_SUCCESS) {
-                       cs_error(link->handle, GetTupleData, rc);
+                       cs_error(link, GetTupleData, rc);
                        break;
                }
-               rc = pcmcia_parse_tuple(link->handle, &tuple, &parse);
+               rc = pcmcia_parse_tuple(link, &tuple, &parse);
                if(rc != CS_SUCCESS) {
-                       cs_error(link->handle, ParseTuple, rc);
+                       cs_error(link, ParseTuple, rc);
                        break;
                }
 
@@ -451,7 +450,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_
                        DEBUG(2, "Unknown tuple code %d", tuple.TupleCode);
                }
 
-               rc = pcmcia_get_next_tuple(link->handle, &tuple);
+               rc = pcmcia_get_next_tuple(link, &tuple);
        }
        if(!dev->pcmcia_map.size)
                dev->pcmcia_map.size = MAX_PCMCIA_ADDR;
@@ -488,7 +487,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void pcmciamtd_config(dev_link_t *link)
+static int pcmciamtd_config(struct pcmcia_device *link)
 {
        struct pcmciamtd_dev *dev = link->priv;
        struct mtd_info *mtd = NULL;
@@ -504,13 +503,10 @@ static void pcmciamtd_config(dev_link_t *link)
 
        DEBUG(3, "link=0x%p", link);
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
        DEBUG(2, "Validating CIS");
-       ret = pcmcia_validate_cis(link->handle, &cisinfo);
+       ret = pcmcia_validate_cis(link, &cisinfo);
        if(ret != CS_SUCCESS) {
-               cs_error(link->handle, GetTupleData, ret);
+               cs_error(link, GetTupleData, ret);
        } else {
                DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains);
        }
@@ -538,7 +534,7 @@ static void pcmciamtd_config(dev_link_t *link)
        req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
        req.Base = 0;
        req.AccessSpeed = mem_speed;
-       link->win = (window_handle_t)link->handle;
+       link->win = (window_handle_t)link;
        req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
        dev->win_size = 0;
 
@@ -546,7 +542,7 @@ static void pcmciamtd_config(dev_link_t *link)
                int ret;
                DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
                      req.Size >> 10, req.AccessSpeed);
-               ret = pcmcia_request_window(&link->handle, &req, &link->win);
+               ret = pcmcia_request_window(&link, &req, &link->win);
                DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
                if(ret) {
                        req.Size >>= 1;
@@ -562,19 +558,19 @@ static void pcmciamtd_config(dev_link_t *link)
        if(!dev->win_size) {
                err("Cant allocate memory window");
                pcmciamtd_release(link);
-               return;
+               return -ENODEV;
        }
        DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
 
        /* Get write protect status */
-       CS_CHECK(GetStatus, pcmcia_get_status(link->handle, &status));
+       CS_CHECK(GetStatus, pcmcia_get_status(link, &status));
        DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx",
              status.CardState, (unsigned long)link->win);
        dev->win_base = ioremap(req.Base, req.Size);
        if(!dev->win_base) {
                err("ioremap(%lu, %u) failed", req.Base, req.Size);
                pcmciamtd_release(link);
-               return;
+               return -ENODEV;
        }
        DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
              dev, req.Base, dev->win_base, req.Size);
@@ -584,17 +580,14 @@ static void pcmciamtd_config(dev_link_t *link)
        dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
 
        DEBUG(2, "Getting configuration");
-       CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link->handle, &t));
+       CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &t));
        DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2);
        dev->vpp = (vpp) ? vpp : t.Vpp1;
        link->conf.Attributes = 0;
-       link->conf.Vcc = t.Vcc;
        if(setvpp == 2) {
-               link->conf.Vpp1 = dev->vpp;
-               link->conf.Vpp2 = dev->vpp;
+               link->conf.Vpp = dev->vpp;
        } else {
-               link->conf.Vpp1 = 0;
-               link->conf.Vpp2 = 0;
+               link->conf.Vpp = 0;
        }
 
        link->conf.IntType = INT_MEMORY;
@@ -606,9 +599,10 @@ static void pcmciamtd_config(dev_link_t *link)
        link->conf.ConfigIndex = 0;
        link->conf.Present = t.Present;
        DEBUG(2, "Setting Configuration");
-       ret = pcmcia_request_configuration(link->handle, &link->conf);
+       ret = pcmcia_request_configuration(link, &link->conf);
        if(ret != CS_SUCCESS) {
-               cs_error(link->handle, RequestConfiguration, ret);
+               cs_error(link, RequestConfiguration, ret);
+               return -ENODEV;
        }
 
        if(mem_type == 1) {
@@ -616,7 +610,7 @@ static void pcmciamtd_config(dev_link_t *link)
        } else if(mem_type == 2) {
                mtd = do_map_probe("map_rom", &dev->pcmcia_map);
        } else {
-               for(i = 0; i < sizeof(probes) / sizeof(char *); i++) {
+               for(i = 0; i < ARRAY_SIZE(probes); i++) {
                        DEBUG(1, "Trying %s", probes[i]);
                        mtd = do_map_probe(probes[i], &dev->pcmcia_map);
                        if(mtd)
@@ -629,7 +623,7 @@ static void pcmciamtd_config(dev_link_t *link)
        if(!mtd) {
                DEBUG(1, "Cant find an MTD");
                pcmciamtd_release(link);
-               return;
+               return -ENODEV;
        }
 
        dev->mtd_info = mtd;
@@ -654,7 +648,6 @@ static void pcmciamtd_config(dev_link_t *link)
           use the faster non-remapping read/write functions */
        if(mtd->size <= dev->win_size) {
                DEBUG(1, "Using non remapping memory functions");
-               dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state);
                dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
                if (dev->pcmcia_map.bankwidth == 1) {
                        dev->pcmcia_map.read = pcmcia_read8;
@@ -672,19 +665,18 @@ static void pcmciamtd_config(dev_link_t *link)
                dev->mtd_info = NULL;
                err("Couldnt register MTD device");
                pcmciamtd_release(link);
-               return;
+               return -ENODEV;
        }
        snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index);
        info("mtd%d: %s", mtd->index, mtd->name);
-       link->state &= ~DEV_CONFIG_PENDING;
-       link->dev = &dev->node;
-       return;
+       link->dev_node = &dev->node;
+       return 0;
 
  cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
        err("CS Error, exiting");
        pcmciamtd_release(link);
-       return;
+       return -ENODEV;
 }
 
 
@@ -713,21 +705,18 @@ static int pcmciamtd_resume(struct pcmcia_device *dev)
  * when the device is released.
  */
 
-static void pcmciamtd_detach(struct pcmcia_device *p_dev)
+static void pcmciamtd_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
+       struct pcmciamtd_dev *dev = link->priv;
 
        DEBUG(3, "link=0x%p", link);
 
-       if(link->state & DEV_CONFIG) {
-               struct pcmciamtd_dev *dev = link->priv;
-               if(dev->mtd_info) {
-                       del_mtd_device(dev->mtd_info);
-                       info("mtd%d: Removed", dev->mtd_info->index);
-               }
-
-               pcmciamtd_release(link);
+       if(dev->mtd_info) {
+               del_mtd_device(dev->mtd_info);
+               info("mtd%d: Removed", dev->mtd_info->index);
        }
+
+       pcmciamtd_release(link);
 }
 
 
@@ -736,10 +725,9 @@ static void pcmciamtd_detach(struct pcmcia_device *p_dev)
  * with Card Services.
  */
 
-static int pcmciamtd_attach(struct pcmcia_device *p_dev)
+static int pcmciamtd_probe(struct pcmcia_device *link)
 {
        struct pcmciamtd_dev *dev;
-       dev_link_t *link;
 
        /* Create new memory card device */
        dev = kmalloc(sizeof(*dev), GFP_KERNEL);
@@ -747,20 +735,13 @@ static int pcmciamtd_attach(struct pcmcia_device *p_dev)
        DEBUG(1, "dev=0x%p", dev);
 
        memset(dev, 0, sizeof(*dev));
-       link = &dev->link;
+       dev->p_dev = link;
        link->priv = dev;
 
        link->conf.Attributes = 0;
        link->conf.IntType = INT_MEMORY;
 
-       link->next = NULL;
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       pcmciamtd_config(link);
-
-       return 0;
+       return pcmciamtd_config(link);
 }
 
 static struct pcmcia_device_id pcmciamtd_ids[] = {
@@ -794,7 +775,7 @@ static struct pcmcia_driver pcmciamtd_driver = {
        .drv            = {
                .name   = "pcmciamtd"
        },
-       .probe          = pcmciamtd_attach,
+       .probe          = pcmciamtd_probe,
        .remove         = pcmciamtd_detach,
        .owner          = THIS_MODULE,
        .id_table       = pcmciamtd_ids,
index 5b76ed8..50b1403 100644 (file)
@@ -121,8 +121,7 @@ struct map_info redwood_flash_map = {
 };
 
 
-#define NUM_REDWOOD_FLASH_PARTITIONS \
-       (sizeof(redwood_flash_partitions)/sizeof(redwood_flash_partitions[0]))
+#define NUM_REDWOOD_FLASH_PARTITIONS ARRAY_SIZE(redwood_flash_partitions)
 
 static struct mtd_info *redwood_mtd;
 
index 225cdd9..350286d 100644 (file)
@@ -66,7 +66,7 @@ static struct map_info sbc8240_map[2] = {
        }
 };
 
-#define NUM_FLASH_BANKS        (sizeof(sbc8240_map) / sizeof(struct map_info))
+#define NUM_FLASH_BANKS        ARRAY_SIZE(sbc8240_map)
 
 /*
  * The following defines the partition layout of SBC8240 boards.
@@ -125,8 +125,6 @@ static struct mtd_partition sbc8240_fs_partitions [] = {
        }
 };
 
-#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
-
 /* trivial struct to describe partition information */
 struct mtd_part_def
 {
@@ -190,10 +188,10 @@ int __init init_sbc8240_mtd (void)
 #ifdef CONFIG_MTD_PARTITIONS
        sbc8240_part_banks[0].mtd_part   = sbc8240_uboot_partitions;
        sbc8240_part_banks[0].type       = "static image";
-       sbc8240_part_banks[0].nums       = NB_OF(sbc8240_uboot_partitions);
+       sbc8240_part_banks[0].nums       = ARRAY_SIZE(sbc8240_uboot_partitions);
        sbc8240_part_banks[1].mtd_part   = sbc8240_fs_partitions;
        sbc8240_part_banks[1].type       = "static file system";
-       sbc8240_part_banks[1].nums       = NB_OF(sbc8240_fs_partitions);
+       sbc8240_part_banks[1].nums       = ARRAY_SIZE(sbc8240_fs_partitions);
 
        for (i = 0; i < NUM_FLASH_BANKS; i++) {
 
index ed92afa..e8c130e 100644 (file)
@@ -107,7 +107,7 @@ static struct map_info sc520cdp_map[] = {
        },
 };
 
-#define NUM_FLASH_BANKS        (sizeof(sc520cdp_map)/sizeof(struct map_info))
+#define NUM_FLASH_BANKS        ARRAY_SIZE(sc520cdp_map)
 
 static struct mtd_info *mymtd[NUM_FLASH_BANKS];
 static struct mtd_info *merged_mtd;
index 2c91dff..28b8a57 100644 (file)
@@ -70,7 +70,7 @@ static struct mtd_partition partition_info[] = {
                .size   = 0x80000
        },
 };
-#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
 #endif
 
 
index 999f4bb..12fe53c 100644 (file)
@@ -49,8 +49,6 @@ static struct mtd_partition sharpsl_partitions[1] = {
        }
 };
 
-#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
-
 int __init init_sharpsl(void)
 {
        struct mtd_partition *parts;
@@ -92,7 +90,7 @@ int __init init_sharpsl(void)
        }
 
        parts = sharpsl_partitions;
-       nb_parts = NB_OF(sharpsl_partitions);
+       nb_parts = ARRAY_SIZE(sharpsl_partitions);
 
        printk(KERN_NOTICE "Using %s partision definition\n", part_type);
        add_mtd_partitions(mymtd, parts, nb_parts);
index 4b372bc..a7422c2 100644 (file)
@@ -64,7 +64,7 @@ static struct mtd_partition ts5500_partitions[] = {
        }
 };
 
-#define NUM_PARTITIONS (sizeof(ts5500_partitions)/sizeof(struct mtd_partition))
+#define NUM_PARTITIONS ARRAY_SIZE(ts5500_partitions)
 
 static struct mtd_info *mymtd;
 
index 79d9280..f7264dc 100644 (file)
@@ -37,7 +37,7 @@ struct mtd_partition uclinux_romfs[] = {
        { .name = "ROMfs" }
 };
 
-#define        NUM_PARTITIONS  (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0]))
+#define        NUM_PARTITIONS  ARRAY_SIZE(uclinux_romfs)
 
 /****************************************************************************/
 
index e006394..b3e4873 100644 (file)
@@ -182,7 +182,7 @@ int __init init_vmax301(void)
                }
        }
 
-       if (!vmax_mtd[1] && !vmax_mtd[2]) {
+       if (!vmax_mtd[0] && !vmax_mtd[1]) {
                iounmap((void *)iomapadr);
                return -ENXIO;
        }
index 840dd66..458d3c8 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/hdreg.h>
 #include <linux/init.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
 static LIST_HEAD(blktrans_majors);
 
-extern struct semaphore mtd_table_mutex;
+extern struct mutex mtd_table_mutex;
 extern struct mtd_info *mtd_table[];
 
 struct mtd_blkcore_priv {
@@ -122,9 +122,9 @@ static int mtd_blktrans_thread(void *arg)
 
                spin_unlock_irq(rq->queue_lock);
 
-               down(&dev->sem);
+               mutex_lock(&dev->lock);
                res = do_blktrans_request(tr, dev, req);
-               up(&dev->sem);
+               mutex_unlock(&dev->lock);
 
                spin_lock_irq(rq->queue_lock);
 
@@ -235,8 +235,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
        int last_devnum = -1;
        struct gendisk *gd;
 
-       if (!down_trylock(&mtd_table_mutex)) {
-               up(&mtd_table_mutex);
+       if (!!mutex_trylock(&mtd_table_mutex)) {
+               mutex_unlock(&mtd_table_mutex);
                BUG();
        }
 
@@ -267,7 +267,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
                return -EBUSY;
        }
 
-       init_MUTEX(&new->sem);
+       mutex_init(&new->lock);
        list_add_tail(&new->list, &tr->devs);
  added:
        if (!tr->writesect)
@@ -313,8 +313,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 
 int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
 {
-       if (!down_trylock(&mtd_table_mutex)) {
-               up(&mtd_table_mutex);
+       if (!!mutex_trylock(&mtd_table_mutex)) {
+               mutex_unlock(&mtd_table_mutex);
                BUG();
        }
 
@@ -378,14 +378,14 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
 
        memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv));
 
-       down(&mtd_table_mutex);
+       mutex_lock(&mtd_table_mutex);
 
        ret = register_blkdev(tr->major, tr->name);
        if (ret) {
                printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",
                       tr->name, tr->major, ret);
                kfree(tr->blkcore_priv);
-               up(&mtd_table_mutex);
+               mutex_unlock(&mtd_table_mutex);
                return ret;
        }
        spin_lock_init(&tr->blkcore_priv->queue_lock);
@@ -396,7 +396,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
        if (!tr->blkcore_priv->rq) {
                unregister_blkdev(tr->major, tr->name);
                kfree(tr->blkcore_priv);
-               up(&mtd_table_mutex);
+               mutex_unlock(&mtd_table_mutex);
                return -ENOMEM;
        }
 
@@ -407,7 +407,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
                blk_cleanup_queue(tr->blkcore_priv->rq);
                unregister_blkdev(tr->major, tr->name);
                kfree(tr->blkcore_priv);
-               up(&mtd_table_mutex);
+               mutex_unlock(&mtd_table_mutex);
                return ret;
        }
 
@@ -419,7 +419,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
                        tr->add_mtd(tr, mtd_table[i]);
        }
 
-       up(&mtd_table_mutex);
+       mutex_unlock(&mtd_table_mutex);
 
        return 0;
 }
@@ -428,7 +428,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
 {
        struct list_head *this, *next;
 
-       down(&mtd_table_mutex);
+       mutex_lock(&mtd_table_mutex);
 
        /* Clean up the kernel thread */
        tr->blkcore_priv->exiting = 1;
@@ -446,7 +446,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
        blk_cleanup_queue(tr->blkcore_priv->rq);
        unregister_blkdev(tr->major, tr->name);
 
-       up(&mtd_table_mutex);
+       mutex_unlock(&mtd_table_mutex);
 
        kfree(tr->blkcore_priv);
 
index e847566..2cef280 100644 (file)
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/blktrans.h>
+#include <linux/mutex.h>
+
 
 static struct mtdblk_dev {
        struct mtd_info *mtd;
        int count;
-       struct semaphore cache_sem;
+       struct mutex cache_mutex;
        unsigned char *cache_data;
        unsigned long cache_offset;
        unsigned int cache_size;
@@ -284,7 +286,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
        mtdblk->count = 1;
        mtdblk->mtd = mtd;
 
-       init_MUTEX (&mtdblk->cache_sem);
+       mutex_init(&mtdblk->cache_mutex);
        mtdblk->cache_state = STATE_EMPTY;
        if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM &&
            mtdblk->mtd->erasesize) {
@@ -306,9 +308,9 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
 
        DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
 
-       down(&mtdblk->cache_sem);
+       mutex_lock(&mtdblk->cache_mutex);
        write_cached_data(mtdblk);
-       up(&mtdblk->cache_sem);
+       mutex_unlock(&mtdblk->cache_mutex);
 
        if (!--mtdblk->count) {
                /* It was the last usage. Free the device */
@@ -327,9 +329,9 @@ static int mtdblock_flush(struct mtd_blktrans_dev *dev)
 {
        struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];
 
-       down(&mtdblk->cache_sem);
+       mutex_lock(&mtdblk->cache_mutex);
        write_cached_data(mtdblk);
-       up(&mtdblk->cache_sem);
+       mutex_unlock(&mtdblk->cache_mutex);
 
        if (mtdblk->mtd->sync)
                mtdblk->mtd->sync(mtdblk->mtd);
index dade02a..9905870 100644 (file)
 #include <linux/ioctl.h>
 #include <linux/init.h>
 #include <linux/mtd/compatmac.h>
-#ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
-#endif
 
 #include <linux/mtd/mtd.h>
 
 /* These are exported solely for the purpose of mtd_blkdevs.c. You
    should not use them for _anything_ else */
-DECLARE_MUTEX(mtd_table_mutex);
+DEFINE_MUTEX(mtd_table_mutex);
 struct mtd_info *mtd_table[MAX_MTD_DEVICES];
 
 EXPORT_SYMBOL_GPL(mtd_table_mutex);
@@ -49,7 +47,7 @@ int add_mtd_device(struct mtd_info *mtd)
 {
        int i;
 
-       down(&mtd_table_mutex);
+       mutex_lock(&mtd_table_mutex);
 
        for (i=0; i < MAX_MTD_DEVICES; i++)
                if (!mtd_table[i]) {
@@ -67,7 +65,7 @@ int add_mtd_device(struct mtd_info *mtd)
                                not->add(mtd);
                        }
 
-                       up(&mtd_table_mutex);
+                       mutex_unlock(&mtd_table_mutex);
                        /* We _know_ we aren't being removed, because
                           our caller is still holding us here. So none
                           of this try_ nonsense, and no bitching about it
@@ -76,7 +74,7 @@ int add_mtd_device(struct mtd_info *mtd)
                        return 0;
                }
 
-       up(&mtd_table_mutex);
+       mutex_unlock(&mtd_table_mutex);
        return 1;
 }
 
@@ -94,7 +92,7 @@ int del_mtd_device (struct mtd_info *mtd)
 {
        int ret;
 
-       down(&mtd_table_mutex);
+       mutex_lock(&mtd_table_mutex);
 
        if (mtd_table[mtd->index] != mtd) {
                ret = -ENODEV;
@@ -118,7 +116,7 @@ int del_mtd_device (struct mtd_info *mtd)
                ret = 0;
        }
 
-       up(&mtd_table_mutex);
+       mutex_unlock(&mtd_table_mutex);
        return ret;
 }
 
@@ -135,7 +133,7 @@ void register_mtd_user (struct mtd_notifier *new)
 {
        int i;
 
-       down(&mtd_table_mutex);
+       mutex_lock(&mtd_table_mutex);
 
        list_add(&new->list, &mtd_notifiers);
 
@@ -145,7 +143,7 @@ void register_mtd_user (struct mtd_notifier *new)
                if (mtd_table[i])
                        new->add(mtd_table[i]);
 
-       up(&mtd_table_mutex);
+       mutex_unlock(&mtd_table_mutex);
 }
 
 /**
@@ -162,7 +160,7 @@ int unregister_mtd_user (struct mtd_notifier *old)
 {
        int i;
 
-       down(&mtd_table_mutex);
+       mutex_lock(&mtd_table_mutex);
 
        module_put(THIS_MODULE);
 
@@ -171,7 +169,7 @@ int unregister_mtd_user (struct mtd_notifier *old)
                        old->remove(mtd_table[i]);
 
        list_del(&old->list);
-       up(&mtd_table_mutex);
+       mutex_unlock(&mtd_table_mutex);
        return 0;
 }
 
@@ -193,7 +191,7 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
        struct mtd_info *ret = NULL;
        int i;
 
-       down(&mtd_table_mutex);
+       mutex_lock(&mtd_table_mutex);
 
        if (num == -1) {
                for (i=0; i< MAX_MTD_DEVICES; i++)
@@ -211,7 +209,7 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
        if (ret)
                ret->usecount++;
 
-       up(&mtd_table_mutex);
+       mutex_unlock(&mtd_table_mutex);
        return ret;
 }
 
@@ -219,9 +217,9 @@ void put_mtd_device(struct mtd_info *mtd)
 {
        int c;
 
-       down(&mtd_table_mutex);
+       mutex_lock(&mtd_table_mutex);
        c = --mtd->usecount;
-       up(&mtd_table_mutex);
+       mutex_unlock(&mtd_table_mutex);
        BUG_ON(c < 0);
 
        module_put(mtd->owner);
@@ -296,10 +294,11 @@ EXPORT_SYMBOL(unregister_mtd_user);
 EXPORT_SYMBOL(default_mtd_writev);
 EXPORT_SYMBOL(default_mtd_readv);
 
+#ifdef CONFIG_PROC_FS
+
 /*====================================================================*/
 /* Support for /proc/mtd */
 
-#ifdef CONFIG_PROC_FS
 static struct proc_dir_entry *proc_mtd;
 
 static inline int mtd_proc_info (char *buf, int i)
@@ -319,7 +318,7 @@ static int mtd_read_proc (char *page, char **start, off_t off, int count,
        int len, l, i;
         off_t   begin = 0;
 
-       down(&mtd_table_mutex);
+       mutex_lock(&mtd_table_mutex);
 
        len = sprintf(page, "dev:    size   erasesize  name\n");
         for (i=0; i< MAX_MTD_DEVICES; i++) {
@@ -337,38 +336,34 @@ static int mtd_read_proc (char *page, char **start, off_t off, int count,
         *eof = 1;
 
 done:
-       up(&mtd_table_mutex);
+       mutex_unlock(&mtd_table_mutex);
         if (off >= len+begin)
                 return 0;
         *start = page + (off-begin);
         return ((count < begin+len-off) ? count : begin+len-off);
 }
 
-#endif /* CONFIG_PROC_FS */
-
 /*====================================================================*/
 /* Init code */
 
 static int __init init_mtd(void)
 {
-#ifdef CONFIG_PROC_FS
        if ((proc_mtd = create_proc_entry( "mtd", 0, NULL )))
                proc_mtd->read_proc = mtd_read_proc;
-#endif
        return 0;
 }
 
 static void __exit cleanup_mtd(void)
 {
-#ifdef CONFIG_PROC_FS
         if (proc_mtd)
                remove_proc_entry( "mtd", NULL);
-#endif
 }
 
 module_init(init_mtd);
 module_exit(cleanup_mtd);
 
+#endif /* CONFIG_PROC_FS */
+
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
index 1fc4c13..cfe288a 100644 (file)
@@ -178,17 +178,16 @@ config MTD_NAND_DISKONCHIP_BBTWRITE
          Even if you leave this disabled, you can enable BBT writes at module
          load time (assuming you build diskonchip as a module) with the module
          parameter "inftl_bbt_write=1".
-         
- config MTD_NAND_SHARPSL
-       bool "Support for NAND Flash on Sharp SL Series (C7xx + others)"
-       depends on MTD_NAND && ARCH_PXA
- config MTD_NAND_NANDSIM
-       bool "Support for NAND Flash Simulator"
-       depends on MTD_NAND && MTD_PARTITIONS
 
+config MTD_NAND_SHARPSL
+       tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
+       depends on MTD_NAND && ARCH_PXA
+
+config MTD_NAND_NANDSIM
+       tristate "Support for NAND Flash Simulator"
+       depends on MTD_NAND && MTD_PARTITIONS
        help
          The simulator may simulate verious NAND flash chips for the
          MTD nand layer.
+
 endmenu
index 201e136..bde3550 100644 (file)
@@ -55,8 +55,6 @@ static const struct mtd_partition partition_info[] = {
                .size   =    MTDPART_SIZ_FULL
        }
 };
-#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
-
 
 /**
  * au_read_byte -  read one byte from the chip
@@ -462,7 +460,7 @@ int __init au1xxx_nand_init (void)
        }
 
        /* Register the partitions */
-       add_mtd_partitions(au1550_mtd, partition_info, NB_OF(partition_info));
+       add_mtd_partitions(au1550_mtd, partition_info, ARRAY_SIZE(partition_info));
 
        return 0;
 
index 5d22246..95e96fa 100644 (file)
@@ -80,6 +80,7 @@
 #include <linux/mtd/compatmac.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
+#include <linux/leds.h>
 #include <asm/io.h>
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -515,6 +516,8 @@ static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, i
        return nand_isbad_bbt (mtd, ofs, allowbbt);
 }
 
+DEFINE_LED_TRIGGER(nand_led_trigger);
+
 /*
  * Wait for the ready pin, after a command
  * The timeout is catched later.
@@ -524,12 +527,14 @@ static void nand_wait_ready(struct mtd_info *mtd)
        struct nand_chip *this = mtd->priv;
        unsigned long   timeo = jiffies + 2;
 
+       led_trigger_event(nand_led_trigger, LED_FULL);
        /* wait until command is processed or timeout occures */
        do {
                if (this->dev_ready(mtd))
-                       return;
+                       break;
                touch_softlockup_watchdog();
        } while (time_before(jiffies, timeo));
+       led_trigger_event(nand_led_trigger, LED_OFF);
 }
 
 /**
@@ -817,6 +822,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
        else
                 timeo += (HZ * 20) / 1000;
 
+       led_trigger_event(nand_led_trigger, LED_FULL);
+
        /* Apply this short delay always to ensure that we do wait tWB in
         * any case on any machine. */
        ndelay (100);
@@ -840,6 +847,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
                }
                cond_resched();
        }
+       led_trigger_event(nand_led_trigger, LED_OFF);
+
        status = (int) this->read_byte(mtd);
        return status;
 }
@@ -2724,6 +2733,21 @@ void nand_release (struct mtd_info *mtd)
 EXPORT_SYMBOL_GPL (nand_scan);
 EXPORT_SYMBOL_GPL (nand_release);
 
+
+static int __init nand_base_init(void)
+{
+       led_trigger_register_simple("nand-disk", &nand_led_trigger);
+       return 0;
+}
+
+static void __exit nand_base_exit(void)
+{
+       led_trigger_unregister_simple(nand_led_trigger);
+}
+
+module_init(nand_base_init);
+module_exit(nand_base_exit);
+
 MODULE_LICENSE ("GPL");
 MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
 MODULE_DESCRIPTION ("Generic NAND flash driver code");
index 8815c8d..c077d2e 100644 (file)
@@ -85,10 +85,6 @@ static int parse_redboot_partitions(struct mtd_info *master,
 
        numslots = (master->erasesize / sizeof(struct fis_image_desc));
        for (i = 0; i < numslots; i++) {
-               if (buf[i].name[0] == 0xff) {
-                       i = numslots;
-                       break;
-               }
                if (!memcmp(buf[i].name, "FIS directory", 14)) {
                        /* This is apparently the FIS directory entry for the
                         * FIS directory itself.  The FIS directory size is
@@ -128,7 +124,7 @@ static int parse_redboot_partitions(struct mtd_info *master,
                struct fis_list *new_fl, **prev;
 
                if (buf[i].name[0] == 0xff)
-                       break;
+                       continue;
                if (!redboot_checksum(&buf[i]))
                        break;
 
index 70f6389..274b013 100644 (file)
@@ -788,7 +788,7 @@ struct vortex_private {
        int options;                                            /* User-settable misc. driver options. */
        unsigned int media_override:4,          /* Passed-in media type. */
                default_media:4,                                /* Read from the EEPROM/Wn3_Config. */
-               full_duplex:1, force_fd:1, autoselect:1,
+               full_duplex:1, autoselect:1,
                bus_master:1,                                   /* Vortex can only do a fragment bus-m. */
                full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang  */
                flow_ctrl:1,                                    /* Use 802.3x flow control (PAUSE only) */
@@ -1633,12 +1633,6 @@ vortex_set_duplex(struct net_device *dev)
                        ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ?
                                        0x100 : 0),
                        ioaddr + Wn3_MAC_Ctrl);
-
-       issue_and_wait(dev, TxReset);
-       /*
-        * Don't reset the PHY - that upsets autonegotiation during DHCP operations.
-        */
-       issue_and_wait(dev, RxReset|0x04);
 }
 
 static void vortex_check_media(struct net_device *dev, unsigned int init)
@@ -1663,7 +1657,7 @@ vortex_up(struct net_device *dev)
        struct vortex_private *vp = netdev_priv(dev);
        void __iomem *ioaddr = vp->ioaddr;
        unsigned int config;
-       int i;
+       int i, mii_reg1, mii_reg5;
 
        if (VORTEX_PCI(vp)) {
                pci_set_power_state(VORTEX_PCI(vp), PCI_D0);    /* Go active */
@@ -1723,14 +1717,23 @@ vortex_up(struct net_device *dev)
                printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config);
        iowrite32(config, ioaddr + Wn3_Config);
 
-       netif_carrier_off(dev);
        if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
                EL3WINDOW(4);
+               mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR);
+               mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
+               vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
+
                vortex_check_media(dev, 1);
        }
        else
                vortex_set_duplex(dev);
 
+       issue_and_wait(dev, TxReset);
+       /*
+        * Don't reset the PHY - that upsets autonegotiation during DHCP operations.
+        */
+       issue_and_wait(dev, RxReset|0x04);
+
 
        iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
 
@@ -2083,16 +2086,14 @@ vortex_error(struct net_device *dev, int status)
                }
                if (tx_status & 0x14)  vp->stats.tx_fifo_errors++;
                if (tx_status & 0x38)  vp->stats.tx_aborted_errors++;
+               if (tx_status & 0x08)  vp->xstats.tx_max_collisions++;
                iowrite8(0, ioaddr + TxStatus);
                if (tx_status & 0x30) {                 /* txJabber or txUnderrun */
                        do_tx_reset = 1;
-               } else if (tx_status & 0x08) {  /* maxCollisions */
-                       vp->xstats.tx_max_collisions++;
-                       if (vp->drv_flags & MAX_COLLISION_RESET) {
-                               do_tx_reset = 1;
-                               reset_mask = 0x0108;            /* Reset interface logic, but not download logic */
-                       }
-               } else {                                                /* Merely re-enable the transmitter. */
+               } else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET))  {      /* maxCollisions */
+                       do_tx_reset = 1;
+                       reset_mask = 0x0108;            /* Reset interface logic, but not download logic */
+               } else {                                /* Merely re-enable the transmitter. */
                        iowrite16(TxEnable, ioaddr + EL3_CMD);
                }
        }
index e20b849..bdaaad8 100644 (file)
@@ -2313,13 +2313,11 @@ config S2IO_NAPI
 
 endmenu
 
-if !UML
 source "drivers/net/tokenring/Kconfig"
 
 source "drivers/net/wireless/Kconfig"
 
 source "drivers/net/pcmcia/Kconfig"
-endif
 
 source "drivers/net/wan/Kconfig"
 
index 43150b2..0d45553 100644 (file)
@@ -125,11 +125,11 @@ static void __init com90xx_probe(void)
        if (!io && !irq && !shmem && !*device && com90xx_skip_probe)
                return;
 
-       shmems = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(unsigned long),
+       shmems = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(unsigned long),
                         GFP_KERNEL);
        if (!shmems)
                return;
-       iomem = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(void __iomem *),
+       iomem = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(void __iomem *),
                         GFP_KERNEL);
        if (!iomem) {
                kfree(shmems);
index ceb98fd..52d0102 100644 (file)
@@ -235,7 +235,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
 
                lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
                    
-               if(lpar_rc != H_Success) {
+               if(lpar_rc != H_SUCCESS) {
                        pool->free_map[free_index] = index;
                        pool->skbuff[index] = NULL;
                        pool->consumer_index--;
@@ -373,7 +373,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
 
        lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
                    
-       if(lpar_rc != H_Success) {
+       if(lpar_rc != H_SUCCESS) {
                ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc);
                ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
        }
@@ -511,7 +511,7 @@ static int ibmveth_open(struct net_device *netdev)
                                         adapter->filter_list_dma,
                                         mac_address);
 
-       if(lpar_rc != H_Success) {
+       if(lpar_rc != H_SUCCESS) {
                ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
                ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n",
                                     adapter->buffer_list_dma,
@@ -527,7 +527,7 @@ static int ibmveth_open(struct net_device *netdev)
                ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
                do {
                        rc = h_free_logical_lan(adapter->vdev->unit_address);
-               } while (H_isLongBusy(rc) || (rc == H_Busy));
+               } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));
 
                ibmveth_cleanup(adapter);
                return rc;
@@ -556,9 +556,9 @@ static int ibmveth_close(struct net_device *netdev)
 
        do {
                lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
-       } while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy));
+       } while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
 
-       if(lpar_rc != H_Success)
+       if(lpar_rc != H_SUCCESS)
        {
                ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n",
                                     lpar_rc);
@@ -693,9 +693,9 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
                                             desc[4].desc,
                                             desc[5].desc,
                                             correlator);
-       } while ((lpar_rc == H_Busy) && (retry_count--));
+       } while ((lpar_rc == H_BUSY) && (retry_count--));
     
-       if(lpar_rc != H_Success && lpar_rc != H_Dropped) {
+       if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
                int i;
                ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
                for(i = 0; i < 6; i++) {
@@ -786,14 +786,14 @@ static int ibmveth_poll(struct net_device *netdev, int *budget)
        /* we think we are done - reenable interrupts, then check once more to make sure we are done */
        lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE);
 
-       ibmveth_assert(lpar_rc == H_Success);
+       ibmveth_assert(lpar_rc == H_SUCCESS);
 
        netif_rx_complete(netdev);
 
        if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed))
        {
                lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
-               ibmveth_assert(lpar_rc == H_Success);
+               ibmveth_assert(lpar_rc == H_SUCCESS);
                more_work = 1;
                goto restart_poll;
        }
@@ -813,7 +813,7 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs
 
        if(netif_rx_schedule_prep(netdev)) {
                lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
-               ibmveth_assert(lpar_rc == H_Success);
+               ibmveth_assert(lpar_rc == H_SUCCESS);
                __netif_rx_schedule(netdev);
        }
        return IRQ_HANDLED;
@@ -835,7 +835,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
                                           IbmVethMcastEnableRecv |
                                           IbmVethMcastDisableFiltering,
                                           0);
-               if(lpar_rc != H_Success) {
+               if(lpar_rc != H_SUCCESS) {
                        ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc);
                }
        } else {
@@ -847,7 +847,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
                                           IbmVethMcastDisableFiltering |
                                           IbmVethMcastClearFilterTable,
                                           0);
-               if(lpar_rc != H_Success) {
+               if(lpar_rc != H_SUCCESS) {
                        ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc);
                }
                /* add the addresses to the filter table */
@@ -858,7 +858,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
                        lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
                                                   IbmVethMcastAddFilter,
                                                   mcast_addr);
-                       if(lpar_rc != H_Success) {
+                       if(lpar_rc != H_SUCCESS) {
                                ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
                        }
                }
@@ -867,7 +867,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
                lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
                                           IbmVethMcastEnableFiltering,
                                           0);
-               if(lpar_rc != H_Success) {
+               if(lpar_rc != H_SUCCESS) {
                        ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc);
                }
        }
index edd1b53..75b35ad 100644 (file)
@@ -94,7 +94,7 @@ static struct console netconsole = {
 static int option_setup(char *opt)
 {
        configured = !netpoll_parse_options(&np, opt);
-       return 0;
+       return 1;
 }
 
 __setup("netconsole=", option_setup);
index ce90bec..fab9336 100644 (file)
@@ -204,7 +204,7 @@ enum Window4 {              /* Window 4: Xcvr/media bits. */
 #define MEDIA_TP       0x00C0  /* Enable link beat and jabber for 10baseT. */
 
 struct el3_private {
-       dev_link_t link;
+       struct pcmcia_device    *p_dev;
        dev_node_t node;
        struct net_device_stats stats;
        u16 advertising, partner;               /* NWay media advertisement */
@@ -225,8 +225,8 @@ static char mii_preamble_required = 0;
 
 /* Index of functions. */
 
-static void tc574_config(dev_link_t *link);
-static void tc574_release(dev_link_t *link);
+static int tc574_config(struct pcmcia_device *link);
+static void tc574_release(struct pcmcia_device *link);
 
 static void mdio_sync(kio_addr_t ioaddr, int bits);
 static int mdio_read(kio_addr_t ioaddr, int phy_id, int location);
@@ -256,10 +256,9 @@ static void tc574_detach(struct pcmcia_device *p_dev);
        with Card Services.
 */
 
-static int tc574_attach(struct pcmcia_device *p_dev)
+static int tc574_probe(struct pcmcia_device *link)
 {
        struct el3_private *lp;
-       dev_link_t *link;
        struct net_device *dev;
 
        DEBUG(0, "3c574_attach()\n");
@@ -269,8 +268,8 @@ static int tc574_attach(struct pcmcia_device *p_dev)
        if (!dev)
                return -ENOMEM;
        lp = netdev_priv(dev);
-       link = &lp->link;
        link->priv = dev;
+       lp->p_dev = link;
 
        spin_lock_init(&lp->window_lock);
        link->io.NumPorts1 = 32;
@@ -280,7 +279,6 @@ static int tc574_attach(struct pcmcia_device *p_dev)
        link->irq.Handler = &el3_interrupt;
        link->irq.Instance = dev;
        link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.Vcc = 50;
        link->conf.IntType = INT_MEMORY_AND_IO;
        link->conf.ConfigIndex = 1;
        link->conf.Present = PRESENT_OPTION;
@@ -298,13 +296,7 @@ static int tc574_attach(struct pcmcia_device *p_dev)
        dev->watchdog_timeo = TX_TIMEOUT;
 #endif
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       tc574_config(link);
-
-       return 0;
+       return tc574_config(link);
 } /* tc574_attach */
 
 /*
@@ -316,18 +308,16 @@ static int tc574_attach(struct pcmcia_device *p_dev)
 
 */
 
-static void tc574_detach(struct pcmcia_device *p_dev)
+static void tc574_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
        DEBUG(0, "3c574_detach(0x%p)\n", link);
 
-       if (link->dev)
+       if (link->dev_node)
                unregister_netdev(dev);
 
-       if (link->state & DEV_CONFIG)
-               tc574_release(link);
+       tc574_release(link);
 
        free_netdev(dev);
 } /* tc574_detach */
@@ -343,9 +333,8 @@ static void tc574_detach(struct pcmcia_device *p_dev)
 
 static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
 
-static void tc574_config(dev_link_t *link)
+static int tc574_config(struct pcmcia_device *link)
 {
-       client_handle_t handle = link->handle;
        struct net_device *dev = link->priv;
        struct el3_private *lp = netdev_priv(dev);
        tuple_t tuple;
@@ -363,30 +352,27 @@ static void tc574_config(dev_link_t *link)
 
        tuple.Attributes = 0;
        tuple.DesiredTuple = CISTPL_CONFIG;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        tuple.TupleData = (cisdata_t *)buf;
        tuple.TupleDataMax = 64;
        tuple.TupleOffset = 0;
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
        link->io.IOAddrLines = 16;
        for (i = j = 0; j < 0x400; j += 0x20) {
                link->io.BasePort1 = j ^ 0x300;
-               i = pcmcia_request_io(link->handle, &link->io);
+               i = pcmcia_request_io(link, &link->io);
                if (i == CS_SUCCESS) break;
        }
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestIO, i);
+               cs_error(link, RequestIO, i);
                goto failed;
        }
-       CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+       CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
        dev->irq = link->irq.AssignedIRQ;
        dev->base_addr = link->io.BasePort1;
@@ -397,8 +383,8 @@ static void tc574_config(dev_link_t *link)
           the hardware address.  The future products may include a modem chip
           and put the address in the CIS. */
        tuple.DesiredTuple = 0x88;
-       if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
-               pcmcia_get_tuple_data(handle, &tuple);
+       if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+               pcmcia_get_tuple_data(link, &tuple);
                for (i = 0; i < 3; i++)
                        phys_addr[i] = htons(buf[i]);
        } else {
@@ -412,9 +398,9 @@ static void tc574_config(dev_link_t *link)
                }
        }
        tuple.DesiredTuple = CISTPL_VERS_1;
-       if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS &&
-               pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS &&
-               pcmcia_parse_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
+       if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS &&
+               pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS &&
+               pcmcia_parse_tuple(link, &tuple, &parse) == CS_SUCCESS) {
                cardname = parse.version_1.str + parse.version_1.ofs[1];
        } else
                cardname = "3Com 3c574";
@@ -473,13 +459,12 @@ static void tc574_config(dev_link_t *link)
                }
        }
 
-       link->state &= ~DEV_CONFIG_PENDING;
-       link->dev = &lp->node;
-       SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+       link->dev_node = &lp->node;
+       SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
        if (register_netdev(dev) != 0) {
                printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
-               link->dev = NULL;
+               link->dev_node = NULL;
                goto failed;
        }
 
@@ -493,13 +478,13 @@ static void tc574_config(dev_link_t *link)
                   8 << config.u.ram_size, ram_split[config.u.ram_split],
                   config.u.autoselect ? "autoselect " : "");
 
-       return;
+       return 0;
 
 cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 failed:
        tc574_release(link);
-       return;
+       return -ENODEV;
 
 } /* tc574_config */
 
@@ -509,44 +494,28 @@ failed:
        still open, this will be postponed until it is closed.
 */
 
-static void tc574_release(dev_link_t *link)
+static void tc574_release(struct pcmcia_device *link)
 {
-       DEBUG(0, "3c574_release(0x%p)\n", link);
-
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
-
-       link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
 }
 
-static int tc574_suspend(struct pcmcia_device *p_dev)
+static int tc574_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-       }
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int tc574_resume(struct pcmcia_device *p_dev)
+static int tc574_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       tc574_reset(dev);
-                       netif_device_attach(dev);
-               }
+       if (link->open) {
+               tc574_reset(dev);
+               netif_device_attach(dev);
        }
 
        return 0;
@@ -757,9 +726,9 @@ static void tc574_reset(struct net_device *dev)
 static int el3_open(struct net_device *dev)
 {
        struct el3_private *lp = netdev_priv(dev);
-       dev_link_t *link = &lp->link;
+       struct pcmcia_device *link = lp->p_dev;
 
-       if (!DEV_OK(link))
+       if (!pcmcia_dev_present(link))
                return -ENODEV;
        
        link->open++;
@@ -1203,11 +1172,11 @@ static int el3_close(struct net_device *dev)
 {
        kio_addr_t ioaddr = dev->base_addr;
        struct el3_private *lp = netdev_priv(dev);
-       dev_link_t *link = &lp->link;
+       struct pcmcia_device *link = lp->p_dev;
 
        DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
        
-       if (DEV_OK(link)) {
+       if (pcmcia_dev_present(link)) {
                unsigned long flags;
 
                /* Turn off statistics ASAP.  We update lp->stats below. */
@@ -1246,7 +1215,7 @@ static struct pcmcia_driver tc574_driver = {
        .drv            = {
                .name   = "3c574_cs",
        },
-       .probe          = tc574_attach,
+       .probe          = tc574_probe,
        .remove         = tc574_detach,
        .id_table       = tc574_ids,
        .suspend        = tc574_suspend,
index 3dba508..875a0fe 100644 (file)
@@ -105,7 +105,7 @@ enum RxFilter {
 #define TX_TIMEOUT     ((400*HZ)/1000)
 
 struct el3_private {
-    dev_link_t         link;
+       struct pcmcia_device    *p_dev;
     dev_node_t                 node;
     struct net_device_stats stats;
     /* For transceiver monitoring */
@@ -142,8 +142,8 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)";
 
 /*====================================================================*/
 
-static void tc589_config(dev_link_t *link);
-static void tc589_release(dev_link_t *link);
+static int tc589_config(struct pcmcia_device *link);
+static void tc589_release(struct pcmcia_device *link);
 
 static u16 read_eeprom(kio_addr_t ioaddr, int index);
 static void tc589_reset(struct net_device *dev);
@@ -170,10 +170,9 @@ static void tc589_detach(struct pcmcia_device *p_dev);
 
 ======================================================================*/
 
-static int tc589_attach(struct pcmcia_device *p_dev)
+static int tc589_probe(struct pcmcia_device *link)
 {
     struct el3_private *lp;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "3c589_attach()\n");
@@ -183,8 +182,8 @@ static int tc589_attach(struct pcmcia_device *p_dev)
     if (!dev)
         return -ENOMEM;
     lp = netdev_priv(dev);
-    link = &lp->link;
     link->priv = dev;
+    lp->p_dev = link;
 
     spin_lock_init(&lp->lock);
     link->io.NumPorts1 = 16;
@@ -194,7 +193,6 @@ static int tc589_attach(struct pcmcia_device *p_dev)
     link->irq.Handler = &el3_interrupt;
     link->irq.Instance = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
@@ -213,13 +211,7 @@ static int tc589_attach(struct pcmcia_device *p_dev)
 #endif
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    tc589_config(link);
-
-    return 0;
+    return tc589_config(link);
 } /* tc589_attach */
 
 /*======================================================================
@@ -231,18 +223,16 @@ static int tc589_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void tc589_detach(struct pcmcia_device *p_dev)
+static void tc589_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "3c589_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
        unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-       tc589_release(link);
+    tc589_release(link);
 
     free_netdev(dev);
 } /* tc589_detach */
@@ -258,9 +248,8 @@ static void tc589_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void tc589_config(dev_link_t *link)
+static int tc589_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct el3_private *lp = netdev_priv(dev);
     tuple_t tuple;
@@ -275,43 +264,40 @@ static void tc589_config(dev_link_t *link)
     phys_addr = (u16 *)dev->dev_addr;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     tuple.TupleData = (cisdata_t *)buf;
     tuple.TupleDataMax = sizeof(buf);
     tuple.TupleOffset = 0;
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
     
     /* Is this a 3c562? */
     tuple.DesiredTuple = CISTPL_MANFID;
     tuple.Attributes = TUPLE_RETURN_COMMON;
-    if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
-       (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) {
+    if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+       (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) {
        if (le16_to_cpu(buf[0]) != MANFID_3COM)
            printk(KERN_INFO "3c589_cs: hmmm, is this really a "
                   "3Com card??\n");
        multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562);
     }
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
 
     /* For the 3c562, the base address must be xx00-xx7f */
     link->io.IOAddrLines = 16;
     for (i = j = 0; j < 0x400; j += 0x10) {
        if (multi && (j & 0x80)) continue;
        link->io.BasePort1 = j ^ 0x300;
-       i = pcmcia_request_io(link->handle, &link->io);
+       i = pcmcia_request_io(link, &link->io);
        if (i == CS_SUCCESS) break;
     }
     if (i != CS_SUCCESS) {
-       cs_error(link->handle, RequestIO, i);
+       cs_error(link, RequestIO, i);
        goto failed;
     }
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
        
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
@@ -321,8 +307,8 @@ static void tc589_config(dev_link_t *link)
     /* The 3c589 has an extra EEPROM for configuration info, including
        the hardware address.  The 3c562 puts the address in the CIS. */
     tuple.DesiredTuple = 0x88;
-    if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
-       pcmcia_get_tuple_data(handle, &tuple);
+    if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+       pcmcia_get_tuple_data(link, &tuple);
        for (i = 0; i < 3; i++)
            phys_addr[i] = htons(buf[i]);
     } else {
@@ -346,13 +332,12 @@ static void tc589_config(dev_link_t *link)
     else
        printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
     
-    link->dev = &lp->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &lp->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if (register_netdev(dev) != 0) {
        printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
-       link->dev = NULL;
+       link->dev_node = NULL;
        goto failed;
     }
 
@@ -366,14 +351,13 @@ static void tc589_config(dev_link_t *link)
     printk(KERN_INFO "  %dK FIFO split %s Rx:Tx, %s xcvr\n",
           (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
           if_names[dev->if_port]);
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     tc589_release(link);
-    return;
-    
+    return -ENODEV;
 } /* tc589_config */
 
 /*======================================================================
@@ -384,44 +368,28 @@ failed:
     
 ======================================================================*/
 
-static void tc589_release(dev_link_t *link)
+static void tc589_release(struct pcmcia_device *link)
 {
-    DEBUG(0, "3c589_release(0x%p)\n", link);
-    
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    
-    link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
 }
 
-static int tc589_suspend(struct pcmcia_device *p_dev)
+static int tc589_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-       }
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int tc589_resume(struct pcmcia_device *p_dev)
+static int tc589_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       tc589_reset(dev);
-                       netif_device_attach(dev);
-               }
+       if (link->open) {
+               tc589_reset(dev);
+               netif_device_attach(dev);
        }
 
        return 0;
@@ -587,9 +555,9 @@ static int el3_config(struct net_device *dev, struct ifmap *map)
 static int el3_open(struct net_device *dev)
 {
     struct el3_private *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
     
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
        return -ENODEV;
 
     link->open++;
@@ -848,9 +816,9 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
 {
     struct el3_private *lp = netdev_priv(dev);
     unsigned long flags;
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
 
-    if (DEV_OK(link)) {
+    if (pcmcia_dev_present(link)) {
        spin_lock_irqsave(&lp->lock, flags);
        update_stats(dev);
        spin_unlock_irqrestore(&lp->lock, flags);
@@ -950,11 +918,11 @@ static int el3_rx(struct net_device *dev)
 static void set_multicast_list(struct net_device *dev)
 {
     struct el3_private *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
     kio_addr_t ioaddr = dev->base_addr;
     u16 opts = SetRxFilter | RxStation | RxBroadcast;
 
-    if (!(DEV_OK(link))) return;
+    if (!pcmcia_dev_present(link)) return;
     if (dev->flags & IFF_PROMISC)
        opts |= RxMulticast | RxProm;
     else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
@@ -965,12 +933,12 @@ static void set_multicast_list(struct net_device *dev)
 static int el3_close(struct net_device *dev)
 {
     struct el3_private *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
     kio_addr_t ioaddr = dev->base_addr;
     
     DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
 
-    if (DEV_OK(link)) {
+    if (pcmcia_dev_present(link)) {
        /* Turn off statistics ASAP.  We update lp->stats below. */
        outw(StatsDisable, ioaddr + EL3_CMD);
        
@@ -1020,7 +988,7 @@ static struct pcmcia_driver tc589_driver = {
        .drv            = {
                .name   = "3c589_cs",
        },
-       .probe          = tc589_attach,
+       .probe          = tc589_probe,
        .remove         = tc589_detach,
         .id_table       = tc589_ids,
        .suspend        = tc589_suspend,
index 1cc94b2..56233af 100644 (file)
@@ -86,8 +86,8 @@ static char *version =
 
 /*====================================================================*/
 
-static void axnet_config(dev_link_t *link);
-static void axnet_release(dev_link_t *link);
+static int axnet_config(struct pcmcia_device *link);
+static void axnet_release(struct pcmcia_device *link);
 static int axnet_open(struct net_device *dev);
 static int axnet_close(struct net_device *dev);
 static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -117,7 +117,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 /*====================================================================*/
 
 typedef struct axnet_dev_t {
-    dev_link_t         link;
+       struct pcmcia_device    *p_dev;
     dev_node_t         node;
     caddr_t            base;
     struct timer_list  watchdog;
@@ -142,10 +142,9 @@ static inline axnet_dev_t *PRIV(struct net_device *dev)
 
 ======================================================================*/
 
-static int axnet_attach(struct pcmcia_device *p_dev)
+static int axnet_probe(struct pcmcia_device *link)
 {
     axnet_dev_t *info;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "axnet_attach()\n");
@@ -157,7 +156,7 @@ static int axnet_attach(struct pcmcia_device *p_dev)
        return -ENOMEM;
 
     info = PRIV(dev);
-    link = &info->link;
+    info->p_dev = link;
     link->priv = dev;
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
@@ -169,13 +168,7 @@ static int axnet_attach(struct pcmcia_device *p_dev)
     dev->do_ioctl = &axnet_ioctl;
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    axnet_config(link);
-
-    return 0;
+    return axnet_config(link);
 } /* axnet_attach */
 
 /*======================================================================
@@ -187,18 +180,16 @@ static int axnet_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void axnet_detach(struct pcmcia_device *p_dev)
+static void axnet_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "axnet_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
        unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-       axnet_release(link);
+    axnet_release(link);
 
     free_netdev(dev);
 } /* axnet_detach */
@@ -209,7 +200,7 @@ static void axnet_detach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static int get_prom(dev_link_t *link)
+static int get_prom(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     kio_addr_t ioaddr = dev->base_addr;
@@ -263,7 +254,7 @@ static int get_prom(dev_link_t *link)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static int try_io_port(dev_link_t *link)
+static int try_io_port(struct pcmcia_device *link)
 {
     int j, ret;
     if (link->io.NumPorts1 == 32) {
@@ -284,25 +275,23 @@ static int try_io_port(dev_link_t *link)
        for (j = 0; j < 0x400; j += 0x20) {
            link->io.BasePort1 = j ^ 0x300;
            link->io.BasePort2 = (j ^ 0x300) + 0x10;
-           ret = pcmcia_request_io(link->handle, &link->io);
+           ret = pcmcia_request_io(link, &link->io);
            if (ret == CS_SUCCESS) return ret;
        }
        return ret;
     } else {
-       return pcmcia_request_io(link->handle, &link->io);
+       return pcmcia_request_io(link, &link->io);
     }
 }
 
-static void axnet_config(dev_link_t *link)
+static int axnet_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     axnet_dev_t *info = PRIV(dev);
     tuple_t tuple;
     cisparse_t parse;
     int i, j, last_ret, last_fn;
     u_short buf[64];
-    config_info_t conf;
 
     DEBUG(0, "axnet_config(0x%p)\n", link);
 
@@ -311,29 +300,22 @@ static void axnet_config(dev_link_t *link)
     tuple.TupleDataMax = sizeof(buf);
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     /* don't trust the CIS on this; Linksys got it wrong */
     link->conf.Present = 0x63;
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
-    /* Look up current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-    link->conf.Vcc = conf.Vcc;
-
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
     tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (last_ret == CS_SUCCESS) {
        cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
        cistpl_io_t *io = &(parse.cftable_entry.io);
        
-       if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-               pcmcia_parse_tuple(handle, &tuple, &parse) != 0 ||
+       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+               pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
                cfg->index == 0 || cfg->io.nwin == 0)
            goto next_entry;
        
@@ -355,21 +337,21 @@ static void axnet_config(dev_link_t *link)
            if (last_ret == CS_SUCCESS) break;
        }
     next_entry:
-       last_ret = pcmcia_get_next_tuple(handle, &tuple);
+       last_ret = pcmcia_get_next_tuple(link, &tuple);
     }
     if (last_ret != CS_SUCCESS) {
-       cs_error(handle, RequestIO, last_ret);
+       cs_error(link, RequestIO, last_ret);
        goto failed;
     }
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     
     if (link->io.NumPorts2 == 8) {
        link->conf.Attributes |= CONF_ENABLE_SPKR;
        link->conf.Status = CCSR_AUDIO_ENA;
     }
     
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
 
@@ -406,7 +388,7 @@ static void axnet_config(dev_link_t *link)
        Bit 2 of CCSR is active low. */ 
     if (i == 32) {
        conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 };
-       pcmcia_access_configuration_register(link->handle, &reg);
+       pcmcia_access_configuration_register(link, &reg);
        for (i = 0; i < 32; i++) {
            j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
            if ((j != 0) && (j != 0xffff)) break;
@@ -414,13 +396,12 @@ static void axnet_config(dev_link_t *link)
     }
 
     info->phy_id = (i < 32) ? i : -1;
-    link->dev = &info->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &info->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if (register_netdev(dev) != 0) {
        printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
-       link->dev = NULL;
+       link->dev_node = NULL;
        goto failed;
     }
 
@@ -436,14 +417,13 @@ static void axnet_config(dev_link_t *link)
     } else {
        printk(KERN_NOTICE "  No MII transceivers found!\n");
     }
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     axnet_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
+    return -ENODEV;
 } /* axnet_config */
 
 /*======================================================================
@@ -454,45 +434,29 @@ failed:
 
 ======================================================================*/
 
-static void axnet_release(dev_link_t *link)
+static void axnet_release(struct pcmcia_device *link)
 {
-    DEBUG(0, "axnet_release(0x%p)\n", link);
-
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-
-    link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
 }
 
-static int axnet_suspend(struct pcmcia_device *p_dev)
+static int axnet_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-       }
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int axnet_resume(struct pcmcia_device *p_dev)
+static int axnet_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       axnet_reset_8390(dev);
-                       AX88190_init(dev, 1);
-                       netif_device_attach(dev);
-               }
+       if (link->open) {
+               axnet_reset_8390(dev);
+               AX88190_init(dev, 1);
+               netif_device_attach(dev);
        }
 
        return 0;
@@ -562,11 +526,11 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
 static int axnet_open(struct net_device *dev)
 {
     axnet_dev_t *info = PRIV(dev);
-    dev_link_t *link = &info->link;
+    struct pcmcia_device *link = info->p_dev;
     
     DEBUG(2, "axnet_open('%s')\n", dev->name);
 
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
        return -ENODEV;
 
     link->open++;
@@ -588,7 +552,7 @@ static int axnet_open(struct net_device *dev)
 static int axnet_close(struct net_device *dev)
 {
     axnet_dev_t *info = PRIV(dev);
-    dev_link_t *link = &info->link;
+    struct pcmcia_device *link = info->p_dev;
 
     DEBUG(2, "axnet_close('%s')\n", dev->name);
 
@@ -833,7 +797,7 @@ static struct pcmcia_driver axnet_cs_driver = {
        .drv            = {
                .name   = "axnet_cs",
        },
-       .probe          = axnet_attach,
+       .probe          = axnet_probe,
        .remove         = axnet_detach,
        .id_table       = axnet_ids,
        .suspend        = axnet_suspend,
index 2827a48..441de82 100644 (file)
@@ -118,8 +118,8 @@ MODULE_LICENSE("GPL");
 
 /*====================================================================*/
 
-static void com20020_config(dev_link_t *link);
-static void com20020_release(dev_link_t *link);
+static int com20020_config(struct pcmcia_device *link);
+static void com20020_release(struct pcmcia_device *link);
 
 static void com20020_detach(struct pcmcia_device *p_dev);
 
@@ -138,9 +138,8 @@ typedef struct com20020_dev_t {
 
 ======================================================================*/
 
-static int com20020_attach(struct pcmcia_device *p_dev)
+static int com20020_probe(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link;
     com20020_dev_t *info;
     struct net_device *dev;
     struct arcnet_local *lp;
@@ -148,10 +147,6 @@ static int com20020_attach(struct pcmcia_device *p_dev)
     DEBUG(0, "com20020_attach()\n");
 
     /* Create new network device */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    if (!link)
-       return -ENOMEM;
-
     info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
     if (!info)
        goto fail_alloc_info;
@@ -161,7 +156,6 @@ static int com20020_attach(struct pcmcia_device *p_dev)
        goto fail_alloc_dev;
 
     memset(info, 0, sizeof(struct com20020_dev_t));
-    memset(link, 0, sizeof(struct dev_link_t));
     lp = dev->priv;
     lp->timeout = timeout;
     lp->backplane = backplane;
@@ -172,28 +166,23 @@ static int com20020_attach(struct pcmcia_device *p_dev)
     /* fill in our module parameters as defaults */
     dev->dev_addr[0] = node;
 
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.NumPorts1 = 16;
-    link->io.IOAddrLines = 16;
-    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.Present = PRESENT_OPTION;
-
-    link->irq.Instance = info->dev = dev;
-    link->priv = info;
+    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+    p_dev->io.NumPorts1 = 16;
+    p_dev->io.IOAddrLines = 16;
+    p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->conf.IntType = INT_MEMORY_AND_IO;
+    p_dev->conf.Present = PRESENT_OPTION;
 
-    link->state |= DEV_PRESENT;
-    com20020_config(link);
+    p_dev->irq.Instance = info->dev = dev;
+    p_dev->priv = info;
 
-    return 0;
+    return com20020_config(p_dev);
 
 fail_alloc_dev:
     kfree(info);
 fail_alloc_info:
-    kfree(link);
     return -ENOMEM;
 } /* com20020_attach */
 
@@ -206,9 +195,8 @@ fail_alloc_info:
 
 ======================================================================*/
 
-static void com20020_detach(struct pcmcia_device *p_dev)
+static void com20020_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct com20020_dev_t *info = link->priv;
     struct net_device *dev = info->dev;
 
@@ -216,7 +204,7 @@ static void com20020_detach(struct pcmcia_device *p_dev)
 
     DEBUG(0, "com20020_detach(0x%p)\n", link);
 
-    if (link->dev) {
+    if (link->dev_node) {
        DEBUG(1,"unregister...\n");
 
        unregister_netdev(dev);
@@ -229,8 +217,7 @@ static void com20020_detach(struct pcmcia_device *p_dev)
            free_irq(dev->irq, dev);
     }
 
-    if (link->state & DEV_CONFIG)
-        com20020_release(link);
+    com20020_release(link);
 
     /* Unlink device structure, free bits */
     DEBUG(1,"unlinking...\n");
@@ -245,8 +232,6 @@ static void com20020_detach(struct pcmcia_device *p_dev)
        DEBUG(1,"kfree2...\n");
        kfree(info);
     }
-    DEBUG(1,"kfree3...\n");
-    kfree(link);
 
 } /* com20020_detach */
 
@@ -261,10 +246,9 @@ static void com20020_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void com20020_config(dev_link_t *link)
+static int com20020_config(struct pcmcia_device *link)
 {
     struct arcnet_local *lp;
-    client_handle_t handle;
     tuple_t tuple;
     cisparse_t parse;
     com20020_dev_t *info;
@@ -273,7 +257,6 @@ static void com20020_config(dev_link_t *link)
     u_char buf[64];
     int ioaddr;
 
-    handle = link->handle;
     info = link->priv;
     dev = info->dev;
 
@@ -286,14 +269,11 @@ static void com20020_config(dev_link_t *link)
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
     i = !CS_SUCCESS;
     if (!link->io.BasePort1)
@@ -301,13 +281,13 @@ static void com20020_config(dev_link_t *link)
        for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
        {
            link->io.BasePort1 = ioaddr;
-           i = pcmcia_request_io(link->handle, &link->io);
+           i = pcmcia_request_io(link, &link->io);
            if (i == CS_SUCCESS)
                break;
        }
     }
     else
-       i = pcmcia_request_io(link->handle, &link->io);
+       i = pcmcia_request_io(link, &link->io);
     
     if (i != CS_SUCCESS)
     {
@@ -321,7 +301,7 @@ static void com20020_config(dev_link_t *link)
     DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
           link->irq.AssignedIRQ,
           link->irq.IRQInfo1, link->irq.IRQInfo2);
-    i = pcmcia_request_irq(link->handle, &link->irq);
+    i = pcmcia_request_irq(link, &link->irq);
     if (i != CS_SUCCESS)
     {
        DEBUG(1,"arcnet: requestIRQ failed totally!\n");
@@ -330,7 +310,7 @@ static void com20020_config(dev_link_t *link)
 
     dev->irq = link->irq.AssignedIRQ;
 
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     if (com20020_check(dev))
     {
@@ -342,15 +322,14 @@ static void com20020_config(dev_link_t *link)
     lp->card_name = "PCMCIA COM20020";
     lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
 
-    link->dev = &info->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &info->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     i = com20020_found(dev, 0);        /* calls register_netdev */
     
     if (i != 0) {
        DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
-       link->dev = NULL;
+       link->dev_node = NULL;
        goto failed;
     }
 
@@ -358,13 +337,14 @@ static void com20020_config(dev_link_t *link)
 
     DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
            dev->name, dev->base_addr, dev->irq);
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     DEBUG(1,"com20020_config failed...\n");
     com20020_release(link);
+    return -ENODEV;
 } /* com20020_config */
 
 /*======================================================================
@@ -375,52 +355,33 @@ failed:
 
 ======================================================================*/
 
-static void com20020_release(dev_link_t *link)
+static void com20020_release(struct pcmcia_device *link)
 {
-
-    DEBUG(1,"release...\n");
-
-    DEBUG(0, "com20020_release(0x%p)\n", link);
-
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-
-    link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+       DEBUG(0, "com20020_release(0x%p)\n", link);
+       pcmcia_disable_device(link);
 }
 
-static int com20020_suspend(struct pcmcia_device *p_dev)
+static int com20020_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        com20020_dev_t *info = link->priv;
        struct net_device *dev = info->dev;
 
-       link->state |= DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-               if (link->open) {
-                       netif_device_detach(dev);
-               }
-               pcmcia_release_configuration(link->handle);
-        }
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int com20020_resume(struct pcmcia_device *p_dev)
+static int com20020_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        com20020_dev_t *info = link->priv;
        struct net_device *dev = info->dev;
 
-       link->state &= ~DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       int ioaddr = dev->base_addr;
-                       struct arcnet_local *lp = dev->priv;
-                       ARCRESET;
-               }
-        }
+       if (link->open) {
+               int ioaddr = dev->base_addr;
+               struct arcnet_local *lp = dev->priv;
+               ARCRESET;
+       }
 
        return 0;
 }
@@ -436,7 +397,7 @@ static struct pcmcia_driver com20020_cs_driver = {
        .drv            = {
                .name   = "com20020_cs",
        },
-       .probe          = com20020_attach,
+       .probe          = com20020_probe,
        .remove         = com20020_detach,
        .id_table       = com20020_ids,
        .suspend        = com20020_suspend,
index b7ac14b..09b1176 100644 (file)
@@ -84,10 +84,10 @@ static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23";
 /*
     PCMCIA event handlers
  */
-static void fmvj18x_config(dev_link_t *link);
-static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id);
-static int fmvj18x_setup_mfc(dev_link_t *link);
-static void fmvj18x_release(dev_link_t *link);
+static int fmvj18x_config(struct pcmcia_device *link);
+static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id);
+static int fmvj18x_setup_mfc(struct pcmcia_device *link);
+static void fmvj18x_release(struct pcmcia_device *link);
 static void fmvj18x_detach(struct pcmcia_device *p_dev);
 
 /*
@@ -116,7 +116,7 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
     driver specific data structure
 */
 typedef struct local_info_t {
-    dev_link_t link;
+       struct pcmcia_device    *p_dev;
     dev_node_t node;
     struct net_device_stats stats;
     long open_time;
@@ -228,10 +228,9 @@ typedef struct local_info_t {
 #define BANK_1U              0x24 /* bank 1 (CONFIG_1) */
 #define BANK_2U              0x28 /* bank 2 (CONFIG_1) */
 
-static int fmvj18x_attach(struct pcmcia_device *p_dev)
+static int fmvj18x_probe(struct pcmcia_device *link)
 {
     local_info_t *lp;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "fmvj18x_attach()\n");
@@ -241,8 +240,8 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev)
     if (!dev)
        return -ENOMEM;
     lp = netdev_priv(dev);
-    link = &lp->link;
     link->priv = dev;
+    lp->p_dev = link;
 
     /* The io structure describes IO port mapping */
     link->io.NumPorts1 = 32;
@@ -257,7 +256,6 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev)
 
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
     /* The FMVJ18x specific entries in the device structure. */
@@ -274,29 +272,21 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev)
 #endif
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    fmvj18x_config(link);
-
-    return 0;
+    return fmvj18x_config(link);
 } /* fmvj18x_attach */
 
 /*====================================================================*/
 
-static void fmvj18x_detach(struct pcmcia_device *p_dev)
+static void fmvj18x_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
        unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-       fmvj18x_release(link);
+    fmvj18x_release(link);
 
     free_netdev(dev);
 } /* fmvj18x_detach */
@@ -306,7 +296,7 @@ static void fmvj18x_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static int mfc_try_io_port(dev_link_t *link)
+static int mfc_try_io_port(struct pcmcia_device *link)
 {
     int i, ret;
     static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
@@ -318,13 +308,13 @@ static int mfc_try_io_port(dev_link_t *link)
            link->io.NumPorts2 = 0;
            printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
        }
-       ret = pcmcia_request_io(link->handle, &link->io);
+       ret = pcmcia_request_io(link, &link->io);
        if (ret == CS_SUCCESS) return ret;
     }
     return ret;
 }
 
-static int ungermann_try_io_port(dev_link_t *link)
+static int ungermann_try_io_port(struct pcmcia_device *link)
 {
     int ret;
     kio_addr_t ioaddr;
@@ -334,7 +324,7 @@ static int ungermann_try_io_port(dev_link_t *link)
     */
     for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
        link->io.BasePort1 = ioaddr;
-       ret = pcmcia_request_io(link->handle, &link->io);
+       ret = pcmcia_request_io(link, &link->io);
        if (ret == CS_SUCCESS) {
            /* calculate ConfigIndex value */
            link->conf.ConfigIndex = 
@@ -345,9 +335,8 @@ static int ungermann_try_io_port(dev_link_t *link)
     return ret;        /* RequestIO failed */
 }
 
-static void fmvj18x_config(dev_link_t *link)
+static int fmvj18x_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     local_info_t *lp = netdev_priv(dev);
     tuple_t tuple;
@@ -366,42 +355,34 @@ static void fmvj18x_config(dev_link_t *link)
        registers.
     */
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     tuple.TupleData = (u_char *)buf;
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 
     link->conf.ConfigBase = parse.config.base; 
     link->conf.Present = parse.config.rmask[0];
 
     tuple.DesiredTuple = CISTPL_FUNCE;
     tuple.TupleOffset = 0;
-    if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
+    if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
        /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigIndex = parse.cftable_entry.index;
        tuple.DesiredTuple = CISTPL_MANFID;
-       if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS)
-           CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+       if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
+           CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
        else
            buf[0] = 0xffff;
        switch (le16_to_cpu(buf[0])) {
        case MANFID_TDK:
            cardtype = TDK;
-           if (le16_to_cpu(buf[1]) == PRODID_TDK_CF010) {
-               cs_status_t status;
-               pcmcia_get_status(handle, &status);
-               if (status.CardState & CS_EVENT_3VCARD)
-                   link->conf.Vcc = 33; /* inserted in 3.3V slot */
-           } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
+           if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
                        || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610
                        || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) {
                /* MultiFunction Card */
@@ -429,8 +410,8 @@ static void fmvj18x_config(dev_link_t *link)
     } else {
        /* old type card */
        tuple.DesiredTuple = CISTPL_MANFID;
-       if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS)
-           CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+       if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
+           CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
        else
            buf[0] = 0xffff;
        switch (le16_to_cpu(buf[0])) {
@@ -461,10 +442,10 @@ static void fmvj18x_config(dev_link_t *link)
        ret = ungermann_try_io_port(link);
        if (ret != CS_SUCCESS) goto cs_failed;
     } else { 
-       CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+       CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
     }
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
 
@@ -493,17 +474,17 @@ static void fmvj18x_config(dev_link_t *link)
     case CONTEC:
        tuple.DesiredTuple = CISTPL_FUNCE;
        tuple.TupleOffset = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        tuple.TupleOffset = 0;
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
        if (cardtype == MBH10304) {
            /* MBH10304's CIS_FUNCE is corrupted */
            node_id = &(tuple.TupleData[5]);
            card_name = "FMV-J182";
        } else {
            while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) {
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
-               CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+               CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
            }
            node_id = &(tuple.TupleData[2]);
            if( cardtype == TDK ) {
@@ -545,13 +526,12 @@ static void fmvj18x_config(dev_link_t *link)
     }
 
     lp->cardtype = cardtype;
-    link->dev = &lp->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &lp->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if (register_netdev(dev) != 0) {
        printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
-       link->dev = NULL;
+       link->dev_node = NULL;
        goto failed;
     }
 
@@ -564,19 +544,18 @@ static void fmvj18x_config(dev_link_t *link)
     for (i = 0; i < 6; i++)
        printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
 
-    return;
+    return 0;
     
 cs_failed:
     /* All Card Services errors end up here */
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     fmvj18x_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
-
+    return -ENODEV;
 } /* fmvj18x_config */
 /*====================================================================*/
 
-static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
+static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 {
     win_req_t req;
     memreq_t mem;
@@ -587,9 +566,9 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
     req.Base = 0; req.Size = 0;
     req.AccessSpeed = 0;
-    i = pcmcia_request_window(&link->handle, &req, &link->win);
+    i = pcmcia_request_window(&link, &req, &link->win);
     if (i != CS_SUCCESS) {
-       cs_error(link->handle, RequestWindow, i);
+       cs_error(link, RequestWindow, i);
        return -1;
     }
 
@@ -623,13 +602,13 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
     iounmap(base);
     j = pcmcia_release_window(link->win);
     if (j != CS_SUCCESS)
-       cs_error(link->handle, ReleaseWindow, j);
+       cs_error(link, ReleaseWindow, j);
     return (i != 0x200) ? 0 : -1;
 
 } /* fmvj18x_get_hwinfo */
 /*====================================================================*/
 
-static int fmvj18x_setup_mfc(dev_link_t *link)
+static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 {
     win_req_t req;
     memreq_t mem;
@@ -642,9 +621,9 @@ static int fmvj18x_setup_mfc(dev_link_t *link)
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
     req.Base = 0; req.Size = 0;
     req.AccessSpeed = 0;
-    i = pcmcia_request_window(&link->handle, &req, &link->win);
+    i = pcmcia_request_window(&link, &req, &link->win);
     if (i != CS_SUCCESS) {
-       cs_error(link->handle, RequestWindow, i);
+       cs_error(link, RequestWindow, i);
        return -1;
     }
 
@@ -666,54 +645,35 @@ static int fmvj18x_setup_mfc(dev_link_t *link)
     iounmap(base);
     j = pcmcia_release_window(link->win);
     if (j != CS_SUCCESS)
-       cs_error(link->handle, ReleaseWindow, j);
+       cs_error(link, ReleaseWindow, j);
     return 0;
 
 }
 /*====================================================================*/
 
-static void fmvj18x_release(dev_link_t *link)
+static void fmvj18x_release(struct pcmcia_device *link)
 {
-
-    DEBUG(0, "fmvj18x_release(0x%p)\n", link);
-
-    /* Don't bother checking to see if these succeed or not */
-    pcmcia_release_window(link->win);
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    
-    link->state &= ~DEV_CONFIG;
+       DEBUG(0, "fmvj18x_release(0x%p)\n", link);
+       pcmcia_disable_device(link);
 }
 
-static int fmvj18x_suspend(struct pcmcia_device *p_dev)
+static int fmvj18x_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-       }
-
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int fmvj18x_resume(struct pcmcia_device *p_dev)
+static int fmvj18x_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       fjn_reset(dev);
-                       netif_device_attach(dev);
-               }
+       if (link->open) {
+               fjn_reset(dev);
+               netif_device_attach(dev);
        }
 
        return 0;
@@ -751,7 +711,7 @@ static struct pcmcia_driver fmvj18x_cs_driver = {
        .drv            = {
                .name   = "fmvj18x_cs",
        },
-       .probe          = fmvj18x_attach,
+       .probe          = fmvj18x_probe,
        .remove         = fmvj18x_detach,
        .id_table       = fmvj18x_ids,
        .suspend        = fmvj18x_suspend,
@@ -1148,11 +1108,11 @@ static int fjn_config(struct net_device *dev, struct ifmap *map){
 static int fjn_open(struct net_device *dev)
 {
     struct local_info_t *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
 
     DEBUG(4, "fjn_open('%s').\n", dev->name);
 
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
        return -ENODEV;
     
     link->open++;
@@ -1173,7 +1133,7 @@ static int fjn_open(struct net_device *dev)
 static int fjn_close(struct net_device *dev)
 {
     struct local_info_t *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
     kio_addr_t ioaddr = dev->base_addr;
 
     DEBUG(4, "fjn_close('%s').\n", dev->name);
index b9c7e39..b8fe70b 100644 (file)
@@ -105,15 +105,15 @@ MODULE_LICENSE("GPL");
 
 /*====================================================================*/
 
-static void ibmtr_config(dev_link_t *link);
+static int ibmtr_config(struct pcmcia_device *link);
 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
-static void ibmtr_release(dev_link_t *link);
+static void ibmtr_release(struct pcmcia_device *link);
 static void ibmtr_detach(struct pcmcia_device *p_dev);
 
 /*====================================================================*/
 
 typedef struct ibmtr_dev_t {
-    dev_link_t         link;
+       struct pcmcia_device    *p_dev;
     struct net_device  *dev;
     dev_node_t          node;
     window_handle_t     sram_win_handle;
@@ -138,12 +138,11 @@ static struct ethtool_ops netdev_ethtool_ops = {
 
 ======================================================================*/
 
-static int ibmtr_attach(struct pcmcia_device *p_dev)
+static int ibmtr_attach(struct pcmcia_device *link)
 {
     ibmtr_dev_t *info;
-    dev_link_t *link;
     struct net_device *dev;
-    
+
     DEBUG(0, "ibmtr_attach()\n");
 
     /* Create new token-ring device */
@@ -156,7 +155,7 @@ static int ibmtr_attach(struct pcmcia_device *p_dev)
        return -ENOMEM;
     }
 
-    link = &info->link;
+    info->p_dev = link;
     link->priv = info;
     info->ti = netdev_priv(dev);
 
@@ -167,21 +166,14 @@ static int ibmtr_attach(struct pcmcia_device *p_dev)
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->irq.Handler = &tok_interrupt;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
 
     link->irq.Instance = info->dev = dev;
-    
-    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-
-    link->handle = p_dev;
-    p_dev->instance = link;
 
-    link->state |= DEV_PRESENT;
-    ibmtr_config(link);
+    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    return 0;
+    return ibmtr_config(link);
 } /* ibmtr_attach */
 
 /*======================================================================
@@ -193,23 +185,22 @@ static int ibmtr_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void ibmtr_detach(struct pcmcia_device *p_dev)
+static void ibmtr_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct ibmtr_dev_t *info = link->priv;
     struct net_device *dev = info->dev;
 
     DEBUG(0, "ibmtr_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
        unregister_netdev(dev);
 
     {
        struct tok_info *ti = netdev_priv(dev);
        del_timer_sync(&(ti->tr_timer));
     }
-    if (link->state & DEV_CONFIG)
-        ibmtr_release(link);
+
+    ibmtr_release(link);
 
     free_netdev(dev);
     kfree(info);
@@ -226,9 +217,8 @@ static void ibmtr_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void ibmtr_config(dev_link_t *link)
+static int ibmtr_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     ibmtr_dev_t *info = link->priv;
     struct net_device *dev = info->dev;
     struct tok_info *ti = netdev_priv(dev);
@@ -246,29 +236,25 @@ static void ibmtr_config(dev_link_t *link)
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
-
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     link->conf.ConfigIndex = 0x61;
 
     /* Determine if this is PRIMARY or ALTERNATE. */
 
     /* Try PRIMARY card at 0xA20-0xA23 */
     link->io.BasePort1 = 0xA20;
-    i = pcmcia_request_io(link->handle, &link->io);
+    i = pcmcia_request_io(link, &link->io);
     if (i != CS_SUCCESS) {
        /* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
        link->io.BasePort1 = 0xA24;
-       CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+       CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
     }
     dev->base_addr = link->io.BasePort1;
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     dev->irq = link->irq.AssignedIRQ;
     ti->irq = link->irq.AssignedIRQ;
     ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
@@ -279,7 +265,7 @@ static void ibmtr_config(dev_link_t *link)
     req.Base = 0; 
     req.Size = 0x2000;
     req.AccessSpeed = 250;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
 
     mem.CardOffset = mmiobase;
     mem.Page = 0;
@@ -292,7 +278,7 @@ static void ibmtr_config(dev_link_t *link)
     req.Base = 0;
     req.Size = sramsize * 1024;
     req.AccessSpeed = 250;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &info->sram_win_handle));
 
     mem.CardOffset = srambase;
     mem.Page = 0;
@@ -302,21 +288,20 @@ static void ibmtr_config(dev_link_t *link)
     ti->sram_virt = ioremap(req.Base, req.Size);
     ti->sram_phys = req.Base;
 
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     /*  Set up the Token-Ring Controller Configuration Register and
         turn on the card.  Check the "Local Area Network Credit Card
         Adapters Technical Reference"  SC30-3585 for this info.  */
     ibmtr_hw_setup(dev, mmiobase);
 
-    link->dev = &info->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &info->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     i = ibmtr_probe_card(dev);
     if (i != 0) {
        printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
-       link->dev = NULL;
+       link->dev_node = NULL;
        goto failed;
     }
 
@@ -330,12 +315,13 @@ static void ibmtr_config(dev_link_t *link)
     for (i = 0; i < TR_ALEN; i++)
         printk("%02X", dev->dev_addr[i]);
     printk("\n");
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     ibmtr_release(link);
+    return -ENODEV;
 } /* ibmtr_config */
 
 /*======================================================================
@@ -346,56 +332,41 @@ failed:
 
 ======================================================================*/
 
-static void ibmtr_release(dev_link_t *link)
+static void ibmtr_release(struct pcmcia_device *link)
 {
-    ibmtr_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
-
-    DEBUG(0, "ibmtr_release(0x%p)\n", link);
+       ibmtr_dev_t *info = link->priv;
+       struct net_device *dev = info->dev;
 
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    if (link->win) {
-       struct tok_info *ti = netdev_priv(dev);
-       iounmap(ti->mmio);
-       pcmcia_release_window(link->win);
-       pcmcia_release_window(info->sram_win_handle);
-    }
+       DEBUG(0, "ibmtr_release(0x%p)\n", link);
 
-    link->state &= ~DEV_CONFIG;
+       if (link->win) {
+               struct tok_info *ti = netdev_priv(dev);
+               iounmap(ti->mmio);
+               pcmcia_release_window(info->sram_win_handle);
+       }
+       pcmcia_disable_device(link);
 }
 
-static int ibmtr_suspend(struct pcmcia_device *p_dev)
+static int ibmtr_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        ibmtr_dev_t *info = link->priv;
        struct net_device *dev = info->dev;
 
-       link->state |= DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-        }
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int ibmtr_resume(struct pcmcia_device *p_dev)
+static int ibmtr_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        ibmtr_dev_t *info = link->priv;
        struct net_device *dev = info->dev;
 
-       link->state &= ~DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       ibmtr_probe(dev);       /* really? */
-                       netif_device_attach(dev);
-               }
-        }
+       if (link->open) {
+               ibmtr_probe(dev);       /* really? */
+               netif_device_attach(dev);
+       }
 
        return 0;
 }
index 787176c..4260c21 100644 (file)
@@ -362,7 +362,7 @@ typedef struct _mace_statistics {
 } mace_statistics;
 
 typedef struct _mace_private {
-    dev_link_t link;
+       struct pcmcia_device    *p_dev;
     dev_node_t node;
     struct net_device_stats linux_stats; /* Linux statistics counters */
     mace_statistics mace_stats; /* MACE chip statistics counters */
@@ -417,8 +417,8 @@ INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
 Function Prototypes
 ---------------------------------------------------------------------------- */
 
-static void nmclan_config(dev_link_t *link);
-static void nmclan_release(dev_link_t *link);
+static int nmclan_config(struct pcmcia_device *link);
+static void nmclan_release(struct pcmcia_device *link);
 
 static void nmclan_reset(struct net_device *dev);
 static int mace_config(struct net_device *dev, struct ifmap *map);
@@ -443,10 +443,9 @@ nmclan_attach
        Services.
 ---------------------------------------------------------------------------- */
 
-static int nmclan_attach(struct pcmcia_device *p_dev)
+static int nmclan_probe(struct pcmcia_device *link)
 {
     mace_private *lp;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "nmclan_attach()\n");
@@ -457,7 +456,7 @@ static int nmclan_attach(struct pcmcia_device *p_dev)
     if (!dev)
            return -ENOMEM;
     lp = netdev_priv(dev);
-    link = &lp->link;
+    lp->p_dev = link;
     link->priv = dev;
     
     spin_lock_init(&lp->bank_lock);
@@ -469,7 +468,6 @@ static int nmclan_attach(struct pcmcia_device *p_dev)
     link->irq.Handler = &mace_interrupt;
     link->irq.Instance = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
@@ -489,13 +487,7 @@ static int nmclan_attach(struct pcmcia_device *p_dev)
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    nmclan_config(link);
-
-    return 0;
+    return nmclan_config(link);
 } /* nmclan_attach */
 
 /* ----------------------------------------------------------------------------
@@ -506,18 +498,16 @@ nmclan_detach
        when the device is released.
 ---------------------------------------------------------------------------- */
 
-static void nmclan_detach(struct pcmcia_device *p_dev)
+static void nmclan_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "nmclan_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
        unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-       nmclan_release(link);
+    nmclan_release(link);
 
     free_netdev(dev);
 } /* nmclan_detach */
@@ -661,9 +651,8 @@ nmclan_config
 #define CS_CHECK(fn, ret) \
   do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void nmclan_config(dev_link_t *link)
+static int nmclan_config(struct pcmcia_device *link)
 {
-  client_handle_t handle = link->handle;
   struct net_device *dev = link->priv;
   mace_private *lp = netdev_priv(dev);
   tuple_t tuple;
@@ -679,17 +668,14 @@ static void nmclan_config(dev_link_t *link)
   tuple.TupleDataMax = 64;
   tuple.TupleOffset = 0;
   tuple.DesiredTuple = CISTPL_CONFIG;
-  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-  CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+  CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
   link->conf.ConfigBase = parse.config.base;
 
-  /* Configure card */
-  link->state |= DEV_CONFIG;
-
-  CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
-  CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-  CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+  CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+  CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+  CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
   dev->irq = link->irq.AssignedIRQ;
   dev->base_addr = link->io.BasePort1;
 
@@ -700,8 +686,8 @@ static void nmclan_config(dev_link_t *link)
   tuple.TupleData = buf;
   tuple.TupleDataMax = 64;
   tuple.TupleOffset = 0;
-  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
   memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN);
 
   /* Verify configuration by reading the MACE ID. */
@@ -716,8 +702,7 @@ static void nmclan_config(dev_link_t *link)
     } else {
       printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should"
             " be 0x40 0x?9\n", sig[0], sig[1]);
-      link->state &= ~DEV_CONFIG_PENDING;
-      return;
+      return -ENODEV;
     }
   }
 
@@ -730,14 +715,13 @@ static void nmclan_config(dev_link_t *link)
   else
     printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
 
-  link->dev = &lp->node;
-  link->state &= ~DEV_CONFIG_PENDING;
-  SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+  link->dev_node = &lp->node;
+  SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
   i = register_netdev(dev);
   if (i != 0) {
     printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
-    link->dev = NULL;
+    link->dev_node = NULL;
     goto failed;
   }
 
@@ -747,14 +731,13 @@ static void nmclan_config(dev_link_t *link)
         dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]);
   for (i = 0; i < 6; i++)
       printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
-  return;
+  return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 failed:
-    nmclan_release(link);
-    return;
-
+       nmclan_release(link);
+       return -ENODEV;
 } /* nmclan_config */
 
 /* ----------------------------------------------------------------------------
@@ -763,46 +746,29 @@ nmclan_release
        net device, and release the PCMCIA configuration.  If the device
        is still open, this will be postponed until it is closed.
 ---------------------------------------------------------------------------- */
-static void nmclan_release(dev_link_t *link)
+static void nmclan_release(struct pcmcia_device *link)
 {
-
-  DEBUG(0, "nmclan_release(0x%p)\n", link);
-
-  pcmcia_release_configuration(link->handle);
-  pcmcia_release_io(link->handle, &link->io);
-  pcmcia_release_irq(link->handle, &link->irq);
-
-  link->state &= ~DEV_CONFIG;
+       DEBUG(0, "nmclan_release(0x%p)\n", link);
+       pcmcia_disable_device(link);
 }
 
-static int nmclan_suspend(struct pcmcia_device *p_dev)
+static int nmclan_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-       }
-
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int nmclan_resume(struct pcmcia_device *p_dev)
+static int nmclan_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       nmclan_reset(dev);
-                       netif_device_attach(dev);
-               }
+       if (link->open) {
+               nmclan_reset(dev);
+               netif_device_attach(dev);
        }
 
        return 0;
@@ -818,7 +784,7 @@ static void nmclan_reset(struct net_device *dev)
   mace_private *lp = netdev_priv(dev);
 
 #if RESET_XILINX
-  dev_link_t *link = &lp->link;
+  struct pcmcia_device *link = &lp->link;
   conf_reg_t reg;
   u_long OrigCorValue; 
 
@@ -827,7 +793,7 @@ static void nmclan_reset(struct net_device *dev)
   reg.Action = CS_READ;
   reg.Offset = CISREG_COR;
   reg.Value = 0;
-  pcmcia_access_configuration_register(link->handle, &reg);
+  pcmcia_access_configuration_register(link, &reg);
   OrigCorValue = reg.Value;
 
   /* Reset Xilinx */
@@ -836,12 +802,12 @@ static void nmclan_reset(struct net_device *dev)
   DEBUG(1, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n",
        OrigCorValue);
   reg.Value = COR_SOFT_RESET;
-  pcmcia_access_configuration_register(link->handle, &reg);
+  pcmcia_access_configuration_register(link, &reg);
   /* Need to wait for 20 ms for PCMCIA to finish reset. */
 
   /* Restore original COR configuration index */
   reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK);
-  pcmcia_access_configuration_register(link->handle, &reg);
+  pcmcia_access_configuration_register(link, &reg);
   /* Xilinx is now completely reset along with the MACE chip. */
   lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
 
@@ -885,9 +851,9 @@ static int mace_open(struct net_device *dev)
 {
   kio_addr_t ioaddr = dev->base_addr;
   mace_private *lp = netdev_priv(dev);
-  dev_link_t *link = &lp->link;
+  struct pcmcia_device *link = lp->p_dev;
 
-  if (!DEV_OK(link))
+  if (!pcmcia_dev_present(link))
     return -ENODEV;
 
   link->open++;
@@ -908,7 +874,7 @@ static int mace_close(struct net_device *dev)
 {
   kio_addr_t ioaddr = dev->base_addr;
   mace_private *lp = netdev_priv(dev);
-  dev_link_t *link = &lp->link;
+  struct pcmcia_device *link = lp->p_dev;
 
   DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
 
@@ -963,12 +929,12 @@ mace_start_xmit
 static void mace_tx_timeout(struct net_device *dev)
 {
   mace_private *lp = netdev_priv(dev);
-  dev_link_t *link = &lp->link;
+  struct pcmcia_device *link = lp->p_dev;
 
   printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
 #if RESET_ON_TIMEOUT
   printk("resetting card\n");
-  pcmcia_reset_card(link->handle, NULL);
+  pcmcia_reset_card(link, NULL);
 #else /* #if RESET_ON_TIMEOUT */
   printk("NOT resetting card\n");
 #endif /* #if RESET_ON_TIMEOUT */
@@ -1635,7 +1601,7 @@ static struct pcmcia_driver nmclan_cs_driver = {
        .drv            = {
                .name   = "nmclan_cs",
        },
-       .probe          = nmclan_attach,
+       .probe          = nmclan_probe,
        .remove         = nmclan_detach,
        .id_table       = nmclan_ids,
        .suspend        = nmclan_suspend,
index b46e5f7..506e777 100644 (file)
@@ -103,8 +103,8 @@ module_param_array(hw_addr, int, NULL, 0);
 /*====================================================================*/
 
 static void mii_phy_probe(struct net_device *dev);
-static void pcnet_config(dev_link_t *link);
-static void pcnet_release(dev_link_t *link);
+static int pcnet_config(struct pcmcia_device *link);
+static void pcnet_release(struct pcmcia_device *link);
 static int pcnet_open(struct net_device *dev);
 static int pcnet_close(struct net_device *dev);
 static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -113,9 +113,9 @@ static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs);
 static void ei_watchdog(u_long arg);
 static void pcnet_reset_8390(struct net_device *dev);
 static int set_config(struct net_device *dev, struct ifmap *map);
-static int setup_shmem_window(dev_link_t *link, int start_pg,
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
                              int stop_pg, int cm_offset);
-static int setup_dma_config(dev_link_t *link, int start_pg,
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
                            int stop_pg);
 
 static void pcnet_detach(struct pcmcia_device *p_dev);
@@ -214,7 +214,7 @@ static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
 static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
 
 typedef struct pcnet_dev_t {
-    dev_link_t         link;
+       struct pcmcia_device    *p_dev;
     dev_node_t         node;
     u_int              flags;
     void               __iomem *base;
@@ -240,10 +240,9 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev)
 
 ======================================================================*/
 
-static int pcnet_probe(struct pcmcia_device *p_dev)
+static int pcnet_probe(struct pcmcia_device *link)
 {
     pcnet_dev_t *info;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "pcnet_attach()\n");
@@ -252,7 +251,7 @@ static int pcnet_probe(struct pcmcia_device *p_dev)
     dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
     if (!dev) return -ENOMEM;
     info = PRIV(dev);
-    link = &info->link;
+    info->p_dev = link;
     link->priv = dev;
 
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
@@ -265,13 +264,7 @@ static int pcnet_probe(struct pcmcia_device *p_dev)
     dev->stop = &pcnet_close;
     dev->set_config = &set_config;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    pcnet_config(link);
-
-    return 0;
+    return pcnet_config(link);
 } /* pcnet_attach */
 
 /*======================================================================
@@ -283,18 +276,16 @@ static int pcnet_probe(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void pcnet_detach(struct pcmcia_device *p_dev)
+static void pcnet_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
        DEBUG(0, "pcnet_detach(0x%p)\n", link);
 
-       if (link->dev)
+       if (link->dev_node)
                unregister_netdev(dev);
 
-       if (link->state & DEV_CONFIG)
-               pcnet_release(link);
+       pcnet_release(link);
 
        free_netdev(dev);
 } /* pcnet_detach */
@@ -306,7 +297,7 @@ static void pcnet_detach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static hw_info_t *get_hwinfo(dev_link_t *link)
+static hw_info_t *get_hwinfo(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     win_req_t req;
@@ -318,9 +309,9 @@ static hw_info_t *get_hwinfo(dev_link_t *link)
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
     req.Base = 0; req.Size = 0;
     req.AccessSpeed = 0;
-    i = pcmcia_request_window(&link->handle, &req, &link->win);
+    i = pcmcia_request_window(&link, &req, &link->win);
     if (i != CS_SUCCESS) {
-       cs_error(link->handle, RequestWindow, i);
+       cs_error(link, RequestWindow, i);
        return NULL;
     }
 
@@ -343,7 +334,7 @@ static hw_info_t *get_hwinfo(dev_link_t *link)
     iounmap(virt);
     j = pcmcia_release_window(link->win);
     if (j != CS_SUCCESS)
-       cs_error(link->handle, ReleaseWindow, j);
+       cs_error(link, ReleaseWindow, j);
     return (i < NR_INFO) ? hw_info+i : NULL;
 } /* get_hwinfo */
 
@@ -355,7 +346,7 @@ static hw_info_t *get_hwinfo(dev_link_t *link)
 
 ======================================================================*/
 
-static hw_info_t *get_prom(dev_link_t *link)
+static hw_info_t *get_prom(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     kio_addr_t ioaddr = dev->base_addr;
@@ -409,7 +400,7 @@ static hw_info_t *get_prom(dev_link_t *link)
 
 ======================================================================*/
 
-static hw_info_t *get_dl10019(dev_link_t *link)
+static hw_info_t *get_dl10019(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     int i;
@@ -431,7 +422,7 @@ static hw_info_t *get_dl10019(dev_link_t *link)
 
 ======================================================================*/
 
-static hw_info_t *get_ax88190(dev_link_t *link)
+static hw_info_t *get_ax88190(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     kio_addr_t ioaddr = dev->base_addr;
@@ -464,7 +455,7 @@ static hw_info_t *get_ax88190(dev_link_t *link)
 
 ======================================================================*/
 
-static hw_info_t *get_hwired(dev_link_t *link)
+static hw_info_t *get_hwired(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     int i;
@@ -491,7 +482,7 @@ static hw_info_t *get_hwired(dev_link_t *link)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static int try_io_port(dev_link_t *link)
+static int try_io_port(struct pcmcia_device *link)
 {
     int j, ret;
     if (link->io.NumPorts1 == 32) {
@@ -512,18 +503,17 @@ static int try_io_port(dev_link_t *link)
        for (j = 0; j < 0x400; j += 0x20) {
            link->io.BasePort1 = j ^ 0x300;
            link->io.BasePort2 = (j ^ 0x300) + 0x10;
-           ret = pcmcia_request_io(link->handle, &link->io);
+           ret = pcmcia_request_io(link, &link->io);
            if (ret == CS_SUCCESS) return ret;
        }
        return ret;
     } else {
-       return pcmcia_request_io(link->handle, &link->io);
+       return pcmcia_request_io(link, &link->io);
     }
 }
 
-static void pcnet_config(dev_link_t *link)
+static int pcnet_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     pcnet_dev_t *info = PRIV(dev);
     tuple_t tuple;
@@ -531,7 +521,6 @@ static void pcnet_config(dev_link_t *link)
     int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
     int manfid = 0, prodid = 0, has_shmem = 0;
     u_short buf[64];
-    config_info_t conf;
     hw_info_t *hw_info;
 
     DEBUG(0, "pcnet_config(0x%p)\n", link);
@@ -541,36 +530,29 @@ static void pcnet_config(dev_link_t *link)
     tuple.TupleDataMax = sizeof(buf);
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
-    /* Look up current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-    link->conf.Vcc = conf.Vcc;
-
     tuple.DesiredTuple = CISTPL_MANFID;
     tuple.Attributes = TUPLE_RETURN_COMMON;
-    if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
-       (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) {
+    if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+       (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) {
        manfid = le16_to_cpu(buf[0]);
        prodid = le16_to_cpu(buf[1]);
     }
     
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
     tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (last_ret == CS_SUCCESS) {
        cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
        cistpl_io_t *io = &(parse.cftable_entry.io);
        
-       if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-                       pcmcia_parse_tuple(handle, &tuple, &parse) != 0 ||
+       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+                       pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
                        cfg->index == 0 || cfg->io.nwin == 0)
                goto next_entry;
        
@@ -594,14 +576,14 @@ static void pcnet_config(dev_link_t *link)
            if (last_ret == CS_SUCCESS) break;
        }
     next_entry:
-       last_ret = pcmcia_get_next_tuple(handle, &tuple);
+       last_ret = pcmcia_get_next_tuple(link, &tuple);
     }
     if (last_ret != CS_SUCCESS) {
-       cs_error(handle, RequestIO, last_ret);
+       cs_error(link, RequestIO, last_ret);
        goto failed;
     }
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     
     if (link->io.NumPorts2 == 8) {
        link->conf.Attributes |= CONF_ENABLE_SPKR;
@@ -611,7 +593,7 @@ static void pcnet_config(dev_link_t *link)
        (prodid == PRODID_IBM_HOME_AND_AWAY))
        link->conf.ConfigIndex |= 0x10;
     
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
     if (info->flags & HAS_MISC_REG) {
@@ -679,9 +661,8 @@ static void pcnet_config(dev_link_t *link)
            info->eth_phy = 0;
     }
 
-    link->dev = &info->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &info->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
     dev->poll_controller = ei_poll;
@@ -689,7 +670,7 @@ static void pcnet_config(dev_link_t *link)
 
     if (register_netdev(dev) != 0) {
        printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n");
-       link->dev = NULL;
+       link->dev_node = NULL;
        goto failed;
     }
 
@@ -712,14 +693,13 @@ static void pcnet_config(dev_link_t *link)
     printk(" hw_addr ");
     for (i = 0; i < 6; i++)
        printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     pcnet_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
+    return -ENODEV;
 } /* pcnet_config */
 
 /*======================================================================
@@ -730,21 +710,16 @@ failed:
 
 ======================================================================*/
 
-static void pcnet_release(dev_link_t *link)
+static void pcnet_release(struct pcmcia_device *link)
 {
-    pcnet_dev_t *info = PRIV(link->priv);
+       pcnet_dev_t *info = PRIV(link->priv);
 
-    DEBUG(0, "pcnet_release(0x%p)\n", link);
+       DEBUG(0, "pcnet_release(0x%p)\n", link);
 
-    if (info->flags & USE_SHMEM) {
-       iounmap(info->base);
-       pcmcia_release_window(link->win);
-    }
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
+       if (info->flags & USE_SHMEM)
+               iounmap(info->base);
 
-    link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
 }
 
 /*======================================================================
@@ -756,34 +731,24 @@ static void pcnet_release(dev_link_t *link)
 
 ======================================================================*/
 
-static int pcnet_suspend(struct pcmcia_device *p_dev)
+static int pcnet_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-       }
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int pcnet_resume(struct pcmcia_device *p_dev)
+static int pcnet_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       pcnet_reset_8390(dev);
-                       NS8390_init(dev, 1);
-                       netif_device_attach(dev);
-               }
+       if (link->open) {
+               pcnet_reset_8390(dev);
+               NS8390_init(dev, 1);
+               netif_device_attach(dev);
        }
 
        return 0;
@@ -1023,11 +988,11 @@ static void mii_phy_probe(struct net_device *dev)
 static int pcnet_open(struct net_device *dev)
 {
     pcnet_dev_t *info = PRIV(dev);
-    dev_link_t *link = &info->link;
-    
+    struct pcmcia_device *link = info->p_dev;
+
     DEBUG(2, "pcnet_open('%s')\n", dev->name);
 
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
        return -ENODEV;
 
     link->open++;
@@ -1051,7 +1016,7 @@ static int pcnet_open(struct net_device *dev)
 static int pcnet_close(struct net_device *dev)
 {
     pcnet_dev_t *info = PRIV(dev);
-    dev_link_t *link = &info->link;
+    struct pcmcia_device *link = info->p_dev;
 
     DEBUG(2, "pcnet_close('%s')\n", dev->name);
 
@@ -1429,7 +1394,7 @@ static void dma_block_output(struct net_device *dev, int count,
 
 /*====================================================================*/
 
-static int setup_dma_config(dev_link_t *link, int start_pg,
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
                            int stop_pg)
 {
     struct net_device *dev = link->priv;
@@ -1532,7 +1497,7 @@ static void shmem_block_output(struct net_device *dev, int count,
 
 /*====================================================================*/
 
-static int setup_shmem_window(dev_link_t *link, int start_pg,
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
                              int stop_pg, int cm_offset)
 {
     struct net_device *dev = link->priv;
@@ -1554,7 +1519,7 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
     req.Attributes |= WIN_USE_WAIT;
     req.Base = 0; req.Size = window_size;
     req.AccessSpeed = mem_speed;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
 
     mem.CardOffset = (start_pg << 8) + cm_offset;
     offset = mem.CardOffset % window_size;
@@ -1595,7 +1560,7 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
     return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     return 1;
 }
index 8839c4f..e74bf50 100644 (file)
@@ -49,6 +49,7 @@
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
+#include <pcmcia/ss.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -103,7 +104,7 @@ static const char *version =
 #define MEMORY_WAIT_TIME               8
 
 struct smc_private {
-    dev_link_t                 link;
+       struct pcmcia_device    *p_dev;
     spinlock_t                 lock;
     u_short                    manfid;
     u_short                    cardid;
@@ -278,8 +279,8 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002,
 /*====================================================================*/
 
 static void smc91c92_detach(struct pcmcia_device *p_dev);
-static void smc91c92_config(dev_link_t *link);
-static void smc91c92_release(dev_link_t *link);
+static int smc91c92_config(struct pcmcia_device *link);
+static void smc91c92_release(struct pcmcia_device *link);
 
 static int smc_open(struct net_device *dev);
 static int smc_close(struct net_device *dev);
@@ -308,10 +309,9 @@ static struct ethtool_ops ethtool_ops;
 
 ======================================================================*/
 
-static int smc91c92_attach(struct pcmcia_device *p_dev)
+static int smc91c92_probe(struct pcmcia_device *link)
 {
     struct smc_private *smc;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "smc91c92_attach()\n");
@@ -321,7 +321,7 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
     if (!dev)
        return -ENOMEM;
     smc = netdev_priv(dev);
-    link = &smc->link;
+    smc->p_dev = link;
     link->priv = dev;
 
     spin_lock_init(&smc->lock);
@@ -333,7 +333,6 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
     link->irq.Handler = &smc_interrupt;
     link->irq.Instance = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
     /* The SMC91c92-specific entries in the device structure. */
@@ -357,13 +356,7 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
     smc->mii_if.phy_id_mask = 0x1f;
     smc->mii_if.reg_num_mask = 0x1f;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    smc91c92_config(link);
-
-    return 0;
+    return smc91c92_config(link);
 } /* smc91c92_attach */
 
 /*======================================================================
@@ -375,18 +368,16 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void smc91c92_detach(struct pcmcia_device *p_dev)
+static void smc91c92_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "smc91c92_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
        unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-       smc91c92_release(link);
+    smc91c92_release(link);
 
     free_netdev(dev);
 } /* smc91c92_detach */
@@ -414,7 +405,7 @@ static int cvt_ascii_address(struct net_device *dev, char *s)
 
 /*====================================================================*/
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                cisparse_t *parse)
 {
        int i;
@@ -425,7 +416,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
        return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                cisparse_t *parse)
 {
        int i;
@@ -447,7 +438,7 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
 
 ======================================================================*/
 
-static int mhz_3288_power(dev_link_t *link)
+static int mhz_3288_power(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
@@ -469,7 +460,7 @@ static int mhz_3288_power(dev_link_t *link)
     return 0;
 }
 
-static int mhz_mfc_config(dev_link_t *link)
+static int mhz_mfc_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
@@ -504,7 +495,7 @@ static int mhz_mfc_config(dev_link_t *link)
     tuple->TupleDataMax = 255;
     tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
 
-    i = first_tuple(link->handle, tuple, parse);
+    i = first_tuple(link, tuple, parse);
     /* The Megahertz combo cards have modem-like CIS entries, so
        we have to explicitly try a bunch of port combinations. */
     while (i == CS_SUCCESS) {
@@ -513,11 +504,11 @@ static int mhz_mfc_config(dev_link_t *link)
        for (k = 0; k < 0x400; k += 0x10) {
            if (k & 0x80) continue;
            link->io.BasePort1 = k ^ 0x300;
-           i = pcmcia_request_io(link->handle, &link->io);
+           i = pcmcia_request_io(link, &link->io);
            if (i == CS_SUCCESS) break;
        }
        if (i == CS_SUCCESS) break;
-       i = next_tuple(link->handle, tuple, parse);
+       i = next_tuple(link, tuple, parse);
     }
     if (i != CS_SUCCESS)
        goto free_cfg_mem;
@@ -527,7 +518,7 @@ static int mhz_mfc_config(dev_link_t *link)
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
     req.Base = req.Size = 0;
     req.AccessSpeed = 0;
-    i = pcmcia_request_window(&link->handle, &req, &link->win);
+    i = pcmcia_request_window(&link, &req, &link->win);
     if (i != CS_SUCCESS)
        goto free_cfg_mem;
     smc->base = ioremap(req.Base, req.Size);
@@ -546,9 +537,8 @@ free_cfg_mem:
     return i;
 }
 
-static int mhz_setup(dev_link_t *link)
+static int mhz_setup(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct smc_cfg_mem *cfg_mem;
     tuple_t *tuple;
@@ -571,13 +561,13 @@ static int mhz_setup(dev_link_t *link)
     /* Read the station address from the CIS.  It is stored as the last
        (fourth) string in the Version 1 Version/ID tuple. */
     tuple->DesiredTuple = CISTPL_VERS_1;
-    if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
+    if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
        rc = -1;
        goto free_cfg_mem;
     }
     /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
-    if (next_tuple(handle, tuple, parse) != CS_SUCCESS)
-       first_tuple(handle, tuple, parse);
+    if (next_tuple(link, tuple, parse) != CS_SUCCESS)
+       first_tuple(link, tuple, parse);
     if (parse->version_1.ns > 3) {
        station_addr = parse->version_1.str + parse->version_1.ofs[3];
        if (cvt_ascii_address(dev, station_addr) == 0) {
@@ -588,11 +578,11 @@ static int mhz_setup(dev_link_t *link)
 
     /* Another possibility: for the EM3288, in a special tuple */
     tuple->DesiredTuple = 0x81;
-    if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) {
+    if (pcmcia_get_first_tuple(link, tuple) != CS_SUCCESS) {
        rc = -1;
        goto free_cfg_mem;
     }
-    if (pcmcia_get_tuple_data(handle, tuple) != CS_SUCCESS) {
+    if (pcmcia_get_tuple_data(link, tuple) != CS_SUCCESS) {
        rc = -1;
        goto free_cfg_mem;
     }
@@ -616,7 +606,7 @@ free_cfg_mem:
 
 ======================================================================*/
 
-static void mot_config(dev_link_t *link)
+static void mot_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
@@ -637,7 +627,7 @@ static void mot_config(dev_link_t *link)
     mdelay(100);
 }
 
-static int mot_setup(dev_link_t *link)
+static int mot_setup(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     kio_addr_t ioaddr = dev->base_addr;
@@ -671,7 +661,7 @@ static int mot_setup(dev_link_t *link)
 
 /*====================================================================*/
 
-static int smc_config(dev_link_t *link)
+static int smc_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_cfg_mem *cfg_mem;
@@ -696,16 +686,16 @@ static int smc_config(dev_link_t *link)
     tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
 
     link->io.NumPorts1 = 16;
-    i = first_tuple(link->handle, tuple, parse);
+    i = first_tuple(link, tuple, parse);
     while (i != CS_NO_MORE_ITEMS) {
        if (i == CS_SUCCESS) {
            link->conf.ConfigIndex = cf->index;
            link->io.BasePort1 = cf->io.win[0].base;
            link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-           i = pcmcia_request_io(link->handle, &link->io);
+           i = pcmcia_request_io(link, &link->io);
            if (i == CS_SUCCESS) break;
        }
-       i = next_tuple(link->handle, tuple, parse);
+       i = next_tuple(link, tuple, parse);
     }
     if (i == CS_SUCCESS)
        dev->base_addr = link->io.BasePort1;
@@ -714,9 +704,8 @@ static int smc_config(dev_link_t *link)
     return i;
 }
 
-static int smc_setup(dev_link_t *link)
+static int smc_setup(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct smc_cfg_mem *cfg_mem;
     tuple_t *tuple;
@@ -739,11 +728,11 @@ static int smc_setup(dev_link_t *link)
 
     /* Check for a LAN function extension tuple */
     tuple->DesiredTuple = CISTPL_FUNCE;
-    i = first_tuple(handle, tuple, parse);
+    i = first_tuple(link, tuple, parse);
     while (i == CS_SUCCESS) {
        if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID)
            break;
-       i = next_tuple(handle, tuple, parse);
+       i = next_tuple(link, tuple, parse);
     }
     if (i == CS_SUCCESS) {
        node_id = (cistpl_lan_node_id_t *)parse->funce.data;
@@ -756,7 +745,7 @@ static int smc_setup(dev_link_t *link)
     }
     /* Try the third string in the Version 1 Version/ID tuple. */
     tuple->DesiredTuple = CISTPL_VERS_1;
-    if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
+    if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
        rc = -1;
        goto free_cfg_mem;
     }
@@ -774,7 +763,7 @@ free_cfg_mem:
 
 /*====================================================================*/
 
-static int osi_config(dev_link_t *link)
+static int osi_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     static const kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
@@ -794,22 +783,21 @@ static int osi_config(dev_link_t *link)
 
     for (i = j = 0; j < 4; j++) {
        link->io.BasePort2 = com[j];
-       i = pcmcia_request_io(link->handle, &link->io);
+       i = pcmcia_request_io(link, &link->io);
        if (i == CS_SUCCESS) break;
     }
     if (i != CS_SUCCESS) {
        /* Fallback: turn off hard decode */
        link->conf.ConfigIndex = 0x03;
        link->io.NumPorts2 = 0;
-       i = pcmcia_request_io(link->handle, &link->io);
+       i = pcmcia_request_io(link, &link->io);
     }
     dev->base_addr = link->io.BasePort1 + 0x10;
     return i;
 }
 
-static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
+static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct smc_cfg_mem *cfg_mem;
     tuple_t *tuple;
@@ -830,12 +818,12 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
 
     /* Read the station address from tuple 0x90, subtuple 0x04 */
     tuple->DesiredTuple = 0x90;
-    i = pcmcia_get_first_tuple(handle, tuple);
+    i = pcmcia_get_first_tuple(link, tuple);
     while (i == CS_SUCCESS) {
-       i = pcmcia_get_tuple_data(handle, tuple);
+       i = pcmcia_get_tuple_data(link, tuple);
        if ((i != CS_SUCCESS) || (buf[0] == 0x04))
            break;
-       i = pcmcia_get_next_tuple(handle, tuple);
+       i = pcmcia_get_next_tuple(link, tuple);
     }
     if (i != CS_SUCCESS) {
        rc = -1;
@@ -868,57 +856,47 @@ free_cfg_mem:
    return rc;
 }
 
-static int smc91c92_suspend(struct pcmcia_device *p_dev)
+static int smc91c92_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-       }
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int smc91c92_resume(struct pcmcia_device *p_dev)
+static int smc91c92_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
        struct smc_private *smc = netdev_priv(dev);
        int i;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               if ((smc->manfid == MANFID_MEGAHERTZ) &&
-                   (smc->cardid == PRODID_MEGAHERTZ_EM3288))
-                       mhz_3288_power(link);
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (smc->manfid == MANFID_MOTOROLA)
-                       mot_config(link);
-               if ((smc->manfid == MANFID_OSITECH) &&
-                   (smc->cardid != PRODID_OSITECH_SEVEN)) {
-                       /* Power up the card and enable interrupts */
-                       set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
-                       set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
-               }
-               if (((smc->manfid == MANFID_OSITECH) &&
-                    (smc->cardid == PRODID_OSITECH_SEVEN)) ||
-                   ((smc->manfid == MANFID_PSION) &&
-                    (smc->cardid == PRODID_PSION_NET100))) {
-                       /* Download the Seven of Diamonds firmware */
-                       for (i = 0; i < sizeof(__Xilinx7OD); i++) {
-                               outb(__Xilinx7OD[i], link->io.BasePort1+2);
-                               udelay(50);
-                       }
-               }
-               if (link->open) {
-                       smc_reset(dev);
-                       netif_device_attach(dev);
+       if ((smc->manfid == MANFID_MEGAHERTZ) &&
+           (smc->cardid == PRODID_MEGAHERTZ_EM3288))
+               mhz_3288_power(link);
+       if (smc->manfid == MANFID_MOTOROLA)
+               mot_config(link);
+       if ((smc->manfid == MANFID_OSITECH) &&
+           (smc->cardid != PRODID_OSITECH_SEVEN)) {
+               /* Power up the card and enable interrupts */
+               set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
+               set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
+       }
+       if (((smc->manfid == MANFID_OSITECH) &&
+            (smc->cardid == PRODID_OSITECH_SEVEN)) ||
+           ((smc->manfid == MANFID_PSION) &&
+            (smc->cardid == PRODID_PSION_NET100))) {
+               /* Download the Seven of Diamonds firmware */
+               for (i = 0; i < sizeof(__Xilinx7OD); i++) {
+                       outb(__Xilinx7OD[i], link->io.BasePort1+2);
+                       udelay(50);
                }
        }
+       if (link->open) {
+               smc_reset(dev);
+               netif_device_attach(dev);
+       }
 
        return 0;
 }
@@ -931,7 +909,7 @@ static int smc91c92_resume(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static int check_sig(dev_link_t *link)
+static int check_sig(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     kio_addr_t ioaddr = dev->base_addr;
@@ -964,13 +942,15 @@ static int check_sig(dev_link_t *link)
     }
 
     if (width) {
-       printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
-       smc91c92_suspend(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-       pcmcia_request_io(link->handle, &link->io);
-       smc91c92_resume(link->handle);
-       return check_sig(link);
+           modconf_t mod = {
+                   .Attributes = CONF_IO_CHANGE_WIDTH,
+           };
+           printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
+
+           smc91c92_suspend(link);
+           pcmcia_modify_configuration(link, &mod);
+           smc91c92_resume(link);
+           return check_sig(link);
     }
     return -ENODEV;
 }
@@ -984,11 +964,10 @@ static int check_sig(dev_link_t *link)
 ======================================================================*/
 
 #define CS_EXIT_TEST(ret, svc, label) \
-if (ret != CS_SUCCESS) { cs_error(link->handle, svc, ret); goto label; }
+if (ret != CS_SUCCESS) { cs_error(link, svc, ret); goto label; }
 
-static void smc91c92_config(dev_link_t *link)
+static int smc91c92_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
     struct smc_cfg_mem *cfg_mem;
@@ -1015,21 +994,18 @@ static void smc91c92_config(dev_link_t *link)
     tuple->TupleDataMax = 64;
 
     tuple->DesiredTuple = CISTPL_CONFIG;
-    i = first_tuple(handle, tuple, parse);
+    i = first_tuple(link, tuple, parse);
     CS_EXIT_TEST(i, ParseTuple, config_failed);
     link->conf.ConfigBase = parse->config.base;
     link->conf.Present = parse->config.rmask[0];
 
     tuple->DesiredTuple = CISTPL_MANFID;
     tuple->Attributes = TUPLE_RETURN_COMMON;
-    if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+    if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
        smc->manfid = parse->manfid.manf;
        smc->cardid = parse->manfid.card;
     }
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     if ((smc->manfid == MANFID_OSITECH) &&
        (smc->cardid != PRODID_OSITECH_SEVEN)) {
        i = osi_config(link);
@@ -1043,9 +1019,9 @@ static void smc91c92_config(dev_link_t *link)
     }
     CS_EXIT_TEST(i, RequestIO, config_failed);
 
-    i = pcmcia_request_irq(link->handle, &link->irq);
+    i = pcmcia_request_irq(link, &link->irq);
     CS_EXIT_TEST(i, RequestIRQ, config_failed);
-    i = pcmcia_request_configuration(link->handle, &link->conf);
+    i = pcmcia_request_configuration(link, &link->conf);
     CS_EXIT_TEST(i, RequestConfiguration, config_failed);
 
     if (smc->manfid == MANFID_MOTOROLA)
@@ -1124,13 +1100,12 @@ static void smc91c92_config(dev_link_t *link)
        SMC_SELECT_BANK(0);
     }
 
-    link->dev = &smc->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &smc->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if (register_netdev(dev) != 0) {
        printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
-       link->dev = NULL;
+       link->dev_node = NULL;
        goto config_undo;
     }
 
@@ -1160,15 +1135,14 @@ static void smc91c92_config(dev_link_t *link)
        }
     }
     kfree(cfg_mem);
-    return;
+    return 0;
 
 config_undo:
     unregister_netdev(dev);
 config_failed:                 /* CS_EXIT_TEST() calls jump to here... */
     smc91c92_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
     kfree(cfg_mem);
-
+    return -ENODEV;
 } /* smc91c92_config */
 
 /*======================================================================
@@ -1179,22 +1153,15 @@ config_failed:                  /* CS_EXIT_TEST() calls jump to here... */
 
 ======================================================================*/
 
-static void smc91c92_release(dev_link_t *link)
+static void smc91c92_release(struct pcmcia_device *link)
 {
-
-    DEBUG(0, "smc91c92_release(0x%p)\n", link);
-
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    if (link->win) {
-       struct net_device *dev = link->priv;
-       struct smc_private *smc = netdev_priv(dev);
-       iounmap(smc->base);
-       pcmcia_release_window(link->win);
-    }
-
-    link->state &= ~DEV_CONFIG;
+       DEBUG(0, "smc91c92_release(0x%p)\n", link);
+       if (link->win) {
+               struct net_device *dev = link->priv;
+               struct smc_private *smc = netdev_priv(dev);
+               iounmap(smc->base);
+       }
+       pcmcia_disable_device(link);
 }
 
 /*======================================================================
@@ -1283,7 +1250,7 @@ static void smc_dump(struct net_device *dev)
 static int smc_open(struct net_device *dev)
 {
     struct smc_private *smc = netdev_priv(dev);
-    dev_link_t *link = &smc->link;
+    struct pcmcia_device *link = smc->p_dev;
 
 #ifdef PCMCIA_DEBUG
     DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n",
@@ -1292,7 +1259,7 @@ static int smc_open(struct net_device *dev)
 #endif
 
     /* Check that the PCMCIA card is still here. */
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
        return -ENODEV;
     /* Physical device present signature. */
     if (check_sig(link) < 0) {
@@ -1320,7 +1287,7 @@ static int smc_open(struct net_device *dev)
 static int smc_close(struct net_device *dev)
 {
     struct smc_private *smc = netdev_priv(dev);
-    dev_link_t *link = &smc->link;
+    struct pcmcia_device *link = smc->p_dev;
     kio_addr_t ioaddr = dev->base_addr;
 
     DEBUG(0, "%s: smc_close(), status %4.4x.\n",
@@ -2311,7 +2278,7 @@ static struct pcmcia_driver smc91c92_cs_driver = {
        .drv            = {
                .name   = "smc91c92_cs",
        },
-       .probe          = smc91c92_attach,
+       .probe          = smc91c92_probe,
        .remove         = smc91c92_detach,
        .id_table       = smc91c92_ids,
        .suspend        = smc91c92_suspend,
index eed4968..71f4505 100644 (file)
@@ -289,9 +289,9 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg,
  * and ejection events.  They are invoked from the event handler.
  */
 
-static int has_ce2_string(dev_link_t * link);
-static void xirc2ps_config(dev_link_t * link);
-static void xirc2ps_release(dev_link_t * link);
+static int has_ce2_string(struct pcmcia_device * link);
+static int xirc2ps_config(struct pcmcia_device * link);
+static void xirc2ps_release(struct pcmcia_device * link);
 
 /****************
  * The attach() and detach() entry points are used to create and destroy
@@ -313,10 +313,10 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs
 /****************
  * A linked list of "instances" of the device.  Each actual
  * PCMCIA card corresponds to one device instance, and is described
- * by one dev_link_t structure (defined in ds.h).
+ * by one struct pcmcia_device structure (defined in ds.h).
  *
  * You may not want to use a linked list for this -- for example, the
- * memory card driver uses an array of dev_link_t pointers, where minor
+ * memory card driver uses an array of struct pcmcia_device pointers, where minor
  * device numbers are used to derive the corresponding array index.
  */
 
@@ -326,13 +326,13 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs
  * example, ethernet cards, modems).  In other cases, there may be
  * many actual or logical devices (SCSI adapters, memory cards with
  * multiple partitions).  The dev_node_t structures need to be kept
- * in a linked list starting at the 'dev' field of a dev_link_t
+ * in a linked list starting at the 'dev' field of a struct pcmcia_device
  * structure.  We allocate them in the card's private data structure,
  * because they generally can't be allocated dynamically.
  */
 
 typedef struct local_info_t {
-    dev_link_t link;
+       struct pcmcia_device    *p_dev;
     dev_node_t node;
     struct net_device_stats stats;
     int card_type;
@@ -355,7 +355,7 @@ static void do_tx_timeout(struct net_device *dev);
 static struct net_device_stats *do_get_stats(struct net_device *dev);
 static void set_addresses(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
-static int set_card_type(dev_link_t *link, const void *s);
+static int set_card_type(struct pcmcia_device *link, const void *s);
 static int do_config(struct net_device *dev, struct ifmap *map);
 static int do_open(struct net_device *dev);
 static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -368,7 +368,7 @@ static int do_stop(struct net_device *dev);
 
 /*=============== Helper functions =========================*/
 static int
-first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        int err;
 
@@ -379,7 +379,7 @@ first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
 }
 
 static int
-next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
        int err;
 
@@ -553,9 +553,8 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len)
  */
 
 static int
-xirc2ps_attach(struct pcmcia_device *p_dev)
+xirc2ps_probe(struct pcmcia_device *link)
 {
-    dev_link_t *link;
     struct net_device *dev;
     local_info_t *local;
 
@@ -566,12 +565,11 @@ xirc2ps_attach(struct pcmcia_device *p_dev)
     if (!dev)
            return -ENOMEM;
     local = netdev_priv(dev);
-    link = &local->link;
+    local->p_dev = link;
     link->priv = dev;
 
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
@@ -593,13 +591,7 @@ xirc2ps_attach(struct pcmcia_device *p_dev)
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    xirc2ps_config(link);
-
-    return 0;
+    return xirc2ps_config(link);
 } /* xirc2ps_attach */
 
 /****************
@@ -610,18 +602,16 @@ xirc2ps_attach(struct pcmcia_device *p_dev)
  */
 
 static void
-xirc2ps_detach(struct pcmcia_device *p_dev)
+xirc2ps_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
        unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-       xirc2ps_release(link);
+    xirc2ps_release(link);
 
     free_netdev(dev);
 } /* xirc2ps_detach */
@@ -645,7 +635,7 @@ xirc2ps_detach(struct pcmcia_device *p_dev)
  *
  */
 static int
-set_card_type(dev_link_t *link, const void *s)
+set_card_type(struct pcmcia_device *link, const void *s)
 {
     struct net_device *dev = link->priv;
     local_info_t *local = netdev_priv(dev);
@@ -714,9 +704,8 @@ set_card_type(dev_link_t *link, const void *s)
  * Returns: true if this is a CE2
  */
 static int
-has_ce2_string(dev_link_t * link)
+has_ce2_string(struct pcmcia_device * link)
 {
-    client_handle_t handle = link->handle;
     tuple_t tuple;
     cisparse_t parse;
     u_char buf[256];
@@ -726,7 +715,7 @@ has_ce2_string(dev_link_t * link)
     tuple.TupleDataMax = 254;
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_VERS_1;
-    if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) {
+    if (!first_tuple(link, &tuple, &parse) && parse.version_1.ns > 2) {
        if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2"))
            return 1;
     }
@@ -738,10 +727,9 @@ has_ce2_string(dev_link_t * link)
  * is received, to configure the PCMCIA socket, and to make the
  * ethernet device available to the system.
  */
-static void
-xirc2ps_config(dev_link_t * link)
+static int
+xirc2ps_config(struct pcmcia_device * link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     local_info_t *local = netdev_priv(dev);
     tuple_t tuple;
@@ -767,7 +755,7 @@ xirc2ps_config(dev_link_t * link)
 
     /* Is this a valid card */
     tuple.DesiredTuple = CISTPL_MANFID;
-    if ((err=first_tuple(handle, &tuple, &parse))) {
+    if ((err=first_tuple(link, &tuple, &parse))) {
        printk(KNOT_XIRC "manfid not found in CIS\n");
        goto failure;
     }
@@ -803,15 +791,15 @@ xirc2ps_config(dev_link_t * link)
 
     /* get configuration stuff */
     tuple.DesiredTuple = CISTPL_CONFIG;
-    if ((err=first_tuple(handle, &tuple, &parse)))
+    if ((err=first_tuple(link, &tuple, &parse)))
        goto cis_error;
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present =    parse.config.rmask[0];
 
     /* get the ethernet address from the CIS */
     tuple.DesiredTuple = CISTPL_FUNCE;
-    for (err = first_tuple(handle, &tuple, &parse); !err;
-                            err = next_tuple(handle, &tuple, &parse)) {
+    for (err = first_tuple(link, &tuple, &parse); !err;
+                            err = next_tuple(link, &tuple, &parse)) {
        /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries:
         * the first one with a length of zero the second correct -
         * so I skip all entries with length 0 */
@@ -821,8 +809,8 @@ xirc2ps_config(dev_link_t * link)
     }
     if (err) { /* not found: try to get the node-id from tuple 0x89 */
        tuple.DesiredTuple = 0x89;  /* data layout looks like tuple 0x22 */
-       if ((err = pcmcia_get_first_tuple(handle, &tuple)) == 0 &&
-               (err = pcmcia_get_tuple_data(handle, &tuple)) == 0) {
+       if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 &&
+               (err = pcmcia_get_tuple_data(link, &tuple)) == 0) {
            if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID)
                memcpy(&parse, buf, 8);
            else
@@ -831,8 +819,8 @@ xirc2ps_config(dev_link_t * link)
     }
     if (err) { /* another try  (James Lehmer's CE2 version 4.1)*/
        tuple.DesiredTuple = CISTPL_FUNCE;
-       for (err = first_tuple(handle, &tuple, &parse); !err;
-                                err = next_tuple(handle, &tuple, &parse)) {
+       for (err = first_tuple(link, &tuple, &parse); !err;
+                                err = next_tuple(link, &tuple, &parse)) {
            if (parse.funce.type == 0x02 && parse.funce.data[0] == 1
                && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) {
                buf[1] = 4;
@@ -853,9 +841,6 @@ xirc2ps_config(dev_link_t * link)
     for (i=0; i < 6; i++)
        dev->dev_addr[i] = node_id->id[i];
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     link->io.IOAddrLines =10;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
     link->irq.Attributes = IRQ_HANDLE_PRESENT;
@@ -875,14 +860,14 @@ xirc2ps_config(dev_link_t * link)
             * Ethernet port */
            link->io.NumPorts1 = 16; /* no Mako stuff anymore */
            tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-           for (err = first_tuple(handle, &tuple, &parse); !err;
-                                err = next_tuple(handle, &tuple, &parse)) {
+           for (err = first_tuple(link, &tuple, &parse); !err;
+                                err = next_tuple(link, &tuple, &parse)) {
                if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
                    for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
                        link->conf.ConfigIndex = cf->index ;
                        link->io.BasePort2 = cf->io.win[0].base;
                        link->io.BasePort1 = ioaddr;
-                       if (!(err=pcmcia_request_io(link->handle, &link->io)))
+                       if (!(err=pcmcia_request_io(link, &link->io)))
                            goto port_found;
                    }
                }
@@ -896,15 +881,15 @@ xirc2ps_config(dev_link_t * link)
             */
            for (pass=0; pass < 2; pass++) {
                tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-               for (err = first_tuple(handle, &tuple, &parse); !err;
-                                    err = next_tuple(handle, &tuple, &parse)){
+               for (err = first_tuple(link, &tuple, &parse); !err;
+                                    err = next_tuple(link, &tuple, &parse)){
                    if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8){
                        link->conf.ConfigIndex = cf->index ;
                        link->io.BasePort2 = cf->io.win[0].base;
                        link->io.BasePort1 = link->io.BasePort2
                                    + (pass ? (cf->index & 0x20 ? -24:8)
                                            : (cf->index & 0x20 ?   8:-24));
-                       if (!(err=pcmcia_request_io(link->handle, &link->io)))
+                       if (!(err=pcmcia_request_io(link, &link->io)))
                            goto port_found;
                    }
                }
@@ -919,12 +904,12 @@ xirc2ps_config(dev_link_t * link)
        link->io.NumPorts1 = 16;
        for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
            link->io.BasePort1 = ioaddr;
-           if (!(err=pcmcia_request_io(link->handle, &link->io)))
+           if (!(err=pcmcia_request_io(link, &link->io)))
                goto port_found;
        }
        link->io.BasePort1 = 0; /* let CS decide */
-       if ((err=pcmcia_request_io(link->handle, &link->io))) {
-           cs_error(link->handle, RequestIO, err);
+       if ((err=pcmcia_request_io(link, &link->io))) {
+           cs_error(link, RequestIO, err);
            goto config_error;
        }
     }
@@ -936,8 +921,8 @@ xirc2ps_config(dev_link_t * link)
      * Now allocate an interrupt line. Note that this does not
      * actually assign a handler to the interrupt.
      */
-    if ((err=pcmcia_request_irq(link->handle, &link->irq))) {
-       cs_error(link->handle, RequestIRQ, err);
+    if ((err=pcmcia_request_irq(link, &link->irq))) {
+       cs_error(link, RequestIRQ, err);
        goto config_error;
     }
 
@@ -945,8 +930,8 @@ xirc2ps_config(dev_link_t * link)
      * This actually configures the PCMCIA socket -- setting up
      * the I/O windows and the interrupt mapping.
      */
-    if ((err=pcmcia_request_configuration(link->handle, &link->conf))) {
-       cs_error(link->handle, RequestConfiguration, err);
+    if ((err=pcmcia_request_configuration(link, &link->conf))) {
+       cs_error(link, RequestConfiguration, err);
        goto config_error;
     }
 
@@ -963,15 +948,15 @@ xirc2ps_config(dev_link_t * link)
        reg.Action = CS_WRITE;
        reg.Offset = CISREG_IOBASE_0;
        reg.Value = link->io.BasePort2 & 0xff;
-       if ((err = pcmcia_access_configuration_register(link->handle, &reg))) {
-           cs_error(link->handle, AccessConfigurationRegister, err);
+       if ((err = pcmcia_access_configuration_register(link, &reg))) {
+           cs_error(link, AccessConfigurationRegister, err);
            goto config_error;
        }
        reg.Action = CS_WRITE;
        reg.Offset = CISREG_IOBASE_1;
        reg.Value = (link->io.BasePort2 >> 8) & 0xff;
-       if ((err = pcmcia_access_configuration_register(link->handle, &reg))) {
-           cs_error(link->handle, AccessConfigurationRegister, err);
+       if ((err = pcmcia_access_configuration_register(link, &reg))) {
+           cs_error(link, AccessConfigurationRegister, err);
            goto config_error;
        }
 
@@ -982,15 +967,15 @@ xirc2ps_config(dev_link_t * link)
        req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
        req.Base = req.Size = 0;
        req.AccessSpeed = 0;
-       if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) {
-           cs_error(link->handle, RequestWindow, err);
+       if ((err = pcmcia_request_window(&link, &req, &link->win))) {
+           cs_error(link, RequestWindow, err);
            goto config_error;
        }
        local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;
        mem.CardOffset = 0x0;
        mem.Page = 0;
        if ((err = pcmcia_map_mem_page(link->win, &mem))) {
-           cs_error(link->handle, MapMemPage, err);
+           cs_error(link, MapMemPage, err);
            goto config_error;
        }
 
@@ -1050,13 +1035,12 @@ xirc2ps_config(dev_link_t * link)
     if (local->dingo)
        do_reset(dev, 1); /* a kludge to make the cem56 work */
 
-    link->dev = &local->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &local->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if ((err=register_netdev(dev))) {
        printk(KNOT_XIRC "register_netdev() failed\n");
-       link->dev = NULL;
+       link->dev_node = NULL;
        goto config_error;
     }
 
@@ -1069,17 +1053,16 @@ xirc2ps_config(dev_link_t * link)
        printk("%c%02X", i?':':' ', dev->dev_addr[i]);
     printk("\n");
 
-    return;
+    return 0;
 
   config_error:
-    link->state &= ~DEV_CONFIG_PENDING;
     xirc2ps_release(link);
-    return;
+    return -ENODEV;
 
   cis_error:
     printk(KNOT_XIRC "unable to parse CIS\n");
   failure:
-    link->state &= ~DEV_CONFIG_PENDING;
+    return -ENODEV;
 } /* xirc2ps_config */
 
 /****************
@@ -1088,57 +1071,41 @@ xirc2ps_config(dev_link_t * link)
  * still open, this will be postponed until it is closed.
  */
 static void
-xirc2ps_release(dev_link_t *link)
+xirc2ps_release(struct pcmcia_device *link)
 {
+       DEBUG(0, "release(0x%p)\n", link);
 
-    DEBUG(0, "release(0x%p)\n", link);
-
-    if (link->win) {
-       struct net_device *dev = link->priv;
-       local_info_t *local = netdev_priv(dev);
-       if (local->dingo)
-           iounmap(local->dingo_ccr - 0x0800);
-       pcmcia_release_window(link->win);
-    }
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
-
+       if (link->win) {
+               struct net_device *dev = link->priv;
+               local_info_t *local = netdev_priv(dev);
+               if (local->dingo)
+                       iounmap(local->dingo_ccr - 0x0800);
+       }
+       pcmcia_disable_device(link);
 } /* xirc2ps_release */
 
 /*====================================================================*/
 
 
-static int xirc2ps_suspend(struct pcmcia_device *p_dev)
+static int xirc2ps_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               if (link->open) {
-                       netif_device_detach(dev);
-                       do_powerdown(dev);
-               }
-               pcmcia_release_configuration(link->handle);
+       if (link->open) {
+               netif_device_detach(dev);
+               do_powerdown(dev);
        }
 
        return 0;
 }
 
-static int xirc2ps_resume(struct pcmcia_device *p_dev)
+static int xirc2ps_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       do_reset(dev,1);
-                       netif_device_attach(dev);
-               }
+       if (link->open) {
+               do_reset(dev,1);
+               netif_device_attach(dev);
        }
 
        return 0;
@@ -1552,13 +1519,13 @@ static int
 do_open(struct net_device *dev)
 {
     local_info_t *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
 
     DEBUG(0, "do_open(%p)\n", dev);
 
     /* Check that the PCMCIA card is still here. */
     /* Physical device present signature. */
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
        return -ENODEV;
 
     /* okay */
@@ -1882,7 +1849,7 @@ do_stop(struct net_device *dev)
 {
     kio_addr_t ioaddr = dev->base_addr;
     local_info_t *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
 
     DEBUG(0, "do_stop(%p)\n", dev);
 
@@ -1935,7 +1902,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = {
        .drv            = {
                .name   = "xirc2ps_cs",
        },
-       .probe          = xirc2ps_attach,
+       .probe          = xirc2ps_probe,
        .remove         = xirc2ps_detach,
        .id_table       = xirc2ps_ids,
        .suspend        = xirc2ps_suspend,
@@ -1973,7 +1940,7 @@ static int __init setup_xirc2ps_cs(char *str)
        MAYBE_SET(lockup_hack, 6);
 #undef  MAYBE_SET
 
-       return 0;
+       return 1;
 }
 
 __setup("xirc2ps_cs=", setup_xirc2ps_cs);
index 964c096..770e6b6 100644 (file)
@@ -69,8 +69,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.55"
-#define DRV_MODULE_RELDATE     "Mar 27, 2006"
+#define DRV_MODULE_VERSION     "3.56"
+#define DRV_MODULE_RELDATE     "Apr 1, 2006"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -497,40 +497,33 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
        unsigned long flags;
 
        spin_lock_irqsave(&tp->indirect_lock, flags);
-       if (tp->write32 != tg3_write_indirect_reg32) {
-               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
-               tw32_f(TG3PCI_MEM_WIN_DATA, val);
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 
-               /* Always leave this as zero. */
-               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
-       } else {
-               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
-               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
-
-               /* Always leave this as zero. */
-               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
-       }
+       /* Always leave this as zero. */
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
        spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
+static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val)
+{
+       /* If no workaround is needed, write to mem space directly */
+       if (tp->write32 != tg3_write_indirect_reg32)
+               tw32(NIC_SRAM_WIN_BASE + off, val);
+       else
+               tg3_write_mem(tp, off, val);
+}
+
 static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&tp->indirect_lock, flags);
-       if (tp->write32 != tg3_write_indirect_reg32) {
-               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
-               *val = tr32(TG3PCI_MEM_WIN_DATA);
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+       pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 
-               /* Always leave this as zero. */
-               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
-       } else {
-               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
-               pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
-
-               /* Always leave this as zero. */
-               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
-       }
+       /* Always leave this as zero. */
+       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
        spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
@@ -1374,12 +1367,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                }
        }
 
-       tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
-
        /* Finally, set the new power state. */
        pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
        udelay(100);    /* Delay after power state change */
 
+       tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
+
        return 0;
 }
 
@@ -6547,11 +6540,11 @@ static void tg3_timer(unsigned long __opaque)
                if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
                        u32 val;
 
-                       tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
-                                     FWCMD_NICDRV_ALIVE2);
-                       tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
+                       tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX,
+                                          FWCMD_NICDRV_ALIVE2);
+                       tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
                        /* 5 seconds timeout */
-                       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
+                       tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
                        val = tr32(GRC_RX_CPU_EVENT);
                        val |= (1 << 14);
                        tw32(GRC_RX_CPU_EVENT, val);
index e4cfc80..99c4c19 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 menu "Token Ring devices"
-       depends on NETDEVICES
+       depends on NETDEVICES && !UML
 
 # So far, we only have PCI, ISA, and MCA token ring devices
 config TR
index f85e301..bad09eb 100644 (file)
@@ -356,7 +356,7 @@ config PCI_HERMES
 
 config ATMEL
       tristate "Atmel at76c50x chipset  802.11b support"
-      depends on NET_RADIO
+      depends on NET_RADIO && (PCI || PCMCIA)
       select FW_LOADER
       select CRC32
        ---help---
index a496460..af0cbb6 100644 (file)
@@ -80,8 +80,8 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
    event handler. 
 */
 
-static void airo_config(dev_link_t *link);
-static void airo_release(dev_link_t *link);
+static int airo_config(struct pcmcia_device *link);
+static void airo_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -101,10 +101,10 @@ static void airo_detach(struct pcmcia_device *p_dev);
 /*
    A linked list of "instances" of the  aironet device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
+   by one struct pcmcia_device structure (defined in ds.h).
 
    You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
+   memory card driver uses an array of struct pcmcia_device pointers, where minor
    device numbers are used to derive the corresponding array index.
 */
 
@@ -114,7 +114,7 @@ static void airo_detach(struct pcmcia_device *p_dev);
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally shouldn't be allocated dynamically.
 
@@ -141,24 +141,16 @@ typedef struct local_info_t {
   
   ======================================================================*/
 
-static int airo_attach(struct pcmcia_device *p_dev)
+static int airo_probe(struct pcmcia_device *p_dev)
 {
-       dev_link_t *link;
        local_info_t *local;
 
        DEBUG(0, "airo_attach()\n");
 
-       /* Initialize the dev_link_t structure */
-       link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-       if (!link) {
-               printk(KERN_ERR "airo_cs: no memory for new device\n");
-               return -ENOMEM;
-       }
-       
        /* Interrupt setup */
-       link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-       link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-       link->irq.Handler = NULL;
+       p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+       p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+       p_dev->irq.Handler = NULL;
        
        /*
          General socket configuration defaults can go here.  In this
@@ -167,26 +159,18 @@ static int airo_attach(struct pcmcia_device *p_dev)
          and attributes of IO windows) are fixed by the nature of the
          device, and can be hard-wired here.
        */
-       link->conf.Attributes = 0;
-       link->conf.Vcc = 50;
-       link->conf.IntType = INT_MEMORY_AND_IO;
+       p_dev->conf.Attributes = 0;
+       p_dev->conf.IntType = INT_MEMORY_AND_IO;
        
        /* Allocate space for private device-specific data */
        local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
        if (!local) {
                printk(KERN_ERR "airo_cs: no memory for new device\n");
-               kfree (link);
                return -ENOMEM;
        }
-       link->priv = local;
+       p_dev->priv = local;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       airo_config(link);
-
-       return 0;
+       return airo_config(p_dev);
 } /* airo_attach */
 
 /*======================================================================
@@ -198,14 +182,11 @@ static int airo_attach(struct pcmcia_device *p_dev)
   
   ======================================================================*/
 
-static void airo_detach(struct pcmcia_device *p_dev)
+static void airo_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
-
        DEBUG(0, "airo_detach(0x%p)\n", link);
 
-       if (link->state & DEV_CONFIG)
-               airo_release(link);
+       airo_release(link);
 
        if ( ((local_info_t*)link->priv)->eth_dev ) {
                stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
@@ -213,7 +194,6 @@ static void airo_detach(struct pcmcia_device *p_dev)
        ((local_info_t*)link->priv)->eth_dev = NULL;
 
        kfree(link->priv);
-       kfree(link);
 } /* airo_detach */
 
 /*======================================================================
@@ -227,9 +207,8 @@ static void airo_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void airo_config(dev_link_t *link)
+static int airo_config(struct pcmcia_device *link)
 {
-       client_handle_t handle;
        tuple_t tuple;
        cisparse_t parse;
        local_info_t *dev;
@@ -237,8 +216,7 @@ static void airo_config(dev_link_t *link)
        u_char buf[64];
        win_req_t req;
        memreq_t map;
-       
-       handle = link->handle;
+
        dev = link->priv;
 
        DEBUG(0, "airo_config(0x%p)\n", link);
@@ -252,15 +230,12 @@ static void airo_config(dev_link_t *link)
        tuple.TupleData = buf;
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
-       
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-       
+
        /*
          In this loop, we scan the CIS for configuration table entries,
          each of which describes a valid card configuration, including
@@ -274,12 +249,12 @@ static void airo_config(dev_link_t *link)
          will only use the CIS to fill in implementation-defined details.
        */
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        while (1) {
                cistpl_cftable_entry_t dflt = { 0 };
                cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-               if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-                               pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+                               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
                        goto next_entry;
                
                if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -294,16 +269,11 @@ static void airo_config(dev_link_t *link)
                
                /* Use power settings for Vcc and Vpp if present */
                /*  Note that the CIS values need to be rescaled */
-               if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
-               else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
-               
                if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                                cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
                else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                                dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
                
                /* Do we need to allocate an interrupt? */
@@ -329,12 +299,12 @@ static void airo_config(dev_link_t *link)
                }
                
                /* This reserves IO space but doesn't actually enable it */
-               if (pcmcia_request_io(link->handle, &link->io) != 0)
+               if (pcmcia_request_io(link, &link->io) != 0)
                        goto next_entry;
                
                /*
                  Now set up a common memory window, if needed.  There is room
-                 in the dev_link_t structure for one memory window handle,
+                 in the struct pcmcia_device structure for one memory window handle,
                  but if the base addresses need to be saved, or if multiple
                  windows are needed, the info should go in the private data
                  structure for this device.
@@ -350,7 +320,7 @@ static void airo_config(dev_link_t *link)
                        req.Base = mem->win[0].host_addr;
                        req.Size = mem->win[0].len;
                        req.AccessSpeed = 0;
-                       if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+                       if (pcmcia_request_window(&link, &req, &link->win) != 0)
                                goto next_entry;
                        map.Page = 0; map.CardOffset = mem->win[0].card_addr;
                        if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -360,7 +330,7 @@ static void airo_config(dev_link_t *link)
                break;
                
        next_entry:
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
        }
        
     /*
@@ -369,33 +339,32 @@ static void airo_config(dev_link_t *link)
       irq structure is initialized.
     */
        if (link->conf.Attributes & CONF_ENABLE_IRQ)
-               CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+               CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
        
        /*
          This actually configures the PCMCIA socket -- setting up
          the I/O windows and the interrupt mapping, and putting the
          card and host interface into "Memory and IO" mode.
        */
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
        ((local_info_t*)link->priv)->eth_dev = 
                init_airo_card( link->irq.AssignedIRQ,
-                               link->io.BasePort1, 1, &handle_to_dev(handle) );
+                               link->io.BasePort1, 1, &handle_to_dev(link) );
        if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed;
        
        /*
          At this point, the dev_node_t structure(s) need to be
-         initialized and arranged in a linked list at link->dev.
+         initialized and arranged in a linked list at link->dev_node.
        */
        strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
        dev->node.major = dev->node.minor = 0;
-       link->dev = &dev->node;
+       link->dev_node = &dev->node;
        
        /* Finally, report what we've done */
-       printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-              dev->node.dev_name, link->conf.ConfigIndex,
-              link->conf.Vcc/10, link->conf.Vcc%10);
-       if (link->conf.Vpp1)
-               printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+       printk(KERN_INFO "%s: index 0x%02x: ",
+              dev->node.dev_name, link->conf.ConfigIndex);
+       if (link->conf.Vpp)
+               printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
        if (link->conf.Attributes & CONF_ENABLE_IRQ)
                printk(", irq %d", link->irq.AssignedIRQ);
        if (link->io.NumPorts1)
@@ -408,14 +377,12 @@ static void airo_config(dev_link_t *link)
                printk(", mem 0x%06lx-0x%06lx", req.Base,
                       req.Base+req.Size-1);
        printk("\n");
-       
-       link->state &= ~DEV_CONFIG_PENDING;
-       return;
-       
+       return 0;
+
  cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
        airo_release(link);
-       
+       return -ENODEV;
 } /* airo_config */
 
 /*======================================================================
@@ -426,51 +393,26 @@ static void airo_config(dev_link_t *link)
   
   ======================================================================*/
 
-static void airo_release(dev_link_t *link)
+static void airo_release(struct pcmcia_device *link)
 {
        DEBUG(0, "airo_release(0x%p)\n", link);
-       
-       /* Unlink the device chain */
-       link->dev = NULL;
-       
-       /*
-         In a normal driver, additional code may be needed to release
-         other kernel data structures associated with this device. 
-       */
-       
-       /* Don't bother checking to see if these succeed or not */
-       if (link->win)
-               pcmcia_release_window(link->win);
-       pcmcia_release_configuration(link->handle);
-       if (link->io.NumPorts1)
-               pcmcia_release_io(link->handle, &link->io);
-       if (link->irq.AssignedIRQ)
-               pcmcia_release_irq(link->handle, &link->irq);
-       link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
 }
 
-static int airo_suspend(struct pcmcia_device *p_dev)
+static int airo_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        local_info_t *local = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               netif_device_detach(local->eth_dev);
-               pcmcia_release_configuration(link->handle);
-       }
+       netif_device_detach(local->eth_dev);
 
        return 0;
 }
 
-static int airo_resume(struct pcmcia_device *p_dev)
+static int airo_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        local_info_t *local = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
+       if (link->open) {
                reset_airo_card(local->eth_dev);
                netif_device_attach(local->eth_dev);
        }
@@ -492,7 +434,7 @@ static struct pcmcia_driver airo_driver = {
        .drv            = {
                .name   = "airo_cs",
        },
-       .probe          = airo_attach,
+       .probe          = airo_probe,
        .remove         = airo_detach,
        .id_table       = airo_ids,
        .suspend        = airo_suspend,
index d6f4a5a..26bf112 100644 (file)
@@ -91,8 +91,8 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
    event handler. 
 */
 
-static void atmel_config(dev_link_t *link);
-static void atmel_release(dev_link_t *link);
+static int atmel_config(struct pcmcia_device *link);
+static void atmel_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -112,10 +112,10 @@ static void atmel_detach(struct pcmcia_device *p_dev);
 /*
    A linked list of "instances" of the  atmelnet device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
+   by one struct pcmcia_device structure (defined in ds.h).
 
    You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
+   memory card driver uses an array of struct pcmcia_device pointers, where minor
    device numbers are used to derive the corresponding array index.
 */
 
@@ -125,7 +125,7 @@ static void atmel_detach(struct pcmcia_device *p_dev);
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally shouldn't be allocated dynamically.
 
@@ -152,24 +152,16 @@ typedef struct local_info_t {
   
   ======================================================================*/
 
-static int atmel_attach(struct pcmcia_device *p_dev)
+static int atmel_probe(struct pcmcia_device *p_dev)
 {
-       dev_link_t *link;
        local_info_t *local;
 
        DEBUG(0, "atmel_attach()\n");
 
-       /* Initialize the dev_link_t structure */
-       link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-       if (!link) {
-               printk(KERN_ERR "atmel_cs: no memory for new device\n");
-               return -ENOMEM;
-       }
-
        /* Interrupt setup */
-       link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-       link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-       link->irq.Handler = NULL;
+       p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+       p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+       p_dev->irq.Handler = NULL;
 
        /*
          General socket configuration defaults can go here.  In this
@@ -178,26 +170,18 @@ static int atmel_attach(struct pcmcia_device *p_dev)
          and attributes of IO windows) are fixed by the nature of the
          device, and can be hard-wired here.
        */
-       link->conf.Attributes = 0;
-       link->conf.Vcc = 50;
-       link->conf.IntType = INT_MEMORY_AND_IO;
+       p_dev->conf.Attributes = 0;
+       p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
        /* Allocate space for private device-specific data */
        local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
        if (!local) {
                printk(KERN_ERR "atmel_cs: no memory for new device\n");
-               kfree (link);
                return -ENOMEM;
        }
-       link->priv = local;
+       p_dev->priv = local;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       atmel_config(link);
-
-       return 0;
+       return atmel_config(p_dev);
 } /* atmel_attach */
 
 /*======================================================================
@@ -209,17 +193,13 @@ static int atmel_attach(struct pcmcia_device *p_dev)
   
   ======================================================================*/
 
-static void atmel_detach(struct pcmcia_device *p_dev)
+static void atmel_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
-
        DEBUG(0, "atmel_detach(0x%p)\n", link);
 
-       if (link->state & DEV_CONFIG)
-               atmel_release(link);
+       atmel_release(link);
 
        kfree(link->priv);
-       kfree(link);
 }
 
 /*======================================================================
@@ -236,19 +216,17 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 /* Call-back function to interrogate PCMCIA-specific information
    about the current existance of the card */
 static int card_present(void *arg)
-{ 
-       dev_link_t *link = (dev_link_t *)arg;
-       if (link->state & DEV_SUSPEND)
-               return 0;
-       else if (link->state & DEV_PRESENT)
+{
+       struct pcmcia_device *link = (struct pcmcia_device *)arg;
+
+       if (pcmcia_dev_present(link))
                return 1;
-       
+
        return 0;
 }
 
-static void atmel_config(dev_link_t *link)
+static int atmel_config(struct pcmcia_device *link)
 {
-       client_handle_t handle;
        tuple_t tuple;
        cisparse_t parse;
        local_info_t *dev;
@@ -256,9 +234,8 @@ static void atmel_config(dev_link_t *link)
        u_char buf[64];
        struct pcmcia_device_id *did;
 
-       handle = link->handle;
        dev = link->priv;
-       did = handle_to_dev(handle).driver_data;
+       did = handle_to_dev(link).driver_data;
 
        DEBUG(0, "atmel_config(0x%p)\n", link);
        
@@ -272,15 +249,12 @@ static void atmel_config(dev_link_t *link)
          registers.
        */
        tuple.DesiredTuple = CISTPL_CONFIG;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
-       
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-       
+
        /*
          In this loop, we scan the CIS for configuration table entries,
          each of which describes a valid card configuration, including
@@ -294,12 +268,12 @@ static void atmel_config(dev_link_t *link)
          will only use the CIS to fill in implementation-defined details.
        */
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        while (1) {
                cistpl_cftable_entry_t dflt = { 0 };
                cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-               if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-                               pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+                               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
                        goto next_entry;
                
                if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -314,16 +288,11 @@ static void atmel_config(dev_link_t *link)
                
                /* Use power settings for Vcc and Vpp if present */
                /*  Note that the CIS values need to be rescaled */
-               if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
-               else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
-               
                if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                                cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
                else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                                dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
                
                /* Do we need to allocate an interrupt? */
@@ -349,14 +318,14 @@ static void atmel_config(dev_link_t *link)
                }
                
                /* This reserves IO space but doesn't actually enable it */
-               if (pcmcia_request_io(link->handle, &link->io) != 0)
+               if (pcmcia_request_io(link, &link->io) != 0)
                        goto next_entry;
 
                /* If we got this far, we're cool! */
                break;
                
        next_entry:
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
        }
        
        /*
@@ -365,14 +334,14 @@ static void atmel_config(dev_link_t *link)
          irq structure is initialized.
        */
        if (link->conf.Attributes & CONF_ENABLE_IRQ)
-               CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+               CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
        
        /*
          This actually configures the PCMCIA socket -- setting up
          the I/O windows and the interrupt mapping, and putting the
          card and host interface into "Memory and IO" mode.
        */
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
        
        if (link->irq.AssignedIRQ == 0) {
                printk(KERN_ALERT 
@@ -384,7 +353,7 @@ static void atmel_config(dev_link_t *link)
                init_atmel_card(link->irq.AssignedIRQ,
                                link->io.BasePort1,
                                did ? did->driver_info : ATMEL_FW_TYPE_NONE,
-                               &handle_to_dev(handle),
+                               &handle_to_dev(link),
                                card_present, 
                                link);
        if (!((local_info_t*)link->priv)->eth_dev) 
@@ -393,18 +362,18 @@ static void atmel_config(dev_link_t *link)
        
        /*
          At this point, the dev_node_t structure(s) need to be
-         initialized and arranged in a linked list at link->dev.
+         initialized and arranged in a linked list at link->dev_node.
        */
        strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
        dev->node.major = dev->node.minor = 0;
-       link->dev = &dev->node;
-                       
-       link->state &= ~DEV_CONFIG_PENDING;
-       return;
-       
+       link->dev_node = &dev->node;
+
+       return 0;
+
  cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
        atmel_release(link);
+       return -ENODEV;
 }
 
 /*======================================================================
@@ -415,53 +384,34 @@ static void atmel_config(dev_link_t *link)
   
   ======================================================================*/
 
-static void atmel_release(dev_link_t *link)
+static void atmel_release(struct pcmcia_device *link)
 {
        struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
-               
+
        DEBUG(0, "atmel_release(0x%p)\n", link);
-       
-       /* Unlink the device chain */
-       link->dev = NULL;
-       
-       if (dev) 
+
+       if (dev)
                stop_atmel_card(dev);
-       ((local_info_t*)link->priv)->eth_dev = NULL; 
-       
-       /* Don't bother checking to see if these succeed or not */
-       pcmcia_release_configuration(link->handle);
-       if (link->io.NumPorts1)
-               pcmcia_release_io(link->handle, &link->io);
-       if (link->irq.AssignedIRQ)
-               pcmcia_release_irq(link->handle, &link->irq);
-       link->state &= ~DEV_CONFIG;
+       ((local_info_t*)link->priv)->eth_dev = NULL;
+
+       pcmcia_disable_device(link);
 }
 
-static int atmel_suspend(struct pcmcia_device *dev)
+static int atmel_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        local_info_t *local = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               netif_device_detach(local->eth_dev);
-               pcmcia_release_configuration(link->handle);
-       }
+       netif_device_detach(local->eth_dev);
 
        return 0;
 }
 
-static int atmel_resume(struct pcmcia_device *dev)
+static int atmel_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        local_info_t *local = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               atmel_open(local->eth_dev);
-               netif_device_attach(local->eth_dev);
-       }
+       atmel_open(local->eth_dev);
+       netif_device_attach(local->eth_dev);
 
        return 0;
 }
@@ -515,7 +465,7 @@ static struct pcmcia_driver atmel_driver = {
        .drv            = {
                .name   = "atmel_cs",
         },
-       .probe          = atmel_attach,
+       .probe          = atmel_probe,
        .remove         = atmel_detach,
        .id_table       = atmel_ids,
        .suspend        = atmel_suspend,
index d335b25..55bed92 100644 (file)
@@ -42,7 +42,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
 /* struct local_info::hw_priv */
 struct hostap_cs_priv {
        dev_node_t node;
-       dev_link_t *link;
+       struct pcmcia_device *link;
        int sandisk_connectplus;
 };
 
@@ -204,15 +204,13 @@ static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
 
 static void prism2_detach(struct pcmcia_device *p_dev);
 static void prism2_release(u_long arg);
-static int prism2_config(dev_link_t *link);
+static int prism2_config(struct pcmcia_device *link);
 
 
 static int prism2_pccard_card_present(local_info_t *local)
 {
        struct hostap_cs_priv *hw_priv = local->hw_priv;
-       if (hw_priv != NULL && hw_priv->link != NULL &&
-           ((hw_priv->link->state & (DEV_PRESENT | DEV_CONFIG)) ==
-            (DEV_PRESENT | DEV_CONFIG)))
+       if (hw_priv != NULL && hw_priv->link != NULL && pcmcia_dev_present(hw_priv->link))
                return 1;
        return 0;
 }
@@ -237,7 +235,7 @@ static void sandisk_set_iobase(local_info_t *local)
        reg.Action = CS_WRITE;
        reg.Offset = 0x10; /* 0x3f0 IO base 1 */
        reg.Value = hw_priv->link->io.BasePort1 & 0x00ff;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
@@ -249,7 +247,7 @@ static void sandisk_set_iobase(local_info_t *local)
        reg.Action = CS_WRITE;
        reg.Offset = 0x12; /* 0x3f2 IO base 2 */
        reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
@@ -301,9 +299,9 @@ static int sandisk_enable_wireless(struct net_device *dev)
        tuple.TupleData = buf;
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
-       if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) ||
-           pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) ||
-           pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) ||
+       if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
+           pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
+           pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
            parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) {
                /* No SanDisk manfid found */
                ret = -ENODEV;
@@ -311,9 +309,9 @@ static int sandisk_enable_wireless(struct net_device *dev)
        }
 
        tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
-       if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) ||
-           pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) ||
-           pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) ||
+       if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
+           pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
+           pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
                parse->longlink_mfc.nfn < 2) {
                /* No multi-function links found */
                ret = -ENODEV;
@@ -328,7 +326,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
        reg.Action = CS_WRITE;
        reg.Offset = CISREG_COR;
        reg.Value = COR_SOFT_RESET;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
@@ -345,7 +343,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
         * will be enabled during the first cor_sreset call.
         */
        reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
@@ -380,7 +378,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
        reg.Action = CS_READ;
        reg.Offset = CISREG_COR;
        reg.Value = 0;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
@@ -392,7 +390,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
 
        reg.Action = CS_WRITE;
        reg.Value |= COR_SOFT_RESET;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
@@ -405,7 +403,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
        reg.Value &= ~COR_SOFT_RESET;
        if (hw_priv->sandisk_connectplus)
                reg.Value |= COR_IREQ_ENA;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
@@ -439,7 +437,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
        reg.Action = CS_READ;
        reg.Offset = CISREG_COR;
        reg.Value = 0;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 "
@@ -452,7 +450,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
 
        reg.Action = CS_WRITE;
        reg.Value |= COR_SOFT_RESET;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 "
@@ -466,7 +464,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
        reg.Action = CS_WRITE;
        reg.Value = hcr;
        reg.Offset = CISREG_CCSR;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 "
@@ -478,7 +476,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
        reg.Action = CS_WRITE;
        reg.Offset = CISREG_COR;
        reg.Value = old_cor & ~COR_SOFT_RESET;
-       res = pcmcia_access_configuration_register(hw_priv->link->handle,
+       res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
        if (res != CS_SUCCESS) {
                printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 "
@@ -501,40 +499,27 @@ static struct prism2_helper_functions prism2_pccard_funcs =
 
 /* allocate local data and register with CardServices
  * initialize dev_link structure, but do not configure the card yet */
-static int prism2_attach(struct pcmcia_device *p_dev)
+static int hostap_cs_probe(struct pcmcia_device *p_dev)
 {
-       dev_link_t *link;
-
-       link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
-       if (link == NULL)
-               return -ENOMEM;
-
-       memset(link, 0, sizeof(dev_link_t));
+       int ret;
 
        PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
-       link->conf.Vcc = 33;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-
-       link->handle = p_dev;
-       p_dev->instance = link;
+       p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       if (prism2_config(link))
+       ret = prism2_config(p_dev);
+       if (ret) {
                PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
+       }
 
-       return 0;
+       return ret;
 }
 
 
-static void prism2_detach(struct pcmcia_device *p_dev)
+static void prism2_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
-
        PDEBUG(DEBUG_FLOW, "prism2_detach\n");
 
-       if (link->state & DEV_CONFIG) {
-               prism2_release((u_long)link);
-       }
+       prism2_release((u_long)link);
 
        /* release net devices */
        if (link->priv) {
@@ -547,7 +532,6 @@ static void prism2_detach(struct pcmcia_device *p_dev)
                prism2_free_local_data(dev);
                kfree(hw_priv);
        }
-       kfree(link);
 }
 
 
@@ -558,7 +542,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 do { int ret = (retf); \
 if (ret != 0) { \
        PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \
-       cs_error(link->handle, fn, ret); \
+       cs_error(link, fn, ret); \
        goto next_entry; \
 } \
 } while (0)
@@ -566,7 +550,7 @@ if (ret != 0) { \
 
 /* run after a CARD_INSERTION event is received to configure the PCMCIA
  * socket and make the device available to the system */
-static int prism2_config(dev_link_t *link)
+static int prism2_config(struct pcmcia_device *link)
 {
        struct net_device *dev;
        struct hostap_interface *iface;
@@ -595,27 +579,24 @@ static int prism2_config(dev_link_t *link)
        tuple.TupleData = buf;
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link->handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link->handle, &tuple, parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
        link->conf.ConfigBase = parse->config.base;
        link->conf.Present = parse->config.rmask[0];
 
        CS_CHECK(GetConfigurationInfo,
-                pcmcia_get_configuration_info(link->handle, &conf));
-       PDEBUG(DEBUG_HW, "%s: %s Vcc=%d (from config)\n", dev_info,
-              ignore_cis_vcc ? "ignoring" : "setting", conf.Vcc);
-       link->conf.Vcc = conf.Vcc;
+                pcmcia_get_configuration_info(link, &conf));
 
        /* Look for an appropriate configuration table entry in the CIS */
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        for (;;) {
                cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
                CFG_CHECK2(GetTupleData,
-                          pcmcia_get_tuple_data(link->handle, &tuple));
+                          pcmcia_get_tuple_data(link, &tuple));
                CFG_CHECK2(ParseTuple,
-                          pcmcia_parse_tuple(link->handle, &tuple, parse));
+                          pcmcia_parse_tuple(link, &tuple, parse));
 
                if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
                        dflt = *cfg;
@@ -650,10 +631,10 @@ static int prism2_config(dev_link_t *link)
                }
 
                if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                                cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
                else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                                dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
                /* Do we need to allocate an interrupt? */
@@ -695,19 +676,19 @@ static int prism2_config(dev_link_t *link)
 
                /* This reserves IO space but doesn't actually enable it */
                CFG_CHECK2(RequestIO,
-                          pcmcia_request_io(link->handle, &link->io));
+                          pcmcia_request_io(link, &link->io));
 
                /* This configuration table entry is OK */
                break;
 
        next_entry:
                CS_CHECK(GetNextTuple,
-                        pcmcia_get_next_tuple(link->handle, &tuple));
+                        pcmcia_get_next_tuple(link, &tuple));
        }
 
        /* Need to allocate net_device before requesting IRQ handler */
        dev = prism2_init_local_data(&prism2_pccard_funcs, 0,
-                                    &handle_to_dev(link->handle));
+                                    &handle_to_dev(link));
        if (dev == NULL)
                goto failed;
        link->priv = dev;
@@ -717,7 +698,7 @@ static int prism2_config(dev_link_t *link)
        local->hw_priv = hw_priv;
        hw_priv->link = link;
        strcpy(hw_priv->node.dev_name, dev->name);
-       link->dev = &hw_priv->node;
+       link->dev_node = &hw_priv->node;
 
        /*
         * Allocate an interrupt line.  Note that this does not assign a
@@ -730,7 +711,7 @@ static int prism2_config(dev_link_t *link)
                link->irq.Handler = prism2_interrupt;
                link->irq.Instance = dev;
                CS_CHECK(RequestIRQ,
-                        pcmcia_request_irq(link->handle, &link->irq));
+                        pcmcia_request_irq(link, &link->irq));
        }
 
        /*
@@ -739,18 +720,17 @@ static int prism2_config(dev_link_t *link)
         * card and host interface into "Memory and IO" mode.
         */
        CS_CHECK(RequestConfiguration,
-                pcmcia_request_configuration(link->handle, &link->conf));
+                pcmcia_request_configuration(link, &link->conf));
 
        dev->irq = link->irq.AssignedIRQ;
        dev->base_addr = link->io.BasePort1;
 
        /* Finally, report what we've done */
-       printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-              dev_info, link->conf.ConfigIndex,
-              link->conf.Vcc / 10, link->conf.Vcc % 10);
-       if (link->conf.Vpp1)
-               printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
-                      link->conf.Vpp1 % 10);
+       printk(KERN_INFO "%s: index 0x%02x: ",
+              dev_info, link->conf.ConfigIndex);
+       if (link->conf.Vpp)
+               printk(", Vpp %d.%d", link->conf.Vpp / 10,
+                      link->conf.Vpp % 10);
        if (link->conf.Attributes & CONF_ENABLE_IRQ)
                printk(", irq %d", link->irq.AssignedIRQ);
        if (link->io.NumPorts1)
@@ -761,9 +741,6 @@ static int prism2_config(dev_link_t *link)
                       link->io.BasePort2+link->io.NumPorts2-1);
        printk("\n");
 
-       link->state |= DEV_CONFIG;
-       link->state &= ~DEV_CONFIG_PENDING;
-
        local->shutdown = 0;
 
        sandisk_enable_wireless(dev);
@@ -778,7 +755,7 @@ static int prism2_config(dev_link_t *link)
        return ret;
 
  cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 
  failed:
        kfree(parse);
@@ -790,7 +767,7 @@ static int prism2_config(dev_link_t *link)
 
 static void prism2_release(u_long arg)
 {
-       dev_link_t *link = (dev_link_t *)arg;
+       struct pcmcia_device *link = (struct pcmcia_device *)arg;
 
        PDEBUG(DEBUG_FLOW, "prism2_release\n");
 
@@ -799,71 +776,54 @@ static void prism2_release(u_long arg)
                struct hostap_interface *iface;
 
                iface = netdev_priv(dev);
-               if (link->state & DEV_CONFIG)
-                       prism2_hw_shutdown(dev, 0);
+               prism2_hw_shutdown(dev, 0);
                iface->local->shutdown = 1;
        }
 
-       if (link->win)
-               pcmcia_release_window(link->win);
-       pcmcia_release_configuration(link->handle);
-       if (link->io.NumPorts1)
-               pcmcia_release_io(link->handle, &link->io);
-       if (link->irq.AssignedIRQ)
-               pcmcia_release_irq(link->handle, &link->irq);
-
-       link->state &= ~DEV_CONFIG;
-
+       pcmcia_disable_device(link);
        PDEBUG(DEBUG_FLOW, "release - done\n");
 }
 
-static int hostap_cs_suspend(struct pcmcia_device *p_dev)
+static int hostap_cs_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = (struct net_device *) link->priv;
        int dev_open = 0;
+       struct hostap_interface *iface = NULL;
 
-       PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
-
-       link->state |= DEV_SUSPEND;
+       if (dev)
+               iface = netdev_priv(dev);
 
-       if (link->state & DEV_CONFIG) {
-               struct hostap_interface *iface = netdev_priv(dev);
-               if (iface && iface->local)
-                       dev_open = iface->local->num_dev_open > 0;
-               if (dev_open) {
-                       netif_stop_queue(dev);
-                       netif_device_detach(dev);
-               }
-               prism2_suspend(dev);
-               pcmcia_release_configuration(link->handle);
+       PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
+       if (iface && iface->local)
+               dev_open = iface->local->num_dev_open > 0;
+       if (dev_open) {
+               netif_stop_queue(dev);
+               netif_device_detach(dev);
        }
+       prism2_suspend(dev);
 
        return 0;
 }
 
-static int hostap_cs_resume(struct pcmcia_device *p_dev)
+static int hostap_cs_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = (struct net_device *) link->priv;
        int dev_open = 0;
+       struct hostap_interface *iface = NULL;
 
-       PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
+       if (dev)
+               iface = netdev_priv(dev);
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               struct hostap_interface *iface = netdev_priv(dev);
-               if (iface && iface->local)
-                       dev_open = iface->local->num_dev_open > 0;
+       PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
 
-               pcmcia_request_configuration(link->handle, &link->conf);
+       if (iface && iface->local)
+               dev_open = iface->local->num_dev_open > 0;
 
-               prism2_hw_shutdown(dev, 1);
-               prism2_hw_config(dev, dev_open ? 0 : 1);
-               if (dev_open) {
-                       netif_device_attach(dev);
-                       netif_start_queue(dev);
-               }
+       prism2_hw_shutdown(dev, 1);
+       prism2_hw_config(dev, dev_open ? 0 : 1);
+       if (dev_open) {
+               netif_device_attach(dev);
+               netif_start_queue(dev);
        }
 
        return 0;
@@ -930,7 +890,7 @@ static struct pcmcia_driver hostap_driver = {
        .drv            = {
                .name   = "hostap_cs",
        },
-       .probe          = prism2_attach,
+       .probe          = hostap_cs_probe,
        .remove         = prism2_detach,
        .owner          = THIS_MODULE,
        .id_table       = hostap_cs_ids,
index 75ce6dd..9343d97 100644 (file)
@@ -190,8 +190,8 @@ module_param(mem_speed, int, 0);
 /*====================================================================*/
 
 /* PCMCIA (Card Services) related functions */
-static void netwave_release(dev_link_t *link);     /* Card removal */
-static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card 
+static void netwave_release(struct pcmcia_device *link);     /* Card removal */
+static int netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card
                                                                                                           insertion */
 static void netwave_detach(struct pcmcia_device *p_dev);    /* Destroy instance */
 
@@ -221,10 +221,10 @@ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 
 /*
-   A dev_link_t structure has fields for most things that are needed
+   A struct pcmcia_device structure has fields for most things that are needed
    to keep track of a socket, but there will usually be some device
    specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
+   'priv' pointer in a struct pcmcia_device structure can be used to point to
    a device-specific private data structure, like this.
 
    A driver needs to provide a dev_node_t structure for each device
@@ -232,7 +232,7 @@ static void set_multicast_list(struct net_device *dev);
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally can't be allocated dynamically.
 */
@@ -268,7 +268,7 @@ struct site_survey {
 };     
    
 typedef struct netwave_private {
-    dev_link_t link;
+       struct pcmcia_device    *p_dev;
     spinlock_t spinlock;       /* Serialize access to the hardware (SMP) */
     dev_node_t node;
     u_char     __iomem *ramBase;
@@ -376,20 +376,19 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
  *     configure the card at this point -- we wait until we receive a
  *     card insertion event.
  */
-static int netwave_attach(struct pcmcia_device *p_dev)
+static int netwave_probe(struct pcmcia_device *link)
 {
-    dev_link_t *link;
     struct net_device *dev;
     netwave_private *priv;
 
     DEBUG(0, "netwave_attach()\n");
 
-    /* Initialize the dev_link_t structure */
+    /* Initialize the struct pcmcia_device structure */
     dev = alloc_etherdev(sizeof(netwave_private));
     if (!dev)
        return -ENOMEM;
     priv = netdev_priv(dev);
-    link = &priv->link;
+    priv->p_dev = link;
     link->priv = dev;
 
     /* The io structure describes IO port mapping */
@@ -406,7 +405,6 @@ static int netwave_attach(struct pcmcia_device *p_dev)
     
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
@@ -430,13 +428,7 @@ static int netwave_attach(struct pcmcia_device *p_dev)
     dev->stop = &netwave_close;
     link->irq.Instance = dev;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    netwave_pcmcia_config( link);
-
-    return 0;
+    return netwave_pcmcia_config( link);
 } /* netwave_attach */
 
 /*
@@ -447,17 +439,15 @@ static int netwave_attach(struct pcmcia_device *p_dev)
  *    structures are freed.  Otherwise, the structures will be freed
  *    when the device is released.
  */
-static void netwave_detach(struct pcmcia_device *p_dev)
+static void netwave_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
        DEBUG(0, "netwave_detach(0x%p)\n", link);
 
-       if (link->state & DEV_CONFIG)
-               netwave_release(link);
+       netwave_release(link);
 
-       if (link->dev)
+       if (link->dev_node)
                unregister_netdev(dev);
 
        free_netdev(dev);
@@ -743,8 +733,7 @@ static const struct iw_handler_def  netwave_handler_def =
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void netwave_pcmcia_config(dev_link_t *link) {
-    client_handle_t handle = link->handle;
+static int netwave_pcmcia_config(struct pcmcia_device *link) {
     struct net_device *dev = link->priv;
     netwave_private *priv = netdev_priv(dev);
     tuple_t tuple;
@@ -766,15 +755,12 @@ static void netwave_pcmcia_config(dev_link_t *link) {
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     /*
      *  Try allocating IO ports.  This tries a few fixed addresses.
      *  If you want, you can also read the card's config table to
@@ -782,11 +768,11 @@ static void netwave_pcmcia_config(dev_link_t *link) {
      */
     for (i = j = 0x0; j < 0x400; j += 0x20) {
        link->io.BasePort1 = j ^ 0x300;
-       i = pcmcia_request_io(link->handle, &link->io);
+       i = pcmcia_request_io(link, &link->io);
        if (i == CS_SUCCESS) break;
     }
     if (i != CS_SUCCESS) {
-       cs_error(link->handle, RequestIO, i);
+       cs_error(link, RequestIO, i);
        goto failed;
     }
 
@@ -794,16 +780,16 @@ static void netwave_pcmcia_config(dev_link_t *link) {
      *  Now allocate an interrupt line.  Note that this does not
      *  actually assign a handler to the interrupt.
      */
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
     /*
      *  This actually configures the PCMCIA socket -- setting up
      *  the I/O windows and the interrupt mapping.
      */
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     /*
-     *  Allocate a 32K memory window.  Note that the dev_link_t
+     *  Allocate a 32K memory window.  Note that the struct pcmcia_device
      *  structure provides space for one window handle -- if your
      *  device needs several windows, you'll need to keep track of
      *  the handles in your private data structure, dev->priv.
@@ -813,7 +799,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
     req.Base = 0; req.Size = 0x8000;
     req.AccessSpeed = mem_speed;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
     mem.CardOffset = 0x20000; mem.Page = 0; 
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
 
@@ -823,7 +809,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
 
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if (register_netdev(dev) != 0) {
        printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
@@ -831,8 +817,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
     }
 
     strcpy(priv->node.dev_name, dev->name);
-    link->dev = &priv->node;
-    link->state &= ~DEV_CONFIG_PENDING;
+    link->dev_node = &priv->node;
 
     /* Reset card before reading physical address */
     netwave_doreset(dev->base_addr, ramBase);
@@ -852,12 +837,13 @@ static void netwave_pcmcia_config(dev_link_t *link) {
     printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n", 
           get_uint16(ramBase + NETWAVE_EREG_ARW),
           get_uint16(ramBase + NETWAVE_EREG_ARW+2));
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     netwave_release(link);
+    return -ENODEV;
 } /* netwave_pcmcia_config */
 
 /*
@@ -867,52 +853,35 @@ failed:
  *    device, and release the PCMCIA configuration.  If the device is
  *    still open, this will be postponed until it is closed.
  */
-static void netwave_release(dev_link_t *link)
+static void netwave_release(struct pcmcia_device *link)
 {
-    struct net_device *dev = link->priv;
-    netwave_private *priv = netdev_priv(dev);
-
-    DEBUG(0, "netwave_release(0x%p)\n", link);
+       struct net_device *dev = link->priv;
+       netwave_private *priv = netdev_priv(dev);
 
-    /* Don't bother checking to see if these succeed or not */
-    if (link->win) {
-       iounmap(priv->ramBase);
-       pcmcia_release_window(link->win);
-    }
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
+       DEBUG(0, "netwave_release(0x%p)\n", link);
 
-    link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
+       if (link->win)
+               iounmap(priv->ramBase);
 }
 
-static int netwave_suspend(struct pcmcia_device *p_dev)
+static int netwave_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-       }
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int netwave_resume(struct pcmcia_device *p_dev)
+static int netwave_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       netwave_reset(dev);
-                       netif_device_attach(dev);
-               }
+       if (link->open) {
+               netwave_reset(dev);
+               netif_device_attach(dev);
        }
 
        return 0;
@@ -1119,7 +1088,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs
     u_char __iomem *ramBase;
     struct net_device *dev = (struct net_device *)dev_id;
     struct netwave_private *priv = netdev_priv(dev);
-    dev_link_t *link = &priv->link;
+    struct pcmcia_device *link = priv->p_dev;
     int i;
     
     if (!netif_device_present(dev))
@@ -1138,7 +1107,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs
        
         status = inb(iobase + NETWAVE_REG_ASR);
                
-       if (!DEV_OK(link)) {
+       if (!pcmcia_dev_present(link)) {
            DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x "
                  "from removed or suspended card!\n", status);
            break;
@@ -1373,11 +1342,11 @@ static int netwave_rx(struct net_device *dev)
 
 static int netwave_open(struct net_device *dev) {
     netwave_private *priv = netdev_priv(dev);
-    dev_link_t *link = &priv->link;
+    struct pcmcia_device *link = priv->p_dev;
 
     DEBUG(1, "netwave_open: starting.\n");
     
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
        return -ENODEV;
 
     link->open++;
@@ -1390,7 +1359,7 @@ static int netwave_open(struct net_device *dev) {
 
 static int netwave_close(struct net_device *dev) {
     netwave_private *priv = netdev_priv(dev);
-    dev_link_t *link = &priv->link;
+    struct pcmcia_device *link = priv->p_dev;
 
     DEBUG(1, "netwave_close: finishing.\n");
 
@@ -1411,7 +1380,7 @@ static struct pcmcia_driver netwave_driver = {
        .drv            = {
                .name   = "netwave_cs",
        },
-       .probe          = netwave_attach,
+       .probe          = netwave_probe,
        .remove         = netwave_detach,
        .id_table       = netwave_ids,
        .suspend        = netwave_suspend,
index ec6f2a4..434f7d7 100644 (file)
@@ -49,7 +49,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket
 /* PCMCIA specific device information (goes in the card field of
  * struct orinoco_private */
 struct orinoco_pccard {
-       dev_link_t link;
+       struct pcmcia_device    *p_dev;
        dev_node_t node;
 
        /* Used to handle hard reset */
@@ -63,8 +63,8 @@ struct orinoco_pccard {
 /* Function prototypes                                             */
 /********************************************************************/
 
-static void orinoco_cs_config(dev_link_t *link);
-static void orinoco_cs_release(dev_link_t *link);
+static int orinoco_cs_config(struct pcmcia_device *link);
+static void orinoco_cs_release(struct pcmcia_device *link);
 static void orinoco_cs_detach(struct pcmcia_device *p_dev);
 
 /********************************************************************/
@@ -75,13 +75,13 @@ static int
 orinoco_cs_hard_reset(struct orinoco_private *priv)
 {
        struct orinoco_pccard *card = priv->card;
-       dev_link_t *link = &card->link;
+       struct pcmcia_device *link = card->p_dev;
        int err;
 
        /* We need atomic ops here, because we're not holding the lock */
        set_bit(0, &card->hard_reset_in_progress);
 
-       err = pcmcia_reset_card(link->handle, NULL);
+       err = pcmcia_reset_card(link, NULL);
        if (err)
                return err;
 
@@ -104,12 +104,11 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
  * configure the card at this point -- we wait until we receive a card
  * insertion event.  */
 static int
-orinoco_cs_attach(struct pcmcia_device *p_dev)
+orinoco_cs_probe(struct pcmcia_device *link)
 {
        struct net_device *dev;
        struct orinoco_private *priv;
        struct orinoco_pccard *card;
-       dev_link_t *link;
 
        dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
        if (! dev)
@@ -118,7 +117,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
        card = priv->card;
 
        /* Link both structures together */
-       link = &card->link;
+       card->p_dev = link;
        link->priv = dev;
 
        /* Interrupt setup */
@@ -135,16 +134,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
        link->conf.Attributes = 0;
        link->conf.IntType = INT_MEMORY_AND_IO;
 
-       /* Register with Card Services */
-       link->next = NULL;
-
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       orinoco_cs_config(link);
-
-       return 0;
+       return orinoco_cs_config(link);
 }                              /* orinoco_cs_attach */
 
 /*
@@ -153,16 +143,14 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void orinoco_cs_detach(struct pcmcia_device *p_dev)
+static void orinoco_cs_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       if (link->state & DEV_CONFIG)
-               orinoco_cs_release(link);
+       orinoco_cs_release(link);
 
-       DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
-       if (link->dev) {
+       DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
+       if (link->dev_node) {
                DEBUG(0, PFX "About to unregister net device %p\n",
                      dev);
                unregister_netdev(dev);
@@ -180,11 +168,10 @@ static void orinoco_cs_detach(struct pcmcia_device *p_dev)
                last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
        } while (0)
 
-static void
-orinoco_cs_config(dev_link_t *link)
+static int
+orinoco_cs_config(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
-       client_handle_t handle = link->handle;
        struct orinoco_private *priv = netdev_priv(dev);
        struct orinoco_pccard *card = priv->card;
        hermes_t *hw = &priv->hw;
@@ -196,7 +183,7 @@ orinoco_cs_config(dev_link_t *link)
        cisparse_t parse;
        void __iomem *mem;
 
-       CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+       CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
 
        /*
         * This reads the card's CONFIG tuple to find its
@@ -207,19 +194,15 @@ orinoco_cs_config(dev_link_t *link)
        tuple.TupleData = buf;
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
        /* Look up the current Vcc */
        CS_CHECK(GetConfigurationInfo,
-                pcmcia_get_configuration_info(handle, &conf));
-       link->conf.Vcc = conf.Vcc;
+                pcmcia_get_configuration_info(link, &conf));
 
        /*
         * In this loop, we scan the CIS for configuration table
@@ -236,13 +219,13 @@ orinoco_cs_config(dev_link_t *link)
         * implementation-defined details.
         */
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        while (1) {
                cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
                cistpl_cftable_entry_t dflt = { .index = 0 };
 
-               if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
-                   || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
+               if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
+                   || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
                        goto next_entry;
 
                if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -274,10 +257,10 @@ orinoco_cs_config(dev_link_t *link)
                }
 
                if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                            cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
                else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                            dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
                
                /* Do we need to allocate an interrupt? */
@@ -307,7 +290,7 @@ orinoco_cs_config(dev_link_t *link)
                        }
 
                        /* This reserves IO space but doesn't actually enable it */
-                       if (pcmcia_request_io(link->handle, &link->io) != 0)
+                       if (pcmcia_request_io(link, &link->io) != 0)
                                goto next_entry;
                }
 
@@ -317,9 +300,8 @@ orinoco_cs_config(dev_link_t *link)
                break;
                
        next_entry:
-               if (link->io.NumPorts1)
-                       pcmcia_release_io(link->handle, &link->io);
-               last_ret = pcmcia_get_next_tuple(handle, &tuple);
+               pcmcia_disable_device(link);
+               last_ret = pcmcia_get_next_tuple(link, &tuple);
                if (last_ret  == CS_NO_MORE_ITEMS) {
                        printk(KERN_ERR PFX "GetNextTuple(): No matching "
                               "CIS configuration.  Maybe you need the "
@@ -333,7 +315,7 @@ orinoco_cs_config(dev_link_t *link)
         * a handler to the interrupt, unless the 'Handler' member of
         * the irq structure is initialized.
         */
-       CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+       CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
        /* We initialize the hermes structure before completing PCMCIA
         * configuration just in case the interrupt handler gets
@@ -350,7 +332,7 @@ orinoco_cs_config(dev_link_t *link)
         * card and host interface into "Memory and IO" mode.
         */
        CS_CHECK(RequestConfiguration,
-                pcmcia_request_configuration(link->handle, &link->conf));
+                pcmcia_request_configuration(link, &link->conf));
 
        /* Ok, we have the configuration, prepare to register the netdev */
        dev->base_addr = link->io.BasePort1;
@@ -358,7 +340,7 @@ orinoco_cs_config(dev_link_t *link)
        SET_MODULE_OWNER(dev);
        card->node.major = card->node.minor = 0;
 
-       SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+       SET_NETDEV_DEV(dev, &handle_to_dev(link));
        /* Tell the stack we exist */
        if (register_netdev(dev) != 0) {
                printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -366,20 +348,18 @@ orinoco_cs_config(dev_link_t *link)
        }
 
        /* At this point, the dev_node_t structure(s) needs to be
-        * initialized and arranged in a linked list at link->dev. */
+        * initialized and arranged in a linked list at link->dev_node. */
        strcpy(card->node.dev_name, dev->name);
-       link->dev = &card->node; /* link->dev being non-NULL is also
+       link->dev_node = &card->node; /* link->dev_node being non-NULL is also
                                     used to indicate that the
                                     net_device has been registered */
-       link->state &= ~DEV_CONFIG_PENDING;
 
        /* Finally, report what we've done */
-       printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
-              dev->name, link->conf.ConfigIndex,
-              link->conf.Vcc / 10, link->conf.Vcc % 10);
-       if (link->conf.Vpp1)
-               printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
-                      link->conf.Vpp1 % 10);
+       printk(KERN_DEBUG "%s: index 0x%02x: ",
+              dev->name, link->conf.ConfigIndex);
+       if (link->conf.Vpp)
+               printk(", Vpp %d.%d", link->conf.Vpp / 10,
+                      link->conf.Vpp % 10);
        printk(", irq %d", link->irq.AssignedIRQ);
        if (link->io.NumPorts1)
                printk(", io 0x%04x-0x%04x", link->io.BasePort1,
@@ -389,13 +369,14 @@ orinoco_cs_config(dev_link_t *link)
                       link->io.BasePort2 + link->io.NumPorts2 - 1);
        printk("\n");
 
-       return;
+       return 0;
 
  cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 
  failed:
        orinoco_cs_release(link);
+       return -ENODEV;
 }                              /* orinoco_cs_config */
 
 /*
@@ -404,7 +385,7 @@ orinoco_cs_config(dev_link_t *link)
  * still open, this will be postponed until it is closed.
  */
 static void
-orinoco_cs_release(dev_link_t *link)
+orinoco_cs_release(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
        struct orinoco_private *priv = netdev_priv(dev);
@@ -416,88 +397,68 @@ orinoco_cs_release(dev_link_t *link)
        priv->hw_unavailable++;
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* Don't bother checking to see if these succeed or not */
-       pcmcia_release_configuration(link->handle);
-       if (link->io.NumPorts1)
-               pcmcia_release_io(link->handle, &link->io);
-       if (link->irq.AssignedIRQ)
-               pcmcia_release_irq(link->handle, &link->irq);
-       link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
        if (priv->hw.iobase)
                ioport_unmap(priv->hw.iobase);
 }                              /* orinoco_cs_release */
 
-static int orinoco_cs_suspend(struct pcmcia_device *p_dev)
+static int orinoco_cs_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
        struct orinoco_private *priv = netdev_priv(dev);
        struct orinoco_pccard *card = priv->card;
        int err = 0;
        unsigned long flags;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               /* This is probably racy, but I can't think of
-                  a better way, short of rewriting the PCMCIA
-                  layer to not suck :-( */
-               if (! test_bit(0, &card->hard_reset_in_progress)) {
-                       spin_lock_irqsave(&priv->lock, flags);
+       /* This is probably racy, but I can't think of
+          a better way, short of rewriting the PCMCIA
+          layer to not suck :-( */
+       if (! test_bit(0, &card->hard_reset_in_progress)) {
+               spin_lock_irqsave(&priv->lock, flags);
 
-                       err = __orinoco_down(dev);
-                       if (err)
-                               printk(KERN_WARNING "%s: Error %d downing interface\n",
-                                      dev->name, err);
+               err = __orinoco_down(dev);
+               if (err)
+                       printk(KERN_WARNING "%s: Error %d downing interface\n",
+                              dev->name, err);
 
-                       netif_device_detach(dev);
-                       priv->hw_unavailable++;
+               netif_device_detach(dev);
+               priv->hw_unavailable++;
 
-                       spin_unlock_irqrestore(&priv->lock, flags);
-               }
-
-               pcmcia_release_configuration(link->handle);
+               spin_unlock_irqrestore(&priv->lock, flags);
        }
 
        return 0;
 }
 
-static int orinoco_cs_resume(struct pcmcia_device *p_dev)
+static int orinoco_cs_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
        struct orinoco_private *priv = netdev_priv(dev);
        struct orinoco_pccard *card = priv->card;
        int err = 0;
        unsigned long flags;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               /* FIXME: should we double check that this is
-                * the same card as we had before */
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-               if (! test_bit(0, &card->hard_reset_in_progress)) {
-                       err = orinoco_reinit_firmware(dev);
-                       if (err) {
-                               printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
-                                      dev->name, err);
-                               return -EIO;
-                       }
-
-                       spin_lock_irqsave(&priv->lock, flags);
+       if (! test_bit(0, &card->hard_reset_in_progress)) {
+               err = orinoco_reinit_firmware(dev);
+               if (err) {
+                       printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+                              dev->name, err);
+                       return -EIO;
+               }
 
-                       netif_device_attach(dev);
-                       priv->hw_unavailable--;
+               spin_lock_irqsave(&priv->lock, flags);
 
-                       if (priv->open && ! priv->hw_unavailable) {
-                               err = __orinoco_up(dev);
-                               if (err)
-                                       printk(KERN_ERR "%s: Error %d restarting card\n",
-                                              dev->name, err);
-                       }
+               netif_device_attach(dev);
+               priv->hw_unavailable--;
 
-                       spin_unlock_irqrestore(&priv->lock, flags);
+               if (priv->open && ! priv->hw_unavailable) {
+                       err = __orinoco_up(dev);
+                       if (err)
+                               printk(KERN_ERR "%s: Error %d restarting card\n",
+                                      dev->name, err);
                }
+
+               spin_unlock_irqrestore(&priv->lock, flags);
        }
 
        return 0;
@@ -604,7 +565,7 @@ static struct pcmcia_driver orinoco_driver = {
        .drv            = {
                .name   = DRIVER_NAME,
        },
-       .probe          = orinoco_cs_attach,
+       .probe          = orinoco_cs_probe,
        .remove         = orinoco_cs_detach,
        .id_table       = orinoco_cs_ids,
        .suspend        = orinoco_cs_suspend,
index 7880d8c..879eb42 100644 (file)
@@ -90,8 +90,8 @@ module_param(pc_debug, int, 0);
 #define DEBUG(n, args...)
 #endif
 /** Prototypes based on PCMCIA skeleton driver *******************************/
-static void ray_config(dev_link_t *link);
-static void ray_release(dev_link_t *link);
+static int ray_config(struct pcmcia_device *link);
+static void ray_release(struct pcmcia_device *link);
 static void ray_detach(struct pcmcia_device *p_dev);
 
 /***** Prototypes indicated by device structure ******************************/
@@ -190,20 +190,17 @@ static int bc;
 static char *phy_addr = NULL;
 
 
-/* A linked list of "instances" of the ray device.  Each actual
-   PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
-*/
-static dev_link_t *dev_list = NULL;
-
-/* A dev_link_t structure has fields for most things that are needed
+/* A struct pcmcia_device structure has fields for most things that are needed
    to keep track of a socket, but there will usually be some device
    specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
+   'priv' pointer in a struct pcmcia_device structure can be used to point to
    a device-specific private data structure, like this.
 */
 static unsigned int ray_mem_speed = 500;
 
+/* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */
+static struct pcmcia_device *this_device = NULL;
+
 MODULE_AUTHOR("Corey Thomas <corey@world.std.com>");
 MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver");
 MODULE_LICENSE("GPL");
@@ -306,56 +303,46 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.
     configure the card at this point -- we wait until we receive a
     card insertion event.
 =============================================================================*/
-static int ray_attach(struct pcmcia_device *p_dev)
+static int ray_probe(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link;
     ray_dev_t *local;
     struct net_device *dev;
-    
-    DEBUG(1, "ray_attach()\n");
 
-    /* Initialize the dev_link_t structure */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-
-    if (!link)
-           return -ENOMEM;
+    DEBUG(1, "ray_attach()\n");
 
     /* Allocate space for private device-specific data */
     dev = alloc_etherdev(sizeof(ray_dev_t));
-
     if (!dev)
            goto fail_alloc_dev;
 
     local = dev->priv;
-
-    memset(link, 0, sizeof(struct dev_link_t));
+    local->finder = p_dev;
 
     /* The io structure describes IO port mapping. None used here */
-    link->io.NumPorts1 = 0;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.IOAddrLines = 5;
+    p_dev->io.NumPorts1 = 0;
+    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+    p_dev->io.IOAddrLines = 5;
 
     /* Interrupt setup. For PCMCIA, driver takes what's given */
-    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-    link->irq.Handler = &ray_interrupt;
+    p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+    p_dev->irq.Handler = &ray_interrupt;
 
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
-
-    link->priv = dev;
-    link->irq.Instance = dev;
+    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->conf.IntType = INT_MEMORY_AND_IO;
+    p_dev->conf.ConfigIndex = 1;
+    p_dev->conf.Present = PRESENT_OPTION;
+
+    p_dev->priv = dev;
+    p_dev->irq.Instance = dev;
     
-    local->finder = link;
+    local->finder = p_dev;
     local->card_status = CARD_INSERTED;
     local->authentication_state = UNAUTHENTICATED;
     local->num_multi = 0;
-    DEBUG(2,"ray_attach link = %p,  dev = %p,  local = %p, intr = %p\n",
-          link,dev,local,&ray_interrupt);
+    DEBUG(2,"ray_attach p_dev = %p,  dev = %p,  local = %p, intr = %p\n",
+          p_dev,dev,local,&ray_interrupt);
 
     /* Raylink entries in the device structure */
     dev->hard_start_xmit = &ray_dev_start_xmit;
@@ -379,16 +366,10 @@ static int ray_attach(struct pcmcia_device *p_dev)
 
     init_timer(&local->timer);
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    ray_config(link);
-
-    return 0;
+    this_device = p_dev;
+    return ray_config(p_dev);
 
 fail_alloc_dev:
-    kfree(link);
     return -ENOMEM;
 } /* ray_attach */
 /*=============================================================================
@@ -397,37 +378,25 @@ fail_alloc_dev:
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 =============================================================================*/
-static void ray_detach(struct pcmcia_device *p_dev)
+static void ray_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-    dev_link_t **linkp;
     struct net_device *dev;
     ray_dev_t *local;
 
     DEBUG(1, "ray_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-        if (*linkp == link) break;
-    if (*linkp == NULL)
-        return;
 
+    this_device = NULL;
     dev = link->priv;
 
-    if (link->state & DEV_CONFIG) {
-           ray_release(link);
+    ray_release(link);
 
-           local = (ray_dev_t *)dev->priv;
-            del_timer(&local->timer);
-    }
+    local = (ray_dev_t *)dev->priv;
+    del_timer(&local->timer);
 
-    /* Unlink device structure, free pieces */
-    *linkp = link->next;
     if (link->priv) {
-       if (link->dev) unregister_netdev(dev);
+       if (link->dev_node) unregister_netdev(dev);
         free_netdev(dev);
     }
-    kfree(link);
     DEBUG(2,"ray_cs ray_detach ending\n");
 } /* ray_detach */
 /*=============================================================================
@@ -438,9 +407,8 @@ static void ray_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 #define MAX_TUPLE_SIZE 128
-static void ray_config(dev_link_t *link)
+static int ray_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     tuple_t tuple;
     cisparse_t parse;
     int last_fn = 0, last_ret = 0;
@@ -455,48 +423,45 @@ static void ray_config(dev_link_t *link)
 
     /* This reads the card's CONFIG tuple to find its configuration regs */
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     tuple.TupleData = buf;
     tuple.TupleDataMax = MAX_TUPLE_SIZE;
     tuple.TupleOffset = 0;
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
 
     /* Determine card type and firmware version */
     buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0;
     tuple.DesiredTuple = CISTPL_VERS_1;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     tuple.TupleData = buf;
     tuple.TupleDataMax = MAX_TUPLE_SIZE;
     tuple.TupleOffset = 2;
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
 
     for (i=0; i<tuple.TupleDataLen - 4; i++) 
         if (buf[i] == 0) buf[i] = ' ';
     printk(KERN_INFO "ray_cs Detected: %s\n",buf);
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     /* Now allocate an interrupt line.  Note that this does not
        actually assign a handler to the interrupt.
     */
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     dev->irq = link->irq.AssignedIRQ;
     
     /* This actually configures the PCMCIA socket -- setting up
        the I/O windows and the interrupt mapping.
     */
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
 /*** Set up 32k window for shared memory (transmit and control) ************/
     req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
     req.Base = 0;
     req.Size = 0x8000;
     req.AccessSpeed = ray_mem_speed;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
     mem.CardOffset = 0x0000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
     local->sram = ioremap(req.Base,req.Size);
@@ -506,7 +471,7 @@ static void ray_config(dev_link_t *link)
     req.Base = 0;
     req.Size = 0x4000;
     req.AccessSpeed = ray_mem_speed;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->rmem_handle));
     mem.CardOffset = 0x8000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem));
     local->rmem = ioremap(req.Base,req.Size);
@@ -516,7 +481,7 @@ static void ray_config(dev_link_t *link)
     req.Base = 0;
     req.Size = 0x1000;
     req.AccessSpeed = ray_mem_speed;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->amem_handle));
     mem.CardOffset = 0x0000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem));
     local->amem = ioremap(req.Base,req.Size);
@@ -526,32 +491,32 @@ static void ray_config(dev_link_t *link)
     DEBUG(3,"ray_config amem=%p\n",local->amem);
     if (ray_init(dev) < 0) {
         ray_release(link);
-        return;
+        return -ENODEV;
     }
 
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
     i = register_netdev(dev);
     if (i != 0) {
         printk("ray_config register_netdev() failed\n");
         ray_release(link);
-        return;
+        return i;
     }
 
     strcpy(local->node.dev_name, dev->name);
-    link->dev = &local->node;
+    link->dev_node = &local->node;
 
-    link->state &= ~DEV_CONFIG_PENDING;
     printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ",
        dev->name, dev->irq);
     for (i = 0; i < 6; i++)
     printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
 
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 
     ray_release(link);
+    return -ENODEV;
 } /* ray_config */
 
 static inline struct ccs __iomem *ccs_base(ray_dev_t *dev)
@@ -578,9 +543,9 @@ static int ray_init(struct net_device *dev)
     UCHAR *p;
     struct ccs __iomem *pccs;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     DEBUG(1, "ray_init(0x%p)\n", dev);
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(0,"ray_init - device not present\n");
         return -1;
     }
@@ -640,10 +605,10 @@ static int dl_startup_params(struct net_device *dev)
     int ccsindex;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     struct ccs __iomem *pccs;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
     DEBUG(1,"dl_startup_params entered\n");
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs dl_startup_params - device not present\n");
         return -1;
     }
@@ -747,9 +712,9 @@ static void verify_dl_startup(u_long data)
     ray_dev_t *local = (ray_dev_t *)data;
     struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs;
     UCHAR status;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs verify_dl_startup - device not present\n");
         return;
     }
@@ -787,8 +752,8 @@ static void start_net(u_long data)
     ray_dev_t *local = (ray_dev_t *)data;
     struct ccs __iomem *pccs;
     int ccsindex;
-    dev_link_t *link = local->finder;
-    if (!(link->state & DEV_PRESENT)) {
+    struct pcmcia_device *link = local->finder;
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs start_net - device not present\n");
         return;
     }
@@ -814,9 +779,9 @@ static void join_net(u_long data)
 
     struct ccs __iomem *pccs;
     int ccsindex;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs join_net - device not present\n");
         return;
     }
@@ -840,7 +805,7 @@ static void join_net(u_long data)
     device, and release the PCMCIA configuration.  If the device is
     still open, this will be postponed until it is closed.
 =============================================================================*/
-static void ray_release(dev_link_t *link)
+static void ray_release(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv; 
     ray_dev_t *local = dev->priv;
@@ -849,56 +814,38 @@ static void ray_release(dev_link_t *link)
     DEBUG(1, "ray_release(0x%p)\n", link);
 
     del_timer(&local->timer);
-    link->state &= ~DEV_CONFIG;
 
     iounmap(local->sram);
     iounmap(local->rmem);
     iounmap(local->amem);
     /* Do bother checking to see if these succeed or not */
-    i = pcmcia_release_window(link->win);
-    if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(link->win) ret = %x\n",i);
     i = pcmcia_release_window(local->amem_handle);
     if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
     i = pcmcia_release_window(local->rmem_handle);
     if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
-    i = pcmcia_release_configuration(link->handle);
-    if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseConfiguration ret = %x\n",i);
-    i = pcmcia_release_irq(link->handle, &link->irq);
-    if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i);
+    pcmcia_disable_device(link);
 
     DEBUG(2,"ray_release ending\n");
 }
 
-static int ray_suspend(struct pcmcia_device *p_dev)
+static int ray_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-
-               pcmcia_release_configuration(link->handle);
-        }
-
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int ray_resume(struct pcmcia_device *p_dev)
+static int ray_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       ray_reset(dev);
-                       netif_device_attach(dev);
-               }
-        }
+       if (link->open) {
+               ray_reset(dev);
+               netif_device_attach(dev);
+       }
 
        return 0;
 }
@@ -910,10 +857,10 @@ int ray_dev_init(struct net_device *dev)
     int i;
 #endif /* RAY_IMMEDIATE_INIT */
     ray_dev_t *local = dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
     DEBUG(1,"ray_dev_init(dev=%p)\n",dev);
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_dev_init - device not present\n");
         return -1;
     }
@@ -944,10 +891,10 @@ int ray_dev_init(struct net_device *dev)
 static int ray_dev_config(struct net_device *dev, struct ifmap *map)
 {
     ray_dev_t *local = dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     /* Dummy routine to satisfy device structure */
     DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map);
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_dev_config - device not present\n");
         return -1;
     }
@@ -958,10 +905,10 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map)
 static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     ray_dev_t *local = dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     short length = skb->len;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_dev_start_xmit - device not present\n");
         return -1;
     }
@@ -1570,7 +1517,7 @@ static int ray_commit(struct net_device *dev,
 static iw_stats * ray_get_wireless_stats(struct net_device *   dev)
 {
   ray_dev_t *  local = (ray_dev_t *) dev->priv;
-  dev_link_t *link = local->finder;
+  struct pcmcia_device *link = local->finder;
   struct status __iomem *p = local->sram + STATUS_BASE;
 
   if(local == (ray_dev_t *) NULL)
@@ -1588,7 +1535,7 @@ static iw_stats * ray_get_wireless_stats(struct net_device *      dev)
     }
 #endif /* WIRELESS_SPY */
 
-  if((link->state & DEV_PRESENT)) {
+  if(pcmcia_dev_present(link)) {
     local->wstats.qual.noise = readb(&p->rxnoise);
     local->wstats.qual.updated |= 4;
   }
@@ -1657,18 +1604,14 @@ static const struct iw_handler_def      ray_handler_def =
 /*===========================================================================*/
 static int ray_open(struct net_device *dev)
 {
-    dev_link_t *link;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
+    struct pcmcia_device *link;
+    link = local->finder;
     
     DEBUG(1, "ray_open('%s')\n", dev->name);
 
-    for (link = dev_list; link; link = link->next)
-        if (link->priv == dev) break;
-    if (!DEV_OK(link)) {
-        return -ENODEV;
-    }
-
-    if (link->open == 0) local->num_multi = 0;
+    if (link->open == 0)
+           local->num_multi = 0;
     link->open++;
 
     /* If the card is not started, time to start it ! - Jean II */
@@ -1695,15 +1638,12 @@ static int ray_open(struct net_device *dev)
 /*===========================================================================*/
 static int ray_dev_close(struct net_device *dev)
 {
-    dev_link_t *link;
+    ray_dev_t *local = (ray_dev_t *)dev->priv;
+    struct pcmcia_device *link;
+    link = local->finder;
 
     DEBUG(1, "ray_dev_close('%s')\n", dev->name);
 
-    for (link = dev_list; link; link = link->next)
-        if (link->priv == dev) break;
-    if (link == NULL)
-        return -ENODEV;
-
     link->open--;
     netif_stop_queue(dev);
 
@@ -1725,9 +1665,9 @@ static void ray_reset(struct net_device *dev) {
 static int interrupt_ecf(ray_dev_t *local, int ccs)
 {
     int i = 50;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs interrupt_ecf - device not present\n");
         return -1;
     }
@@ -1752,9 +1692,9 @@ static int get_free_tx_ccs(ray_dev_t *local)
 {
     int i;
     struct ccs __iomem *pccs = ccs_base(local);
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n");
         return ECARDGONE;
     }
@@ -1783,9 +1723,9 @@ static int get_free_ccs(ray_dev_t *local)
 {
     int i;
     struct ccs __iomem *pccs = ccs_base(local);
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs get_free_ccs - device not present\n");
         return ECARDGONE;
     }
@@ -1858,9 +1798,9 @@ static int parse_addr(char *in_str, UCHAR *out)
 static struct net_device_stats *ray_get_stats(struct net_device *dev)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     struct status __iomem *p = local->sram + STATUS_BASE;
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs net_device_stats - device not present\n");
         return &local->stats;
     }
@@ -1888,12 +1828,12 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev)
 static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     int ccsindex;
     int i;
     struct ccs __iomem *pccs;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_update_parm - device not present\n");
         return;
     }
@@ -1925,10 +1865,10 @@ static void ray_update_multi_list(struct net_device *dev, int all)
     struct ccs __iomem *pccs;
     int i = 0;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     void __iomem *p = local->sram + HOST_TO_ECF_BASE;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_update_multi_list - device not present\n");
         return;
     }
@@ -2005,7 +1945,7 @@ static void set_multicast_list(struct net_device *dev)
 static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
     struct net_device *dev = (struct net_device *)dev_id;
-    dev_link_t *link;
+    struct pcmcia_device *link;
     ray_dev_t *local;
     struct ccs __iomem *pccs;
     struct rcs __iomem *prcs;
@@ -2020,8 +1960,8 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
     DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev);
 
     local = (ray_dev_t *)dev->priv;
-    link = (dev_link_t *)local->finder;
-    if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) {
+    link = (struct pcmcia_device *)local->finder;
+    if (!pcmcia_dev_present(link)) {
         DEBUG(2,"ray_cs interrupt from device not present or suspended.\n");
         return IRQ_NONE;
     }
@@ -2540,9 +2480,9 @@ static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs)
 /*===========================================================================*/
 static void authenticate(ray_dev_t *local)
 {
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     DEBUG(0,"ray_cs Starting authentication.\n");
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs authenticate - device not present\n");
         return;
     }
@@ -2606,10 +2546,10 @@ static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,
 static void associate(ray_dev_t *local)
 {
     struct ccs __iomem *pccs;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     struct net_device *dev = link->priv;
     int ccsindex;
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs associate - device not present\n");
         return;
     }
@@ -2689,14 +2629,14 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
  * eg ifconfig 
  */
     int i;
-    dev_link_t *link;
+    struct pcmcia_device *link;
     struct net_device *dev;
     ray_dev_t *local;
     UCHAR *p;
     struct freq_hop_element *pfh;
     UCHAR c[33];
 
-    link = dev_list;
+    link = this_device;
     if (!link)
        return 0;
     dev = (struct net_device *)link->priv;
@@ -2898,7 +2838,7 @@ static struct pcmcia_driver ray_driver = {
        .drv            = {
                .name   = "ray_cs",
        },
-       .probe          = ray_attach,
+       .probe          = ray_probe,
        .remove         = ray_detach,
        .id_table       = ray_ids,
        .suspend        = ray_suspend,
@@ -2940,7 +2880,6 @@ static void __exit exit_ray_cs(void)
 #endif
 
     pcmcia_unregister_driver(&ray_driver);
-    BUG_ON(dev_list != NULL);
 } /* exit_ray_cs */
 
 module_init(init_ray_cs);
index 42660fe..bd73ebf 100644 (file)
@@ -31,7 +31,7 @@ typedef struct ray_dev_t {
     void __iomem *sram;            /* pointer to beginning of shared RAM     */
     void __iomem *amem;            /* pointer to attribute mem window        */
     void __iomem *rmem;            /* pointer to receive buffer window       */
-    dev_link_t *finder;            /* pointer back to dev_link_t for card    */
+    struct pcmcia_device *finder;            /* pointer back to struct pcmcia_device for card    */
     struct timer_list timer;
     long tx_ccs_lock;
     long ccs_lock;
index 5fa6fbe..f7b77ce 100644 (file)
@@ -63,7 +63,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket
 /* PCMCIA specific device information (goes in the card field of
  * struct orinoco_private */
 struct orinoco_pccard {
-       dev_link_t link;
+       struct pcmcia_device    *p_dev;
        dev_node_t node;
 };
 
@@ -71,8 +71,8 @@ struct orinoco_pccard {
 /* Function prototypes                                             */
 /********************************************************************/
 
-static void spectrum_cs_config(dev_link_t *link);
-static void spectrum_cs_release(dev_link_t *link);
+static int spectrum_cs_config(struct pcmcia_device *link);
+static void spectrum_cs_release(struct pcmcia_device *link);
 
 /********************************************************************/
 /* Firmware downloader                                             */
@@ -238,14 +238,14 @@ spectrum_aux_open(hermes_t *hw)
  * If IDLE is 1, stop the firmware, so that it can be safely rewritten.
  */
 static int
-spectrum_reset(dev_link_t *link, int idle)
+spectrum_reset(struct pcmcia_device *link, int idle)
 {
        int last_ret, last_fn;
        conf_reg_t reg;
        u_int save_cor;
 
        /* Doing it if hardware is gone is guaranteed crash */
-       if (!(link->state & DEV_CONFIG))
+       if (pcmcia_dev_present(link))
                return -ENODEV;
 
        /* Save original COR value */
@@ -253,7 +253,7 @@ spectrum_reset(dev_link_t *link, int idle)
        reg.Action = CS_READ;
        reg.Offset = CISREG_COR;
        CS_CHECK(AccessConfigurationRegister,
-                pcmcia_access_configuration_register(link->handle, &reg));
+                pcmcia_access_configuration_register(link, &reg));
        save_cor = reg.Value;
 
        /* Soft-Reset card */
@@ -261,14 +261,14 @@ spectrum_reset(dev_link_t *link, int idle)
        reg.Offset = CISREG_COR;
        reg.Value = (save_cor | COR_SOFT_RESET);
        CS_CHECK(AccessConfigurationRegister,
-                pcmcia_access_configuration_register(link->handle, &reg));
+                pcmcia_access_configuration_register(link, &reg));
        udelay(1000);
 
        /* Read CCSR */
        reg.Action = CS_READ;
        reg.Offset = CISREG_CCSR;
        CS_CHECK(AccessConfigurationRegister,
-                pcmcia_access_configuration_register(link->handle, &reg));
+                pcmcia_access_configuration_register(link, &reg));
 
        /*
         * Start or stop the firmware.  Memory width bit should be
@@ -278,7 +278,7 @@ spectrum_reset(dev_link_t *link, int idle)
        reg.Offset = CISREG_CCSR;
        reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16);
        CS_CHECK(AccessConfigurationRegister,
-                pcmcia_access_configuration_register(link->handle, &reg));
+                pcmcia_access_configuration_register(link, &reg));
        udelay(1000);
 
        /* Restore original COR configuration index */
@@ -286,12 +286,12 @@ spectrum_reset(dev_link_t *link, int idle)
        reg.Offset = CISREG_COR;
        reg.Value = (save_cor & ~COR_SOFT_RESET);
        CS_CHECK(AccessConfigurationRegister,
-                pcmcia_access_configuration_register(link->handle, &reg));
+                pcmcia_access_configuration_register(link, &reg));
        udelay(1000);
        return 0;
 
       cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
        return -ENODEV;
 }
 
@@ -441,7 +441,7 @@ spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
  * care of the PDA - read it and then write it on top of the firmware.
  */
 static int
-spectrum_dl_image(hermes_t *hw, dev_link_t *link,
+spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
                  const unsigned char *image)
 {
        int ret;
@@ -505,14 +505,13 @@ spectrum_dl_image(hermes_t *hw, dev_link_t *link,
  * reset on the card, to make sure it's in a sane state.
  */
 static int
-spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
+spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link)
 {
        int ret;
-       client_handle_t handle = link->handle;
        const struct firmware *fw_entry;
 
        if (request_firmware(&fw_entry, primary_fw_name,
-                            &handle_to_dev(handle)) == 0) {
+                            &handle_to_dev(link)) == 0) {
                primsym = fw_entry->data;
        } else {
                printk(KERN_ERR PFX "Cannot find firmware: %s\n",
@@ -521,7 +520,7 @@ spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
        }
 
        if (request_firmware(&fw_entry, secondary_fw_name,
-                            &handle_to_dev(handle)) == 0) {
+                            &handle_to_dev(link)) == 0) {
                secsym = fw_entry->data;
        } else {
                printk(KERN_ERR PFX "Cannot find firmware: %s\n",
@@ -554,12 +553,12 @@ static int
 spectrum_cs_hard_reset(struct orinoco_private *priv)
 {
        struct orinoco_pccard *card = priv->card;
-       dev_link_t *link = &card->link;
+       struct pcmcia_device *link = card->p_dev;
        int err;
 
        if (!hermes_present(&priv->hw)) {
                /* The firmware needs to be reloaded */
-               if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) {
+               if (spectrum_dl_firmware(&priv->hw, link) != 0) {
                        printk(KERN_ERR PFX "Firmware download failed\n");
                        err = -ENODEV;
                }
@@ -584,12 +583,11 @@ spectrum_cs_hard_reset(struct orinoco_private *priv)
  * configure the card at this point -- we wait until we receive a card
  * insertion event.  */
 static int
-spectrum_cs_attach(struct pcmcia_device *p_dev)
+spectrum_cs_probe(struct pcmcia_device *link)
 {
        struct net_device *dev;
        struct orinoco_private *priv;
        struct orinoco_pccard *card;
-       dev_link_t *link;
 
        dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
        if (! dev)
@@ -598,7 +596,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
        card = priv->card;
 
        /* Link both structures together */
-       link = &card->link;
+       card->p_dev = link;
        link->priv = dev;
 
        /* Interrupt setup */
@@ -615,13 +613,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
        link->conf.Attributes = 0;
        link->conf.IntType = INT_MEMORY_AND_IO;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       spectrum_cs_config(link);
-
-       return 0;
+       return spectrum_cs_config(link);
 }                              /* spectrum_cs_attach */
 
 /*
@@ -630,16 +622,14 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void spectrum_cs_detach(struct pcmcia_device *p_dev)
+static void spectrum_cs_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       if (link->state & DEV_CONFIG)
-               spectrum_cs_release(link);
+       spectrum_cs_release(link);
 
-       DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
-       if (link->dev) {
+       DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
+       if (link->dev_node) {
                DEBUG(0, PFX "About to unregister net device %p\n",
                      dev);
                unregister_netdev(dev);
@@ -653,11 +643,10 @@ static void spectrum_cs_detach(struct pcmcia_device *p_dev)
  * device available to the system.
  */
 
-static void
-spectrum_cs_config(dev_link_t *link)
+static int
+spectrum_cs_config(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
-       client_handle_t handle = link->handle;
        struct orinoco_private *priv = netdev_priv(dev);
        struct orinoco_pccard *card = priv->card;
        hermes_t *hw = &priv->hw;
@@ -669,7 +658,7 @@ spectrum_cs_config(dev_link_t *link)
        cisparse_t parse;
        void __iomem *mem;
 
-       CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+       CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
 
        /*
         * This reads the card's CONFIG tuple to find its
@@ -680,19 +669,15 @@ spectrum_cs_config(dev_link_t *link)
        tuple.TupleData = buf;
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
        /* Look up the current Vcc */
        CS_CHECK(GetConfigurationInfo,
-                pcmcia_get_configuration_info(handle, &conf));
-       link->conf.Vcc = conf.Vcc;
+                pcmcia_get_configuration_info(link, &conf));
 
        /*
         * In this loop, we scan the CIS for configuration table
@@ -709,13 +694,13 @@ spectrum_cs_config(dev_link_t *link)
         * implementation-defined details.
         */
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        while (1) {
                cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
                cistpl_cftable_entry_t dflt = { .index = 0 };
 
-               if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
-                   || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
+               if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
+                   || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
                        goto next_entry;
 
                if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -747,10 +732,10 @@ spectrum_cs_config(dev_link_t *link)
                }
 
                if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                            cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
                else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                            dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
                
                /* Do we need to allocate an interrupt? */
@@ -780,7 +765,7 @@ spectrum_cs_config(dev_link_t *link)
                        }
 
                        /* This reserves IO space but doesn't actually enable it */
-                       if (pcmcia_request_io(link->handle, &link->io) != 0)
+                       if (pcmcia_request_io(link, &link->io) != 0)
                                goto next_entry;
                }
 
@@ -790,9 +775,8 @@ spectrum_cs_config(dev_link_t *link)
                break;
                
        next_entry:
-               if (link->io.NumPorts1)
-                       pcmcia_release_io(link->handle, &link->io);
-               last_ret = pcmcia_get_next_tuple(handle, &tuple);
+               pcmcia_disable_device(link);
+               last_ret = pcmcia_get_next_tuple(link, &tuple);
                if (last_ret  == CS_NO_MORE_ITEMS) {
                        printk(KERN_ERR PFX "GetNextTuple(): No matching "
                               "CIS configuration.  Maybe you need the "
@@ -806,7 +790,7 @@ spectrum_cs_config(dev_link_t *link)
         * a handler to the interrupt, unless the 'Handler' member of
         * the irq structure is initialized.
         */
-       CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+       CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
        /* We initialize the hermes structure before completing PCMCIA
         * configuration just in case the interrupt handler gets
@@ -823,7 +807,7 @@ spectrum_cs_config(dev_link_t *link)
         * card and host interface into "Memory and IO" mode.
         */
        CS_CHECK(RequestConfiguration,
-                pcmcia_request_configuration(link->handle, &link->conf));
+                pcmcia_request_configuration(link, &link->conf));
 
        /* Ok, we have the configuration, prepare to register the netdev */
        dev->base_addr = link->io.BasePort1;
@@ -836,7 +820,7 @@ spectrum_cs_config(dev_link_t *link)
                goto failed;
        }
 
-       SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+       SET_NETDEV_DEV(dev, &handle_to_dev(link));
        /* Tell the stack we exist */
        if (register_netdev(dev) != 0) {
                printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -844,20 +828,18 @@ spectrum_cs_config(dev_link_t *link)
        }
 
        /* At this point, the dev_node_t structure(s) needs to be
-        * initialized and arranged in a linked list at link->dev. */
+        * initialized and arranged in a linked list at link->dev_node. */
        strcpy(card->node.dev_name, dev->name);
-       link->dev = &card->node; /* link->dev being non-NULL is also
+       link->dev_node = &card->node; /* link->dev_node being non-NULL is also
                                     used to indicate that the
                                     net_device has been registered */
-       link->state &= ~DEV_CONFIG_PENDING;
 
        /* Finally, report what we've done */
-       printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
-              dev->name, link->conf.ConfigIndex,
-              link->conf.Vcc / 10, link->conf.Vcc % 10);
-       if (link->conf.Vpp1)
-               printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
-                      link->conf.Vpp1 % 10);
+       printk(KERN_DEBUG "%s: index 0x%02x: ",
+              dev->name, link->conf.ConfigIndex);
+       if (link->conf.Vpp)
+               printk(", Vpp %d.%d", link->conf.Vpp / 10,
+                      link->conf.Vpp % 10);
        printk(", irq %d", link->irq.AssignedIRQ);
        if (link->io.NumPorts1)
                printk(", io 0x%04x-0x%04x", link->io.BasePort1,
@@ -867,13 +849,14 @@ spectrum_cs_config(dev_link_t *link)
                       link->io.BasePort2 + link->io.NumPorts2 - 1);
        printk("\n");
 
-       return;
+       return 0;
 
  cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 
  failed:
        spectrum_cs_release(link);
+       return -ENODEV;
 }                              /* spectrum_cs_config */
 
 /*
@@ -882,7 +865,7 @@ spectrum_cs_config(dev_link_t *link)
  * still open, this will be postponed until it is closed.
  */
 static void
-spectrum_cs_release(dev_link_t *link)
+spectrum_cs_release(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
        struct orinoco_private *priv = netdev_priv(dev);
@@ -894,64 +877,46 @@ spectrum_cs_release(dev_link_t *link)
        priv->hw_unavailable++;
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* Don't bother checking to see if these succeed or not */
-       pcmcia_release_configuration(link->handle);
-       if (link->io.NumPorts1)
-               pcmcia_release_io(link->handle, &link->io);
-       if (link->irq.AssignedIRQ)
-               pcmcia_release_irq(link->handle, &link->irq);
-       link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
        if (priv->hw.iobase)
                ioport_unmap(priv->hw.iobase);
 }                              /* spectrum_cs_release */
 
 
 static int
-spectrum_cs_suspend(struct pcmcia_device *p_dev)
+spectrum_cs_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
        struct orinoco_private *priv = netdev_priv(dev);
        unsigned long flags;
        int err = 0;
 
-       link->state |= DEV_SUSPEND;
        /* Mark the device as stopped, to block IO until later */
-       if (link->state & DEV_CONFIG) {
-               spin_lock_irqsave(&priv->lock, flags);
-
-               err = __orinoco_down(dev);
-               if (err)
-                       printk(KERN_WARNING "%s: Error %d downing interface\n",
-                              dev->name, err);
+       spin_lock_irqsave(&priv->lock, flags);
 
-               netif_device_detach(dev);
-               priv->hw_unavailable++;
+       err = __orinoco_down(dev);
+       if (err)
+               printk(KERN_WARNING "%s: Error %d downing interface\n",
+                      dev->name, err);
 
-               spin_unlock_irqrestore(&priv->lock, flags);
+       netif_device_detach(dev);
+       priv->hw_unavailable++;
 
-               pcmcia_release_configuration(link->handle);
-       }
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        return 0;
 }
 
 static int
-spectrum_cs_resume(struct pcmcia_device *p_dev)
+spectrum_cs_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
        struct orinoco_private *priv = netdev_priv(dev);
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               /* FIXME: should we double check that this is
-                * the same card as we had before */
-               pcmcia_request_configuration(link->handle, &link->conf);
-               netif_device_attach(dev);
-               priv->hw_unavailable--;
-               schedule_work(&priv->reset_work);
-       }
+       netif_device_attach(dev);
+       priv->hw_unavailable--;
+       schedule_work(&priv->reset_work);
+
        return 0;
 }
 
@@ -979,7 +944,7 @@ static struct pcmcia_driver orinoco_driver = {
        .drv            = {
                .name   = DRIVER_NAME,
        },
-       .probe          = spectrum_cs_attach,
+       .probe          = spectrum_cs_probe,
        .remove         = spectrum_cs_detach,
        .suspend        = spectrum_cs_suspend,
        .resume         = spectrum_cs_resume,
index 98122f3..f7724eb 100644 (file)
@@ -1005,7 +1005,7 @@ static inline void
 wv_82593_reconfig(struct net_device *  dev)
 {
   net_local *          lp = netdev_priv(dev);
-  dev_link_t *         link = lp->link;
+  struct pcmcia_device *               link = lp->link;
   unsigned long                flags;
 
   /* Arm the flag, will be cleard in wv_82593_config() */
@@ -3744,16 +3744,16 @@ wv_pcmcia_reset(struct net_device *     dev)
 {
   int          i;
   conf_reg_t   reg = { 0, CS_READ, CISREG_COR, 0 };
-  dev_link_t * link = ((net_local *)netdev_priv(dev))->link;
+  struct pcmcia_device *       link = ((net_local *)netdev_priv(dev))->link;
 
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name);
 #endif
 
-  i = pcmcia_access_configuration_register(link->handle, &reg);
+  i = pcmcia_access_configuration_register(link, &reg);
   if(i != CS_SUCCESS)
     {
-      cs_error(link->handle, AccessConfigurationRegister, i);
+      cs_error(link, AccessConfigurationRegister, i);
       return FALSE;
     }
       
@@ -3764,19 +3764,19 @@ wv_pcmcia_reset(struct net_device *     dev)
 
   reg.Action = CS_WRITE;
   reg.Value = reg.Value | COR_SW_RESET;
-  i = pcmcia_access_configuration_register(link->handle, &reg);
+  i = pcmcia_access_configuration_register(link, &reg);
   if(i != CS_SUCCESS)
     {
-      cs_error(link->handle, AccessConfigurationRegister, i);
+      cs_error(link, AccessConfigurationRegister, i);
       return FALSE;
     }
       
   reg.Action = CS_WRITE;
   reg.Value = COR_LEVEL_IRQ | COR_CONFIG;
-  i = pcmcia_access_configuration_register(link->handle, &reg);
+  i = pcmcia_access_configuration_register(link, &reg);
   if(i != CS_SUCCESS)
     {
-      cs_error(link->handle, AccessConfigurationRegister, i);
+      cs_error(link, AccessConfigurationRegister, i);
       return FALSE;
     }
 
@@ -3940,9 +3940,8 @@ wv_hw_reset(struct net_device *   dev)
  * (called by wavelan_event())
  */
 static inline int
-wv_pcmcia_config(dev_link_t *  link)
+wv_pcmcia_config(struct pcmcia_device *        link)
 {
-  client_handle_t      handle = link->handle;
   tuple_t              tuple;
   cisparse_t           parse;
   struct net_device *  dev = (struct net_device *) link->priv;
@@ -3965,16 +3964,16 @@ wv_pcmcia_config(dev_link_t *   link)
     {
       tuple.Attributes = 0;
       tuple.DesiredTuple = CISTPL_CONFIG;
-      i = pcmcia_get_first_tuple(handle, &tuple);
+      i = pcmcia_get_first_tuple(link, &tuple);
       if(i != CS_SUCCESS)
        break;
       tuple.TupleData = (cisdata_t *)buf;
       tuple.TupleDataMax = 64;
       tuple.TupleOffset = 0;
-      i = pcmcia_get_tuple_data(handle, &tuple);
+      i = pcmcia_get_tuple_data(link, &tuple);
       if(i != CS_SUCCESS)
        break;
-      i = pcmcia_parse_tuple(handle, &tuple, &parse);
+      i = pcmcia_parse_tuple(link, &tuple, &parse);
       if(i != CS_SUCCESS)
        break;
       link->conf.ConfigBase = parse.config.base;
@@ -3983,19 +3982,16 @@ wv_pcmcia_config(dev_link_t *   link)
   while(0);
   if(i != CS_SUCCESS)
     {
-      cs_error(link->handle, ParseTuple, i);
-      link->state &= ~DEV_CONFIG_PENDING;
+      cs_error(link, ParseTuple, i);
       return FALSE;
     }
-    
-  /* Configure card */
-  link->state |= DEV_CONFIG;
+
   do
     {
-      i = pcmcia_request_io(link->handle, &link->io);
+      i = pcmcia_request_io(link, &link->io);
       if(i != CS_SUCCESS)
        {
-         cs_error(link->handle, RequestIO, i);
+         cs_error(link, RequestIO, i);
          break;
        }
 
@@ -4003,10 +3999,10 @@ wv_pcmcia_config(dev_link_t *   link)
        * Now allocate an interrupt line.  Note that this does not
        * actually assign a handler to the interrupt.
        */
-      i = pcmcia_request_irq(link->handle, &link->irq);
+      i = pcmcia_request_irq(link, &link->irq);
       if(i != CS_SUCCESS)
        {
-         cs_error(link->handle, RequestIRQ, i);
+         cs_error(link, RequestIRQ, i);
          break;
        }
 
@@ -4015,15 +4011,15 @@ wv_pcmcia_config(dev_link_t *   link)
        * the I/O windows and the interrupt mapping.
        */
       link->conf.ConfigIndex = 1;
-      i = pcmcia_request_configuration(link->handle, &link->conf);
+      i = pcmcia_request_configuration(link, &link->conf);
       if(i != CS_SUCCESS)
        {
-         cs_error(link->handle, RequestConfiguration, i);
+         cs_error(link, RequestConfiguration, i);
          break;
        }
 
       /*
-       * Allocate a small memory window.  Note that the dev_link_t
+       * Allocate a small memory window.  Note that the struct pcmcia_device
        * structure provides space for one window handle -- if your
        * device needs several windows, you'll need to keep track of
        * the handles in your private data structure, link->priv.
@@ -4031,10 +4027,10 @@ wv_pcmcia_config(dev_link_t *   link)
       req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
       req.Base = req.Size = 0;
       req.AccessSpeed = mem_speed;
-      i = pcmcia_request_window(&link->handle, &req, &link->win);
+      i = pcmcia_request_window(&link, &req, &link->win);
       if(i != CS_SUCCESS)
        {
-         cs_error(link->handle, RequestWindow, i);
+         cs_error(link, RequestWindow, i);
          break;
        }
 
@@ -4046,7 +4042,7 @@ wv_pcmcia_config(dev_link_t *     link)
       i = pcmcia_map_mem_page(link->win, &mem);
       if(i != CS_SUCCESS)
        {
-         cs_error(link->handle, MapMemPage, i);
+         cs_error(link, MapMemPage, i);
          break;
        }
 
@@ -4060,7 +4056,7 @@ wv_pcmcia_config(dev_link_t *     link)
             lp->mem, dev->irq, (u_int) dev->base_addr);
 #endif
 
-      SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+      SET_NETDEV_DEV(dev, &handle_to_dev(link));
       i = register_netdev(dev);
       if(i != 0)
        {
@@ -4072,7 +4068,6 @@ wv_pcmcia_config(dev_link_t *     link)
     }
   while(0);            /* Humm... Disguised goto !!! */
 
-  link->state &= ~DEV_CONFIG_PENDING;
   /* If any step failed, release any partially configured state */
   if(i != 0)
     {
@@ -4081,7 +4076,7 @@ wv_pcmcia_config(dev_link_t *     link)
     }
 
   strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name);
-  link->dev = &((net_local *) netdev_priv(dev))->node;
+  link->dev_node = &((net_local *) netdev_priv(dev))->node;
 
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "<-wv_pcmcia_config()\n");
@@ -4096,26 +4091,20 @@ wv_pcmcia_config(dev_link_t *   link)
  * still open, this will be postponed until it is closed.
  */
 static void
-wv_pcmcia_release(dev_link_t *link)
+wv_pcmcia_release(struct pcmcia_device *link)
 {
-  struct net_device *  dev = (struct net_device *) link->priv;
-  net_local *          lp = netdev_priv(dev);
+       struct net_device *     dev = (struct net_device *) link->priv;
+       net_local *             lp = netdev_priv(dev);
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link);
+       printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link);
 #endif
 
-  /* Don't bother checking to see if these succeed or not */
-  iounmap(lp->mem);
-  pcmcia_release_window(link->win);
-  pcmcia_release_configuration(link->handle);
-  pcmcia_release_io(link->handle, &link->io);
-  pcmcia_release_irq(link->handle, &link->irq);
-
-  link->state &= ~DEV_CONFIG;
+       iounmap(lp->mem);
+       pcmcia_disable_device(link);
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name);
+       printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name);
 #endif
 }
 
@@ -4479,7 +4468,7 @@ static int
 wavelan_open(struct net_device *       dev)
 {
   net_local *  lp = netdev_priv(dev);
-  dev_link_t * link = lp->link;
+  struct pcmcia_device *       link = lp->link;
   kio_addr_t   base = dev->base_addr;
 
 #ifdef DEBUG_CALLBACK_TRACE
@@ -4533,7 +4522,7 @@ wavelan_open(struct net_device *  dev)
 static int
 wavelan_close(struct net_device *      dev)
 {
-  dev_link_t * link = ((net_local *)netdev_priv(dev))->link;
+  struct pcmcia_device *       link = ((net_local *)netdev_priv(dev))->link;
   kio_addr_t   base = dev->base_addr;
 
 #ifdef DEBUG_CALLBACK_TRACE
@@ -4587,45 +4576,36 @@ wavelan_close(struct net_device *       dev)
  * card insertion event.
  */
 static int
-wavelan_attach(struct pcmcia_device *p_dev)
+wavelan_probe(struct pcmcia_device *p_dev)
 {
-  dev_link_t * link;           /* Info for cardmgr */
   struct net_device *  dev;            /* Interface generic data */
   net_local *  lp;             /* Interface specific data */
+  int ret;
 
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "-> wavelan_attach()\n");
 #endif
 
-  /* Initialize the dev_link_t structure */
-  link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-  if (!link) return -ENOMEM;
-
   /* The io structure describes IO port mapping */
-  link->io.NumPorts1 = 8;
-  link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-  link->io.IOAddrLines = 3;
+  p_dev->io.NumPorts1 = 8;
+  p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+  p_dev->io.IOAddrLines = 3;
 
   /* Interrupt setup */
-  link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-  link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-  link->irq.Handler = wavelan_interrupt;
+  p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+  p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+  p_dev->irq.Handler = wavelan_interrupt;
 
   /* General socket configuration */
-  link->conf.Attributes = CONF_ENABLE_IRQ;
-  link->conf.Vcc = 50;
-  link->conf.IntType = INT_MEMORY_AND_IO;
-
-  /* Chain drivers */
-  link->next = NULL;
+  p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+  p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
   /* Allocate the generic data structure */
   dev = alloc_etherdev(sizeof(net_local));
-  if (!dev) {
-      kfree(link);
+  if (!dev)
       return -ENOMEM;
-  }
-  link->priv = link->irq.Instance = dev;
+
+  p_dev->priv = p_dev->irq.Instance = dev;
 
   lp = netdev_priv(dev);
 
@@ -4642,7 +4622,6 @@ wavelan_attach(struct pcmcia_device *p_dev)
   spin_lock_init(&lp->spinlock);
 
   /* back links */
-  lp->link = link;
   lp->dev = dev;
 
   /* wavelan NET3 callbacks */
@@ -4668,15 +4647,18 @@ wavelan_attach(struct pcmcia_device *p_dev)
   /* Other specific data */
   dev->mtu = WAVELAN_MTU;
 
-  link->handle = p_dev;
-  p_dev->instance = link;
+  ret = wv_pcmcia_config(p_dev);
+  if (ret)
+         return ret;
 
-  link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-  if(wv_pcmcia_config(link) &&
-     wv_hw_config(dev))
-         wv_init_info(dev);
-  else
+  ret = wv_hw_config(dev);
+  if (ret) {
          dev->irq = 0;
+         pcmcia_disable_device(p_dev);
+         return ret;
+  }
+
+  wv_init_info(dev);
 
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "<- wavelan_attach()\n");
@@ -4693,25 +4675,14 @@ wavelan_attach(struct pcmcia_device *p_dev)
  * is released.
  */
 static void
-wavelan_detach(struct pcmcia_device *p_dev)
+wavelan_detach(struct pcmcia_device *link)
 {
-   dev_link_t *link = dev_to_instance(p_dev);
-
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link);
 #endif
 
-  /*
-   * If the device is currently configured and active, we won't
-   * actually delete it yet.  Instead, it is marked so that when the
-   * release() function is called, that will trigger a proper
-   * detach().
-   */
-  if(link->state & DEV_CONFIG)
-    {
-      /* Some others haven't done their job : give them another chance */
-      wv_pcmcia_release(link);
-    }
+  /* Some others haven't done their job : give them another chance */
+  wv_pcmcia_release(link);
 
   /* Free pieces */
   if(link->priv)
@@ -4720,23 +4691,21 @@ wavelan_detach(struct pcmcia_device *p_dev)
 
       /* Remove ourselves from the kernel list of ethernet devices */
       /* Warning : can't be called from interrupt, timer or wavelan_close() */
-      if (link->dev)
+      if (link->dev_node)
        unregister_netdev(dev);
-      link->dev = NULL;
+      link->dev_node = NULL;
       ((net_local *)netdev_priv(dev))->link = NULL;
       ((net_local *)netdev_priv(dev))->dev = NULL;
       free_netdev(dev);
     }
-  kfree(link);
 
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "<- wavelan_detach()\n");
 #endif
 }
 
-static int wavelan_suspend(struct pcmcia_device *p_dev)
+static int wavelan_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *     dev = (struct net_device *) link->priv;
 
        /* NB: wavelan_close will be called, but too late, so we are
@@ -4748,36 +4717,22 @@ static int wavelan_suspend(struct pcmcia_device *p_dev)
        /* Stop receiving new messages and wait end of transmission */
        wv_ru_stop(dev);
 
+       if (link->open)
+               netif_device_detach(dev);
+
        /* Power down the module */
        hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT));
 
-       /* The card is now suspended */
-       link->state |= DEV_SUSPEND;
-
-       if(link->state & DEV_CONFIG)
-       {
-               if(link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-       }
-
        return 0;
 }
 
-static int wavelan_resume(struct pcmcia_device *p_dev)
+static int wavelan_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *     dev = (struct net_device *) link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if(link->state & DEV_CONFIG)
-       {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if(link->open)  /* If RESET -> True, If RESUME -> False ? */
-               {
-                       wv_hw_reset(dev);
-                       netif_device_attach(dev);
-               }
+       if (link->open) {
+               wv_hw_reset(dev);
+               netif_device_attach(dev);
        }
 
        return 0;
@@ -4798,7 +4753,7 @@ static struct pcmcia_driver wavelan_driver = {
        .drv            = {
                .name   = "wavelan_cs",
        },
-       .probe          = wavelan_attach,
+       .probe          = wavelan_probe,
        .remove         = wavelan_detach,
        .id_table       = wavelan_ids,
        .suspend        = wavelan_suspend,
index 451f627..c65fe7a 100644 (file)
@@ -602,7 +602,7 @@ struct net_local
   dev_node_t   node;           /* ???? What is this stuff ???? */
   struct net_device *  dev;            /* Reverse link... */
   spinlock_t   spinlock;       /* Serialize access to the hardware (SMP) */
-  dev_link_t * link;           /* pcmcia structure */
+  struct pcmcia_device *       link;           /* pcmcia structure */
   en_stats     stats;          /* Ethernet interface statistics */
   int          nresets;        /* Number of hw resets */
   u_char       configured;     /* If it is configured */
@@ -733,9 +733,9 @@ static int
 static inline void
        wv_hw_reset(struct net_device *);       /* Same, + start receiver unit */
 static inline int
-       wv_pcmcia_config(dev_link_t *); /* Configure the pcmcia interface */
+       wv_pcmcia_config(struct pcmcia_device *);       /* Configure the pcmcia interface */
 static void
-       wv_pcmcia_release(dev_link_t *);/* Remove a device */
+       wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */
 /* ---------------------- INTERRUPT HANDLING ---------------------- */
 static irqreturn_t
        wavelan_interrupt(int,  /* Interrupt handler */
index 4303c50..65ceb08 100644 (file)
@@ -611,5 +611,6 @@ struct wl3501_card {
        struct iw_spy_data              spy_data;
        struct iw_public_data           wireless_data;
        struct dev_node_t               node;
+       struct pcmcia_device            *p_dev;
 };
 #endif
index 48e10b0..e52a650 100644 (file)
@@ -103,8 +103,8 @@ module_param(pc_debug, int, 0);
  * release a socket, in response to card insertion and ejection events.  They
  * are invoked from the wl24 event handler.
  */
-static void wl3501_config(dev_link_t *link);
-static void wl3501_release(dev_link_t *link);
+static int wl3501_config(struct pcmcia_device *link);
+static void wl3501_release(struct pcmcia_device *link);
 
 /*
  * The dev_info variable is the "key" that is used to match up this
@@ -226,17 +226,6 @@ static void iw_copy_mgmt_info_element(struct iw_mgmt_info_element *to,
        iw_set_mgmt_info_element(from->id, to, from->data, from->len);
 }
 
-/*
- * A linked list of "instances" of the wl24 device.  Each actual PCMCIA card
- * corresponds to one device instance, and is described by one dev_link_t
- * structure (defined in ds.h).
- *
- * You may not want to use a linked list for this -- for example, the memory
- * card driver uses an array of dev_link_t pointers, where minor device numbers
- * are used to derive the corresponding array index.
- */
-static dev_link_t *wl3501_dev_list;
-
 static inline void wl3501_switch_page(struct wl3501_card *this, u8 page)
 {
        wl3501_outb(page, this->base_addr + WL3501_NIC_BSS);
@@ -1281,15 +1270,10 @@ static int wl3501_close(struct net_device *dev)
        struct wl3501_card *this = dev->priv;
        int rc = -ENODEV;
        unsigned long flags;
-       dev_link_t *link;
+       struct pcmcia_device *link;
+       link = this->p_dev;
 
        spin_lock_irqsave(&this->lock, flags);
-       /* Check if the device is in wl3501_dev_list */
-       for (link = wl3501_dev_list; link; link = link->next)
-               if (link->priv == dev)
-                       break;
-       if (!link)
-               goto out;
        link->open--;
 
        /* Stop wl3501_hard_start_xmit() from now on */
@@ -1301,7 +1285,6 @@ static int wl3501_close(struct net_device *dev)
 
        rc = 0;
        printk(KERN_INFO "%s: WL3501 closed\n", dev->name);
-out:
        spin_unlock_irqrestore(&this->lock, flags);
        return rc;
 }
@@ -1400,14 +1383,11 @@ static int wl3501_open(struct net_device *dev)
        int rc = -ENODEV;
        struct wl3501_card *this = dev->priv;
        unsigned long flags;
-       dev_link_t *link;
+       struct pcmcia_device *link;
+       link = this->p_dev;
 
        spin_lock_irqsave(&this->lock, flags);
-       /* Check if the device is in wl3501_dev_list */
-       for (link = wl3501_dev_list; link; link = link->next)
-               if (link->priv == dev)
-                       break;
-       if (!DEV_OK(link))
+       if (!pcmcia_dev_present(link))
                goto out;
        netif_device_attach(dev);
        link->open++;
@@ -1497,38 +1477,23 @@ static struct ethtool_ops ops = {
  * Services. If it has been released, all local data structures are freed.
  * Otherwise, the structures will be freed when the device is released.
  */
-static void wl3501_detach(struct pcmcia_device *p_dev)
+static void wl3501_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
-       dev_link_t **linkp;
        struct net_device *dev = link->priv;
 
-       /* Locate device structure */
-       for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)
-               if (*linkp == link)
-                       break;
-       if (!*linkp)
-               goto out;
-
        /* If the device is currently configured and active, we won't actually
         * delete it yet.  Instead, it is marked so that when the release()
         * function is called, that will trigger a proper detach(). */
 
-       if (link->state & DEV_CONFIG) {
-               while (link->open > 0)
-                       wl3501_close(dev);
-
-               netif_device_detach(dev);
-               wl3501_release(link);
-       }
+       while (link->open > 0)
+               wl3501_close(dev);
 
-       /* Unlink device structure, free pieces */
-       *linkp = link->next;
+       netif_device_detach(dev);
+       wl3501_release(link);
 
        if (link->priv)
                free_netdev(link->priv);
-       kfree(link);
-out:
+
        return;
 }
 
@@ -1953,33 +1918,26 @@ static const struct iw_handler_def wl3501_handler_def = {
  * The dev_link structure is initialized, but we don't actually configure the
  * card at this point -- we wait until we receive a card insertion event.
  */
-static int wl3501_attach(struct pcmcia_device *p_dev)
+static int wl3501_probe(struct pcmcia_device *p_dev)
 {
-       dev_link_t *link;
        struct net_device *dev;
        struct wl3501_card *this;
 
-       /* Initialize the dev_link_t structure */
-       link = kzalloc(sizeof(*link), GFP_KERNEL);
-       if (!link)
-               return -ENOMEM;
-
        /* The io structure describes IO port mapping */
-       link->io.NumPorts1      = 16;
-       link->io.Attributes1    = IO_DATA_PATH_WIDTH_8;
-       link->io.IOAddrLines    = 5;
+       p_dev->io.NumPorts1     = 16;
+       p_dev->io.Attributes1   = IO_DATA_PATH_WIDTH_8;
+       p_dev->io.IOAddrLines   = 5;
 
        /* Interrupt setup */
-       link->irq.Attributes    = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-       link->irq.IRQInfo1      = IRQ_LEVEL_ID;
-       link->irq.Handler = wl3501_interrupt;
+       p_dev->irq.Attributes   = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+       p_dev->irq.IRQInfo1     = IRQ_LEVEL_ID;
+       p_dev->irq.Handler = wl3501_interrupt;
 
        /* General socket configuration */
-       link->conf.Attributes   = CONF_ENABLE_IRQ;
-       link->conf.Vcc          = 50;
-       link->conf.IntType      = INT_MEMORY_AND_IO;
-       link->conf.ConfigIndex  = 1;
-       link->conf.Present      = PRESENT_OPTION;
+       p_dev->conf.Attributes  = CONF_ENABLE_IRQ;
+       p_dev->conf.IntType     = INT_MEMORY_AND_IO;
+       p_dev->conf.ConfigIndex = 1;
+       p_dev->conf.Present     = PRESENT_OPTION;
 
        dev = alloc_etherdev(sizeof(struct wl3501_card));
        if (!dev)
@@ -1992,22 +1950,15 @@ static int wl3501_attach(struct pcmcia_device *p_dev)
        dev->get_stats          = wl3501_get_stats;
        this = dev->priv;
        this->wireless_data.spy_data = &this->spy_data;
+       this->p_dev = p_dev;
        dev->wireless_data      = &this->wireless_data;
        dev->wireless_handlers  = (struct iw_handler_def *)&wl3501_handler_def;
        SET_ETHTOOL_OPS(dev, &ops);
        netif_stop_queue(dev);
-       link->priv = link->irq.Instance = dev;
-
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       wl3501_config(link);
+       p_dev->priv = p_dev->irq.Instance = dev;
 
-       return 0;
+       return wl3501_config(p_dev);
 out_link:
-       kfree(link);
-       link = NULL;
        return -ENOMEM;
 }
 
@@ -2022,11 +1973,10 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
  * received, to configure the PCMCIA socket, and to make the ethernet device
  * available to the system.
  */
-static void wl3501_config(dev_link_t *link)
+static int wl3501_config(struct pcmcia_device *link)
 {
        tuple_t tuple;
        cisparse_t parse;
-       client_handle_t handle = link->handle;
        struct net_device *dev = link->priv;
        int i = 0, j, last_fn, last_ret;
        unsigned char bf[64];
@@ -2035,18 +1985,15 @@ static void wl3501_config(dev_link_t *link)
        /* This reads the card's CONFIG tuple to find its config registers. */
        tuple.Attributes        = 0;
        tuple.DesiredTuple      = CISTPL_CONFIG;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        tuple.TupleData         = bf;
        tuple.TupleDataMax      = sizeof(bf);
        tuple.TupleOffset       = 0;
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase   = parse.config.base;
        link->conf.Present      = parse.config.rmask[0];
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
        /* Try allocating IO ports.  This tries a few fixed addresses.  If you
         * want, you can also read the card's config table to pick addresses --
         * see the serial driver for an example. */
@@ -2056,28 +2003,28 @@ static void wl3501_config(dev_link_t *link)
                 * 0x200-0x2ff, and so on, because this seems safer */
                link->io.BasePort1 = j;
                link->io.BasePort2 = link->io.BasePort1 + 0x10;
-               i = pcmcia_request_io(link->handle, &link->io);
+               i = pcmcia_request_io(link, &link->io);
                if (i == CS_SUCCESS)
                        break;
        }
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestIO, i);
+               cs_error(link, RequestIO, i);
                goto failed;
        }
 
        /* Now allocate an interrupt line. Note that this does not actually
         * assign a handler to the interrupt. */
 
-       CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+       CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
        /* This actually configures the PCMCIA socket -- setting up the I/O
         * windows and the interrupt mapping.  */
 
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
        dev->irq = link->irq.AssignedIRQ;
        dev->base_addr = link->io.BasePort1;
-       SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+       SET_NETDEV_DEV(dev, &handle_to_dev(link));
        if (register_netdev(dev)) {
                printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");
                goto failed;
@@ -2088,10 +2035,9 @@ static void wl3501_config(dev_link_t *link)
        this = dev->priv;
        /*
         * At this point, the dev_node_t structure(s) should be initialized and
-        * arranged in a linked list at link->dev.
+        * arranged in a linked list at link->dev_node.
         */
-       link->dev = &this->node;
-       link->state &= ~DEV_CONFIG_PENDING;
+       link->dev_node = &this->node;
 
        this->base_addr = dev->base_addr;
 
@@ -2127,13 +2073,13 @@ static void wl3501_config(dev_link_t *link)
        spin_lock_init(&this->lock);
        init_waitqueue_head(&this->wait);
        netif_start_queue(dev);
-       goto out;
+       return 0;
+
 cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 failed:
        wl3501_release(link);
-out:
-       return;
+       return -ENODEV;
 }
 
 /**
@@ -2144,52 +2090,36 @@ out:
  * and release the PCMCIA configuration.  If the device is still open, this
  * will be postponed until it is closed.
  */
-static void wl3501_release(dev_link_t *link)
+static void wl3501_release(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
 
        /* Unlink the device chain */
-       if (link->dev) {
+       if (link->dev_node)
                unregister_netdev(dev);
-               link->dev = NULL;
-       }
 
-       /* Don't bother checking to see if these succeed or not */
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
-       link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
 }
 
-static int wl3501_suspend(struct pcmcia_device *p_dev)
+static int wl3501_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       link->state |= DEV_SUSPEND;
-
        wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
-       if (link->state & DEV_CONFIG) {
-               if (link->open)
-                       netif_device_detach(dev);
-               pcmcia_release_configuration(link->handle);
-       }
+       if (link->open)
+               netif_device_detach(dev);
 
        return 0;
 }
 
-static int wl3501_resume(struct pcmcia_device *p_dev)
+static int wl3501_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
        wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if (link->open) {
-                       wl3501_reset(dev);
-                       netif_device_attach(dev);
-               }
+       if (link->open) {
+               wl3501_reset(dev);
+               netif_device_attach(dev);
        }
 
        return 0;
@@ -2207,7 +2137,7 @@ static struct pcmcia_driver wl3501_driver = {
        .drv            = {
                .name   = "wl3501_cs",
        },
-       .probe          = wl3501_attach,
+       .probe          = wl3501_probe,
        .remove         = wl3501_detach,
        .id_table       = wl3501_ids,
        .suspend        = wl3501_suspend,
@@ -2221,9 +2151,7 @@ static int __init wl3501_init_module(void)
 
 static void __exit wl3501_exit_module(void)
 {
-       dprintk(0, ": unloading");
        pcmcia_unregister_driver(&wl3501_driver);
-       BUG_ON(wl3501_dev_list != NULL);
 }
 
 module_init(wl3501_init_module);
index 93f8a8f..a5d8262 100644 (file)
@@ -1560,7 +1560,7 @@ static int ccio_probe(struct parisc_device *dev)
        *ioc_p = ioc;
 
        ioc->hw_path = dev->hw_path;
-       ioc->ioc_regs = ioremap(dev->hpa.start, 4096);
+       ioc->ioc_regs = ioremap_nocache(dev->hpa.start, 4096);
        ccio_ioc_init(ioc);
        ccio_init_resources(ioc);
        hppa_dma_ops = &ccio_ops;
index 3d1a7f9..6e8ed0c 100644 (file)
@@ -5,6 +5,7 @@
 **     (c) Copyright 1999 SuSE GmbH
 **     (c) Copyright 1999,2000 Hewlett-Packard Company
 **     (c) Copyright 2000 Grant Grundler
+**     (c) Copyright 2006 Helge Deller
 **
 **     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
@@ -785,7 +786,7 @@ dino_bridge_init(struct dino_device *dino_dev, const char *name)
                if((io_addr & (1 << i)) == 0)
                        continue;
 
-               start = (unsigned long)(signed int)(0xf0000000 | (i << 23));
+               start = F_EXTEND(0xf0000000UL) | (i << 23);
                end = start + 8 * 1024 * 1024 - 1;
 
                DBG("DINO RANGE %d is at 0x%lx-0x%lx\n", count,
@@ -996,7 +997,7 @@ static int __init dino_probe(struct parisc_device *dev)
        }
 
        dino_dev->hba.dev = dev;
-       dino_dev->hba.base_addr = ioremap(hpa, 4096);
+       dino_dev->hba.base_addr = ioremap_nocache(hpa, 4096);
        dino_dev->hba.lmmio_space_offset = 0;   /* CPU addrs == bus addrs */
        spin_lock_init(&dino_dev->dinosaur_pen);
        dino_dev->hba.iommu = ccio_get_iommu(dev);
index 3d94d86..9d3bd15 100644 (file)
@@ -366,7 +366,7 @@ static int __devinit eisa_probe(struct parisc_device *dev)
                        eisa_dev.eeprom_addr = MIRAGE_EEPROM_BASE_ADDR;
                }
        }
-       eisa_eeprom_addr = ioremap(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH);
+       eisa_eeprom_addr = ioremap_nocache(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH);
        result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space,
                        &eisa_dev.hba.lmmio_space);
        init_eisa_pic();
index 8d7a363..7a458d5 100644 (file)
@@ -879,7 +879,7 @@ void *iosapic_register(unsigned long hpa)
                return NULL;
        }
 
-       isi->addr = ioremap(hpa, 4096);
+       isi->addr = ioremap_nocache(hpa, 4096);
        isi->isi_hpa = hpa;
        isi->isi_version = iosapic_rd_version(isi);
        isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
index e8a2a4a..3fe4a77 100644 (file)
@@ -1213,7 +1213,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
                        ** Postable I/O port space is per PCI host adapter.
                        ** base of 64MB PIOP region
                        */
-                       lba_dev->iop_base = ioremap(p->start, 64 * 1024 * 1024);
+                       lba_dev->iop_base = ioremap_nocache(p->start, 64 * 1024 * 1024);
 
                        sprintf(lba_dev->hba.io_name, "PCI%02lx Ports",
                                        lba_dev->hba.bus_num.start);
@@ -1525,7 +1525,7 @@ lba_driver_probe(struct parisc_device *dev)
        u32 func_class;
        void *tmp_obj;
        char *version;
-       void __iomem *addr = ioremap(dev->hpa.start, 4096);
+       void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096);
 
        /* Read HW Rev First */
        func_class = READ_REG32(addr + LBA_FCLASS);
@@ -1619,7 +1619,7 @@ lba_driver_probe(struct parisc_device *dev)
        } else {
                if (!astro_iop_base) {
                        /* Sprockets PDC uses NPIOP region */
-                       astro_iop_base = ioremap(LBA_PORT_BASE, 64 * 1024);
+                       astro_iop_base = ioremap_nocache(LBA_PORT_BASE, 64 * 1024);
                        pci_port = &lba_astro_port_ops;
                }
 
@@ -1700,7 +1700,7 @@ void __init lba_init(void)
 */
 void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
 {
-       void __iomem * base_addr = ioremap(lba->hpa.start, 4096);
+       void __iomem * base_addr = ioremap_nocache(lba->hpa.start, 4096);
 
        imask <<= 2;    /* adjust for hints - 2 more bits */
 
index a28e178..4e53be9 100644 (file)
@@ -4,9 +4,8 @@
  *    Copyright (C) 2005-2006 Thibaut VARENE <varenet@parisc-linux.org>
  *
  *    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.
+ *    it under the terms of the GNU General Public License, version 2, as
+ *    published by the Free Software Foundation.
  *
  *    This program is distributed in the hope that it will be useful,
  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
index 0821747..42b32ff 100644 (file)
@@ -1642,9 +1642,9 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
 **
 **************************************************************************/
 
-static void __iomem *ioc_remap(struct sba_device *sba_dev, int offset)
+static void __iomem *ioc_remap(struct sba_device *sba_dev, unsigned int offset)
 {
-       return ioremap(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE);
+       return ioremap_nocache(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE);
 }
 
 static void sba_hw_init(struct sba_device *sba_dev)
@@ -2040,7 +2040,7 @@ sba_driver_callback(struct parisc_device *dev)
        u32 func_class;
        int i;
        char *version;
-       void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE);
+       void __iomem *sba_addr = ioremap_nocache(dev->hpa.start, SBA_FUNC_SIZE);
        struct proc_dir_entry *info_entry, *bitmap_entry, *root;
 
        sba_dump_ranges(sba_addr);
index ad6d3b2..719b863 100644 (file)
@@ -12,6 +12,7 @@
  *      (C) Copyright 2001 John Marvin <jsm fc hp com>
  *      (C) Copyright 2003 Grant Grundler <grundler parisc-linux org>
  *     (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org>
+ *     (C) Copyright 2006 Helge Deller <deller@gmx.de>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License as
@@ -388,43 +389,34 @@ int superio_fixup_irq(struct pci_dev *pcidev)
        return local_irq;
 }
 
-static struct uart_port serial[] = {
-       {
-               .iotype         = UPIO_PORT,
-               .line           = 0,
-               .type           = PORT_16550A,
-               .uartclk        = 115200*16,
-               .fifosize       = 16,
-       },
-       {
-               .iotype         = UPIO_PORT,
-               .line           = 1,
-               .type           = PORT_16550A,
-               .uartclk        = 115200*16,
-               .fifosize       = 16,
-       }
-};
-
 static void __devinit superio_serial_init(void)
 {
 #ifdef CONFIG_SERIAL_8250
        int retval;
-        
-       serial[0].iobase = sio_dev.sp1_base;
-       serial[0].irq = SP1_IRQ;
-       spin_lock_init(&serial[0].lock);
-
-       retval = early_serial_setup(&serial[0]);
+       struct uart_port serial_port;
+
+       memset(&serial_port, 0, sizeof(serial_port));
+       serial_port.iotype      = UPIO_PORT;
+       serial_port.type        = PORT_16550A;
+       serial_port.uartclk     = 115200*16;
+       serial_port.fifosize    = 16;
+       spin_lock_init(&serial_port.lock);
+
+       /* serial port #1 */
+       serial_port.iobase      = sio_dev.sp1_base;
+       serial_port.irq         = SP1_IRQ;
+       serial_port.line        = 0;
+       retval = early_serial_setup(&serial_port);
        if (retval < 0) {
                printk(KERN_WARNING PFX "Register Serial #0 failed.\n");
                return;
        }
 
-       serial[1].iobase = sio_dev.sp2_base;
-       serial[1].irq = SP2_IRQ;
-       spin_lock_init(&serial[1].lock);
-       retval = early_serial_setup(&serial[1]);
-
+       /* serial port #2 */
+       serial_port.iobase      = sio_dev.sp2_base;
+       serial_port.irq         = SP2_IRQ;
+       serial_port.line        = 1;
+       retval = early_serial_setup(&serial_port);
        if (retval < 0)
                printk(KERN_WARNING PFX "Register Serial #1 failed.\n");
 #endif /* CONFIG_SERIAL_8250 */
index 158d925..b953d59 100644 (file)
@@ -81,15 +81,15 @@ static char *version =
 #define FORCE_EPP_MODE 0x08
 
 typedef struct parport_info_t {
-    dev_link_t         link;
+       struct pcmcia_device    *p_dev;
     int                        ndev;
     dev_node_t         node;
     struct parport     *port;
 } parport_info_t;
 
 static void parport_detach(struct pcmcia_device *p_dev);
-static void parport_config(dev_link_t *link);
-static void parport_cs_release(dev_link_t *);
+static int parport_config(struct pcmcia_device *link);
+static void parport_cs_release(struct pcmcia_device *);
 
 /*======================================================================
 
@@ -99,10 +99,9 @@ static void parport_cs_release(dev_link_t *);
 
 ======================================================================*/
 
-static int parport_attach(struct pcmcia_device *p_dev)
+static int parport_probe(struct pcmcia_device *link)
 {
     parport_info_t *info;
-    dev_link_t *link;
 
     DEBUG(0, "parport_attach()\n");
 
@@ -110,23 +109,17 @@ static int parport_attach(struct pcmcia_device *p_dev)
     info = kmalloc(sizeof(*info), GFP_KERNEL);
     if (!info) return -ENOMEM;
     memset(info, 0, sizeof(*info));
-    link = &info->link; link->priv = info;
+    link->priv = info;
+    info->p_dev = link;
 
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    parport_config(link);
-
-    return 0;
+    return parport_config(link);
 } /* parport_attach */
 
 /*======================================================================
@@ -138,14 +131,11 @@ static int parport_attach(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void parport_detach(struct pcmcia_device *p_dev)
+static void parport_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-
     DEBUG(0, "parport_detach(0x%p)\n", link);
 
-    if (link->state & DEV_CONFIG)
-       parport_cs_release(link);
+    parport_cs_release(link);
 
     kfree(link->priv);
 } /* parport_detach */
@@ -161,14 +151,12 @@ static void parport_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-void parport_config(dev_link_t *link)
+static int parport_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     parport_info_t *info = link->priv;
     tuple_t tuple;
     u_short buf[128];
     cisparse_t parse;
-    config_info_t conf;
     cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
     cistpl_cftable_entry_t dflt = { 0 };
     struct parport *p;
@@ -180,24 +168,18 @@ void parport_config(dev_link_t *link)
     tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
 
-    /* Not sure if this is right... look up the current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-    
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
     tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (1) {
-       if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-               pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
            goto next_entry;
 
        if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
@@ -212,7 +194,7 @@ void parport_config(dev_link_t *link)
                link->io.BasePort2 = io->win[1].base;
                link->io.NumPorts2 = io->win[1].len;
            }
-           if (pcmcia_request_io(link->handle, &link->io) != 0)
+           if (pcmcia_request_io(link, &link->io) != 0)
                goto next_entry;
            /* If we've got this far, we're done */
            break;
@@ -220,15 +202,12 @@ void parport_config(dev_link_t *link)
        
     next_entry:
        if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
-       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
     }
     
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
-    release_region(link->io.BasePort1, link->io.NumPorts1);
-    if (link->io.NumPorts2)
-       release_region(link->io.BasePort2, link->io.NumPorts2);
     p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
                              link->irq.AssignedIRQ, PARPORT_DMA_NONE,
                              NULL);
@@ -247,17 +226,15 @@ void parport_config(dev_link_t *link)
     info->node.minor = p->number;
     info->port = p;
     strcpy(info->node.dev_name, p->name);
-    link->dev = &info->node;
+    link->dev_node = &info->node;
+
+    return 0;
 
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
-    
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     parport_cs_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
-
+    return -ENODEV;
 } /* parport_config */
 
 /*======================================================================
@@ -268,53 +245,21 @@ failed:
     
 ======================================================================*/
 
-void parport_cs_release(dev_link_t *link)
-{
-    parport_info_t *info = link->priv;
-    
-    DEBUG(0, "parport_release(0x%p)\n", link);
-
-    if (info->ndev) {
-       struct parport *p = info->port;
-       parport_pc_unregister_port(p);
-       request_region(link->io.BasePort1, link->io.NumPorts1,
-                      info->node.dev_name);
-       if (link->io.NumPorts2)
-           request_region(link->io.BasePort2, link->io.NumPorts2,
-                          info->node.dev_name);
-    }
-    info->ndev = 0;
-    link->dev = NULL;
-    
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    
-    link->state &= ~DEV_CONFIG;
-
-} /* parport_cs_release */
-
-static int parport_suspend(struct pcmcia_device *dev)
+void parport_cs_release(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
+       parport_info_t *info = link->priv;
 
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
+       DEBUG(0, "parport_release(0x%p)\n", link);
 
-       return 0;
-}
-
-static int parport_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
+       if (info->ndev) {
+               struct parport *p = info->port;
+               parport_pc_unregister_port(p);
+       }
+       info->ndev = 0;
 
-       link->state &= ~DEV_SUSPEND;
-       if (DEV_OK(link))
-               pcmcia_request_configuration(link->handle, &link->conf);
+       pcmcia_disable_device(link);
+} /* parport_cs_release */
 
-       return 0;
-}
 
 static struct pcmcia_device_id parport_ids[] = {
        PCMCIA_DEVICE_FUNC_ID(3),
@@ -328,11 +273,9 @@ static struct pcmcia_driver parport_cs_driver = {
        .drv            = {
                .name   = "parport_cs",
        },
-       .probe          = parport_attach,
+       .probe          = parport_probe,
        .remove         = parport_detach,
        .id_table       = parport_ids,
-       .suspend        = parport_suspend,
-       .resume         = parport_resume,
 };
 
 static int __init init_parport_cs(void)
index 1f4ad0e..cba6c9e 100644 (file)
@@ -263,6 +263,13 @@ config OMAP_CF
          Say Y here to support the CompactFlash controller on OMAP.
          Note that this doesn't support "True IDE" mode.
 
+config AT91_CF
+       tristate "AT91 CompactFlash Controller"
+       depends on PCMCIA && ARCH_AT91RM9200
+       help
+         Say Y here to support the CompactFlash controller on AT91 chips.
+         Or choose M to compile the driver as a module named "at91_cf".
+
 config PCCARD_NONSTATIC
        tristate
 
index bcecf51..4276965 100644 (file)
@@ -10,7 +10,7 @@ pcmcia_core-y                                 += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o
 pcmcia_core-$(CONFIG_CARDBUS)                  += cardbus.o
 obj-$(CONFIG_PCCARD)                           += pcmcia_core.o
 
-pcmcia-y                                       += ds.o pcmcia_compat.o pcmcia_resource.o
+pcmcia-y                                       += ds.o pcmcia_resource.o
 pcmcia-$(CONFIG_PCMCIA_IOCTL)                  += pcmcia_ioctl.o
 obj-$(CONFIG_PCMCIA)                           += pcmcia.o
 
@@ -36,6 +36,7 @@ obj-$(CONFIG_PCMCIA_AU1X00)                   += au1x00_ss.o
 obj-$(CONFIG_PCMCIA_VRC4171)                   += vrc4171_card.o
 obj-$(CONFIG_PCMCIA_VRC4173)                   += vrc4173_cardu.o
 obj-$(CONFIG_OMAP_CF)                          += omap_cf.o
+obj-$(CONFIG_AT91_CF)                          += at91_cf.o
 
 sa11xx_core-y                                  += soc_common.o sa11xx_base.o
 pxa2xx_core-y                                  += soc_common.o pxa2xx_base.o
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
new file mode 100644 (file)
index 0000000..67cc5f7
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * at91_cf.c -- AT91 CompactFlash controller driver
+ *
+ * Copyright (C) 2005 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+#define        CF_SIZE         0x30000000      /* CS5+CS6: unavailable */
+
+/*
+ * A0..A10 work in each range; A23 indicates I/O space;  A25 is CFRNW;
+ * some other bit in {A24,A22..A11} is nREG to flag memory access
+ * (vs attributes).  So more than 2KB/region would just be waste.
+ */
+#define        CF_ATTR_PHYS    (AT91_CF_BASE)
+#define        CF_IO_PHYS      (AT91_CF_BASE  + (1 << 23))
+#define        CF_MEM_PHYS     (AT91_CF_BASE  + 0x017ff800)
+
+/*--------------------------------------------------------------------------*/
+
+static const char driver_name[] = "at91_cf";
+
+struct at91_cf_socket {
+       struct pcmcia_socket    socket;
+
+       unsigned                present:1;
+
+       struct platform_device  *pdev;
+       struct at91_cf_data     *board;
+};
+
+#define        SZ_2K                   (2 * SZ_1K)
+
+static inline int at91_cf_present(struct at91_cf_socket *cf)
+{
+       return !at91_get_gpio_value(cf->board->det_pin);
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int at91_cf_ss_init(struct pcmcia_socket *s)
+{
+       return 0;
+}
+
+static irqreturn_t at91_cf_irq(int irq, void *_cf, struct pt_regs *r)
+{
+       struct at91_cf_socket   *cf = (struct at91_cf_socket *) _cf;
+
+       if (irq == cf->board->det_pin) {
+               unsigned present = at91_cf_present(cf);
+
+               /* kick pccard as needed */
+               if (present != cf->present) {
+                       cf->present = present;
+                       pr_debug("%s: card %s\n", driver_name, present ? "present" : "gone");
+                       pcmcia_parse_events(&cf->socket, SS_DETECT);
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+       struct at91_cf_socket   *cf;
+
+       if (!sp)
+               return -EINVAL;
+
+       cf = container_of(s, struct at91_cf_socket, socket);
+
+       /* NOTE: we assume 3VCARD, not XVCARD...  */
+       if (at91_cf_present(cf)) {
+               int rdy = cf->board->irq_pin;   /* RDY/nIRQ */
+               int vcc = cf->board->vcc_pin;
+
+               *sp = SS_DETECT | SS_3VCARD;
+               if (!rdy || at91_get_gpio_value(rdy))
+                       *sp |= SS_READY;
+               if (!vcc || at91_get_gpio_value(vcc))
+                       *sp |= SS_POWERON;
+       } else
+               *sp = 0;
+
+       return 0;
+}
+
+static int at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+{
+       struct at91_cf_socket   *cf;
+
+       cf = container_of(sock, struct at91_cf_socket, socket);
+
+       /* switch Vcc if needed and possible */
+       if (cf->board->vcc_pin) {
+               switch (s->Vcc) {
+                       case 0:
+                               at91_set_gpio_value(cf->board->vcc_pin, 0);
+                               break;
+                       case 33:
+                               at91_set_gpio_value(cf->board->vcc_pin, 1);
+                               break;
+                       default:
+                               return -EINVAL;
+               }
+       }
+
+       /* toggle reset if needed */
+       at91_set_gpio_value(cf->board->rst_pin, s->flags & SS_RESET);
+
+       pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
+               driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+
+       return 0;
+}
+
+static int at91_cf_ss_suspend(struct pcmcia_socket *s)
+{
+       return at91_cf_set_socket(s, &dead_socket);
+}
+
+/* we already mapped the I/O region */
+static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
+{
+       struct at91_cf_socket   *cf;
+       u32                     csr;
+
+       cf = container_of(s, struct at91_cf_socket, socket);
+       io->flags &= (MAP_ACTIVE | MAP_16BIT | MAP_AUTOSZ);
+
+       /*
+        * Use 16 bit accesses unless/until we need 8-bit i/o space.
+        * Always set CSR4 ... PCMCIA won't always unmap things.
+        */
+       csr = at91_sys_read(AT91_SMC_CSR(4)) & ~AT91_SMC_DBW;
+
+       /*
+        * NOTE: this CF controller ignores IOIS16, so we can't really do
+        * MAP_AUTOSZ.  The 16bit mode allows single byte access on either
+        * D0-D7 (even addr) or D8-D15 (odd), so it's close enough for many
+        * purposes (and handles ide-cs).
+        *
+        * The 8bit mode is needed for odd byte access on D0-D7.  It seems
+        * some cards only like that way to get at the odd byte, despite
+        * CF 3.0 spec table 35 also giving the D8-D15 option.
+        */
+       if (!(io->flags & (MAP_16BIT|MAP_AUTOSZ))) {
+               csr |= AT91_SMC_DBW_8;
+               pr_debug("%s: 8bit i/o bus\n", driver_name);
+       } else {
+               csr |= AT91_SMC_DBW_16;
+               pr_debug("%s: 16bit i/o bus\n", driver_name);
+       }
+       at91_sys_write(AT91_SMC_CSR(4), csr);
+
+       io->start = cf->socket.io_offset;
+       io->stop = io->start + SZ_2K - 1;
+
+       return 0;
+}
+
+/* pcmcia layer maps/unmaps mem regions */
+static int at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
+{
+       struct at91_cf_socket   *cf;
+
+       if (map->card_start)
+               return -EINVAL;
+
+       cf = container_of(s, struct at91_cf_socket, socket);
+
+       map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+       if (map->flags & MAP_ATTRIB)
+               map->static_start = CF_ATTR_PHYS;
+       else
+               map->static_start = CF_MEM_PHYS;
+
+       return 0;
+}
+
+static struct pccard_operations at91_cf_ops = {
+       .init                   = at91_cf_ss_init,
+       .suspend                = at91_cf_ss_suspend,
+       .get_status             = at91_cf_get_status,
+       .set_socket             = at91_cf_set_socket,
+       .set_io_map             = at91_cf_set_io_map,
+       .set_mem_map            = at91_cf_set_mem_map,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init at91_cf_probe(struct device *dev)
+{
+       struct at91_cf_socket   *cf;
+       struct at91_cf_data     *board = dev->platform_data;
+       struct platform_device  *pdev = to_platform_device(dev);
+       unsigned int            csa;
+       int                     status;
+
+       if (!board || !board->det_pin || !board->rst_pin)
+               return -ENODEV;
+
+       cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+       if (!cf)
+               return -ENOMEM;
+
+       cf->board = board;
+       cf->pdev = pdev;
+       dev_set_drvdata(dev, cf);
+
+       /* CF takes over CS4, CS5, CS6 */
+       csa = at91_sys_read(AT91_EBI_CSA);
+       at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH);
+
+       /* force poweron defaults for these pins ... */
+       (void) at91_set_A_periph(AT91_PIN_PC9, 0);      /* A25/CFRNW */
+       (void) at91_set_A_periph(AT91_PIN_PC10, 0);     /* NCS4/CFCS */
+       (void) at91_set_A_periph(AT91_PIN_PC11, 0);     /* NCS5/CFCE1 */
+       (void) at91_set_A_periph(AT91_PIN_PC12, 0);     /* NCS6/CFCE2 */
+
+       /* nWAIT is _not_ a default setting */
+       (void) at91_set_A_periph(AT91_PIN_PC6, 1);      /*  nWAIT */
+
+       /*
+        * Static memory controller timing adjustments.
+        * REVISIT:  these timings are in terms of MCK cycles, so
+        * when MCK changes (cpufreq etc) so must these values...
+        */
+       at91_sys_write(AT91_SMC_CSR(4), AT91_SMC_ACSS_STD | AT91_SMC_DBW_16 | AT91_SMC_BAT | AT91_SMC_WSEN
+                               | AT91_SMC_NWS_(32)             /* wait states */
+                               | AT91_SMC_RWSETUP_(6)          /* setup time */
+                               | AT91_SMC_RWHOLD_(4)           /* hold time */
+       );
+
+       /* must be a GPIO; ergo must trigger on both edges */
+       status = request_irq(board->det_pin, at91_cf_irq,
+                       SA_SAMPLE_RANDOM, driver_name, cf);
+       if (status < 0)
+               goto fail0;
+
+       /*
+        * The card driver will request this irq later as needed.
+        * but it causes lots of "irqNN: nobody cared" messages
+        * unless we report that we handle everything (sigh).
+        * (Note:  DK board doesn't wire the IRQ pin...)
+        */
+       if (board->irq_pin) {
+               status = request_irq(board->irq_pin, at91_cf_irq,
+                               SA_SHIRQ, driver_name, cf);
+               if (status < 0)
+                       goto fail0a;
+               cf->socket.pci_irq = board->irq_pin;
+       }
+       else
+               cf->socket.pci_irq = NR_IRQS + 1;
+
+       /* pcmcia layer only remaps "real" memory not iospace */
+       cf->socket.io_offset = (unsigned long) ioremap(CF_IO_PHYS, SZ_2K);
+       if (!cf->socket.io_offset)
+               goto fail1;
+
+       /* reserve CS4, CS5, and CS6 regions; but use just CS4 */
+       if (!request_mem_region(AT91_CF_BASE, CF_SIZE, driver_name))
+               goto fail1;
+
+       pr_info("%s: irqs det #%d, io #%d\n", driver_name,
+               board->det_pin, board->irq_pin);
+
+       cf->socket.owner = THIS_MODULE;
+       cf->socket.dev.dev = dev;
+       cf->socket.ops = &at91_cf_ops;
+       cf->socket.resource_ops = &pccard_static_ops;
+       cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
+                               | SS_CAP_MEM_ALIGN;
+       cf->socket.map_size = SZ_2K;
+       cf->socket.io[0].NumPorts = SZ_2K;
+
+       status = pcmcia_register_socket(&cf->socket);
+       if (status < 0)
+               goto fail2;
+
+       return 0;
+
+fail2:
+       iounmap((void __iomem *) cf->socket.io_offset);
+       release_mem_region(AT91_CF_BASE, CF_SIZE);
+fail1:
+       if (board->irq_pin)
+               free_irq(board->irq_pin, cf);
+fail0a:
+       free_irq(board->det_pin, cf);
+fail0:
+       at91_sys_write(AT91_EBI_CSA, csa);
+       kfree(cf);
+       return status;
+}
+
+static int __exit at91_cf_remove(struct device *dev)
+{
+       struct at91_cf_socket *cf = dev_get_drvdata(dev);
+       unsigned int csa;
+
+       pcmcia_unregister_socket(&cf->socket);
+       free_irq(cf->board->irq_pin, cf);
+       free_irq(cf->board->det_pin, cf);
+       iounmap((void __iomem *) cf->socket.io_offset);
+       release_mem_region(AT91_CF_BASE, CF_SIZE);
+
+       csa = at91_sys_read(AT91_EBI_CSA);
+       at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A);
+
+       kfree(cf);
+       return 0;
+}
+
+static struct device_driver at91_cf_driver = {
+       .name           = (char *) driver_name,
+       .bus            = &platform_bus_type,
+       .probe          = at91_cf_probe,
+       .remove         = __exit_p(at91_cf_remove),
+       .suspend        = pcmcia_socket_dev_suspend,
+       .resume         = pcmcia_socket_dev_resume,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init at91_cf_init(void)
+{
+       return driver_register(&at91_cf_driver);
+}
+module_init(at91_cf_init);
+
+static void __exit at91_cf_exit(void)
+{
+       driver_unregister(&at91_cf_driver);
+}
+module_exit(at91_cf_exit);
+
+MODULE_DESCRIPTION("AT91 Compact Flash Driver");
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
index 120fa8d..912c03e 100644 (file)
@@ -12,7 +12,6 @@
  * (C) 1999            David A. Hinds
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
index 613f2f1..3162998 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/major.h>
 #include <linux/errno.h>
@@ -111,9 +110,9 @@ int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state)
        list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
                if (socket->dev.dev != dev)
                        continue;
-               down(&socket->skt_sem);
+               mutex_lock(&socket->skt_mutex);
                socket_suspend(socket);
-               up(&socket->skt_sem);
+               mutex_unlock(&socket->skt_mutex);
        }
        up_read(&pcmcia_socket_list_rwsem);
 
@@ -129,9 +128,9 @@ int pcmcia_socket_dev_resume(struct device *dev)
        list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
                if (socket->dev.dev != dev)
                        continue;
-               down(&socket->skt_sem);
+               mutex_lock(&socket->skt_mutex);
                socket_resume(socket);
-               up(&socket->skt_sem);
+               mutex_unlock(&socket->skt_mutex);
        }
        up_read(&pcmcia_socket_list_rwsem);
 
@@ -237,7 +236,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
        init_completion(&socket->socket_released);
        init_completion(&socket->thread_done);
        init_waitqueue_head(&socket->thread_wait);
-       init_MUTEX(&socket->skt_sem);
+       mutex_init(&socket->skt_mutex);
        spin_lock_init(&socket->thread_lock);
 
        ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
@@ -406,8 +405,6 @@ static void socket_shutdown(struct pcmcia_socket *s)
        cb_free(s);
 #endif
        s->functions = 0;
-       kfree(s->config);
-       s->config = NULL;
 
        s->ops->get_status(s, &status);
        if (status & SS_POWERON) {
@@ -664,7 +661,7 @@ static int pccardd(void *__skt)
                spin_unlock_irqrestore(&skt->thread_lock, flags);
 
                if (events) {
-                       down(&skt->skt_sem);
+                       mutex_lock(&skt->skt_mutex);
                        if (events & SS_DETECT)
                                socket_detect_change(skt);
                        if (events & SS_BATDEAD)
@@ -673,7 +670,7 @@ static int pccardd(void *__skt)
                                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);
+                       mutex_unlock(&skt->skt_mutex);
                        continue;
                }
 
@@ -717,8 +714,8 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
 {
         int ret = 0;
 
-       /* s->skt_sem also protects s->callback */
-       down(&s->skt_sem);
+       /* s->skt_mutex also protects s->callback */
+       mutex_lock(&s->skt_mutex);
 
        if (c) {
                /* registration */
@@ -734,7 +731,7 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
        } else
                s->callback = NULL;
  err:
-       up(&s->skt_sem);
+       mutex_unlock(&s->skt_mutex);
 
        return ret;
 }
@@ -752,7 +749,7 @@ int pccard_reset_card(struct pcmcia_socket *skt)
 
        cs_dbg(skt, 1, "resetting socket\n");
 
-       down(&skt->skt_sem);
+       mutex_lock(&skt->skt_mutex);
        do {
                if (!(skt->state & SOCKET_PRESENT)) {
                        ret = CS_NO_CARD;
@@ -781,7 +778,7 @@ int pccard_reset_card(struct pcmcia_socket *skt)
 
                ret = CS_SUCCESS;
        } while (0);
-       up(&skt->skt_sem);
+       mutex_unlock(&skt->skt_mutex);
 
        return ret;
 } /* reset_card */
@@ -797,7 +794,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
 
        cs_dbg(skt, 1, "suspending socket\n");
 
-       down(&skt->skt_sem);
+       mutex_lock(&skt->skt_mutex);
        do {
                if (!(skt->state & SOCKET_PRESENT)) {
                        ret = CS_NO_CARD;
@@ -814,7 +811,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
                }
                ret = socket_suspend(skt);
        } while (0);
-       up(&skt->skt_sem);
+       mutex_unlock(&skt->skt_mutex);
 
        return ret;
 } /* suspend_card */
@@ -827,7 +824,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
     
        cs_dbg(skt, 1, "waking up socket\n");
 
-       down(&skt->skt_sem);
+       mutex_lock(&skt->skt_mutex);
        do {
                if (!(skt->state & SOCKET_PRESENT)) {
                        ret = CS_NO_CARD;
@@ -841,7 +838,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
                if (!ret && skt->callback)
                        skt->callback->resume(skt);
        } while (0);
-       up(&skt->skt_sem);
+       mutex_unlock(&skt->skt_mutex);
 
        return ret;
 } /* resume_card */
@@ -855,7 +852,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt)
     
        cs_dbg(skt, 1, "user eject request\n");
 
-       down(&skt->skt_sem);
+       mutex_lock(&skt->skt_mutex);
        do {
                if (!(skt->state & SOCKET_PRESENT)) {
                        ret = -ENODEV;
@@ -871,7 +868,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt)
                socket_remove(skt);
                ret = 0;
        } while (0);
-       up(&skt->skt_sem);
+       mutex_unlock(&skt->skt_mutex);
 
        return ret;
 } /* eject_card */
@@ -884,7 +881,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
 
        cs_dbg(skt, 1, "user insert request\n");
 
-       down(&skt->skt_sem);
+       mutex_lock(&skt->skt_mutex);
        do {
                if (skt->state & SOCKET_PRESENT) {
                        ret = -EBUSY;
@@ -896,7 +893,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
                }
                ret = 0;
        } while (0);
-       up(&skt->skt_sem);
+       mutex_unlock(&skt->skt_mutex);
 
        return ret;
 } /* insert_card */
index 7b37eba..d6164cd 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef _LINUX_CS_INTERNAL_H
 #define _LINUX_CS_INTERNAL_H
 
-#include <linux/config.h>
+#include <linux/kref.h>
 
 /* Flags in client state */
 #define CLIENT_CONFIG_LOCKED   0x0001
@@ -23,7 +23,7 @@
 #define CLIENT_IO_REQ          0x0004
 #define CLIENT_UNBOUND         0x0008
 #define CLIENT_STALE           0x0010
-#define CLIENT_WIN_REQ(i)      (0x20<<(i))
+#define CLIENT_WIN_REQ(i)      (0x1<<(i))
 #define CLIENT_CARDBUS         0x8000
 
 #define REGION_MAGIC   0xE3C9
@@ -31,7 +31,7 @@ typedef struct region_t {
     u_short            region_magic;
     u_short            state;
     dev_info_t         dev_info;
-    client_handle_t    mtd;
+    struct pcmcia_device       *mtd;
     u_int              MediaID;
     region_info_t      info;
 } region_t;
@@ -40,12 +40,12 @@ typedef struct region_t {
 
 /* Each card function gets one of these guys */
 typedef struct config_t {
+       struct kref     ref;
     u_int              state;
     u_int              Attributes;
     u_int              IntType;
     u_int              ConfigBase;
     u_char             Status, Pin, Copy, Option, ExtStatus;
-    u_int              Present;
     u_int              CardValues;
     io_req_t           io;
     struct {
@@ -95,12 +95,6 @@ static inline void cs_socket_put(struct pcmcia_socket *skt)
        }
 }
 
-#define CHECK_SOCKET(s) \
-    (((s) >= sockets) || (socket_table[s]->ops == NULL))
-
-#define SOCKET(h) (h->socket)
-#define CONFIG(h) (&SOCKET(h)->config[(h)->func])
-
 /* In cardbus.c */
 int cb_alloc(struct pcmcia_socket *s);
 void cb_free(struct pcmcia_socket *s);
@@ -133,10 +127,9 @@ extern struct class_interface pccard_sysfs_interface;
 extern struct rw_semaphore pcmcia_socket_list_rwsem;
 extern struct list_head pcmcia_socket_list;
 int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req);
-int pccard_get_configuration_info(struct pcmcia_socket *s, unsigned int function, config_info_t *config);
+int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config);
 int pccard_reset_card(struct pcmcia_socket *skt);
-int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status);
-int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg);
+int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status);
 
 
 struct pcmcia_callback{
index bb96ce1..ae10d1e 100644 (file)
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * (C) 1999            David A. Hinds
- * (C) 2003 - 2005     Dominik Brodowski
+ * (C) 2003 - 2006     Dominik Brodowski
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -23,6 +22,7 @@
 #include <linux/workqueue.h>
 #include <linux/crc32.h>
 #include <linux/firmware.h>
+#include <linux/kref.h>
 
 #define IN_CARD_SERVICES
 #include <pcmcia/cs_types.h>
@@ -343,12 +343,19 @@ void pcmcia_put_dev(struct pcmcia_device *p_dev)
                put_device(&p_dev->dev);
 }
 
+static void pcmcia_release_function(struct kref *ref)
+{
+       struct config_t *c = container_of(ref, struct config_t, ref);
+       kfree(c);
+}
+
 static void pcmcia_release_dev(struct device *dev)
 {
        struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
        ds_dbg(1, "releasing dev %p\n", p_dev);
        pcmcia_put_socket(p_dev->socket);
        kfree(p_dev->devname);
+       kref_put(&p_dev->function_config->ref, pcmcia_release_function);
        kfree(p_dev);
 }
 
@@ -377,29 +384,12 @@ static int pcmcia_device_probe(struct device * dev)
        p_drv = to_pcmcia_drv(dev->driver);
        s = p_dev->socket;
 
-       if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) {
+       if ((!p_drv->probe) || (!p_dev->function_config) ||
+           (!try_module_get(p_drv->owner))) {
                ret = -EINVAL;
                goto put_dev;
        }
 
-       p_dev->state &= ~CLIENT_UNBOUND;
-
-       /* set up the device configuration, if it hasn't been done before */
-       if (!s->functions) {
-               cistpl_longlink_mfc_t mfc;
-               if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC,
-                                     &mfc) == CS_SUCCESS)
-                       s->functions = mfc.nfn;
-               else
-                       s->functions = 1;
-               s->config = kzalloc(sizeof(config_t) * s->functions,
-                                   GFP_KERNEL);
-               if (!s->config) {
-                       ret = -ENOMEM;
-                       goto put_module;
-               }
-       }
-
        ret = p_drv->probe(p_dev);
        if (ret)
                goto put_module;
@@ -425,15 +415,61 @@ static int pcmcia_device_probe(struct device * dev)
 }
 
 
+/*
+ * Removes a PCMCIA card from the device tree and socket list.
+ */
+static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *leftover)
+{
+       struct pcmcia_device    *p_dev;
+       struct pcmcia_device    *tmp;
+       unsigned long           flags;
+
+       ds_dbg(2, "unbind_request(%d)\n", s->sock);
+
+
+       if (!leftover)
+               s->device_count = 0;
+       else
+               s->device_count = 1;
+
+       /* unregister all pcmcia_devices registered with this socket, except leftover */
+       list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) {
+               if (p_dev == leftover)
+                       continue;
+
+               spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+               list_del(&p_dev->socket_device_list);
+               p_dev->_removed=1;
+               spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+               device_unregister(&p_dev->dev);
+       }
+
+       return;
+}
+
+
 static int pcmcia_device_remove(struct device * dev)
 {
        struct pcmcia_device *p_dev;
        struct pcmcia_driver *p_drv;
+       struct pcmcia_device_id *did;
        int i;
 
-       /* detach the "instance" */
        p_dev = to_pcmcia_dev(dev);
        p_drv = to_pcmcia_drv(dev->driver);
+
+       /* If we're removing the primary module driving a
+        * pseudo multi-function card, we need to unbind
+        * all devices
+        */
+       did = (struct pcmcia_device_id *) p_dev->dev.driver_data;
+       if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
+           (p_dev->socket->device_count != 0) &&
+           (p_dev->device_no == 0))
+               pcmcia_card_remove(p_dev->socket, p_dev);
+
+       /* detach the "instance" */
        if (!p_drv)
                return 0;
 
@@ -441,17 +477,16 @@ static int pcmcia_device_remove(struct device * dev)
                p_drv->remove(p_dev);
 
        /* check for proper unloading */
-       if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+       if (p_dev->_irq || p_dev->_io || p_dev->_locked)
                printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
                       p_drv->drv.name);
 
        for (i = 0; i < MAX_WIN; i++)
-               if (p_dev->state & CLIENT_WIN_REQ(i))
+               if (p_dev->_win & CLIENT_WIN_REQ(i))
                        printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
                               p_drv->drv.name);
 
        /* references from pcmcia_probe_device */
-       p_dev->state = CLIENT_UNBOUND;
        pcmcia_put_dev(p_dev);
        module_put(p_drv->owner);
 
@@ -459,37 +494,6 @@ static int pcmcia_device_remove(struct device * dev)
 }
 
 
-/*
- * Removes a PCMCIA card from the device tree and socket list.
- */
-static void pcmcia_card_remove(struct pcmcia_socket *s)
-{
-       struct pcmcia_device    *p_dev;
-       unsigned long           flags;
-
-       ds_dbg(2, "unbind_request(%d)\n", s->sock);
-
-       s->device_count = 0;
-
-       for (;;) {
-               /* unregister all pcmcia_devices registered with this socket*/
-               spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
-               if (list_empty(&s->devices_list)) {
-                       spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-                       return;
-               }
-               p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
-               list_del(&p_dev->socket_device_list);
-               p_dev->state |= CLIENT_STALE;
-               spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-
-               device_unregister(&p_dev->dev);
-       }
-
-       return;
-} /* unbind_request */
-
-
 /*
  * pcmcia_device_query -- determine information about a pcmcia device
  */
@@ -546,7 +550,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
                        tmp = vers1->str + vers1->ofs[i];
 
                        length = strlen(tmp) + 1;
-                       if ((length < 3) || (length > 255))
+                       if ((length < 2) || (length > 255))
                                continue;
 
                        p_dev->prod_id[i] = kmalloc(sizeof(char) * length,
@@ -571,11 +575,11 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
  * won't work, this doesn't matter much at the moment: the driver core doesn't
  * support it either.
  */
-static DECLARE_MUTEX(device_add_lock);
+static DEFINE_MUTEX(device_add_lock);
 
 struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function)
 {
-       struct pcmcia_device *p_dev;
+       struct pcmcia_device *p_dev, *tmp_dev;
        unsigned long flags;
        int bus_id_len;
 
@@ -583,7 +587,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
        if (!s)
                return NULL;
 
-       down(&device_add_lock);
+       mutex_lock(&device_add_lock);
 
        /* max of 2 devices per card */
        if (s->device_count == 2)
@@ -596,6 +600,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
        p_dev->socket = s;
        p_dev->device_no = (s->device_count++);
        p_dev->func   = function;
+       if (s->functions <= function)
+               s->functions = function + 1;
 
        p_dev->dev.bus = &pcmcia_bus_type;
        p_dev->dev.parent = s->dev.dev;
@@ -608,36 +614,55 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
        sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
 
        /* compat */
-       p_dev->state = CLIENT_UNBOUND;
+       spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+
+       /*
+        * p_dev->function_config must be the same for all card functions.
+        * Note that this is serialized by the device_add_lock, so that
+        * only one such struct will be created.
+        */
+        list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list)
+                if (p_dev->func == tmp_dev->func) {
+                       p_dev->function_config = tmp_dev->function_config;
+                       kref_get(&p_dev->function_config->ref);
+               }
 
        /* Add to the list in pcmcia_bus_socket */
-       spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
        list_add_tail(&p_dev->socket_device_list, &s->devices_list);
+
        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
+       if (!p_dev->function_config) {
+               p_dev->function_config = kzalloc(sizeof(struct config_t),
+                                                GFP_KERNEL);
+               if (!p_dev->function_config)
+                       goto err_unreg;
+               kref_init(&p_dev->function_config->ref);
+       }
+
        printk(KERN_NOTICE "pcmcia: registering new device %s\n",
               p_dev->devname);
 
        pcmcia_device_query(p_dev);
 
-       if (device_register(&p_dev->dev)) {
-               spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
-               list_del(&p_dev->socket_device_list);
-               spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-
-               goto err_free;
-       }
+       if (device_register(&p_dev->dev))
+               goto err_unreg;
 
-       up(&device_add_lock);
+       mutex_unlock(&device_add_lock);
 
        return p_dev;
 
+ err_unreg:
+       spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+       list_del(&p_dev->socket_device_list);
+       spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
  err_free:
        kfree(p_dev->devname);
        kfree(p_dev);
        s->device_count--;
  err_put:
-       up(&device_add_lock);
+       mutex_unlock(&device_add_lock);
        pcmcia_put_socket(s);
 
        return NULL;
@@ -696,7 +721,7 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt)
        int no_devices=0;
        unsigned long flags;
 
-       /* must be called with skt_sem held */
+       /* must be called with skt_mutex held */
        spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
        if (list_empty(&skt->devices_list))
                no_devices=1;
@@ -819,9 +844,11 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
        struct pcmcia_driver * p_drv = to_pcmcia_drv(drv);
        struct pcmcia_device_id *did = p_drv->id_table;
 
+#ifdef CONFIG_PCMCIA_IOCTL
        /* matching by cardmgr */
        if (p_dev->cardmgr == p_drv)
                return 1;
+#endif
 
        while (did && did->match_flags) {
                if (pcmcia_devmatch(p_dev, did))
@@ -927,7 +954,7 @@ static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute
 {
        struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
 
-       if (p_dev->dev.power.power_state.event != PM_EVENT_ON)
+       if (p_dev->suspended)
                return sprintf(buf, "off\n");
        else
                return sprintf(buf, "on\n");
@@ -942,11 +969,9 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute
         if (!count)
                 return -EINVAL;
 
-       if ((p_dev->dev.power.power_state.event == PM_EVENT_ON) &&
-           (!strncmp(buf, "off", 3)))
+       if ((!p_dev->suspended) && !strncmp(buf, "off", 3))
                ret = dpm_runtime_suspend(dev, PMSG_SUSPEND);
-       else if ((p_dev->dev.power.power_state.event != PM_EVENT_ON) &&
-                (!strncmp(buf, "on", 2)))
+       else if (p_dev->suspended && !strncmp(buf, "on", 2))
                dpm_runtime_resume(dev);
 
        return ret ? ret : count;
@@ -982,9 +1007,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
        if (!count)
                return -EINVAL;
 
-       down(&p_dev->socket->skt_sem);
+       mutex_lock(&p_dev->socket->skt_mutex);
        p_dev->allow_func_id_match = 1;
-       up(&p_dev->socket->skt_sem);
+       mutex_unlock(&p_dev->socket->skt_mutex);
 
        bus_rescan_devices(&pcmcia_bus_type);
 
@@ -1012,14 +1037,27 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
 {
        struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
        struct pcmcia_driver *p_drv = NULL;
+       int ret = 0;
 
        if (dev->driver)
                p_drv = to_pcmcia_drv(dev->driver);
 
-       if (p_drv && p_drv->suspend)
-               return p_drv->suspend(p_dev);
+       if (!p_drv)
+               goto out;
 
-       return 0;
+       if (p_drv->suspend) {
+               ret = p_drv->suspend(p_dev);
+               if (ret)
+                       goto out;
+       }
+
+       if (p_dev->device_no == p_dev->func)
+               pcmcia_release_configuration(p_dev);
+
+ out:
+       if (!ret)
+               p_dev->suspended = 1;
+       return ret;
 }
 
 
@@ -1027,14 +1065,27 @@ static int pcmcia_dev_resume(struct device * dev)
 {
        struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
         struct pcmcia_driver *p_drv = NULL;
+       int ret = 0;
 
        if (dev->driver)
                p_drv = to_pcmcia_drv(dev->driver);
 
-       if (p_drv && p_drv->resume)
-               return p_drv->resume(p_dev);
+       if (!p_drv)
+               goto out;
 
-       return 0;
+       if (p_dev->device_no == p_dev->func) {
+               ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+               if (ret)
+                       goto out;
+       }
+
+       if (p_drv->resume)
+               ret = p_drv->resume(p_dev);
+
+ out:
+       if (!ret)
+               p_dev->suspended = 0;
+       return ret;
 }
 
 
@@ -1100,7 +1151,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
        switch (event) {
        case CS_EVENT_CARD_REMOVAL:
                s->pcmcia_state.present = 0;
-               pcmcia_card_remove(skt);
+               pcmcia_card_remove(skt, NULL);
                handle_event(skt, event);
                break;
 
@@ -1128,6 +1179,32 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
 } /* ds_event */
 
 
+struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *_p_dev)
+{
+       struct pcmcia_device *p_dev;
+       struct pcmcia_device *ret = NULL;
+
+       p_dev = pcmcia_get_dev(_p_dev);
+       if (!p_dev)
+               return NULL;
+
+       if (!p_dev->socket->pcmcia_state.present)
+               goto out;
+
+       if (p_dev->_removed)
+               goto out;
+
+       if (p_dev->suspended)
+               goto out;
+
+       ret = p_dev;
+ out:
+       pcmcia_put_dev(p_dev);
+       return ret;
+}
+EXPORT_SYMBOL(pcmcia_dev_present);
+
+
 static struct pcmcia_callback pcmcia_bus_callback = {
        .owner = THIS_MODULE,
        .event = ds_event,
index d359bd2..3a2b25e 100644 (file)
@@ -8,6 +8,8 @@ extern void pcmcia_put_dev(struct pcmcia_device *p_dev);
 
 struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function);
 
+extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
+
 #ifdef CONFIG_PCMCIA_IOCTL
 extern void __init pcmcia_setup_ioctl(void);
 extern void __exit pcmcia_cleanup_ioctl(void);
@@ -15,7 +17,7 @@ extern void handle_event(struct pcmcia_socket *s, event_t event);
 extern int handle_request(struct pcmcia_socket *s, event_t event);
 #else
 static inline void __init pcmcia_setup_ioctl(void) { return; }
-static inline void __init pcmcia_cleanup_ioctl(void) { return; }
+static inline void __exit pcmcia_cleanup_ioctl(void) { return; }
 static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; }
 static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; }
 #endif
index 7979c85..d5f03a3 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
index 35a92d1..bd0308e 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/string.h>
diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c
deleted file mode 100644 (file)
index ebb161c..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * PCMCIA 16-bit compatibility functions
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
- *
- * Copyright (C) 2004 Dominik Brodowski
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#define IN_CARD_SERVICES
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/ss.h>
-
-#include "cs_internal.h"
-
-int pcmcia_get_first_tuple(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
-       return pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_first_tuple);
-
-int pcmcia_get_next_tuple(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
-       return pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_next_tuple);
-
-int pcmcia_get_tuple_data(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
-       return pccard_get_tuple_data(p_dev->socket, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_tuple_data);
-
-int pcmcia_parse_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, cisparse_t *parse)
-{
-       return pccard_parse_tuple(tuple, parse);
-}
-EXPORT_SYMBOL(pcmcia_parse_tuple);
-
-int pcmcia_validate_cis(struct pcmcia_device *p_dev, cisinfo_t *info)
-{
-       return pccard_validate_cis(p_dev->socket, p_dev->func, info);
-}
-EXPORT_SYMBOL(pcmcia_validate_cis);
-
-
-int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req)
-{
-       return pccard_reset_card(p_dev->socket);
-}
-EXPORT_SYMBOL(pcmcia_reset_card);
index 80969f7..c53db7c 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -70,10 +69,26 @@ extern int ds_pc_debug;
 #define ds_dbg(lvl, fmt, arg...) do { } while (0)
 #endif
 
+static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s,
+                                               unsigned int function)
+{
+       struct pcmcia_device *p_dev = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+       list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
+               if (p_dev->func == function) {
+                       spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+                       return pcmcia_get_dev(p_dev);
+               }
+       }
+       spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+       return NULL;
+}
 
 /* backwards-compatible accessing of driver --- by name! */
 
-static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info)
+static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info)
 {
        struct device_driver *drv;
        struct pcmcia_driver *p_drv;
@@ -214,7 +229,7 @@ static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info)
                                         * by userspace before, we need to
                                         * return the "instance". */
                                        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-                                       bind_info->instance = p_dev->instance;
+                                       bind_info->instance = p_dev;
                                        ret = -EBUSY;
                                        goto err_put_module;
                                } else {
@@ -253,9 +268,9 @@ rescan:
        /*
         * Prevent this racing with a card insertion.
         */
-       down(&s->skt_sem);
+       mutex_lock(&s->skt_mutex);
        bus_rescan_devices(&pcmcia_bus_type);
-       up(&s->skt_sem);
+       mutex_unlock(&s->skt_mutex);
 
        /* check whether the driver indeed matched. I don't care if this
         * is racy or not, because it can only happen on cardmgr access
@@ -289,6 +304,7 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int
 {
        dev_node_t *node;
        struct pcmcia_device *p_dev;
+       struct pcmcia_driver *p_drv;
        unsigned long flags;
        int ret = 0;
 
@@ -343,16 +359,16 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int
  found:
        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
-       if ((!p_dev->instance) ||
-           (p_dev->instance->state & DEV_CONFIG_PENDING)) {
+       p_drv = to_pcmcia_drv(p_dev->dev.driver);
+       if (p_drv && !p_dev->_locked) {
                ret = -EAGAIN;
                goto err_put;
        }
 
        if (first)
-               node = p_dev->instance->dev;
+               node = p_dev->dev_node;
        else
-               for (node = p_dev->instance->dev; node; node = node->next)
+               for (node = p_dev->dev_node; node; node = node->next)
                        if (node == bind_info->next)
                                break;
        if (!node) {
@@ -583,14 +599,16 @@ static int ds_ioctl(struct inode * inode, struct file * file,
        if (buf->config.Function &&
           (buf->config.Function >= s->functions))
            ret = CS_BAD_ARGS;
-       else
-           ret = pccard_get_configuration_info(s,
-                       buf->config.Function, &buf->config);
+       else {
+           struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
+           ret = pccard_get_configuration_info(s, p_dev, &buf->config);
+           pcmcia_put_dev(p_dev);
+       }
        break;
     case DS_GET_FIRST_TUPLE:
-       down(&s->skt_sem);
+       mutex_lock(&s->skt_mutex);
        pcmcia_validate_mem(s);
-       up(&s->skt_sem);
+       mutex_unlock(&s->skt_mutex);
        ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple);
        break;
     case DS_GET_NEXT_TUPLE:
@@ -609,16 +627,19 @@ static int ds_ioctl(struct inode * inode, struct file * file,
        ret = pccard_reset_card(s);
        break;
     case DS_GET_STATUS:
-       if (buf->status.Function &&
-          (buf->status.Function >= s->functions))
-           ret = CS_BAD_ARGS;
-       else
-       ret = pccard_get_status(s, buf->status.Function, &buf->status);
-       break;
+           if (buf->status.Function &&
+               (buf->status.Function >= s->functions))
+                   ret = CS_BAD_ARGS;
+           else {
+                   struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
+                   ret = pccard_get_status(s, p_dev, &buf->status);
+                   pcmcia_put_dev(p_dev);
+           }
+           break;
     case DS_VALIDATE_CIS:
-       down(&s->skt_sem);
+       mutex_lock(&s->skt_mutex);
        pcmcia_validate_mem(s);
-       up(&s->skt_sem);
+       mutex_unlock(&s->skt_mutex);
        ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo);
        break;
     case DS_SUSPEND_CARD:
@@ -638,12 +659,16 @@ static int ds_ioctl(struct inode * inode, struct file * file,
            err = -EPERM;
            goto free_out;
        }
-       if (buf->conf_reg.Function &&
-          (buf->conf_reg.Function >= s->functions))
-           ret = CS_BAD_ARGS;
-       else
-           ret = pccard_access_configuration_register(s,
-                       buf->conf_reg.Function, &buf->conf_reg);
+
+       ret = CS_BAD_ARGS;
+
+       if (!(buf->conf_reg.Function &&
+            (buf->conf_reg.Function >= s->functions))) {
+               struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function);
+               if (p_dev)
+                       ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg);
+               pcmcia_put_dev(p_dev);
+       }
        break;
     case DS_GET_FIRST_REGION:
     case DS_GET_NEXT_REGION:
index 89022ad..45063b4 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
@@ -89,7 +88,7 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
        }
        if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) {
                *base = s->io_offset | (*base & 0x0fff);
-               s->io[0].Attributes = attr;
+               s->io[0].res->flags = (s->io[0].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS);
                return 0;
        }
        /* Check for an already-allocated window that must conflict with
@@ -97,38 +96,36 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
         * potential conflicts, just the most obvious ones.
         */
        for (i = 0; i < MAX_IO_WIN; i++)
-               if ((s->io[i].NumPorts != 0) &&
-                   ((s->io[i].BasePort & (align-1)) == *base))
+               if ((s->io[i].res) &&
+                   ((s->io[i].res->start & (align-1)) == *base))
                        return 1;
        for (i = 0; i < MAX_IO_WIN; i++) {
-               if (s->io[i].NumPorts == 0) {
+               if (!s->io[i].res) {
                        s->io[i].res = pcmcia_find_io_region(*base, num, align, s);
                        if (s->io[i].res) {
-                               s->io[i].Attributes = attr;
-                               s->io[i].BasePort = *base = s->io[i].res->start;
-                               s->io[i].NumPorts = s->io[i].InUse = num;
+                               *base = s->io[i].res->start;
+                               s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS);
+                               s->io[i].InUse = num;
                                break;
                        } else
                                return 1;
-               } else if (s->io[i].Attributes != attr)
+               } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS))
                        continue;
                /* Try to extend top of window */
-               try = s->io[i].BasePort + s->io[i].NumPorts;
+               try = s->io[i].res->end + 1;
                if ((*base == 0) || (*base == try))
                        if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start,
                                                    s->io[i].res->end + num, s) == 0) {
                                *base = try;
-                               s->io[i].NumPorts += num;
                                s->io[i].InUse += num;
                                break;
                        }
                /* Try to extend bottom of window */
-               try = s->io[i].BasePort - num;
+               try = s->io[i].res->start - num;
                if ((*base == 0) || (*base == try))
                        if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num,
                                                    s->io[i].res->end, s) == 0) {
-                               s->io[i].BasePort = *base = try;
-                               s->io[i].NumPorts += num;
+                               *base = try;
                                s->io[i].InUse += num;
                                break;
                        }
@@ -143,12 +140,13 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
        int i;
 
        for (i = 0; i < MAX_IO_WIN; i++) {
-               if ((s->io[i].BasePort <= base) &&
-                   (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {
+               if (!s->io[i].res)
+                       continue;
+               if ((s->io[i].res->start <= base) &&
+                   (s->io[i].res->end >= base+num-1)) {
                        s->io[i].InUse -= num;
                        /* Free the window if no one else is using it */
                        if (s->io[i].InUse == 0) {
-                               s->io[i].NumPorts = 0;
                                release_resource(s->io[i].res);
                                kfree(s->io[i].res);
                                s->io[i].res = NULL;
@@ -165,21 +163,19 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
  * this and the tuple reading services.
  */
 
-int pccard_access_configuration_register(struct pcmcia_socket *s,
-                                        unsigned int function,
+int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
                                         conf_reg_t *reg)
 {
+       struct pcmcia_socket *s;
        config_t *c;
        int addr;
        u_char val;
 
-       if (!s || !s->config)
+       if (!p_dev || !p_dev->function_config)
                return CS_NO_CARD;
 
-       c = &s->config[function];
-
-       if (c == NULL)
-               return CS_NO_CARD;
+       s = p_dev->socket;
+       c = p_dev->function_config;
 
        if (!(c->state & CONFIG_LOCKED))
                return CS_CONFIGURATION_LOCKED;
@@ -200,20 +196,12 @@ int pccard_access_configuration_register(struct pcmcia_socket *s,
                break;
        }
        return CS_SUCCESS;
-} /* pccard_access_configuration_register */
-
-int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
-                                        conf_reg_t *reg)
-{
-       return pccard_access_configuration_register(p_dev->socket,
-                                                   p_dev->func, reg);
-}
+} /* pcmcia_access_configuration_register */
 EXPORT_SYMBOL(pcmcia_access_configuration_register);
 
 
-
 int pccard_get_configuration_info(struct pcmcia_socket *s,
-                                 unsigned int function,
+                                 struct pcmcia_device *p_dev,
                                  config_info_t *config)
 {
        config_t *c;
@@ -221,7 +209,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s,
        if (!(s->state & SOCKET_PRESENT))
                return CS_NO_CARD;
 
-       config->Function = function;
+       config->Function = p_dev->func;
 
 #ifdef CONFIG_CARDBUS
        if (s->state & SOCKET_CARDBUS) {
@@ -235,14 +223,14 @@ int pccard_get_configuration_info(struct pcmcia_socket *s,
                        config->AssignedIRQ = s->irq.AssignedIRQ;
                        if (config->AssignedIRQ)
                                config->Attributes |= CONF_ENABLE_IRQ;
-                       config->BasePort1 = s->io[0].BasePort;
-                       config->NumPorts1 = s->io[0].NumPorts;
+                       config->BasePort1 = s->io[0].res->start;
+                       config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1;
                }
                return CS_SUCCESS;
        }
 #endif
 
-       c = (s->config != NULL) ? &s->config[function] : NULL;
+       c = (p_dev) ? p_dev->function_config : NULL;
 
        if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
                config->Attributes = 0;
@@ -271,7 +259,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s,
 int pcmcia_get_configuration_info(struct pcmcia_device *p_dev,
                                  config_info_t *config)
 {
-       return pccard_get_configuration_info(p_dev->socket, p_dev->func,
+       return pccard_get_configuration_info(p_dev->socket, p_dev,
                                             config);
 }
 EXPORT_SYMBOL(pcmcia_get_configuration_info);
@@ -317,7 +305,7 @@ EXPORT_SYMBOL(pcmcia_get_window);
  * SocketState yet: I haven't seen any point for it.
  */
 
-int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
+int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev,
                      cs_status_t *status)
 {
        config_t *c;
@@ -334,11 +322,12 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
        if (!(s->state & SOCKET_PRESENT))
                return CS_NO_CARD;
 
-       c = (s->config != NULL) ? &s->config[function] : NULL;
+       c = (p_dev) ? p_dev->function_config : NULL;
+
        if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
            (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
                u_char reg;
-               if (c->Present & PRESENT_PIN_REPLACE) {
+               if (c->CardValues & PRESENT_PIN_REPLACE) {
                        pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
                        status->CardState |=
                                (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
@@ -352,7 +341,7 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
                        /* No PRR?  Then assume we're always ready */
                        status->CardState |= CS_EVENT_READY_CHANGE;
                }
-               if (c->Present & PRESENT_EXT_STATUS) {
+               if (c->CardValues & PRESENT_EXT_STATUS) {
                        pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
                        status->CardState |=
                                (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
@@ -370,11 +359,9 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
        return CS_SUCCESS;
 } /* pccard_get_status */
 
-int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
+int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status)
 {
-       struct pcmcia_socket *s;
-       s = SOCKET(handle);
-       return pccard_get_status(s, handle->func, status);
+       return pccard_get_status(p_dev->socket, p_dev, status);
 }
 EXPORT_SYMBOL(pcmcia_get_status);
 
@@ -422,7 +409,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
        config_t *c;
 
        s = p_dev->socket;
-       c = CONFIG(p_dev);
+       c = p_dev->function_config;
+
        if (!(s->state & SOCKET_PRESENT))
                return CS_NO_CARD;
        if (!(c->state & CONFIG_LOCKED))
@@ -454,6 +442,28 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
                   (mod->Attributes & CONF_VPP2_CHANGE_VALID))
                return CS_BAD_VPP;
 
+       if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
+               pccard_io_map io_off = { 0, 0, 0, 0, 1 };
+               pccard_io_map io_on;
+               int i;
+
+               io_on.speed = io_speed;
+               for (i = 0; i < MAX_IO_WIN; i++) {
+                       if (!s->io[i].res)
+                               continue;
+                       io_off.map = i;
+                       io_on.map = i;
+
+                       io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
+                       io_on.start = s->io[i].res->start;
+                       io_on.stop = s->io[i].res->end;
+
+                       s->ops->set_io_map(s, &io_off);
+                       mdelay(40);
+                       s->ops->set_io_map(s, &io_on);
+               }
+       }
+
        return CS_SUCCESS;
 } /* modify_configuration */
 EXPORT_SYMBOL(pcmcia_modify_configuration);
@@ -463,23 +473,23 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
 {
        pccard_io_map io = { 0, 0, 0, 0, 1 };
        struct pcmcia_socket *s = p_dev->socket;
+       config_t *c = p_dev->function_config;
        int i;
 
-       if (!(p_dev->state & CLIENT_CONFIG_LOCKED))
-               return CS_BAD_HANDLE;
-       p_dev->state &= ~CLIENT_CONFIG_LOCKED;
-
-       if (!(p_dev->state & CLIENT_STALE)) {
-               config_t *c = CONFIG(p_dev);
+       if (p_dev->_locked) {
+               p_dev->_locked = 0;
                if (--(s->lock_count) == 0) {
                        s->socket.flags = SS_OUTPUT_ENA;   /* Is this correct? */
                        s->socket.Vpp = 0;
                        s->socket.io_irq = 0;
                        s->ops->set_socket(s, &s->socket);
                }
+       }
+       if (c->state & CONFIG_LOCKED) {
+               c->state &= ~CONFIG_LOCKED;
                if (c->state & CONFIG_IO_REQ)
                        for (i = 0; i < MAX_IO_WIN; i++) {
-                               if (s->io[i].NumPorts == 0)
+                               if (!s->io[i].res)
                                        continue;
                                s->io[i].Config--;
                                if (s->io[i].Config != 0)
@@ -487,12 +497,10 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
                                io.map = i;
                                s->ops->set_io_map(s, &io);
                        }
-               c->state &= ~CONFIG_LOCKED;
        }
 
        return CS_SUCCESS;
 } /* pcmcia_release_configuration */
-EXPORT_SYMBOL(pcmcia_release_configuration);
 
 
 /** pcmcia_release_io
@@ -503,25 +511,23 @@ EXPORT_SYMBOL(pcmcia_release_configuration);
  * don't bother checking the port ranges against the current socket
  * values.
  */
-int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
+static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
 {
        struct pcmcia_socket *s = p_dev->socket;
+       config_t *c = p_dev->function_config;
 
-       if (!(p_dev->state & CLIENT_IO_REQ))
+       if (!p_dev->_io )
                return CS_BAD_HANDLE;
-       p_dev->state &= ~CLIENT_IO_REQ;
-
-       if (!(p_dev->state & CLIENT_STALE)) {
-               config_t *c = CONFIG(p_dev);
-               if (c->state & CONFIG_LOCKED)
-                       return CS_CONFIGURATION_LOCKED;
-               if ((c->io.BasePort1 != req->BasePort1) ||
-                   (c->io.NumPorts1 != req->NumPorts1) ||
-                   (c->io.BasePort2 != req->BasePort2) ||
-                   (c->io.NumPorts2 != req->NumPorts2))
-                       return CS_BAD_ARGS;
-               c->state &= ~CONFIG_IO_REQ;
-       }
+
+       p_dev->_io = 0;
+
+       if ((c->io.BasePort1 != req->BasePort1) ||
+           (c->io.NumPorts1 != req->NumPorts1) ||
+           (c->io.BasePort2 != req->BasePort2) ||
+           (c->io.NumPorts2 != req->NumPorts2))
+               return CS_BAD_ARGS;
+
+       c->state &= ~CONFIG_IO_REQ;
 
        release_io_space(s, req->BasePort1, req->NumPorts1);
        if (req->NumPorts2)
@@ -529,28 +535,26 @@ int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
 
        return CS_SUCCESS;
 } /* pcmcia_release_io */
-EXPORT_SYMBOL(pcmcia_release_io);
 
 
-int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
+static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
 {
        struct pcmcia_socket *s = p_dev->socket;
-       if (!(p_dev->state & CLIENT_IRQ_REQ))
+       config_t *c= p_dev->function_config;
+
+       if (!p_dev->_irq)
                return CS_BAD_HANDLE;
-       p_dev->state &= ~CLIENT_IRQ_REQ;
-
-       if (!(p_dev->state & CLIENT_STALE)) {
-               config_t *c = CONFIG(p_dev);
-               if (c->state & CONFIG_LOCKED)
-                       return CS_CONFIGURATION_LOCKED;
-               if (c->irq.Attributes != req->Attributes)
-                       return CS_BAD_ATTRIBUTE;
-               if (s->irq.AssignedIRQ != req->AssignedIRQ)
-                       return CS_BAD_IRQ;
-               if (--s->irq.Config == 0) {
-                       c->state &= ~CONFIG_IRQ_REQ;
-                       s->irq.AssignedIRQ = 0;
-               }
+       p_dev->_irq = 0;
+
+       if (c->state & CONFIG_LOCKED)
+               return CS_CONFIGURATION_LOCKED;
+       if (c->irq.Attributes != req->Attributes)
+               return CS_BAD_ATTRIBUTE;
+       if (s->irq.AssignedIRQ != req->AssignedIRQ)
+               return CS_BAD_IRQ;
+       if (--s->irq.Config == 0) {
+               c->state &= ~CONFIG_IRQ_REQ;
+               s->irq.AssignedIRQ = 0;
        }
 
        if (req->Attributes & IRQ_HANDLE_PRESENT) {
@@ -563,7 +567,6 @@ int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
 
        return CS_SUCCESS;
 } /* pcmcia_release_irq */
-EXPORT_SYMBOL(pcmcia_release_irq);
 
 
 int pcmcia_release_window(window_handle_t win)
@@ -573,7 +576,7 @@ int pcmcia_release_window(window_handle_t win)
        if ((win == NULL) || (win->magic != WINDOW_MAGIC))
                return CS_BAD_HANDLE;
        s = win->sock;
-       if (!(win->handle->state & CLIENT_WIN_REQ(win->index)))
+       if (!(win->handle->_win & CLIENT_WIN_REQ(win->index)))
                return CS_BAD_HANDLE;
 
        /* Shut down memory window */
@@ -587,7 +590,7 @@ int pcmcia_release_window(window_handle_t win)
                kfree(win->ctl.res);
                win->ctl.res = NULL;
        }
-       win->handle->state &= ~CLIENT_WIN_REQ(win->index);
+       win->handle->_win &= ~CLIENT_WIN_REQ(win->index);
 
        win->magic = 0;
 
@@ -610,16 +613,12 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 
        if (req->IntType & INT_CARDBUS)
                return CS_UNSUPPORTED_MODE;
-       c = CONFIG(p_dev);
+       c = p_dev->function_config;
        if (c->state & CONFIG_LOCKED)
                return CS_CONFIGURATION_LOCKED;
 
        /* Do power control.  We don't allow changes in Vcc. */
-       if (s->socket.Vcc != req->Vcc)
-               return CS_BAD_VCC;
-       if (req->Vpp1 != req->Vpp2)
-               return CS_BAD_VPP;
-       s->socket.Vpp = req->Vpp1;
+       s->socket.Vpp = req->Vpp;
        if (s->ops->set_socket(s, &s->socket))
                return CS_BAD_VPP;
 
@@ -643,7 +642,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 
        /* Set up CIS configuration registers */
        base = c->ConfigBase = req->ConfigBase;
-       c->Present = c->CardValues = req->Present;
+       c->CardValues = req->Present;
        if (req->Present & PRESENT_COPY) {
                c->Copy = req->Copy;
                pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
@@ -690,10 +689,10 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
        if (c->state & CONFIG_IO_REQ) {
                iomap.speed = io_speed;
                for (i = 0; i < MAX_IO_WIN; i++)
-                       if (s->io[i].NumPorts != 0) {
+                       if (s->io[i].res) {
                                iomap.map = i;
                                iomap.flags = MAP_ACTIVE;
-                               switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) {
+                               switch (s->io[i].res->flags & IO_DATA_PATH_WIDTH) {
                                case IO_DATA_PATH_WIDTH_16:
                                        iomap.flags |= MAP_16BIT; break;
                                case IO_DATA_PATH_WIDTH_AUTO:
@@ -701,15 +700,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
                                default:
                                        break;
                                }
-                               iomap.start = s->io[i].BasePort;
-                               iomap.stop = iomap.start + s->io[i].NumPorts - 1;
+                               iomap.start = s->io[i].res->start;
+                               iomap.stop = s->io[i].res->end;
                                s->ops->set_io_map(s, &iomap);
                                s->io[i].Config++;
                        }
        }
 
        c->state |= CONFIG_LOCKED;
-       p_dev->state |= CLIENT_CONFIG_LOCKED;
+       p_dev->_locked = 1;
        return CS_SUCCESS;
 } /* pcmcia_request_configuration */
 EXPORT_SYMBOL(pcmcia_request_configuration);
@@ -730,7 +729,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
 
        if (!req)
                return CS_UNSUPPORTED_MODE;
-       c = CONFIG(p_dev);
+       c = p_dev->function_config;
        if (c->state & CONFIG_LOCKED)
                return CS_CONFIGURATION_LOCKED;
        if (c->state & CONFIG_IO_REQ)
@@ -755,7 +754,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
 
        c->io = *req;
        c->state |= CONFIG_IO_REQ;
-       p_dev->state |= CLIENT_IO_REQ;
+       p_dev->_io = 1;
        return CS_SUCCESS;
 } /* pcmcia_request_io */
 EXPORT_SYMBOL(pcmcia_request_io);
@@ -786,7 +785,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
 
        if (!(s->state & SOCKET_PRESENT))
                return CS_NO_CARD;
-       c = CONFIG(p_dev);
+       c = p_dev->function_config;
        if (c->state & CONFIG_LOCKED)
                return CS_CONFIGURATION_LOCKED;
        if (c->state & CONFIG_IRQ_REQ)
@@ -851,7 +850,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        s->irq.Config++;
 
        c->state |= CONFIG_IRQ_REQ;
-       p_dev->state |= CLIENT_IRQ_REQ;
+       p_dev->_irq = 1;
 
 #ifdef CONFIG_PCMCIA_PROBE
        pcmcia_used_irq[irq]++;
@@ -911,7 +910,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
                if (!win->ctl.res)
                        return CS_IN_USE;
        }
-       (*p_dev)->state |= CLIENT_WIN_REQ(w);
+       (*p_dev)->_win |= CLIENT_WIN_REQ(w);
 
        /* Configure the socket controller */
        win->ctl.map = w+1;
@@ -941,3 +940,14 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
        return CS_SUCCESS;
 } /* pcmcia_request_window */
 EXPORT_SYMBOL(pcmcia_request_window);
+
+void pcmcia_disable_device(struct pcmcia_device *p_dev) {
+       pcmcia_release_configuration(p_dev);
+       pcmcia_release_io(p_dev, &p_dev->io);
+       pcmcia_release_irq(p_dev, &p_dev->irq);
+       if (&p_dev->win)
+               pcmcia_release_window(p_dev->win);
+
+       p_dev->dev_node = NULL;
+}
+EXPORT_SYMBOL(pcmcia_disable_device);
index f2789af..16d1ea7 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
index 5146093..81dfc2c 100644 (file)
@@ -12,7 +12,6 @@
  * (C) 1999            David A. Hinds
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 
@@ -22,6 +21,8 @@
 #include "cs_internal.h"
 
 
+#ifdef CONFIG_PCMCIA_IOCTL
+
 #ifdef CONFIG_PCMCIA_PROBE
 
 static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
@@ -98,6 +99,8 @@ int pcmcia_adjust_resource_info(adjust_t *adj)
 }
 EXPORT_SYMBOL(pcmcia_adjust_resource_info);
 
+#endif
+
 int pcmcia_validate_mem(struct pcmcia_socket *s)
 {
        if (s->resource_ops->validate_mem)
index 5301ac6..0f8b157 100644 (file)
@@ -12,7 +12,6 @@
  * (C) 1999            David A. Hinds
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -61,7 +60,7 @@ struct socket_data {
        unsigned int                    rsrc_mem_probe;
 };
 
-static DECLARE_MUTEX(rsrc_sem);
+static DEFINE_MUTEX(rsrc_mutex);
 #define MEM_PROBE_LOW  (1 << 0)
 #define MEM_PROBE_HIGH (1 << 1)
 
@@ -484,7 +483,7 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 
 
 /*
- * Locking note: Must be called with skt_sem held!
+ * Locking note: Must be called with skt_mutex held!
  */
 static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
 {
@@ -495,7 +494,7 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
        if (!probe_mem)
                return 0;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
 
        if (s->features & SS_CAP_PAGE_REGS)
                probe_mask = MEM_PROBE_HIGH;
@@ -507,7 +506,7 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
                        s_data->rsrc_mem_probe |= probe_mask;
        }
 
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 
        return ret;
 }
@@ -585,7 +584,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
        struct socket_data *s_data = s->resource_data;
        int ret = -ENOMEM;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
        for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
                unsigned long start = m->base;
                unsigned long end = m->base + m->num - 1;
@@ -596,7 +595,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
                ret = adjust_resource(res, r_start, r_end - r_start + 1);
                break;
        }
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 
        return ret;
 }
@@ -630,7 +629,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
        data.offset = base & data.mask;
        data.map = &s_data->io_db;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
 #ifdef CONFIG_PCI
        if (s->cb_dev) {
                ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
@@ -639,7 +638,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
 #endif
                ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
                                        1, pcmcia_align, &data);
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 
        if (ret != 0) {
                kfree(res);
@@ -672,7 +671,7 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
                        min = 0x100000UL + base;
                }
 
-               down(&rsrc_sem);
+               mutex_lock(&rsrc_mutex);
 #ifdef CONFIG_PCI
                if (s->cb_dev) {
                        ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
@@ -682,7 +681,7 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
 #endif
                        ret = allocate_resource(&iomem_resource, res, num, min,
                                                max, 1, pcmcia_align, &data);
-               up(&rsrc_sem);
+               mutex_unlock(&rsrc_mutex);
                if (ret == 0 || low)
                        break;
                low = 1;
@@ -705,7 +704,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
        if (end < start)
                return -EINVAL;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
        switch (action) {
        case ADD_MANAGED_RESOURCE:
                ret = add_interval(&data->mem_db, start, size);
@@ -723,7 +722,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
        default:
                ret = -EINVAL;
        }
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 
        return ret;
 }
@@ -741,7 +740,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
        if (end > IO_SPACE_LIMIT)
                return -EINVAL;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
        switch (action) {
        case ADD_MANAGED_RESOURCE:
                if (add_interval(&data->io_db, start, size) != 0) {
@@ -760,7 +759,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
                ret = -EINVAL;
                break;
        }
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 
        return ret;
 }
@@ -867,7 +866,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
        struct socket_data *data = s->resource_data;
        struct resource_map *p, *q;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
        for (p = data->mem_db.next; p != &data->mem_db; p = q) {
                q = p->next;
                kfree(p);
@@ -876,7 +875,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
                q = p->next;
                kfree(p);
        }
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 }
 
 
@@ -901,7 +900,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf)
        struct resource_map *p;
        ssize_t ret = 0;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
        data = s->resource_data;
 
        for (p = data->io_db.next; p != &data->io_db; p = p->next) {
@@ -913,7 +912,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf)
                                 ((unsigned long) p->base + p->num - 1));
        }
 
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
        return (ret);
 }
 
@@ -953,7 +952,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
        struct resource_map *p;
        ssize_t ret = 0;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
        data = s->resource_data;
 
        for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
@@ -965,7 +964,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
                                 ((unsigned long) p->base + p->num - 1));
        }
 
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
        return (ret);
 }
 
index 2b3c289..eb89928 100644 (file)
@@ -5,7 +5,6 @@
  * Based off the Assabet.
  *
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
index 5ab1cde..c5d7476 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/major.h>
 #include <linux/errno.h>
@@ -25,6 +24,7 @@
 #include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/device.h>
+#include <linux/mutex.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
@@ -183,7 +183,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf,
                s->resource_setup_done = 1;
        spin_unlock_irqrestore(&s->lock, flags);
 
-       down(&s->skt_sem);
+       mutex_lock(&s->skt_mutex);
        if ((s->callback) &&
            (s->state & SOCKET_PRESENT) &&
            !(s->state & SOCKET_CARDBUS)) {
@@ -192,7 +192,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf,
                        module_put(s->callback->owner);
                }
        }
-       up(&s->skt_sem);
+       mutex_unlock(&s->skt_mutex);
 
        return count;
 }
@@ -322,7 +322,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
        kfree(cis);
 
        if (!ret) {
-               down(&s->skt_sem);
+               mutex_lock(&s->skt_mutex);
                if ((s->callback) && (s->state & SOCKET_PRESENT) &&
                    !(s->state & SOCKET_CARDBUS)) {
                        if (try_module_get(s->callback->owner)) {
@@ -330,7 +330,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
                                module_put(s->callback->owner);
                        }
                }
-               up(&s->skt_sem);
+               mutex_unlock(&s->skt_mutex);
        }
 
 
index d5b4ff7..7a3d1b8 100644 (file)
@@ -30,7 +30,6 @@
 #ifndef _LINUX_TI113X_H
 #define _LINUX_TI113X_H
 
-#include <linux/config.h>
 
 /* Register definitions for TI 113X PCI-to-CardBus bridges */
 
index 0574efd..459e6e1 100644 (file)
@@ -634,7 +634,7 @@ static void vrc4171_remove_sockets(void)
 static int __devinit vrc4171_card_setup(char *options)
 {
        if (options == NULL || *options == '\0')
-               return 0;
+               return 1;
 
        if (strncmp(options, "irq:", 4) == 0) {
                int irq;
@@ -644,7 +644,7 @@ static int __devinit vrc4171_card_setup(char *options)
                        vrc4171_irq = irq;
 
                if (*options != ',')
-                       return 0;
+                       return 1;
                options++;
        }
 
@@ -663,10 +663,10 @@ static int __devinit vrc4171_card_setup(char *options)
                        }
 
                        if (*options != ',')
-                               return 0;
+                               return 1;
                        options++;
                } else
-                       return 0;
+                       return 1;
 
        }
 
@@ -688,7 +688,7 @@ static int __devinit vrc4171_card_setup(char *options)
                        }
 
                        if (*options != ',')
-                               return 0;
+                               return 1;
                        options++;
 
                        if (strncmp(options, "memnoprobe", 10) == 0)
@@ -700,7 +700,7 @@ static int __devinit vrc4171_card_setup(char *options)
                }
        }
 
-       return 0;
+       return 1;
 }
 
 __setup("vrc4171_card=", vrc4171_card_setup);
index 57f38db..6004196 100644 (file)
@@ -516,7 +516,7 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
 static int __devinit vrc4173_cardu_setup(char *options)
 {
        if (options == NULL || *options == '\0')
-               return 0;
+               return 1;
 
        if (strncmp(options, "cardu1:", 7) == 0) {
                options += 7;
@@ -527,9 +527,9 @@ static int __devinit vrc4173_cardu_setup(char *options)
                        }
 
                        if (*options != ',')
-                               return 0;
+                               return 1;
                } else
-                       return 0;
+                       return 1;
        }
 
        if (strncmp(options, "cardu2:", 7) == 0) {
@@ -538,7 +538,7 @@ static int __devinit vrc4173_cardu_setup(char *options)
                        cardu_sockets[CARDU2].noprobe = 1;
        }
 
-       return 0;
+       return 1;
 }
 
 __setup("vrc4173_cardu=", vrc4173_cardu_setup);
index ffba656..1bd82c4 100644 (file)
@@ -293,6 +293,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          board_ahci }, /* JMicron JMB360 */
        { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_ahci }, /* JMicron JMB363 */
+       { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ATI SB600 non-raid */
+       { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ATI SB600 raid */
        { }     /* terminate list */
 };
 
index 2d5be84..24e71b5 100644 (file)
@@ -301,7 +301,7 @@ static struct piix_map_db ich6_map_db = {
        .mask = 0x3,
        .map = {
                /* PM   PS   SM   SS       MAP */
-               {  P0,  P1,  P2,  P3 }, /* 00b */
+               {  P0,  P2,  P1,  P3 }, /* 00b */
                { IDE, IDE,  P1,  P3 }, /* 01b */
                {  P0,  P2, IDE, IDE }, /* 10b */
                {  RV,  RV,  RV,  RV },
@@ -312,7 +312,7 @@ static struct piix_map_db ich6m_map_db = {
        .mask = 0x3,
        .map = {
                /* PM   PS   SM   SS       MAP */
-               {  P0,  P1,  P2,  P3 }, /* 00b */
+               {  P0,  P2,  RV,  RV }, /* 00b */
                {  RV,  RV,  RV,  RV },
                {  P0,  P2, IDE, IDE }, /* 10b */
                {  RV,  RV,  RV,  RV },
index 3a8462e..24eb59e 100644 (file)
@@ -2488,7 +2488,7 @@ static int option_setup(char *str)
        }
        ints[0] = i - 1;
        internal_ibmmca_scsi_setup(cur, ints);
-       return 0;
+       return 1;
 }
 
 __setup("ibmmcascsi=", option_setup);
index f47dd87..892e8ed 100644 (file)
@@ -80,7 +80,7 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue,
        tasklet_kill(&hostdata->srp_task);
        do {
                rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
-       } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+       } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
        dma_unmap_single(hostdata->dev,
                         queue->msg_token,
                         queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
@@ -230,7 +230,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
        rc = plpar_hcall_norets(H_REG_CRQ,
                                vdev->unit_address,
                                queue->msg_token, PAGE_SIZE);
-       if (rc == H_Resource) 
+       if (rc == H_RESOURCE)
                /* maybe kexecing and resource is busy. try a reset */
                rc = ibmvscsi_reset_crq_queue(queue,
                                              hostdata);
@@ -269,7 +269,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
       req_irq_failed:
        do {
                rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
-       } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+       } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
       reg_crq_failed:
        dma_unmap_single(hostdata->dev,
                         queue->msg_token,
@@ -295,7 +295,7 @@ int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
        /* Re-enable the CRQ */
        do {
                rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address);
-       } while ((rc == H_InProgress) || (rc == H_Busy) || (H_isLongBusy(rc)));
+       } while ((rc == H_IN_PROGRESS) || (rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
 
        if (rc)
                printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc);
@@ -317,7 +317,7 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
        /* Close the CRQ */
        do {
                rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
-       } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+       } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
 
        /* Clean out the queue */
        memset(queue->msgs, 0x00, PAGE_SIZE);
index 459a4da..eb7bd31 100644 (file)
@@ -112,7 +112,7 @@ lasi700_probe(struct parisc_device *dev)
 
        hostdata->dev = &dev->dev;
        dma_set_mask(&dev->dev, DMA_32BIT_MASK);
-       hostdata->base = ioremap(base, 0x100);
+       hostdata->base = ioremap_nocache(base, 0x100);
        hostdata->differential = 0;
 
        if (dev->id.sversion == LASI_700_SVERSION) {
index 21b0ed5..e63c1ff 100644 (file)
@@ -278,7 +278,7 @@ static void ata_unpack_xfermask(unsigned int xfer_mask,
 }
 
 static const struct ata_xfer_ent {
-       unsigned int shift, bits;
+       int shift, bits;
        u8 base;
 } ata_xfer_tbl[] = {
        { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 },
@@ -989,9 +989,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
        qc->private_data = &wait;
        qc->complete_fn = ata_qc_complete_internal;
 
-       qc->err_mask = ata_qc_issue(qc);
-       if (qc->err_mask)
-               ata_qc_complete(qc);
+       ata_qc_issue(qc);
 
        spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
@@ -3997,15 +3995,14 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
  *
  *     LOCKING:
  *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Zero on success, AC_ERR_* mask on failure
  */
-
-unsigned int ata_qc_issue(struct ata_queued_cmd *qc)
+void ata_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
 
+       qc->ap->active_tag = qc->tag;
+       qc->flags |= ATA_QCFLAG_ACTIVE;
+
        if (ata_should_dma_map(qc)) {
                if (qc->flags & ATA_QCFLAG_SG) {
                        if (ata_sg_setup(qc))
@@ -4020,17 +4017,18 @@ unsigned int ata_qc_issue(struct ata_queued_cmd *qc)
 
        ap->ops->qc_prep(qc);
 
-       qc->ap->active_tag = qc->tag;
-       qc->flags |= ATA_QCFLAG_ACTIVE;
-
-       return ap->ops->qc_issue(qc);
+       qc->err_mask |= ap->ops->qc_issue(qc);
+       if (unlikely(qc->err_mask))
+               goto err;
+       return;
 
 sg_err:
        qc->flags &= ~ATA_QCFLAG_DMAMAP;
-       return AC_ERR_SYSTEM;
+       qc->err_mask |= AC_ERR_SYSTEM;
+err:
+       ata_qc_complete(qc);
 }
 
-
 /**
  *     ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
  *     @qc: command to issue to device
index 628191b..53f5b0d 100644 (file)
@@ -1431,9 +1431,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
                goto early_finish;
 
        /* select device, send command to hardware */
-       qc->err_mask = ata_qc_issue(qc);
-       if (qc->err_mask)
-               ata_qc_complete(qc);
+       ata_qc_issue(qc);
 
        VPRINTK("EXIT\n");
        return;
@@ -2199,9 +2197,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
 
        qc->complete_fn = atapi_sense_complete;
 
-       qc->err_mask = ata_qc_issue(qc);
-       if (qc->err_mask)
-               ata_qc_complete(qc);
+       ata_qc_issue(qc);
 
        DPRINTK("EXIT\n");
 }
index 65f52be..1c755b1 100644 (file)
@@ -47,7 +47,7 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
 extern void ata_port_flush_task(struct ata_port *ap);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
-extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc);
+extern void ata_qc_issue(struct ata_queued_cmd *qc);
 extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
index 5609847..ee449b2 100644 (file)
@@ -89,29 +89,29 @@ MODULE_LICENSE("Dual MPL/GPL");
 /*====================================================================*/
 
 typedef struct scsi_info_t {
-    dev_link_t         link;
+       struct pcmcia_device    *p_dev;
     dev_node_t         node;
     struct Scsi_Host   *host;
 } scsi_info_t;
 
-static void aha152x_release_cs(dev_link_t *link);
+static void aha152x_release_cs(struct pcmcia_device *link);
 static void aha152x_detach(struct pcmcia_device *p_dev);
-static void aha152x_config_cs(dev_link_t *link);
+static int aha152x_config_cs(struct pcmcia_device *link);
 
-static dev_link_t *dev_list;
+static struct pcmcia_device *dev_list;
 
-static int aha152x_attach(struct pcmcia_device *p_dev)
+static int aha152x_probe(struct pcmcia_device *link)
 {
     scsi_info_t *info;
-    dev_link_t *link;
-    
+
     DEBUG(0, "aha152x_attach()\n");
 
     /* Create new SCSI device */
     info = kmalloc(sizeof(*info), GFP_KERNEL);
     if (!info) return -ENOMEM;
     memset(info, 0, sizeof(*info));
-    link = &info->link; link->priv = info;
+    info->p_dev = link;
+    link->priv = info;
 
     link->io.NumPorts1 = 0x20;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -119,41 +119,22 @@ static int aha152x_attach(struct pcmcia_device *p_dev)
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    aha152x_config_cs(link);
-
-    return 0;
+    return aha152x_config_cs(link);
 } /* aha152x_attach */
 
 /*====================================================================*/
 
-static void aha152x_detach(struct pcmcia_device *p_dev)
+static void aha152x_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-    dev_link_t **linkp;
-
     DEBUG(0, "aha152x_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-       if (*linkp == link) break;
-    if (*linkp == NULL)
-       return;
 
-    if (link->state & DEV_CONFIG)
-       aha152x_release_cs(link);
+    aha152x_release_cs(link);
 
     /* Unlink device structure, free bits */
-    *linkp = link->next;
     kfree(link->priv);
-    
 } /* aha152x_detach */
 
 /*====================================================================*/
@@ -161,9 +142,8 @@ static void aha152x_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void aha152x_config_cs(dev_link_t *link)
+static int aha152x_config_cs(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     scsi_info_t *info = link->priv;
     struct aha152x_setup s;
     tuple_t tuple;
@@ -178,19 +158,16 @@ static void aha152x_config_cs(dev_link_t *link)
     tuple.TupleData = tuple_data;
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (1) {
-       if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-               pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
            goto next_entry;
        /* For New Media T&J, look for a SCSI window */
        if (parse.cftable_entry.io.win[0].len >= 0x20)
@@ -201,15 +178,15 @@ static void aha152x_config_cs(dev_link_t *link)
        if ((parse.cftable_entry.io.nwin > 0) &&
            (link->io.BasePort1 < 0xffff)) {
            link->conf.ConfigIndex = parse.cftable_entry.index;
-           i = pcmcia_request_io(handle, &link->io);
+           i = pcmcia_request_io(link, &link->io);
            if (i == CS_SUCCESS) break;
        }
     next_entry:
-       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
     }
     
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     
     /* Set configuration options for the aha152x driver */
     memset(&s, 0, sizeof(s));
@@ -231,53 +208,30 @@ static void aha152x_config_cs(dev_link_t *link)
     }
 
     sprintf(info->node.dev_name, "scsi%d", host->host_no);
-    link->dev = &info->node;
+    link->dev_node = &info->node;
     info->host = host;
 
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
-    
+    return 0;
+
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
     aha152x_release_cs(link);
-    return;
+    return -ENODEV;
 }
 
-static void aha152x_release_cs(dev_link_t *link)
+static void aha152x_release_cs(struct pcmcia_device *link)
 {
        scsi_info_t *info = link->priv;
 
        aha152x_release(info->host);
-       link->dev = NULL;
-    
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
-    
-       link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
 }
 
-static int aha152x_suspend(struct pcmcia_device *dev)
+static int aha152x_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int aha152x_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
        scsi_info_t *info = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               aha152x_host_reset_host(info->host);
-       }
+       aha152x_host_reset_host(info->host);
 
        return 0;
 }
@@ -297,10 +251,9 @@ static struct pcmcia_driver aha152x_cs_driver = {
        .drv            = {
                .name   = "aha152x_cs",
        },
-       .probe          = aha152x_attach,
+       .probe          = aha152x_probe,
        .remove         = aha152x_detach,
        .id_table       = aha152x_ids,
-       .suspend        = aha152x_suspend,
        .resume         = aha152x_resume,
 };
 
@@ -317,4 +270,3 @@ static void __exit exit_aha152x_cs(void)
 
 module_init(init_aha152x_cs);
 module_exit(exit_aha152x_cs);
index 788c58d..85f7ffa 100644 (file)
@@ -73,57 +73,48 @@ static char *version =
 /*====================================================================*/
 
 typedef struct scsi_info_t {
-    dev_link_t         link;
+       struct pcmcia_device    *p_dev;
     dev_node_t         node;
     struct Scsi_Host   *host;
 } scsi_info_t;
 
 
-static void fdomain_release(dev_link_t *link);
+static void fdomain_release(struct pcmcia_device *link);
 static void fdomain_detach(struct pcmcia_device *p_dev);
-static void fdomain_config(dev_link_t *link);
+static int fdomain_config(struct pcmcia_device *link);
 
-static int fdomain_attach(struct pcmcia_device *p_dev)
+static int fdomain_probe(struct pcmcia_device *link)
 {
-    scsi_info_t *info;
-    dev_link_t *link;
-
-    DEBUG(0, "fdomain_attach()\n");
-
-    /* Create new SCSI device */
-    info = kmalloc(sizeof(*info), GFP_KERNEL);
-    if (!info) return -ENOMEM;
-    memset(info, 0, sizeof(*info));
-    link = &info->link; link->priv = info;
-    link->io.NumPorts1 = 0x10;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-    link->io.IOAddrLines = 10;
-    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.Present = PRESENT_OPTION;
-
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    fdomain_config(link);
-
-    return 0;
+       scsi_info_t *info;
+
+       DEBUG(0, "fdomain_attach()\n");
+
+       /* Create new SCSI device */
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       info->p_dev = link;
+       link->priv = info;
+       link->io.NumPorts1 = 0x10;
+       link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+       link->io.IOAddrLines = 10;
+       link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+       link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+       link->conf.Attributes = CONF_ENABLE_IRQ;
+       link->conf.IntType = INT_MEMORY_AND_IO;
+       link->conf.Present = PRESENT_OPTION;
+
+       return fdomain_config(link);
 } /* fdomain_attach */
 
 /*====================================================================*/
 
-static void fdomain_detach(struct pcmcia_device *p_dev)
+static void fdomain_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
-
        DEBUG(0, "fdomain_detach(0x%p)\n", link);
 
-       if (link->state & DEV_CONFIG)
-               fdomain_release(link);
+       fdomain_release(link);
 
        kfree(link->priv);
 } /* fdomain_detach */
@@ -133,9 +124,8 @@ static void fdomain_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void fdomain_config(dev_link_t *link)
+static int fdomain_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     scsi_info_t *info = link->priv;
     tuple_t tuple;
     cisparse_t parse;
@@ -150,103 +140,75 @@ static void fdomain_config(dev_link_t *link)
     tuple.TupleData = tuple_data;
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-    
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (1) {
-       if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-               pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
            goto next_entry;
        link->conf.ConfigIndex = parse.cftable_entry.index;
        link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
-       i = pcmcia_request_io(handle, &link->io);
+       i = pcmcia_request_io(link, &link->io);
        if (i == CS_SUCCESS) break;
     next_entry:
-       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
     }
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
-    
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+
     /* A bad hack... */
     release_region(link->io.BasePort1, link->io.NumPorts1);
 
     /* Set configuration options for the fdomain driver */
     sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
     fdomain_setup(str);
-    
+
     host = __fdomain_16x0_detect(&fdomain_driver_template);
     if (!host) {
         printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
        goto cs_failed;
     }
-    scsi_add_host(host, NULL); /* XXX handle failure */
+
+    if (scsi_add_host(host, NULL))
+           goto cs_failed;
     scsi_scan_host(host);
 
     sprintf(info->node.dev_name, "scsi%d", host->host_no);
-    link->dev = &info->node;
+    link->dev_node = &info->node;
     info->host = host;
-    
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
-    
+
+    return 0;
+
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
     fdomain_release(link);
-    return;
-    
+    return -ENODEV;
 } /* fdomain_config */
 
 /*====================================================================*/
 
-static void fdomain_release(dev_link_t *link)
+static void fdomain_release(struct pcmcia_device *link)
 {
-    scsi_info_t *info = link->priv;
+       scsi_info_t *info = link->priv;
 
-    DEBUG(0, "fdomain_release(0x%p)\n", link);
+       DEBUG(0, "fdomain_release(0x%p)\n", link);
 
-    scsi_remove_host(info->host);
-    link->dev = NULL;
-    
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-
-    scsi_unregister(info->host);
-
-    link->state &= ~DEV_CONFIG;
+       scsi_remove_host(info->host);
+       pcmcia_disable_device(link);
+       scsi_unregister(info->host);
 }
 
 /*====================================================================*/
 
-static int fdomain_suspend(struct pcmcia_device *dev)
+static int fdomain_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int fdomain_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-               fdomain_16x0_bus_reset(NULL);
-       }
+       fdomain_16x0_bus_reset(NULL);
 
        return 0;
 }
@@ -264,10 +226,9 @@ static struct pcmcia_driver fdomain_cs_driver = {
        .drv            = {
                .name   = "fdomain_cs",
        },
-       .probe          = fdomain_attach,
+       .probe          = fdomain_probe,
        .remove         = fdomain_detach,
        .id_table       = fdomain_ids,
-       .suspend        = fdomain_suspend,
        .resume         = fdomain_resume,
 };
 
index 9e3ab3f..231f9c3 100644 (file)
@@ -1593,11 +1593,11 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
     configure the card at this point -- we wait until we receive a
     card insertion event.
 ======================================================================*/
-static int nsp_cs_attach(struct pcmcia_device *p_dev)
+static int nsp_cs_probe(struct pcmcia_device *link)
 {
        scsi_info_t  *info;
-       dev_link_t   *link;
        nsp_hw_data  *data = &nsp_data_base;
+       int ret;
 
        nsp_dbg(NSP_DEBUG_INIT, "in");
 
@@ -1605,7 +1605,7 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev)
        info = kmalloc(sizeof(*info), GFP_KERNEL);
        if (info == NULL) { return -ENOMEM; }
        memset(info, 0, sizeof(*info));
-       link = &info->link;
+       info->p_dev = link;
        link->priv = info;
        data->ScsiInfo = info;
 
@@ -1627,18 +1627,13 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev)
 
        /* General socket configuration */
        link->conf.Attributes    = CONF_ENABLE_IRQ;
-       link->conf.Vcc           = 50;
        link->conf.IntType       = INT_MEMORY_AND_IO;
        link->conf.Present       = PRESENT_OPTION;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       nsp_cs_config(link);
+       ret = nsp_cs_config(link);
 
        nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
-       return 0;
+       return ret;
 } /* nsp_cs_attach */
 
 
@@ -1648,16 +1643,12 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev)
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 ======================================================================*/
-static void nsp_cs_detach(struct pcmcia_device *p_dev)
+static void nsp_cs_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
-
        nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
 
-       if (link->state & DEV_CONFIG) {
-               ((scsi_info_t *)link->priv)->stop = 1;
-               nsp_cs_release(link);
-       }
+       ((scsi_info_t *)link->priv)->stop = 1;
+       nsp_cs_release(link);
 
        kfree(link->priv);
        link->priv = NULL;
@@ -1672,9 +1663,9 @@ static void nsp_cs_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 /*====================================================================*/
-static void nsp_cs_config(dev_link_t *link)
+static int nsp_cs_config(struct pcmcia_device *link)
 {
-       client_handle_t   handle = link->handle;
+       int               ret;
        scsi_info_t      *info   = link->priv;
        tuple_t           tuple;
        cisparse_t        parse;
@@ -1698,26 +1689,22 @@ static void nsp_cs_config(dev_link_t *link)
        tuple.TupleData       = tuple_data;
        tuple.TupleDataMax    = sizeof(tuple_data);
        tuple.TupleOffset     = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData,  pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple,    pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData,  pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple,    pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present    = parse.config.rmask[0];
 
-       /* Configure card */
-       link->state           |= DEV_CONFIG;
-
        /* Look up the current Vcc */
-       CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-       link->conf.Vcc = conf.Vcc;
+       CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
 
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        while (1) {
                cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
 
-               if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-                               pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+                               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
                        goto next_entry;
 
                if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
@@ -1743,10 +1730,10 @@ static void nsp_cs_config(dev_link_t *link)
                }
 
                if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                                cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
                } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                                dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
                }
 
@@ -1773,7 +1760,7 @@ static void nsp_cs_config(dev_link_t *link)
                                link->io.NumPorts2 = io->win[1].len;
                        }
                        /* This reserves IO space but doesn't actually enable it */
-                       if (pcmcia_request_io(link->handle, &link->io) != 0)
+                       if (pcmcia_request_io(link, &link->io) != 0)
                                goto next_entry;
                }
 
@@ -1788,7 +1775,7 @@ static void nsp_cs_config(dev_link_t *link)
                                req.Size = 0x1000;
                        }
                        req.AccessSpeed = 0;
-                       if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+                       if (pcmcia_request_window(&link, &req, &link->win) != 0)
                                goto next_entry;
                        map.Page = 0; map.CardOffset = mem->win[0].card_addr;
                        if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -1802,17 +1789,14 @@ static void nsp_cs_config(dev_link_t *link)
 
        next_entry:
                nsp_dbg(NSP_DEBUG_INIT, "next");
-
-               if (link->io.NumPorts1) {
-                       pcmcia_release_io(link->handle, &link->io);
-               }
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+               pcmcia_disable_device(link);
+               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
        }
 
        if (link->conf.Attributes & CONF_ENABLE_IRQ) {
-               CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+               CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
        }
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
        if (free_ports) {
                if (link->io.BasePort1) {
@@ -1854,16 +1838,19 @@ static void nsp_cs_config(dev_link_t *link)
 
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
-       scsi_add_host (host, NULL);
+       ret = scsi_add_host (host, NULL);
+       if (ret)
+               goto cs_failed;
+
        scsi_scan_host(host);
 
        snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no);
-       link->dev  = &info->node;
+       link->dev_node  = &info->node;
        info->host = host;
 
 #else
        nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO");
-       tail = &link->dev;
+       tail = &link->dev_node;
        info->ndev = 0;
 
        nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
@@ -1908,11 +1895,10 @@ static void nsp_cs_config(dev_link_t *link)
 #endif
 
        /* Finally, report what we've done */
-       printk(KERN_INFO "nsp_cs: index 0x%02x: Vcc %d.%d",
-              link->conf.ConfigIndex,
-              link->conf.Vcc/10, link->conf.Vcc%10);
-       if (link->conf.Vpp1) {
-               printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+       printk(KERN_INFO "nsp_cs: index 0x%02x: ",
+              link->conf.ConfigIndex);
+       if (link->conf.Vpp) {
+               printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
        }
        if (link->conf.Attributes & CONF_ENABLE_IRQ) {
                printk(", irq %d", link->irq.AssignedIRQ);
@@ -1929,15 +1915,14 @@ static void nsp_cs_config(dev_link_t *link)
                       req.Base+req.Size-1);
        printk("\n");
 
-       link->state &= ~DEV_CONFIG_PENDING;
-       return;
+       return 0;
 
  cs_failed:
        nsp_dbg(NSP_DEBUG_INIT, "config fail");
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
        nsp_cs_release(link);
 
-       return;
+       return -ENODEV;
 } /* nsp_cs_config */
 #undef CS_CHECK
 
@@ -1947,7 +1932,7 @@ static void nsp_cs_config(dev_link_t *link)
     device, and release the PCMCIA configuration.  If the device is
     still open, this will be postponed until it is closed.
 ======================================================================*/
-static void nsp_cs_release(dev_link_t *link)
+static void nsp_cs_release(struct pcmcia_device *link)
 {
        scsi_info_t *info = link->priv;
        nsp_hw_data *data = NULL;
@@ -1968,22 +1953,15 @@ static void nsp_cs_release(dev_link_t *link)
 #else
        scsi_unregister_host(&nsp_driver_template);
 #endif
-       link->dev = NULL;
+       link->dev_node = NULL;
 
        if (link->win) {
                if (data != NULL) {
                        iounmap((void *)(data->MmioAddress));
                }
-               pcmcia_release_window(link->win);
-       }
-       pcmcia_release_configuration(link->handle);
-       if (link->io.NumPorts1) {
-               pcmcia_release_io(link->handle, &link->io);
        }
-       if (link->irq.AssignedIRQ) {
-               pcmcia_release_irq(link->handle, &link->irq);
-       }
-       link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
        if (info->host != NULL) {
                scsi_host_put(info->host);
@@ -1991,14 +1969,11 @@ static void nsp_cs_release(dev_link_t *link)
 #endif
 } /* nsp_cs_release */
 
-static int nsp_cs_suspend(struct pcmcia_device *dev)
+static int nsp_cs_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        scsi_info_t *info = link->priv;
        nsp_hw_data *data;
 
-       link->state |= DEV_SUSPEND;
-
        nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
 
        if (info->host != NULL) {
@@ -2011,25 +1986,16 @@ static int nsp_cs_suspend(struct pcmcia_device *dev)
 
        info->stop = 1;
 
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
        return 0;
 }
 
-static int nsp_cs_resume(struct pcmcia_device *dev)
+static int nsp_cs_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        scsi_info_t *info = link->priv;
        nsp_hw_data *data;
 
        nsp_dbg(NSP_DEBUG_INIT, "event: resume");
 
-       link->state &= ~DEV_SUSPEND;
-
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
-
        info->stop = 0;
 
        if (info->host != NULL) {
@@ -2065,7 +2031,7 @@ static struct pcmcia_driver nsp_driver = {
        .drv            = {
                .name   = "nsp_cs",
        },
-       .probe          = nsp_cs_attach,
+       .probe          = nsp_cs_probe,
        .remove         = nsp_cs_detach,
        .id_table       = nsp_cs_ids,
        .suspend        = nsp_cs_suspend,
@@ -2098,19 +2064,7 @@ static int __init nsp_cs_init(void)
 static void __exit nsp_cs_exit(void)
 {
        nsp_msg(KERN_INFO, "unloading...");
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
        pcmcia_unregister_driver(&nsp_driver);
-#else
-       unregister_pcmcia_driver(&dev_info);
-       /* XXX: this really needs to move into generic code.. */
-       while (dev_list != NULL) {
-               if (dev_list->state & DEV_CONFIG) {
-                       nsp_cs_release(dev_list);
-               }
-               nsp_cs_detach(dev_list);
-       }
-#endif
 }
 
 
index b66b140..8908b8e 100644 (file)
 /*====================================================================*/
 
 typedef struct scsi_info_t {
-       dev_link_t             link;
+       struct pcmcia_device    *p_dev;
        struct Scsi_Host      *host;
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
        dev_node_t             node;
@@ -297,8 +297,8 @@ typedef struct _nsp_hw_data {
 
 /* Card service functions */
 static void        nsp_cs_detach (struct pcmcia_device *p_dev);
-static void        nsp_cs_release(dev_link_t *link);
-static void        nsp_cs_config (dev_link_t *link);
+static void        nsp_cs_release(struct pcmcia_device *link);
+static int        nsp_cs_config (struct pcmcia_device *link);
 
 /* Linux SCSI subsystem specific functions */
 static struct Scsi_Host *nsp_detect     (struct scsi_host_template *sht);
@@ -450,7 +450,7 @@ static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno)
        return host;
 }
 
-static void cs_error(client_handle_t handle, int func, int ret)
+static void cs_error(struct pcmcia_device *handle, int func, int ret)
 {
        error_info_t err = { func, ret };
        pcmcia_report_error(handle, &err);
index dce7e68..86c2ac6 100644 (file)
@@ -91,18 +91,18 @@ static struct scsi_host_template qlogicfas_driver_template = {
 /*====================================================================*/
 
 typedef struct scsi_info_t {
-       dev_link_t link;
+       struct pcmcia_device    *p_dev;
        dev_node_t node;
        struct Scsi_Host *host;
        unsigned short manf_id;
 } scsi_info_t;
 
-static void qlogic_release(dev_link_t *link);
+static void qlogic_release(struct pcmcia_device *link);
 static void qlogic_detach(struct pcmcia_device *p_dev);
-static void qlogic_config(dev_link_t * link);
+static int qlogic_config(struct pcmcia_device * link);
 
 static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host,
-                               dev_link_t *link, int qbase, int qlirq)
+                               struct pcmcia_device *link, int qbase, int qlirq)
 {
        int qltyp;              /* type of chip */
        int qinitid;
@@ -156,10 +156,9 @@ free_scsi_host:
 err:
        return NULL;
 }
-static int qlogic_attach(struct pcmcia_device *p_dev)
+static int qlogic_probe(struct pcmcia_device *link)
 {
        scsi_info_t *info;
-       dev_link_t *link;
 
        DEBUG(0, "qlogic_attach()\n");
 
@@ -168,7 +167,7 @@ static int qlogic_attach(struct pcmcia_device *p_dev)
        if (!info)
                return -ENOMEM;
        memset(info, 0, sizeof(*info));
-       link = &info->link;
+       info->p_dev = link;
        link->priv = info;
        link->io.NumPorts1 = 16;
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -176,30 +175,19 @@ static int qlogic_attach(struct pcmcia_device *p_dev)
        link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
        link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.Vcc = 50;
        link->conf.IntType = INT_MEMORY_AND_IO;
        link->conf.Present = PRESENT_OPTION;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       qlogic_config(link);
-
-       return 0;
+       return qlogic_config(link);
 }                              /* qlogic_attach */
 
 /*====================================================================*/
 
-static void qlogic_detach(struct pcmcia_device *p_dev)
+static void qlogic_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
-
        DEBUG(0, "qlogic_detach(0x%p)\n", link);
 
-       if (link->state & DEV_CONFIG)
-               qlogic_release(link);
-
+       qlogic_release(link);
        kfree(link->priv);
 
 }                              /* qlogic_detach */
@@ -209,9 +197,8 @@ static void qlogic_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void qlogic_config(dev_link_t * link)
+static int qlogic_config(struct pcmcia_device * link)
 {
-       client_handle_t handle = link->handle;
        scsi_info_t *info = link->priv;
        tuple_t tuple;
        cisparse_t parse;
@@ -225,38 +212,35 @@ static void qlogic_config(dev_link_t * link)
        tuple.TupleDataMax = 64;
        tuple.TupleOffset = 0;
        tuple.DesiredTuple = CISTPL_CONFIG;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase = parse.config.base;
 
        tuple.DesiredTuple = CISTPL_MANFID;
-       if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
+       if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS))
                info->manf_id = le16_to_cpu(tuple.TupleData[0]);
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        while (1) {
-               if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-                               pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+                               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
                        goto next_entry;
                link->conf.ConfigIndex = parse.cftable_entry.index;
                link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
                link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
                if (link->io.BasePort1 != 0) {
-                       i = pcmcia_request_io(handle, &link->io);
+                       i = pcmcia_request_io(link, &link->io);
                        if (i == CS_SUCCESS)
                                break;
                }
              next_entry:
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
        }
 
-       CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+       CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
        if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
                /* set ATAcmd */
@@ -275,82 +259,54 @@ static void qlogic_config(dev_link_t * link)
        
        if (!host) {
                printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name);
-               goto out;
+               goto cs_failed;
        }
 
        sprintf(info->node.dev_name, "scsi%d", host->host_no);
-       link->dev = &info->node;
+       link->dev_node = &info->node;
        info->host = host;
 
-out:
-       link->state &= ~DEV_CONFIG_PENDING;
-       return;
+       return 0;
 
 cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
-       link->dev = NULL;
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
-       link->state &= ~DEV_CONFIG;
-       return;
+       cs_error(link, last_fn, last_ret);
+       pcmcia_disable_device(link);
+       return -ENODEV;
 
 }                              /* qlogic_config */
 
 /*====================================================================*/
 
-static void qlogic_release(dev_link_t *link)
+static void qlogic_release(struct pcmcia_device *link)
 {
        scsi_info_t *info = link->priv;
 
        DEBUG(0, "qlogic_release(0x%p)\n", link);
 
        scsi_remove_host(info->host);
-       link->dev = NULL;
 
        free_irq(link->irq.AssignedIRQ, info->host);
-
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
+       pcmcia_disable_device(link);
 
        scsi_host_put(info->host);
-
-       link->state &= ~DEV_CONFIG;
 }
 
 /*====================================================================*/
 
-static int qlogic_suspend(struct pcmcia_device *dev)
+static int qlogic_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
+       scsi_info_t *info = link->priv;
 
-static int qlogic_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               scsi_info_t *info = link->priv;
-
-               pcmcia_request_configuration(link->handle, &link->conf);
-               if ((info->manf_id == MANFID_MACNICA) ||
-                   (info->manf_id == MANFID_PIONEER) ||
-                   (info->manf_id == 0x0098)) {
-                       outb(0x80, link->io.BasePort1 + 0xd);
-                       outb(0x24, link->io.BasePort1 + 0x9);
-                       outb(0x04, link->io.BasePort1 + 0xd);
-               }
-               /* Ugggglllyyyy!!! */
-               qlogicfas408_bus_reset(NULL);
+       pcmcia_request_configuration(link, &link->conf);
+       if ((info->manf_id == MANFID_MACNICA) ||
+           (info->manf_id == MANFID_PIONEER) ||
+           (info->manf_id == 0x0098)) {
+               outb(0x80, link->io.BasePort1 + 0xd);
+               outb(0x24, link->io.BasePort1 + 0x9);
+               outb(0x04, link->io.BasePort1 + 0xd);
        }
+       /* Ugggglllyyyy!!! */
+       qlogicfas408_bus_reset(NULL);
 
        return 0;
 }
@@ -382,10 +338,9 @@ static struct pcmcia_driver qlogic_cs_driver = {
        .drv            = {
        .name           = "qlogic_cs",
        },
-       .probe          = qlogic_attach,
+       .probe          = qlogic_probe,
        .remove         = qlogic_detach,
        .id_table       = qlogic_ids,
-       .suspend        = qlogic_suspend,
        .resume         = qlogic_resume,
 };
 
index 3a4dd6f..9f59827 100644 (file)
@@ -202,7 +202,7 @@ static char *version =
 /* ================================================================== */
 
 struct scsi_info_t {
-       dev_link_t link;
+       struct pcmcia_device    *p_dev;
        dev_node_t node;
        struct Scsi_Host *host;
        unsigned short manf_id;
@@ -527,7 +527,7 @@ idle_out:
 }
 
 static void
-SYM53C500_release(dev_link_t *link)
+SYM53C500_release(struct pcmcia_device *link)
 {
        struct scsi_info_t *info = link->priv;
        struct Scsi_Host *shost = info->host;
@@ -550,13 +550,7 @@ SYM53C500_release(dev_link_t *link)
        if (shost->io_port && shost->n_io_port)
                release_region(shost->io_port, shost->n_io_port);
 
-       link->dev = NULL;
-
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
-
-       link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
 
        scsi_host_put(shost);
 } /* SYM53C500_release */
@@ -713,10 +707,9 @@ static struct scsi_host_template sym53c500_driver_template = {
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void
-SYM53C500_config(dev_link_t *link)
+static int
+SYM53C500_config(struct pcmcia_device *link)
 {
-       client_handle_t handle = link->handle;
        struct scsi_info_t *info = link->priv;
        tuple_t tuple;
        cisparse_t parse;
@@ -733,40 +726,37 @@ SYM53C500_config(dev_link_t *link)
        tuple.TupleDataMax = 64;
        tuple.TupleOffset = 0;
        tuple.DesiredTuple = CISTPL_CONFIG;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase = parse.config.base;
 
        tuple.DesiredTuple = CISTPL_MANFID;
-       if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
-           (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
+       if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+           (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS))
                info->manf_id = le16_to_cpu(tuple.TupleData[0]);
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        while (1) {
-               if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-                   pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+                   pcmcia_parse_tuple(link, &tuple, &parse) != 0)
                        goto next_entry;
                link->conf.ConfigIndex = parse.cftable_entry.index;
                link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
                link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
 
                if (link->io.BasePort1 != 0) {
-                       i = pcmcia_request_io(handle, &link->io);
+                       i = pcmcia_request_io(link, &link->io);
                        if (i == CS_SUCCESS)
                                break;
                }
 next_entry:
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
        }
 
-       CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+       CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
        /*
        *  That's the trouble with copying liberally from another driver.
@@ -835,7 +825,7 @@ next_entry:
        data->fast_pio = USE_FAST_PIO;
 
        sprintf(info->node.dev_name, "scsi%d", host->host_no);
-       link->dev = &info->node;
+       link->dev_node = &info->node;
        info->host = host;
 
        if (scsi_add_host(host, NULL))
@@ -843,7 +833,7 @@ next_entry:
 
        scsi_scan_host(host);
 
-       goto out;       /* SUCCESS */
+       return 0;
 
 err_free_irq:
        free_irq(irq_level, host);
@@ -852,74 +842,50 @@ err_free_scsi:
 err_release:
        release_region(port_base, 0x10);
        printk(KERN_INFO "sym53c500_cs: no SCSI devices found\n");
-
-out:
-       link->state &= ~DEV_CONFIG_PENDING;
-       return;
+       return -ENODEV;
 
 cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
        SYM53C500_release(link);
-       return;
+       return -ENODEV;
 } /* SYM53C500_config */
 
-static int sym53c500_suspend(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int sym53c500_resume(struct pcmcia_device *dev)
+static int sym53c500_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        struct scsi_info_t *info = link->priv;
 
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG) {
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-               /* See earlier comment about manufacturer IDs. */
-               if ((info->manf_id == MANFID_MACNICA) ||
-                   (info->manf_id == MANFID_PIONEER) ||
-                   (info->manf_id == 0x0098)) {
-                       outb(0x80, link->io.BasePort1 + 0xd);
-                       outb(0x24, link->io.BasePort1 + 0x9);
-                       outb(0x04, link->io.BasePort1 + 0xd);
-               }
-               /*
-                *  If things don't work after a "resume",
-                *  this is a good place to start looking.
-                */
-               SYM53C500_int_host_reset(link->io.BasePort1);
+       /* See earlier comment about manufacturer IDs. */
+       if ((info->manf_id == MANFID_MACNICA) ||
+           (info->manf_id == MANFID_PIONEER) ||
+           (info->manf_id == 0x0098)) {
+               outb(0x80, link->io.BasePort1 + 0xd);
+               outb(0x24, link->io.BasePort1 + 0x9);
+               outb(0x04, link->io.BasePort1 + 0xd);
        }
+       /*
+        *  If things don't work after a "resume",
+        *  this is a good place to start looking.
+        */
+       SYM53C500_int_host_reset(link->io.BasePort1);
 
        return 0;
 }
 
 static void
-SYM53C500_detach(struct pcmcia_device *p_dev)
+SYM53C500_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
-
        DEBUG(0, "SYM53C500_detach(0x%p)\n", link);
 
-       if (link->state & DEV_CONFIG)
-               SYM53C500_release(link);
+       SYM53C500_release(link);
 
        kfree(link->priv);
        link->priv = NULL;
 } /* SYM53C500_detach */
 
 static int
-SYM53C500_attach(struct pcmcia_device *p_dev)
+SYM53C500_probe(struct pcmcia_device *link)
 {
        struct scsi_info_t *info;
-       dev_link_t *link;
 
        DEBUG(0, "SYM53C500_attach()\n");
 
@@ -928,7 +894,7 @@ SYM53C500_attach(struct pcmcia_device *p_dev)
        if (!info)
                return -ENOMEM;
        memset(info, 0, sizeof(*info));
-       link = &info->link;
+       info->p_dev = link;
        link->priv = info;
        link->io.NumPorts1 = 16;
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -936,17 +902,10 @@ SYM53C500_attach(struct pcmcia_device *p_dev)
        link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
        link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.Vcc = 50;
        link->conf.IntType = INT_MEMORY_AND_IO;
        link->conf.Present = PRESENT_OPTION;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       SYM53C500_config(link);
-
-       return 0;
+       return SYM53C500_config(link);
 } /* SYM53C500_attach */
 
 MODULE_AUTHOR("Bob Tracy <rct@frus.com>");
@@ -966,10 +925,9 @@ static struct pcmcia_driver sym53c500_cs_driver = {
        .drv            = {
                .name   = "sym53c500_cs",
        },
-       .probe          = SYM53C500_attach,
+       .probe          = SYM53C500_probe,
        .remove         = SYM53C500_detach,
        .id_table       = sym53c500_ids,
-       .suspend        = sym53c500_suspend,
        .resume         = sym53c500_resume,
 };
 
index b131432..a6cfbb3 100644 (file)
@@ -88,7 +88,7 @@ zalon_probe(struct parisc_device *dev)
        struct gsc_irq gsc_irq;
        u32 zalon_vers;
        int error = -ENODEV;
-       void __iomem *zalon = ioremap(dev->hpa.start, 4096);
+       void __iomem *zalon = ioremap_nocache(dev->hpa.start, 4096);
        void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET;
        static int unit = 0;
        struct Scsi_Host *host;
index 8b49479..913c71c 100644 (file)
@@ -52,13 +52,14 @@ serial_init_chip(struct parisc_device *dev)
                address += 0x800;
        }
 
-       memset(&port, 0, sizeof(struct uart_port));
-       port.mapbase = address;
-       port.irq = dev->irq;
-       port.iotype = UPIO_MEM;
-       port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-       port.uartclk = LASI_BASE_BAUD * 16;
-       port.dev = &dev->dev;
+       memset(&port, 0, sizeof(port));
+       port.iotype     = UPIO_MEM;
+       port.uartclk    = LASI_BASE_BAUD * 16;
+       port.mapbase    = address;
+       port.membase    = ioremap_nocache(address, 16);
+       port.irq        = dev->irq;
+       port.flags      = UPF_BOOT_AUTOCONF;
+       port.dev        = &dev->dev;
 
        err = serial8250_register_port(&port);
        if (err < 0) {
index fe0d8b8..7d22dc0 100644 (file)
@@ -63,6 +63,33 @@ config SERIAL_8250_CONSOLE
 
          If unsure, say N.
 
+config SERIAL_8250_GSC
+       tristate
+       depends on SERIAL_8250 && GSC
+       default SERIAL_8250
+
+config SERIAL_8250_PCI
+       tristate "8250/16550 PCI device support" if EMBEDDED
+       depends on SERIAL_8250 && PCI
+       default SERIAL_8250
+       help
+         This builds standard PCI serial support. You may be able to
+         disable this feature if you only need legacy serial support.
+         Saves about 9K.
+
+config SERIAL_8250_PNP
+       tristate "8250/16550 PNP device support" if EMBEDDED
+       depends on SERIAL_8250 && PNP
+       default SERIAL_8250
+       help
+         This builds standard PNP serial support. You may be able to
+         disable this feature if you only need legacy serial support.
+
+config SERIAL_8250_HP300
+       tristate
+       depends on SERIAL_8250 && HP300
+       default SERIAL_8250
+
 config SERIAL_8250_CS
        tristate "8250/16550 PCMCIA device support"
        depends on PCMCIA && SERIAL_8250
index d2b4c21..0a71bf6 100644 (file)
@@ -4,15 +4,13 @@
 #  $Id: Makefile,v 1.8 2002/07/21 21:32:30 rmk Exp $
 #
 
-serial-8250-y :=
-serial-8250-$(CONFIG_PNP) += 8250_pnp.o
-serial-8250-$(CONFIG_GSC) += 8250_gsc.o
-serial-8250-$(CONFIG_PCI) += 8250_pci.o
-serial-8250-$(CONFIG_HP300) += 8250_hp300.o
-
 obj-$(CONFIG_SERIAL_CORE) += serial_core.o
 obj-$(CONFIG_SERIAL_21285) += 21285.o
-obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y)
+obj-$(CONFIG_SERIAL_8250) += 8250.o
+obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
+obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
+obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
+obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
 obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
 obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
 obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
index 4d48b62..7d82370 100644 (file)
@@ -142,12 +142,14 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch)
 {
        unsigned long lock_flags;
        struct jsm_channel *channel = (struct jsm_channel *)port;
+       struct termios *termios;
 
        spin_lock_irqsave(&port->lock, lock_flags);
-       if (ch == port->info->tty->termios->c_cc[VSTART])
+       termios = port->info->tty->termios;
+       if (ch == termios->c_cc[VSTART])
                channel->ch_bd->bd_ops->send_start_character(channel);
 
-       if (ch == port->info->tty->termios->c_cc[VSTOP])
+       if (ch == termios->c_cc[VSTOP])
                channel->ch_bd->bd_ops->send_stop_character(channel);
        spin_unlock_irqrestore(&port->lock, lock_flags);
 }
@@ -178,6 +180,7 @@ static int jsm_tty_open(struct uart_port *port)
        struct jsm_board *brd;
        int rc = 0;
        struct jsm_channel *channel = (struct jsm_channel *)port;
+       struct termios *termios;
 
        /* Get board pointer from our array of majors we have allocated */
        brd = channel->ch_bd;
@@ -239,12 +242,13 @@ static int jsm_tty_open(struct uart_port *port)
        channel->ch_cached_lsr = 0;
        channel->ch_stops_sent = 0;
 
-       channel->ch_c_cflag     = port->info->tty->termios->c_cflag;
-       channel->ch_c_iflag     = port->info->tty->termios->c_iflag;
-       channel->ch_c_oflag     = port->info->tty->termios->c_oflag;
-       channel->ch_c_lflag     = port->info->tty->termios->c_lflag;
-       channel->ch_startc = port->info->tty->termios->c_cc[VSTART];
-       channel->ch_stopc = port->info->tty->termios->c_cc[VSTOP];
+       termios = port->info->tty->termios;
+       channel->ch_c_cflag     = termios->c_cflag;
+       channel->ch_c_iflag     = termios->c_iflag;
+       channel->ch_c_oflag     = termios->c_oflag;
+       channel->ch_c_lflag     = termios->c_lflag;
+       channel->ch_startc      = termios->c_cc[VSTART];
+       channel->ch_stopc       = termios->c_cc[VSTOP];
 
        /* Tell UART to init itself */
        brd->bd_ops->uart_init(channel);
@@ -784,6 +788,7 @@ static void jsm_carrier(struct jsm_channel *ch)
 
 void jsm_check_queue_flow_control(struct jsm_channel *ch)
 {
+       struct board_ops *bd_ops = ch->ch_bd->bd_ops;
        int qleft = 0;
 
        /* Store how much space we have left in the queue */
@@ -809,7 +814,7 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
                /* HWFLOW */
                if (ch->ch_c_cflag & CRTSCTS) {
                        if(!(ch->ch_flags & CH_RECEIVER_OFF)) {
-                               ch->ch_bd->bd_ops->disable_receiver(ch);
+                               bd_ops->disable_receiver(ch);
                                ch->ch_flags |= (CH_RECEIVER_OFF);
                                jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
                                        "Internal queue hit hilevel mark (%d)! Turning off interrupts.\n",
@@ -819,7 +824,7 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
                /* SWFLOW */
                else if (ch->ch_c_iflag & IXOFF) {
                        if (ch->ch_stops_sent <= MAX_STOPS_SENT) {
-                               ch->ch_bd->bd_ops->send_stop_character(ch);
+                               bd_ops->send_stop_character(ch);
                                ch->ch_stops_sent++;
                                jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
                                        "Sending stop char! Times sent: %x\n", ch->ch_stops_sent);
@@ -846,7 +851,7 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
                /* HWFLOW */
                if (ch->ch_c_cflag & CRTSCTS) {
                        if (ch->ch_flags & CH_RECEIVER_OFF) {
-                               ch->ch_bd->bd_ops->enable_receiver(ch);
+                               bd_ops->enable_receiver(ch);
                                ch->ch_flags &= ~(CH_RECEIVER_OFF);
                                jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
                                        "Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n",
@@ -856,7 +861,7 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
                /* SWFLOW */
                else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) {
                        ch->ch_stops_sent = 0;
-                       ch->ch_bd->bd_ops->send_start_character(ch);
+                       bd_ops->send_start_character(ch);
                        jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "Sending start char!\n");
                }
        }
index 868eaf4..64c0e89 100644 (file)
@@ -51,7 +51,7 @@
 #define MUX_BREAK(status) ((status & 0xF000) == 0x2000)
 
 #define MUX_NR 256
-static unsigned int port_cnt = 0;
+static unsigned int port_cnt __read_mostly;
 static struct uart_port mux_ports[MUX_NR];
 
 static struct uart_driver mux_driver = {
@@ -461,7 +461,7 @@ static int __init mux_probe(struct parisc_device *dev)
                port->iobase    = 0;
                port->mapbase   = dev->hpa.start + MUX_OFFSET +
                                                (i * MUX_LINE_OFFSET);
-               port->membase   = ioremap(port->mapbase, MUX_LINE_OFFSET);
+               port->membase   = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET);
                port->iotype    = UPIO_MEM;
                port->type      = PORT_MUX;
                port->irq       = NO_IRQ;
index c303336..2c70773 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/serial_core.h>
+#include <linux/delay.h>
 #include <linux/major.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -97,11 +98,13 @@ static const struct multi_id multi_id[] = {
 #define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id))
 
 struct serial_info {
-       dev_link_t              link;
+       struct pcmcia_device    *p_dev;
        int                     ndev;
        int                     multi;
        int                     slave;
        int                     manfid;
+       int                     prodid;
+       int                     c950ctrl;
        dev_node_t              node[4];
        int                     line[4];
 };
@@ -113,9 +116,36 @@ struct serial_cfg_mem {
 };
 
 
-static void serial_config(dev_link_t * link);
+static int serial_config(struct pcmcia_device * link);
 
 
+static void wakeup_card(struct serial_info *info)
+{
+       int ctrl = info->c950ctrl;
+
+       if (info->manfid == MANFID_OXSEMI) {
+               outb(12, ctrl + 1);
+       } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) {
+               /* request_region? oxsemi branch does no request_region too... */
+               /* This sequence is needed to properly initialize MC45 attached to OXCF950.
+                * I tried decreasing these msleep()s, but it worked properly (survived
+                * 1000 stop/start operations) with these timeouts (or bigger). */
+               outb(0xA, ctrl + 1);
+               msleep(100);
+               outb(0xE, ctrl + 1);
+               msleep(300);
+               outb(0xC, ctrl + 1);
+               msleep(100);
+               outb(0xE, ctrl + 1);
+               msleep(200);
+               outb(0xF, ctrl + 1);
+               msleep(100);
+               outb(0xE, ctrl + 1);
+               msleep(100);
+               outb(0xC, ctrl + 1);
+       }
+}
+
 /*======================================================================
 
     After a card is removed, serial_remove() will unregister
@@ -123,67 +153,45 @@ static void serial_config(dev_link_t * link);
     
 ======================================================================*/
 
-static void serial_remove(dev_link_t *link)
+static void serial_remove(struct pcmcia_device *link)
 {
        struct serial_info *info = link->priv;
        int i;
 
-       link->state &= ~DEV_PRESENT;
-
        DEBUG(0, "serial_release(0x%p)\n", link);
 
        /*
         * Recheck to see if the device is still configured.
         */
-       if (info->link.state & DEV_CONFIG) {
-               for (i = 0; i < info->ndev; i++)
-                       serial8250_unregister_port(info->line[i]);
+       for (i = 0; i < info->ndev; i++)
+               serial8250_unregister_port(info->line[i]);
 
-               info->link.dev = NULL;
+       info->p_dev->dev_node = NULL;
 
-               if (!info->slave) {
-                       pcmcia_release_configuration(info->link.handle);
-                       pcmcia_release_io(info->link.handle, &info->link.io);
-                       pcmcia_release_irq(info->link.handle, &info->link.irq);
-               }
-
-               info->link.state &= ~DEV_CONFIG;
-       }
+       if (!info->slave)
+               pcmcia_disable_device(link);
 }
 
-static int serial_suspend(struct pcmcia_device *dev)
+static int serial_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
-       link->state |= DEV_SUSPEND;
-
-       if (link->state & DEV_CONFIG) {
-               struct serial_info *info = link->priv;
-               int i;
-
-               for (i = 0; i < info->ndev; i++)
-                       serial8250_suspend_port(info->line[i]);
+       struct serial_info *info = link->priv;
+       int i;
 
-               if (!info->slave)
-                       pcmcia_release_configuration(link->handle);
-       }
+       for (i = 0; i < info->ndev; i++)
+               serial8250_suspend_port(info->line[i]);
 
        return 0;
 }
 
-static int serial_resume(struct pcmcia_device *dev)
+static int serial_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
-       link->state &= ~DEV_SUSPEND;
-
-       if (DEV_OK(link)) {
+       if (pcmcia_dev_present(link)) {
                struct serial_info *info = link->priv;
                int i;
 
-               if (!info->slave)
-                       pcmcia_request_configuration(link->handle, &link->conf);
-
                for (i = 0; i < info->ndev; i++)
                        serial8250_resume_port(info->line[i]);
+               wakeup_card(info);
        }
 
        return 0;
@@ -197,10 +205,9 @@ static int serial_resume(struct pcmcia_device *dev)
 
 ======================================================================*/
 
-static int serial_probe(struct pcmcia_device *p_dev)
+static int serial_probe(struct pcmcia_device *link)
 {
        struct serial_info *info;
-       dev_link_t *link;
 
        DEBUG(0, "serial_attach()\n");
 
@@ -209,7 +216,7 @@ static int serial_probe(struct pcmcia_device *p_dev)
        if (!info)
                return -ENOMEM;
        memset(info, 0, sizeof (*info));
-       link = &info->link;
+       info->p_dev = link;
        link->priv = info;
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -223,12 +230,7 @@ static int serial_probe(struct pcmcia_device *p_dev)
        }
        link->conf.IntType = INT_MEMORY_AND_IO;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       serial_config(link);
-
-       return 0;
+       return serial_config(link);
 }
 
 /*======================================================================
@@ -240,9 +242,8 @@ static int serial_probe(struct pcmcia_device *p_dev)
 
 ======================================================================*/
 
-static void serial_detach(struct pcmcia_device *p_dev)
+static void serial_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct serial_info *info = link->priv;
 
        DEBUG(0, "serial_detach(0x%p)\n", link);
@@ -263,7 +264,7 @@ static void serial_detach(struct pcmcia_device *p_dev)
 
 /*====================================================================*/
 
-static int setup_serial(client_handle_t handle, struct serial_info * info,
+static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
                        kio_addr_t iobase, int irq)
 {
        struct uart_port port;
@@ -298,7 +299,7 @@ static int setup_serial(client_handle_t handle, struct serial_info * info,
 /*====================================================================*/
 
 static int
-first_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
+first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
 {
        int i;
        i = pcmcia_get_first_tuple(handle, tuple);
@@ -311,7 +312,7 @@ first_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
 }
 
 static int
-next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
+next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
 {
        int i;
        i = pcmcia_get_next_tuple(handle, tuple);
@@ -325,11 +326,10 @@ next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
 
 /*====================================================================*/
 
-static int simple_config(dev_link_t *link)
+static int simple_config(struct pcmcia_device *link)
 {
        static const kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
        static const int size_table[2] = { 8, 16 };
-       client_handle_t handle = link->handle;
        struct serial_info *info = link->priv;
        struct serial_cfg_mem *cfg_mem;
        tuple_t *tuple;
@@ -350,7 +350,7 @@ static int simple_config(dev_link_t *link)
        buf = cfg_mem->buf;
 
        /* If the card is already configured, look up the port and irq */
-       i = pcmcia_get_configuration_info(handle, &config);
+       i = pcmcia_get_configuration_info(link, &config);
        if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
                kio_addr_t port = 0;
                if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
@@ -363,10 +363,9 @@ static int simple_config(dev_link_t *link)
                }
                if (info->slave) {
                        kfree(cfg_mem);
-                       return setup_serial(handle, info, port, config.AssignedIRQ);
+                       return setup_serial(link, info, port, config.AssignedIRQ);
                }
        }
-       link->conf.Vcc = config.Vcc;
 
        /* First pass: look for a config entry that looks normal. */
        tuple->TupleData = (cisdata_t *) buf;
@@ -377,12 +376,12 @@ static int simple_config(dev_link_t *link)
        /* Two tries: without IO aliases, then with aliases */
        for (s = 0; s < 2; s++) {
                for (try = 0; try < 2; try++) {
-                       i = first_tuple(handle, tuple, parse);
+                       i = first_tuple(link, tuple, parse);
                        while (i != CS_NO_MORE_ITEMS) {
                                if (i != CS_SUCCESS)
                                        goto next_entry;
                                if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                                       link->conf.Vpp1 = link->conf.Vpp2 =
+                                       link->conf.Vpp =
                                            cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
                                if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
                                            (cf->io.win[0].base != 0)) {
@@ -390,19 +389,19 @@ static int simple_config(dev_link_t *link)
                                        link->io.BasePort1 = cf->io.win[0].base;
                                        link->io.IOAddrLines = (try == 0) ?
                                            16 : cf->io.flags & CISTPL_IO_LINES_MASK;
-                                       i = pcmcia_request_io(link->handle, &link->io);
+                                       i = pcmcia_request_io(link, &link->io);
                                        if (i == CS_SUCCESS)
                                                goto found_port;
                                }
 next_entry:
-                               i = next_tuple(handle, tuple, parse);
+                               i = next_tuple(link, tuple, parse);
                        }
                }
        }
        /* Second pass: try to find an entry that isn't picky about
           its base address, then try to grab any standard serial port
           address, and finally try to get any free port. */
-       i = first_tuple(handle, tuple, parse);
+       i = first_tuple(link, tuple, parse);
        while (i != CS_NO_MORE_ITEMS) {
                if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
                    ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
@@ -410,50 +409,48 @@ next_entry:
                        for (j = 0; j < 5; j++) {
                                link->io.BasePort1 = base[j];
                                link->io.IOAddrLines = base[j] ? 16 : 3;
-                               i = pcmcia_request_io(link->handle, &link->io);
+                               i = pcmcia_request_io(link, &link->io);
                                if (i == CS_SUCCESS)
                                        goto found_port;
                        }
                }
-               i = next_tuple(handle, tuple, parse);
+               i = next_tuple(link, tuple, parse);
        }
 
       found_port:
        if (i != CS_SUCCESS) {
                printk(KERN_NOTICE
                       "serial_cs: no usable port range found, giving up\n");
-               cs_error(link->handle, RequestIO, i);
+               cs_error(link, RequestIO, i);
                kfree(cfg_mem);
                return -1;
        }
 
-       i = pcmcia_request_irq(link->handle, &link->irq);
+       i = pcmcia_request_irq(link, &link->irq);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestIRQ, i);
+               cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
        if (info->multi && (info->manfid == MANFID_3COM))
                link->conf.ConfigIndex &= ~(0x08);
-       i = pcmcia_request_configuration(link->handle, &link->conf);
+       i = pcmcia_request_configuration(link, &link->conf);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestConfiguration, i);
+               cs_error(link, RequestConfiguration, i);
                kfree(cfg_mem);
                return -1;
        }
        kfree(cfg_mem);
-       return setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
+       return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
 }
 
-static int multi_config(dev_link_t * link)
+static int multi_config(struct pcmcia_device * link)
 {
-       client_handle_t handle = link->handle;
        struct serial_info *info = link->priv;
        struct serial_cfg_mem *cfg_mem;
        tuple_t *tuple;
        u_char *buf;
        cisparse_t *parse;
        cistpl_cftable_entry_t *cf;
-       config_info_t config;
        int i, rc, base2 = 0;
 
        cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
@@ -464,14 +461,6 @@ static int multi_config(dev_link_t * link)
        cf = &parse->cftable_entry;
        buf = cfg_mem->buf;
 
-       i = pcmcia_get_configuration_info(handle, &config);
-       if (i != CS_SUCCESS) {
-               cs_error(handle, GetConfigurationInfo, i);
-               rc = -1;
-               goto free_cfg_mem;
-       }
-       link->conf.Vcc = config.Vcc;
-
        tuple->TupleData = (cisdata_t *) buf;
        tuple->TupleOffset = 0;
        tuple->TupleDataMax = 255;
@@ -480,7 +469,7 @@ static int multi_config(dev_link_t * link)
 
        /* First, look for a generic full-sized window */
        link->io.NumPorts1 = info->multi * 8;
-       i = first_tuple(handle, tuple, parse);
+       i = first_tuple(link, tuple, parse);
        while (i != CS_NO_MORE_ITEMS) {
                /* The quad port cards have bad CIS's, so just look for a
                   window larger than 8 ports and assume it will be right */
@@ -490,19 +479,19 @@ static int multi_config(dev_link_t * link)
                        link->io.BasePort1 = cf->io.win[0].base;
                        link->io.IOAddrLines =
                            cf->io.flags & CISTPL_IO_LINES_MASK;
-                       i = pcmcia_request_io(link->handle, &link->io);
+                       i = pcmcia_request_io(link, &link->io);
                        base2 = link->io.BasePort1 + 8;
                        if (i == CS_SUCCESS)
                                break;
                }
-               i = next_tuple(handle, tuple, parse);
+               i = next_tuple(link, tuple, parse);
        }
 
        /* If that didn't work, look for two windows */
        if (i != CS_SUCCESS) {
                link->io.NumPorts1 = link->io.NumPorts2 = 8;
                info->multi = 2;
-               i = first_tuple(handle, tuple, parse);
+               i = first_tuple(link, tuple, parse);
                while (i != CS_NO_MORE_ITEMS) {
                        if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
                                link->conf.ConfigIndex = cf->index;
@@ -510,26 +499,26 @@ static int multi_config(dev_link_t * link)
                                link->io.BasePort2 = cf->io.win[1].base;
                                link->io.IOAddrLines =
                                    cf->io.flags & CISTPL_IO_LINES_MASK;
-                               i = pcmcia_request_io(link->handle, &link->io);
+                               i = pcmcia_request_io(link, &link->io);
                                base2 = link->io.BasePort2;
                                if (i == CS_SUCCESS)
                                        break;
                        }
-                       i = next_tuple(handle, tuple, parse);
+                       i = next_tuple(link, tuple, parse);
                }
        }
 
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestIO, i);
+               cs_error(link, RequestIO, i);
                rc = -1;
                goto free_cfg_mem;
        }
 
-       i = pcmcia_request_irq(link->handle, &link->irq);
+       i = pcmcia_request_irq(link, &link->irq);
        if (i != CS_SUCCESS) {
                printk(KERN_NOTICE
                       "serial_cs: no usable port range found, giving up\n");
-               cs_error(link->handle, RequestIRQ, i);
+               cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
        /* Socket Dual IO: this enables irq's for second port */
@@ -537,35 +526,43 @@ static int multi_config(dev_link_t * link)
                link->conf.Present |= PRESENT_EXT_STATUS;
                link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
        }
-       i = pcmcia_request_configuration(link->handle, &link->conf);
+       i = pcmcia_request_configuration(link, &link->conf);
        if (i != CS_SUCCESS) {
-               cs_error(link->handle, RequestConfiguration, i);
+               cs_error(link, RequestConfiguration, i);
                rc = -1;
                goto free_cfg_mem;
        }
 
        /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
-          8 registers are for the UART, the others are extra registers */
-       if (info->manfid == MANFID_OXSEMI) {
+        * 8 registers are for the UART, the others are extra registers.
+        * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
+        */
+       if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
+                               info->prodid == PRODID_POSSIO_GCC)) {
+               int err;
+
                if (cf->index == 1 || cf->index == 3) {
-                       setup_serial(handle, info, base2, link->irq.AssignedIRQ);
-                       outb(12, link->io.BasePort1 + 1);
+                       err = setup_serial(link, info, base2,
+                                       link->irq.AssignedIRQ);
+                       base2 = link->io.BasePort1;
                } else {
-                       setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
-                       outb(12, base2 + 1);
+                       err = setup_serial(link, info, link->io.BasePort1,
+                                       link->irq.AssignedIRQ);
                }
+               info->c950ctrl = base2;
+               wakeup_card(info);
                rc = 0;
                goto free_cfg_mem;
        }
 
-       setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
+       setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
        /* The Nokia cards are not really multiport cards */
        if (info->manfid == MANFID_NOKIA) {
                rc = 0;
                goto free_cfg_mem;
        }
        for (i = 0; i < info->multi - 1; i++)
-               setup_serial(handle, info, base2 + (8 * i),
+               setup_serial(link, info, base2 + (8 * i),
                                link->irq.AssignedIRQ);
        rc = 0;
 free_cfg_mem:
@@ -581,9 +578,8 @@ free_cfg_mem:
 
 ======================================================================*/
 
-void serial_config(dev_link_t * link)
+static int serial_config(struct pcmcia_device * link)
 {
-       client_handle_t handle = link->handle;
        struct serial_info *info = link->priv;
        struct serial_cfg_mem *cfg_mem;
        tuple_t *tuple;
@@ -609,7 +605,7 @@ void serial_config(dev_link_t * link)
        tuple->Attributes = 0;
        /* Get configuration register information */
        tuple->DesiredTuple = CISTPL_CONFIG;
-       last_ret = first_tuple(handle, tuple, parse);
+       last_ret = first_tuple(link, tuple, parse);
        if (last_ret != CS_SUCCESS) {
                last_fn = ParseTuple;
                goto cs_failed;
@@ -617,18 +613,16 @@ void serial_config(dev_link_t * link)
        link->conf.ConfigBase = parse->config.base;
        link->conf.Present = parse->config.rmask[0];
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
        /* Is this a compliant multifunction card? */
        tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
        tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
-       info->multi = (first_tuple(handle, tuple, parse) == CS_SUCCESS);
+       info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS);
 
        /* Is this a multiport card? */
        tuple->DesiredTuple = CISTPL_MANFID;
-       if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+       if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
                info->manfid = parse->manfid.manf;
+               info->prodid = le16_to_cpu(buf[1]);
                for (i = 0; i < MULTI_COUNT; i++)
                        if ((info->manfid == multi_id[i].manfid) &&
                            (parse->manfid.card == multi_id[i].prodid))
@@ -641,11 +635,11 @@ void serial_config(dev_link_t * link)
           multifunction cards that ask for appropriate IO port ranges */
        tuple->DesiredTuple = CISTPL_FUNCID;
        if ((info->multi == 0) &&
-           ((first_tuple(handle, tuple, parse) != CS_SUCCESS) ||
+           ((first_tuple(link, tuple, parse) != CS_SUCCESS) ||
             (parse->funcid.func == CISTPL_FUNCID_MULTI) ||
             (parse->funcid.func == CISTPL_FUNCID_SERIAL))) {
                tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
-               if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+               if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
                        if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
                                info->multi = cf->io.win[0].len >> 3;
                        if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
@@ -664,31 +658,30 @@ void serial_config(dev_link_t * link)
 
        if (info->manfid == MANFID_IBM) {
                conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
-               last_ret = pcmcia_access_configuration_register(link->handle, &reg);
+               last_ret = pcmcia_access_configuration_register(link, &reg);
                if (last_ret) {
                        last_fn = AccessConfigurationRegister;
                        goto cs_failed;
                }
                reg.Action = CS_WRITE;
                reg.Value = reg.Value | 1;
-               last_ret = pcmcia_access_configuration_register(link->handle, &reg);
+               last_ret = pcmcia_access_configuration_register(link, &reg);
                if (last_ret) {
                        last_fn = AccessConfigurationRegister;
                        goto cs_failed;
                }
        }
 
-       link->dev = &info->node[0];
-       link->state &= ~DEV_CONFIG_PENDING;
+       link->dev_node = &info->node[0];
        kfree(cfg_mem);
-       return;
+       return 0;
 
  cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
  failed:
        serial_remove(link);
-       link->state &= ~DEV_CONFIG_PENDING;
        kfree(cfg_mem);
+       return -ENODEV;
 }
 
 static struct pcmcia_device_id serial_ids[] = {
@@ -739,6 +732,7 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
        PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
        PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
+       PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
        PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
        PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
        PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
@@ -757,6 +751,7 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
        PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
        PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
+       PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
        PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
        PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
        PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
index d3a7b0c..dda0ca4 100644 (file)
@@ -35,73 +35,52 @@ typedef struct ixj_info_t {
 } ixj_info_t;
 
 static void ixj_detach(struct pcmcia_device *p_dev);
-static void ixj_config(dev_link_t * link);
-static void ixj_cs_release(dev_link_t * link);
+static int ixj_config(struct pcmcia_device * link);
+static void ixj_cs_release(struct pcmcia_device * link);
 
-static int ixj_attach(struct pcmcia_device *p_dev)
+static int ixj_probe(struct pcmcia_device *p_dev)
 {
-       dev_link_t *link;
-
        DEBUG(0, "ixj_attach()\n");
        /* Create new ixj device */
-       link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-       if (!link)
-               return -ENOMEM;
-       memset(link, 0, sizeof(struct dev_link_t));
-       link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-       link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-       link->io.IOAddrLines = 3;
-       link->conf.Vcc = 50;
-       link->conf.IntType = INT_MEMORY_AND_IO;
-       link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
-       if (!link->priv) {
-               kfree(link);
+       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+       p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+       p_dev->io.IOAddrLines = 3;
+       p_dev->conf.IntType = INT_MEMORY_AND_IO;
+       p_dev->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
+       if (!p_dev->priv) {
                return -ENOMEM;
        }
-       memset(link->priv, 0, sizeof(struct ixj_info_t));
-
-       link->handle = p_dev;
-       p_dev->instance = link;
+       memset(p_dev->priv, 0, sizeof(struct ixj_info_t));
 
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       ixj_config(link);
-
-       return 0;
+       return ixj_config(p_dev);
 }
 
-static void ixj_detach(struct pcmcia_device *p_dev)
+static void ixj_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
-
        DEBUG(0, "ixj_detach(0x%p)\n", link);
 
-       link->state &= ~DEV_RELEASE_PENDING;
-       if (link->state & DEV_CONFIG)
-               ixj_cs_release(link);
+       ixj_cs_release(link);
 
         kfree(link->priv);
-        kfree(link);
 }
 
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void ixj_get_serial(dev_link_t * link, IXJ * j)
+static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
 {
-       client_handle_t handle;
        tuple_t tuple;
        u_short buf[128];
        char *str;
        int last_ret, last_fn, i, place;
-       handle = link->handle;
        DEBUG(0, "ixj_get_serial(0x%p)\n", link);
        tuple.TupleData = (cisdata_t *) buf;
        tuple.TupleOffset = 0;
        tuple.TupleDataMax = 80;
        tuple.Attributes = 0;
        tuple.DesiredTuple = CISTPL_VERS_1;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
        str = (char *) buf;
        printk("PCMCIA Version %d.%d\n", str[0], str[1]);
        str += 2;
@@ -149,22 +128,19 @@ static void ixj_get_serial(dev_link_t * link, IXJ * j)
        return;
 }
 
-static void ixj_config(dev_link_t * link)
+static int ixj_config(struct pcmcia_device * link)
 {
        IXJ *j;
-       client_handle_t handle;
        ixj_info_t *info;
        tuple_t tuple;
        u_short buf[128];
        cisparse_t parse;
-       config_info_t conf;
        cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
        cistpl_cftable_entry_t dflt =
        {
                0
        };
        int last_ret, last_fn;
-       handle = link->handle;
        info = link->priv;
        DEBUG(0, "ixj_config(0x%p)\n", link);
        tuple.TupleData = (cisdata_t *) buf;
@@ -172,19 +148,17 @@ static void ixj_config(dev_link_t * link)
        tuple.TupleDataMax = 255;
        tuple.Attributes = 0;
        tuple.DesiredTuple = CISTPL_CONFIG;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
-       link->state |= DEV_CONFIG;
-       CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
        tuple.Attributes = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        while (1) {
-               if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-                               pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+                               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
                        goto next_entry;
                if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
                        cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
@@ -195,7 +169,7 @@ static void ixj_config(dev_link_t * link)
                                link->io.BasePort2 = io->win[1].base;
                                link->io.NumPorts2 = io->win[1].len;
                        }
-                       if (pcmcia_request_io(link->handle, &link->io) != 0)
+                       if (pcmcia_request_io(link, &link->io) != 0)
                                goto next_entry;
                        /* If we've got this far, we're done */
                        break;
@@ -203,10 +177,10 @@ static void ixj_config(dev_link_t * link)
              next_entry:
                if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
                        dflt = *cfg;
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
        }
 
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
        /*
         *      Register the card with the core.
@@ -215,46 +189,21 @@ static void ixj_config(dev_link_t * link)
 
        info->ndev = 1;
        info->node.major = PHONE_MAJOR;
-       link->dev = &info->node;
+       link->dev_node = &info->node;
        ixj_get_serial(link, j);
-       link->state &= ~DEV_CONFIG_PENDING;
-       return;
+       return 0;
       cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
        ixj_cs_release(link);
+       return -ENODEV;
 }
 
-static void ixj_cs_release(dev_link_t *link)
+static void ixj_cs_release(struct pcmcia_device *link)
 {
        ixj_info_t *info = link->priv;
        DEBUG(0, "ixj_cs_release(0x%p)\n", link);
        info->ndev = 0;
-       link->dev = NULL;
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       link->state &= ~DEV_CONFIG;
-}
-
-static int ixj_suspend(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int ixj_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (DEV_OK(link))
-               pcmcia_request_configuration(link->handle, &link->conf);
-
-       return 0;
+       pcmcia_disable_device(link);
 }
 
 static struct pcmcia_device_id ixj_ids[] = {
@@ -268,11 +217,9 @@ static struct pcmcia_driver ixj_driver = {
        .drv            = {
                .name   = "ixj_cs",
        },
-       .probe          = ixj_attach,
+       .probe          = ixj_probe,
        .remove         = ixj_detach,
        .id_table       = ixj_ids,
-       .suspend        = ixj_suspend,
-       .resume         = ixj_resume,
 };
 
 static int __init ixj_pcmcia_init(void)
index 134d200..302aa1e 100644 (file)
@@ -67,11 +67,11 @@ module_param(pc_debug, int, 0644);
 static const char driver_name[DEV_NAME_LEN]  = "sl811_cs";
 
 typedef struct local_info_t {
-       dev_link_t              link;
+       struct pcmcia_device    *p_dev;
        dev_node_t              node;
 } local_info_t;
 
-static void sl811_cs_release(dev_link_t * link);
+static void sl811_cs_release(struct pcmcia_device * link);
 
 /*====================================================================*/
 
@@ -138,41 +138,27 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
 
 /*====================================================================*/
 
-static void sl811_cs_detach(struct pcmcia_device *p_dev)
+static void sl811_cs_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
-
        DBG(0, "sl811_cs_detach(0x%p)\n", link);
 
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-               sl811_cs_release(link);
+       sl811_cs_release(link);
 
        /* This points to the parent local_info_t struct */
        kfree(link->priv);
 }
 
-static void sl811_cs_release(dev_link_t * link)
+static void sl811_cs_release(struct pcmcia_device * link)
 {
-
        DBG(0, "sl811_cs_release(0x%p)\n", link);
 
-       /* Unlink the device chain */
-       link->dev = NULL;
-
+       pcmcia_disable_device(link);
        platform_device_unregister(&platform_dev);
-       pcmcia_release_configuration(link->handle);
-       if (link->io.NumPorts1)
-               pcmcia_release_io(link->handle, &link->io);
-       if (link->irq.AssignedIRQ)
-               pcmcia_release_irq(link->handle, &link->irq);
-       link->state &= ~DEV_CONFIG;
 }
 
-static void sl811_cs_config(dev_link_t *link)
+static int sl811_cs_config(struct pcmcia_device *link)
 {
-       client_handle_t         handle = link->handle;
-       struct device           *parent = &handle_to_dev(handle);
+       struct device           *parent = &handle_to_dev(link);
        local_info_t            *dev = link->priv;
        tuple_t                 tuple;
        cisparse_t              parse;
@@ -188,27 +174,23 @@ static void sl811_cs_config(dev_link_t *link)
        tuple.TupleData = buf;
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
        /* Look up the current Vcc */
        CS_CHECK(GetConfigurationInfo,
-                       pcmcia_get_configuration_info(handle, &conf));
-       link->conf.Vcc = conf.Vcc;
+                       pcmcia_get_configuration_info(link, &conf));
 
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        while (1) {
                cistpl_cftable_entry_t  *cfg = &(parse.cftable_entry);
 
-               if (pcmcia_get_tuple_data(handle, &tuple) != 0
-                               || pcmcia_parse_tuple(handle, &tuple, &parse)
+               if (pcmcia_get_tuple_data(link, &tuple) != 0
+                               || pcmcia_parse_tuple(link, &tuple, &parse)
                                                != 0)
                        goto next_entry;
 
@@ -234,10 +216,10 @@ static void sl811_cs_config(dev_link_t *link)
                }
 
                if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                                cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
                else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp1 = link->conf.Vpp2 =
+                       link->conf.Vpp =
                                dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
 
                /* we need an interrupt */
@@ -254,15 +236,14 @@ static void sl811_cs_config(dev_link_t *link)
                        link->io.BasePort1 = io->win[0].base;
                        link->io.NumPorts1 = io->win[0].len;
 
-                       if (pcmcia_request_io(link->handle, &link->io) != 0)
+                       if (pcmcia_request_io(link, &link->io) != 0)
                                goto next_entry;
                }
                break;
 
 next_entry:
-               if (link->io.NumPorts1)
-                       pcmcia_release_io(link->handle, &link->io);
-               last_ret = pcmcia_get_next_tuple(handle, &tuple);
+               pcmcia_disable_device(link);
+               last_ret = pcmcia_get_next_tuple(link, &tuple);
        }
 
        /* require an IRQ and two registers */
@@ -270,71 +251,46 @@ next_entry:
                goto cs_failed;
        if (link->conf.Attributes & CONF_ENABLE_IRQ)
                CS_CHECK(RequestIRQ,
-                       pcmcia_request_irq(link->handle, &link->irq));
+                       pcmcia_request_irq(link, &link->irq));
        else
                goto cs_failed;
 
        CS_CHECK(RequestConfiguration,
-               pcmcia_request_configuration(link->handle, &link->conf));
+               pcmcia_request_configuration(link, &link->conf));
 
        sprintf(dev->node.dev_name, driver_name);
        dev->node.major = dev->node.minor = 0;
-       link->dev = &dev->node;
+       link->dev_node = &dev->node;
 
-       printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-              dev->node.dev_name, link->conf.ConfigIndex,
-              link->conf.Vcc/10, link->conf.Vcc%10);
-       if (link->conf.Vpp1)
-               printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+       printk(KERN_INFO "%s: index 0x%02x: ",
+              dev->node.dev_name, link->conf.ConfigIndex);
+       if (link->conf.Vpp)
+               printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
        printk(", irq %d", link->irq.AssignedIRQ);
        printk(", io 0x%04x-0x%04x", link->io.BasePort1,
               link->io.BasePort1+link->io.NumPorts1-1);
        printk("\n");
 
-       link->state &= ~DEV_CONFIG_PENDING;
-
        if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
                        < 0) {
 cs_failed:
                printk("sl811_cs_config failed\n");
-               cs_error(link->handle, last_fn, last_ret);
+               cs_error(link, last_fn, last_ret);
                sl811_cs_release(link);
-               link->state &= ~DEV_CONFIG_PENDING;
+               return  -ENODEV;
        }
-}
-
-static int sl811_suspend(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
-       return 0;
-}
-
-static int sl811_resume(struct pcmcia_device *dev)
-{
-       dev_link_t *link = dev_to_instance(dev);
-
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
-
        return 0;
 }
 
-static int sl811_cs_attach(struct pcmcia_device *p_dev)
+static int sl811_cs_probe(struct pcmcia_device *link)
 {
        local_info_t *local;
-       dev_link_t *link;
 
        local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
        if (!local)
                return -ENOMEM;
        memset(local, 0, sizeof(local_info_t));
-       link = &local->link;
+       local->p_dev = link;
        link->priv = local;
 
        /* Initialize */
@@ -343,16 +299,9 @@ static int sl811_cs_attach(struct pcmcia_device *p_dev)
        link->irq.Handler = NULL;
 
        link->conf.Attributes = 0;
-       link->conf.Vcc = 33;
        link->conf.IntType = INT_MEMORY_AND_IO;
 
-       link->handle = p_dev;
-       p_dev->instance = link;
-
-       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       sl811_cs_config(link);
-
-       return 0;
+       return sl811_cs_config(link);
 }
 
 static struct pcmcia_device_id sl811_ids[] = {
@@ -366,11 +315,9 @@ static struct pcmcia_driver sl811_cs_driver = {
        .drv            = {
                .name   = (char *)driver_name,
        },
-       .probe          = sl811_cs_attach,
+       .probe          = sl811_cs_probe,
        .remove         = sl811_cs_detach,
        .id_table       = sl811_ids,
-       .suspend        = sl811_suspend,
-       .resume         = sl811_resume,
 };
 
 /*====================================================================*/
index cb0d80f..25bc85f 100644 (file)
@@ -510,7 +510,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                                case 0x025: map_key_clear(KEY_TV);              break;
                                case 0x026: map_key_clear(KEY_MENU);            break;
                                case 0x031: map_key_clear(KEY_AUDIO);           break;
-                               case 0x032: map_key_clear(KEY_SUBTITLE);        break;
+                               case 0x032: map_key_clear(KEY_TEXT);            break;
                                case 0x033: map_key_clear(KEY_LAST);            break;
                                case 0x047: map_key_clear(KEY_MP3);             break;
                                case 0x048: map_key_clear(KEY_DVD);             break;
index 22e9d69..f87c017 100644 (file)
@@ -904,18 +904,6 @@ config FB_MATROX_MULTIHEAD
          There is no need for enabling 'Matrox multihead support' if you have
          only one Matrox card in the box.
 
-config FB_RADEON_OLD
-       tristate "ATI Radeon display support (Old driver)"
-       depends on FB && PCI
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       select FB_MACMODES if PPC
-       help
-         Choose this option if you want to use an ATI Radeon graphics card as
-         a framebuffer device.  There are both PCI and AGP versions.  You
-         don't need to choose this to run the Radeon in plain VGA mode.
-
 config FB_RADEON
        tristate "ATI Radeon display support"
        depends on FB && PCI
index cb90218..23de3b2 100644 (file)
@@ -39,7 +39,6 @@ obj-$(CONFIG_FB_KYRO)             += kyro/
 obj-$(CONFIG_FB_SAVAGE)                  += savage/
 obj-$(CONFIG_FB_GEODE)           += geode/
 obj-$(CONFIG_FB_I810)             += vgastate.o
-obj-$(CONFIG_FB_RADEON_OLD)      += radeonfb.o
 obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o vgastate.o
 obj-$(CONFIG_FB_VIRGE)            += virgefb.o
 obj-$(CONFIG_FB_3DFX)             += tdfxfb.o
index 9d996f2..b895eaa 100644 (file)
@@ -43,11 +43,11 @@ config LCD_DEVICE
        default y
 
 config BACKLIGHT_CORGI
-       tristate "Sharp Corgi Backlight Driver (SL-C7xx Series)"
+       tristate "Sharp Corgi Backlight Driver (SL Series)"
        depends on BACKLIGHT_DEVICE && PXA_SHARPSL
        default y
        help
-         If you have a Sharp Zaurus SL-C7xx, say y to enable the
+         If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
          backlight driver.
 
 config BACKLIGHT_HP680
index 151fda8..334b1db 100644 (file)
 
 static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
 {
-       int rc;
+       int rc = -ENXIO;
        struct backlight_device *bd = to_backlight_device(cdev);
 
        down(&bd->sem);
-       if (likely(bd->props && bd->props->get_power))
-               rc = sprintf(buf, "%d\n", bd->props->get_power(bd));
-       else
-               rc = -ENXIO;
+       if (likely(bd->props))
+               rc = sprintf(buf, "%d\n", bd->props->power);
        up(&bd->sem);
 
        return rc;
@@ -31,7 +29,7 @@ static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
 
 static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count)
 {
-       int rc, power;
+       int rc = -ENXIO, power;
        char *endp;
        struct backlight_device *bd = to_backlight_device(cdev);
 
@@ -40,12 +38,13 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf,
                return -EINVAL;
 
        down(&bd->sem);
-       if (likely(bd->props && bd->props->set_power)) {
+       if (likely(bd->props)) {
                pr_debug("backlight: set power to %d\n", power);
-               bd->props->set_power(bd, power);
+               bd->props->power = power;
+               if (likely(bd->props->update_status))
+                       bd->props->update_status(bd);
                rc = count;
-       } else
-               rc = -ENXIO;
+       }
        up(&bd->sem);
 
        return rc;
@@ -53,14 +52,12 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf,
 
 static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf)
 {
-       int rc;
+       int rc = -ENXIO;
        struct backlight_device *bd = to_backlight_device(cdev);
 
        down(&bd->sem);
-       if (likely(bd->props && bd->props->get_brightness))
-               rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd));
-       else
-               rc = -ENXIO;
+       if (likely(bd->props))
+               rc = sprintf(buf, "%d\n", bd->props->brightness);
        up(&bd->sem);
 
        return rc;
@@ -68,7 +65,7 @@ static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf)
 
 static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count)
 {
-       int rc, brightness;
+       int rc = -ENXIO, brightness;
        char *endp;
        struct backlight_device *bd = to_backlight_device(cdev);
 
@@ -77,12 +74,18 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char
                return -EINVAL;
 
        down(&bd->sem);
-       if (likely(bd->props && bd->props->set_brightness)) {
-               pr_debug("backlight: set brightness to %d\n", brightness);
-               bd->props->set_brightness(bd, brightness);
-               rc = count;
-       } else
-               rc = -ENXIO;
+       if (likely(bd->props)) {
+               if (brightness > bd->props->max_brightness)
+                       rc = -EINVAL;
+               else {
+                       pr_debug("backlight: set brightness to %d\n",
+                                brightness);
+                       bd->props->brightness = brightness;
+                       if (likely(bd->props->update_status))
+                               bd->props->update_status(bd);
+                       rc = count;
+               }
+       }
        up(&bd->sem);
 
        return rc;
@@ -90,14 +93,26 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char
 
 static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf)
 {
-       int rc;
+       int rc = -ENXIO;
        struct backlight_device *bd = to_backlight_device(cdev);
 
        down(&bd->sem);
        if (likely(bd->props))
                rc = sprintf(buf, "%d\n", bd->props->max_brightness);
-       else
-               rc = -ENXIO;
+       up(&bd->sem);
+
+       return rc;
+}
+
+static ssize_t backlight_show_actual_brightness(struct class_device *cdev,
+                                               char *buf)
+{
+       int rc = -ENXIO;
+       struct backlight_device *bd = to_backlight_device(cdev);
+
+       down(&bd->sem);
+       if (likely(bd->props && bd->props->get_brightness))
+               rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd));
        up(&bd->sem);
 
        return rc;
@@ -123,7 +138,10 @@ static struct class backlight_class = {
 
 static struct class_device_attribute bl_class_device_attributes[] = {
        DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power),
-       DECLARE_ATTR(brightness, 0644, backlight_show_brightness, backlight_store_brightness),
+       DECLARE_ATTR(brightness, 0644, backlight_show_brightness,
+                    backlight_store_brightness),
+       DECLARE_ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
+                    NULL),
        DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
 };
 
@@ -144,8 +162,12 @@ static int fb_notifier_callback(struct notifier_block *self,
        bd = container_of(self, struct backlight_device, fb_notif);
        down(&bd->sem);
        if (bd->props)
-               if (!bd->props->check_fb || bd->props->check_fb(evdata->info))
-                       bd->props->set_power(bd, *(int *)evdata->data);
+               if (!bd->props->check_fb ||
+                   bd->props->check_fb(evdata->info)) {
+                       bd->props->fb_blank = *(int *)evdata->data;
+                       if (likely(bd->props && bd->props->update_status))
+                               bd->props->update_status(bd);
+               }
        up(&bd->sem);
        return 0;
 }
@@ -231,6 +253,12 @@ void backlight_device_unregister(struct backlight_device *bd)
                                         &bl_class_device_attributes[i]);
 
        down(&bd->sem);
+       if (likely(bd->props && bd->props->update_status)) {
+               bd->props->brightness = 0;
+               bd->props->power = 0;
+               bd->props->update_status(bd);
+       }
+
        bd->props = NULL;
        up(&bd->sem);
 
index d0aaf45..2ebbfd9 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  Backlight Driver for Sharp Corgi
+ *  Backlight Driver for Sharp Zaurus Handhelds (various models)
  *
- *  Copyright (c) 2004-2005 Richard Purdie
+ *  Copyright (c) 2004-2006 Richard Purdie
  *
  *  Based on Sharp's 2.4 Backlight Driver
  *
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/fb.h>
 #include <linux/backlight.h>
-
 #include <asm/arch/sharpsl.h>
 #include <asm/hardware/sharpsl_pm.h>
 
-#define CORGI_DEFAULT_INTENSITY                0x1f
-#define CORGI_LIMIT_MASK               0x0b
-
-static int corgibl_powermode = FB_BLANK_UNBLANK;
-static int current_intensity = 0;
-static int corgibl_limit = 0;
-static void (*corgibl_mach_set_intensity)(int intensity);
-static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+static int corgibl_intensity;
+static DEFINE_MUTEX(bl_mutex);
 static struct backlight_properties corgibl_data;
+static struct backlight_device *corgi_backlight_device;
+static struct corgibl_machinfo *bl_machinfo;
 
-static void corgibl_send_intensity(int intensity)
+static unsigned long corgibl_flags;
+#define CORGIBL_SUSPENDED     0x01
+#define CORGIBL_BATTLOW       0x02
+
+static int corgibl_send_intensity(struct backlight_device *bd)
 {
-       unsigned long flags;
        void (*corgi_kick_batt)(void);
+       int intensity = bd->props->brightness;
 
-       if (corgibl_powermode != FB_BLANK_UNBLANK) {
+       if (bd->props->power != FB_BLANK_UNBLANK)
                intensity = 0;
-       } else {
-               if (corgibl_limit)
-                       intensity &= CORGI_LIMIT_MASK;
-       }
-
-       spin_lock_irqsave(&bl_lock, flags);
+       if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+               intensity = 0;
+       if (corgibl_flags & CORGIBL_SUSPENDED)
+               intensity = 0;
+       if (corgibl_flags & CORGIBL_BATTLOW)
+               intensity &= bl_machinfo->limit_mask;
 
-       corgibl_mach_set_intensity(intensity);
+       mutex_lock(&bl_mutex);
+       bl_machinfo->set_bl_intensity(intensity);
+       mutex_unlock(&bl_mutex);
 
-       spin_unlock_irqrestore(&bl_lock, flags);
+       corgibl_intensity = intensity;
 
        corgi_kick_batt = symbol_get(sharpsl_battery_kick);
        if (corgi_kick_batt) {
                corgi_kick_batt();
                symbol_put(sharpsl_battery_kick);
        }
-}
 
-static void corgibl_blank(int blank)
-{
-       switch(blank) {
-
-       case FB_BLANK_NORMAL:
-       case FB_BLANK_VSYNC_SUSPEND:
-       case FB_BLANK_HSYNC_SUSPEND:
-       case FB_BLANK_POWERDOWN:
-               if (corgibl_powermode == FB_BLANK_UNBLANK) {
-                       corgibl_send_intensity(0);
-                       corgibl_powermode = blank;
-               }
-               break;
-       case FB_BLANK_UNBLANK:
-               if (corgibl_powermode != FB_BLANK_UNBLANK) {
-                       corgibl_powermode = blank;
-                       corgibl_send_intensity(current_intensity);
-               }
-               break;
-       }
+       return 0;
 }
 
 #ifdef CONFIG_PM
 static int corgibl_suspend(struct platform_device *dev, pm_message_t state)
 {
-       corgibl_blank(FB_BLANK_POWERDOWN);
+       corgibl_flags |= CORGIBL_SUSPENDED;
+       corgibl_send_intensity(corgi_backlight_device);
        return 0;
 }
 
 static int corgibl_resume(struct platform_device *dev)
 {
-       corgibl_blank(FB_BLANK_UNBLANK);
+       corgibl_flags &= ~CORGIBL_SUSPENDED;
+       corgibl_send_intensity(corgi_backlight_device);
        return 0;
 }
 #else
@@ -96,68 +79,55 @@ static int corgibl_resume(struct platform_device *dev)
 #define corgibl_resume NULL
 #endif
 
-
-static int corgibl_set_power(struct backlight_device *bd, int state)
-{
-       corgibl_blank(state);
-       return 0;
-}
-
-static int corgibl_get_power(struct backlight_device *bd)
+static int corgibl_get_intensity(struct backlight_device *bd)
 {
-       return corgibl_powermode;
+       return corgibl_intensity;
 }
 
-static int corgibl_set_intensity(struct backlight_device *bd, int intensity)
+static int corgibl_set_intensity(struct backlight_device *bd)
 {
-       if (intensity > corgibl_data.max_brightness)
-               intensity = corgibl_data.max_brightness;
-       corgibl_send_intensity(intensity);
-       current_intensity=intensity;
+       corgibl_send_intensity(corgi_backlight_device);
        return 0;
 }
 
-static int corgibl_get_intensity(struct backlight_device *bd)
-{
-       return current_intensity;
-}
-
 /*
  * Called when the battery is low to limit the backlight intensity.
  * If limit==0 clear any limit, otherwise limit the intensity
  */
 void corgibl_limit_intensity(int limit)
 {
-       corgibl_limit = (limit ? 1 : 0);
-       corgibl_send_intensity(current_intensity);
+       if (limit)
+               corgibl_flags |= CORGIBL_BATTLOW;
+       else
+               corgibl_flags &= ~CORGIBL_BATTLOW;
+       corgibl_send_intensity(corgi_backlight_device);
 }
 EXPORT_SYMBOL(corgibl_limit_intensity);
 
 
 static struct backlight_properties corgibl_data = {
-       .owner          = THIS_MODULE,
-       .get_power      = corgibl_get_power,
-       .set_power      = corgibl_set_power,
+       .owner          = THIS_MODULE,
        .get_brightness = corgibl_get_intensity,
-       .set_brightness = corgibl_set_intensity,
+       .update_status  = corgibl_set_intensity,
 };
 
-static struct backlight_device *corgi_backlight_device;
-
 static int __init corgibl_probe(struct platform_device *pdev)
 {
        struct corgibl_machinfo *machinfo = pdev->dev.platform_data;
 
+       bl_machinfo = machinfo;
        corgibl_data.max_brightness = machinfo->max_intensity;
-       corgibl_mach_set_intensity = machinfo->set_bl_intensity;
+       if (!machinfo->limit_mask)
+               machinfo->limit_mask = -1;
 
        corgi_backlight_device = backlight_device_register ("corgi-bl",
                NULL, &corgibl_data);
        if (IS_ERR (corgi_backlight_device))
                return PTR_ERR (corgi_backlight_device);
 
-       corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY);
-       corgibl_limit_intensity(0);
+       corgibl_data.power = FB_BLANK_UNBLANK;
+       corgibl_data.brightness = machinfo->default_intensity;
+       corgibl_send_intensity(corgi_backlight_device);
 
        printk("Corgi Backlight Driver Initialized.\n");
        return 0;
@@ -167,8 +137,6 @@ static int corgibl_remove(struct platform_device *dev)
 {
        backlight_device_unregister(corgi_backlight_device);
 
-       corgibl_set_intensity(NULL, 0);
-
        printk("Corgi Backlight Driver Unloaded\n");
        return 0;
 }
index 95da4c9..a71e984 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/fb.h>
 #include <linux/backlight.h>
 #define HP680_MAX_INTENSITY 255
 #define HP680_DEFAULT_INTENSITY 10
 
-static int hp680bl_powermode = FB_BLANK_UNBLANK;
+static int hp680bl_suspended;
 static int current_intensity = 0;
 static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+static struct backlight_device *hp680_backlight_device;
 
-static void hp680bl_send_intensity(int intensity)
+static void hp680bl_send_intensity(struct backlight_device *bd)
 {
        unsigned long flags;
+       u16 v;
+       int intensity = bd->props->brightness;
 
-       if (hp680bl_powermode != FB_BLANK_UNBLANK)
+       if (bd->props->power != FB_BLANK_UNBLANK)
+               intensity = 0;
+       if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+               intensity = 0;
+       if (hp680bl_suspended)
                intensity = 0;
 
        spin_lock_irqsave(&bl_lock, flags);
-       sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
+       if (intensity && current_intensity == 0) {
+               sh_dac_enable(DAC_LCD_BRIGHTNESS);
+               v = inw(HD64461_GPBDR);
+               v &= ~HD64461_GPBDR_LCDOFF;
+               outw(v, HD64461_GPBDR);
+               sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
+       } else if (intensity == 0 && current_intensity != 0) {
+               sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
+               sh_dac_disable(DAC_LCD_BRIGHTNESS);
+               v = inw(HD64461_GPBDR);
+               v |= HD64461_GPBDR_LCDOFF;
+               outw(v, HD64461_GPBDR);
+       } else if (intensity) {
+               sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
+       }
        spin_unlock_irqrestore(&bl_lock, flags);
-}
 
-static void hp680bl_blank(int blank)
-{
-       u16 v;
-
-       switch(blank) {
-
-       case FB_BLANK_NORMAL:
-       case FB_BLANK_VSYNC_SUSPEND:
-       case FB_BLANK_HSYNC_SUSPEND:
-       case FB_BLANK_POWERDOWN:
-               if (hp680bl_powermode == FB_BLANK_UNBLANK) {
-                       hp680bl_send_intensity(0);
-                       hp680bl_powermode = blank;
-                       sh_dac_disable(DAC_LCD_BRIGHTNESS);
-                       v = inw(HD64461_GPBDR);
-                       v |= HD64461_GPBDR_LCDOFF;
-                       outw(v, HD64461_GPBDR);
-               }
-               break;
-       case FB_BLANK_UNBLANK:
-               if (hp680bl_powermode != FB_BLANK_UNBLANK) {
-                       sh_dac_enable(DAC_LCD_BRIGHTNESS);
-                       v = inw(HD64461_GPBDR);
-                       v &= ~HD64461_GPBDR_LCDOFF;
-                       outw(v, HD64461_GPBDR);
-                       hp680bl_powermode = blank;
-                       hp680bl_send_intensity(current_intensity);
-               }
-               break;
-       }
+       current_intensity = intensity;
 }
 
+
 #ifdef CONFIG_PM
-static int hp680bl_suspend(struct device *dev, pm_message_t state, u32 level)
+static int hp680bl_suspend(struct platform_device *dev, pm_message_t state)
 {
-       if (level == SUSPEND_POWER_DOWN)
-               hp680bl_blank(FB_BLANK_POWERDOWN);
+       hp680bl_suspended = 1;
+       hp680bl_send_intensity(hp680_backlight_device);
        return 0;
 }
 
-static int hp680bl_resume(struct device *dev, u32 level)
+static int hp680bl_resume(struct platform_device *dev)
 {
-       if (level == RESUME_POWER_ON)
-               hp680bl_blank(FB_BLANK_UNBLANK);
+       hp680bl_suspended = 0;
+       hp680bl_send_intensity(hp680_backlight_device);
        return 0;
 }
 #else
@@ -92,24 +84,9 @@ static int hp680bl_resume(struct device *dev, u32 level)
 #define hp680bl_resume NULL
 #endif
 
-
-static int hp680bl_set_power(struct backlight_device *bd, int state)
+static int hp680bl_set_intensity(struct backlight_device *bd)
 {
-       hp680bl_blank(state);
-       return 0;
-}
-
-static int hp680bl_get_power(struct backlight_device *bd)
-{
-       return hp680bl_powermode;
-}
-
-static int hp680bl_set_intensity(struct backlight_device *bd, int intensity)
-{
-       if (intensity > HP680_MAX_INTENSITY)
-               intensity = HP680_MAX_INTENSITY;
-       hp680bl_send_intensity(intensity);
-       current_intensity = intensity;
+       hp680bl_send_intensity(bd);
        return 0;
 }
 
@@ -120,65 +97,67 @@ static int hp680bl_get_intensity(struct backlight_device *bd)
 
 static struct backlight_properties hp680bl_data = {
        .owner          = THIS_MODULE,
-       .get_power      = hp680bl_get_power,
-       .set_power      = hp680bl_set_power,
        .max_brightness = HP680_MAX_INTENSITY,
        .get_brightness = hp680bl_get_intensity,
-       .set_brightness = hp680bl_set_intensity,
+       .update_status  = hp680bl_set_intensity,
 };
 
-static struct backlight_device *hp680_backlight_device;
-
-static int __init hp680bl_probe(struct device *dev)
+static int __init hp680bl_probe(struct platform_device *dev)
 {
        hp680_backlight_device = backlight_device_register ("hp680-bl",
                NULL, &hp680bl_data);
        if (IS_ERR (hp680_backlight_device))
                return PTR_ERR (hp680_backlight_device);
 
-       hp680bl_set_intensity(NULL, HP680_DEFAULT_INTENSITY);
+       hp680_backlight_device->props->brightness = HP680_DEFAULT_INTENSITY;
+       hp680bl_send_intensity(hp680_backlight_device);
 
        return 0;
 }
 
-static int hp680bl_remove(struct device *dev)
+static int hp680bl_remove(struct platform_device *dev)
 {
        backlight_device_unregister(hp680_backlight_device);
 
        return 0;
 }
 
-static struct device_driver hp680bl_driver = {
-       .name           = "hp680-bl",
-       .bus            = &platform_bus_type,
+static struct platform_driver hp680bl_driver = {
        .probe          = hp680bl_probe,
        .remove         = hp680bl_remove,
        .suspend        = hp680bl_suspend,
        .resume         = hp680bl_resume,
+       .driver         = {
+               .name   = "hp680-bl",
+       },
 };
 
-static struct platform_device hp680bl_device = {
-       .name   = "hp680-bl",
-       .id     = -1,
-};
+static struct platform_device *hp680bl_device;
 
 static int __init hp680bl_init(void)
 {
        int ret;
 
-       ret=driver_register(&hp680bl_driver);
+       ret = platform_driver_register(&hp680bl_driver);
        if (!ret) {
-               ret = platform_device_register(&hp680bl_device);
-               if (ret)
-                       driver_unregister(&hp680bl_driver);
+               hp680bl_device = platform_device_alloc("hp680-bl", -1);
+               if (!hp680bl_device)
+                       return -ENOMEM;
+
+               ret = platform_device_add(hp680bl_device);
+
+               if (ret) {
+                       platform_device_put(hp680bl_device);
+                       platform_driver_unregister(&hp680bl_driver);
+               }
        }
        return ret;
 }
 
 static void __exit hp680bl_exit(void)
 {
-       platform_device_unregister(&hp680bl_device);
-       driver_unregister(&hp680bl_driver);
+       platform_device_unregister(hp680bl_device);
+       platform_driver_unregister(&hp680bl_driver);
 }
 
 module_init(hp680bl_init);
index 910e233..8ba6152 100644 (file)
@@ -169,7 +169,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
 
                while (j--) {
                        l--;
-                       color = (*s & 1 << (FB_BIT_NR(l))) ? fgcolor : bgcolor;
+                       color = (*s & (1 << l)) ? fgcolor : bgcolor;
                        val |= FB_SHIFT_HIGH(color, shift);
                        
                        /* Did the bitshift spill bits to the next long? */
index 041d069..ca02071 100644 (file)
@@ -466,7 +466,7 @@ static int __init fb_console_setup(char *this_opt)
        int i, j;
 
        if (!this_opt || !*this_opt)
-               return 0;
+               return 1;
 
        while ((options = strsep(&this_opt, ",")) != NULL) {
                if (!strncmp(options, "font:", 5))
@@ -481,10 +481,10 @@ static int __init fb_console_setup(char *this_opt)
                                        options++;
                                }
                                if (*options != ',')
-                                       return 0;
+                                       return 1;
                                options++;
                        } else
-                               return 0;
+                               return 1;
                }
                
                if (!strncmp(options, "map:", 4)) {
@@ -496,7 +496,7 @@ static int __init fb_console_setup(char *this_opt)
                                        con2fb_map_boot[i] =
                                                (options[j++]-'0') % FB_MAX;
                                }
-                       return 0;
+                       return 1;
                }
 
                if (!strncmp(options, "vc:", 3)) {
@@ -518,7 +518,7 @@ static int __init fb_console_setup(char *this_opt)
                                rotate = 0;
                }
        }
-       return 0;
+       return 1;
 }
 
 __setup("fbcon=", fb_console_setup);
@@ -1142,6 +1142,7 @@ static void fbcon_init(struct vc_data *vc, int init)
                set_blitting_type(vc, info);
        }
 
+       ops->p = &fb_display[fg_console];
 }
 
 static void fbcon_deinit(struct vc_data *vc)
index 0339f56..74ac2ac 100644 (file)
@@ -275,7 +275,7 @@ static int __init sti_setup(char *str)
        if (str)
                strlcpy (default_sti_path, str, sizeof (default_sti_path));
        
-       return 0;
+       return 1;
 }
 
 /*     Assuming the machine has multiple STI consoles (=graphic cards) which
@@ -321,7 +321,7 @@ static int __init sti_font_setup(char *str)
                i++;
        }
 
-       return 0;
+       return 1;
 }
 
 /*     The optional linux kernel parameter "sti_font" defines which font
@@ -373,7 +373,7 @@ sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request)
                glob_cfg->save_addr));
 
        /* dump extended cfg */ 
-       cfg = PTR_STI(glob_cfg->ext_ptr);
+       cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr);
        DPRINTK(( KERN_INFO
                "monitor %d\n"
                "in friendly mode: %d\n"
@@ -453,25 +453,11 @@ sti_init_glob_cfg(struct sti_struct *sti,
                sti->regions_phys[i] =
                        REGION_OFFSET_TO_PHYS(sti->regions[i], newhpa);
                
-               /* remap virtually */
-               /* FIXME: add BTLB support if btlb==1 */
                len = sti->regions[i].region_desc.length * 4096;
-
-/* XXX: Enabling IOREMAP debugging causes a crash, so we must be passing
- * a virtual address to something expecting a physical address that doesn't
- * go through a readX macro */
-#if 0
-               if (len)
-                  glob_cfg->region_ptrs[i] = (unsigned long) (
-                       sti->regions[i].region_desc.cache ?
-                       ioremap(sti->regions_phys[i], len) :
-                       ioremap_nocache(sti->regions_phys[i], len) );
-#else
                if (len)
                        glob_cfg->region_ptrs[i] = sti->regions_phys[i];
-#endif
                
-               DPRINTK(("region #%d: phys %08lx, virt %08x, len=%lukB, "
+               DPRINTK(("region #%d: phys %08lx, region_ptr %08x, len=%lukB, "
                         "btlb=%d, sysonly=%d, cache=%d, last=%d\n",
                        i, sti->regions_phys[i], glob_cfg->region_ptrs[i],
                        len/1024,
index b1a8dca..944855b 100644 (file)
@@ -1588,7 +1588,7 @@ static int __init video_setup(char *options)
                }
        }
 
-       return 0;
+       return 1;
 }
 __setup("video=", video_setup);
 #endif
index 53ad61f..809fc5e 100644 (file)
@@ -232,9 +232,9 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        if (var->yres < MIN_YRES)
                var->yres = MIN_YRES;
        if (var->xres > fbi->max_xres)
-               var->xres = fbi->max_xres;
+               return -EINVAL;
        if (var->yres > fbi->max_yres)
-               var->yres = fbi->max_yres;
+               return -EINVAL;
        var->xres_virtual =
                max(var->xres_virtual, var->xres);
        var->yres_virtual =
@@ -781,7 +781,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
        LCCR0 &= ~LCCR0_LDM;    /* Enable LCD Disable Done Interrupt */
        LCCR0 |= LCCR0_DIS;     /* Disable LCD Controller */
 
-       schedule_timeout(20 * HZ / 1000);
+       schedule_timeout(200 * HZ / 1000);
        remove_wait_queue(&fbi->ctrlr_wait, &wait);
 
        /* disable LCD controller clock */
@@ -1274,7 +1274,7 @@ int __init pxafb_probe(struct platform_device *dev)
        struct pxafb_mach_info *inf;
        int ret;
 
-       dev_dbg(dev, "pxafb_probe\n");
+       dev_dbg(&dev->dev, "pxafb_probe\n");
 
        inf = dev->dev.platform_data;
        ret = -ENOMEM;
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
deleted file mode 100644 (file)
index afb6c2e..0000000
+++ /dev/null
@@ -1,3167 +0,0 @@
-/*
- *     drivers/video/radeonfb.c
- *     framebuffer driver for ATI Radeon chipset video boards
- *
- *     Copyright 2000  Ani Joshi <ajoshi@kernel.crashing.org>
- *
- *
- *     ChangeLog:
- *     2000-08-03      initial version 0.0.1
- *     2000-09-10      more bug fixes, public release 0.0.5
- *     2001-02-19      mode bug fixes, 0.0.7
- *     2001-07-05      fixed scrolling issues, engine initialization,
- *                     and minor mode tweaking, 0.0.9
- *     2001-09-07      Radeon VE support, Nick Kurshev
- *                     blanking, pan_display, and cmap fixes, 0.1.0
- *     2001-10-10      Radeon 7500 and 8500 support, and experimental
- *                     flat panel support, 0.1.1
- *     2001-11-17      Radeon M6 (ppc) support, Daniel Berlin, 0.1.2
- *     2001-11-18      DFP fixes, Kevin Hendricks, 0.1.3
- *     2001-11-29      more cmap, backlight fixes, Benjamin Herrenschmidt
- *     2002-01-18      DFP panel detection via BIOS, Michael Clark, 0.1.4
- *     2002-06-02      console switching, mode set fixes, accel fixes
- *     2002-06-03      MTRR support, Peter Horton, 0.1.5
- *     2002-09-21      rv250, r300, m9 initial support,
- *                     added mirror option, 0.1.6
- *
- *     Special thanks to ATI DevRel team for their hardware donations.
- *
- */
-
-
-#define RADEON_VERSION "0.1.6"
-
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#if defined(__powerpc__)
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include "macmodes.h"
-
-#ifdef CONFIG_NVRAM
-#include <linux/nvram.h>
-#endif
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-
-#ifdef CONFIG_BOOTX_TEXT
-#include <asm/btext.h>
-#endif
-
-#ifdef CONFIG_ADB_PMU
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#endif
-
-#endif /* __powerpc__ */
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include <video/radeon.h>
-#include <linux/radeonfb.h>
-
-#define DEBUG  0
-
-#if DEBUG
-#define RTRACE         printk
-#else
-#define RTRACE         if(0) printk
-#endif
-
-// XXX
-#undef CONFIG_PMAC_PBOOK
-
-
-enum radeon_chips {
-       RADEON_QD,
-       RADEON_QE,
-       RADEON_QF,
-       RADEON_QG,
-       RADEON_QY,
-       RADEON_QZ,
-       RADEON_LW,
-       RADEON_LX,
-       RADEON_LY,
-       RADEON_LZ,
-       RADEON_QL,
-       RADEON_QN,
-       RADEON_QO,
-       RADEON_Ql,
-       RADEON_BB,
-       RADEON_QW,
-       RADEON_QX,
-       RADEON_Id,
-       RADEON_Ie,
-       RADEON_If,
-       RADEON_Ig,
-       RADEON_Ya,
-       RADEON_Yd,
-       RADEON_Ld,
-       RADEON_Le,
-       RADEON_Lf,
-       RADEON_Lg,
-       RADEON_ND,
-       RADEON_NE,
-       RADEON_NF,
-       RADEON_NG,
-       RADEON_QM
-};
-
-enum radeon_arch {
-       RADEON_R100,
-       RADEON_RV100,
-       RADEON_R200,
-       RADEON_RV200,
-       RADEON_RV250,
-       RADEON_R300,
-       RADEON_M6,
-       RADEON_M7,
-       RADEON_M9
-};
-
-static struct radeon_chip_info {
-       const char *name;
-       unsigned char arch;
-} radeon_chip_info[] __devinitdata = {
-       { "QD", RADEON_R100 },
-       { "QE", RADEON_R100 },
-       { "QF", RADEON_R100 },
-       { "QG", RADEON_R100 },
-       { "VE QY", RADEON_RV100 },
-       { "VE QZ", RADEON_RV100 },
-       { "M7 LW", RADEON_M7 },
-       { "M7 LX", RADEON_M7 },
-       { "M6 LY", RADEON_M6 },
-       { "M6 LZ", RADEON_M6 },
-       { "8500 QL", RADEON_R200 },
-       { "8500 QN", RADEON_R200 },
-       { "8500 QO", RADEON_R200 },
-       { "8500 Ql", RADEON_R200 },
-       { "8500 BB", RADEON_R200 },
-       { "7500 QW", RADEON_RV200 },
-       { "7500 QX", RADEON_RV200 },
-       { "9000 Id", RADEON_RV250 },
-       { "9000 Ie", RADEON_RV250 },
-       { "9000 If", RADEON_RV250 },
-       { "9000 Ig", RADEON_RV250 },
-       { "M9 Ld", RADEON_M9 },
-       { "M9 Le", RADEON_M9 },
-       { "M9 Lf", RADEON_M9 },
-       { "M9 Lg", RADEON_M9 },
-       { "9700 ND", RADEON_R300 },
-       { "9700 NE", RADEON_R300 },
-       { "9700 NF", RADEON_R300 },
-       { "9700 NG", RADEON_R300 },
-       { "9100 QM", RADEON_R200 }
-};
-
-
-enum radeon_montype
-{
-       MT_NONE,
-       MT_CRT,         /* CRT */
-       MT_LCD,         /* LCD */
-       MT_DFP,         /* DVI */
-       MT_CTV,         /* composite TV */
-       MT_STV          /* S-Video out */
-};
-
-
-static struct pci_device_id radeonfb_pci_table[] = {
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QD},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QE},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QF},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QG},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QY},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QZ},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LW},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LX},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LY},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LZ},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QL},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QN, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QN},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QO},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ql, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ql},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_BB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_BB},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QW},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QX},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Id},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ie, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ie},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_If, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_If},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ig, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ig},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ya, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ya},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Yd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Yd},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ld, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ld},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Le, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Le},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lf, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Lf},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lg, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Lg},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_ND, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_ND},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NE},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NF},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NG},
-       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QM},
-       { 0, }
-};
-MODULE_DEVICE_TABLE(pci, radeonfb_pci_table);
-
-
-typedef struct {
-       u16 reg;
-       u32 val;
-} reg_val;
-
-
-/* these common regs are cleared before mode setting so they do not
- * interfere with anything
- */
-static reg_val common_regs[] = {
-       { OVR_CLR, 0 }, 
-       { OVR_WID_LEFT_RIGHT, 0 },
-       { OVR_WID_TOP_BOTTOM, 0 },
-       { OV0_SCALE_CNTL, 0 },
-       { SUBPIC_CNTL, 0 },
-       { VIPH_CONTROL, 0 },
-       { I2C_CNTL_1, 0 },
-       { GEN_INT_CNTL, 0 },
-       { CAP0_TRIG_CNTL, 0 },
-};
-
-static reg_val common_regs_m6[] = {
-       { OVR_CLR,      0 },
-       { OVR_WID_LEFT_RIGHT,   0 },
-       { OVR_WID_TOP_BOTTOM,   0 },
-       { OV0_SCALE_CNTL,   0 },
-       { SUBPIC_CNTL,      0 },
-       { GEN_INT_CNTL,     0 },
-       { CAP0_TRIG_CNTL,   0 } 
-};
-
-typedef struct {
-        u8 clock_chip_type;
-        u8 struct_size;
-        u8 accelerator_entry;
-        u8 VGA_entry;
-        u16 VGA_table_offset;
-        u16 POST_table_offset;
-        u16 XCLK;
-        u16 MCLK;
-        u8 num_PLL_blocks;
-        u8 size_PLL_blocks;
-        u16 PCLK_ref_freq;
-        u16 PCLK_ref_divider;
-        u32 PCLK_min_freq;
-        u32 PCLK_max_freq;
-        u16 MCLK_ref_freq;
-        u16 MCLK_ref_divider;
-        u32 MCLK_min_freq;
-        u32 MCLK_max_freq;
-        u16 XCLK_ref_freq;
-        u16 XCLK_ref_divider;
-        u32 XCLK_min_freq;
-        u32 XCLK_max_freq;
-} __attribute__ ((packed)) PLL_BLOCK;
-
-
-struct pll_info {
-       int ppll_max;
-       int ppll_min;
-       int xclk;
-       int ref_div;
-       int ref_clk;
-};
-
-
-struct ram_info {
-       int ml;
-       int mb;
-       int trcd;
-       int trp;
-       int twr;
-       int cl;
-       int tr2w;
-       int loop_latency;
-       int rloop;
-};
-
-
-struct radeon_regs {
-       /* CRTC regs */
-       u32 crtc_h_total_disp;
-       u32 crtc_h_sync_strt_wid;
-       u32 crtc_v_total_disp;
-       u32 crtc_v_sync_strt_wid;
-       u32 crtc_pitch;
-       u32 crtc_gen_cntl;
-       u32 crtc_ext_cntl;
-       u32 dac_cntl;
-
-       u32 flags;
-       u32 pix_clock;
-       int xres, yres;
-
-       /* DDA regs */
-       u32 dda_config;
-       u32 dda_on_off;
-
-       /* PLL regs */
-       u32 ppll_div_3;
-       u32 ppll_ref_div;
-       u32 vclk_ecp_cntl;
-       
-       /* Flat panel regs */
-       u32 fp_crtc_h_total_disp;
-       u32 fp_crtc_v_total_disp;
-       u32 fp_gen_cntl;
-       u32 fp_h_sync_strt_wid;
-       u32 fp_horz_stretch;
-       u32 fp_panel_cntl;
-       u32 fp_v_sync_strt_wid;
-       u32 fp_vert_stretch;
-       u32 lvds_gen_cntl;
-       u32 lvds_pll_cntl;
-       u32 tmds_crc;
-       u32 tmds_transmitter_cntl;
-
-#if defined(__BIG_ENDIAN)
-       u32 surface_cntl;
-#endif
-};
-
-
-struct radeonfb_info {
-       struct fb_info info;
-
-       struct radeon_regs state;
-       struct radeon_regs init_state;
-
-       char name[32];
-       char ram_type[12];
-
-       unsigned long mmio_base_phys;
-       unsigned long fb_base_phys;
-
-       void __iomem *mmio_base;
-       void __iomem *fb_base;
-
-       struct pci_dev *pdev;
-
-       unsigned char *EDID;
-       unsigned char __iomem *bios_seg;
-
-       u32 pseudo_palette[17];
-       struct { u8 red, green, blue, pad; } palette[256];
-
-       int chipset;
-       unsigned char arch;
-       int video_ram;
-       u8 rev;
-       int pitch, bpp, depth;
-       int xres, yres, pixclock;
-       int xres_virtual, yres_virtual;
-       u32 accel_flags;
-
-       int use_default_var;
-       int got_dfpinfo;
-
-       int hasCRTC2;
-       int crtDisp_type;
-       int dviDisp_type;
-
-       int panel_xres, panel_yres;
-       int clock;
-       int hOver_plus, hSync_width, hblank;
-       int vOver_plus, vSync_width, vblank;
-       int hAct_high, vAct_high, interlaced;
-       int synct, misc;
-
-       u32 dp_gui_master_cntl;
-
-       struct pll_info pll;
-       int pll_output_freq, post_div, fb_div;
-
-       struct ram_info ram;
-
-       int mtrr_hdl;
-
-#ifdef CONFIG_PMAC_PBOOK
-       int pm_reg;
-       u32 save_regs[64];
-       u32 mdll, mdll2;
-#endif /* CONFIG_PMAC_PBOOK */
-       int asleep;
-       
-       struct radeonfb_info *next;
-};
-
-
-static struct fb_var_screeninfo radeonfb_default_var = {
-        640, 480, 640, 480, 0, 0, 8, 0,
-        {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
-        0, 0, -1, -1, 0, 39721, 40, 24, 32, 11, 96, 2,
-        0, FB_VMODE_NONINTERLACED
-};
-
-/*
- * IO macros
- */
-
-#define INREG8(addr)           readb((rinfo->mmio_base)+addr)
-#define OUTREG8(addr,val)      writeb(val, (rinfo->mmio_base)+addr)
-#define INREG(addr)            readl((rinfo->mmio_base)+addr)
-#define OUTREG(addr,val)       writel(val, (rinfo->mmio_base)+addr)
-
-#define OUTPLL(addr,val)       \
-       do {    \
-               OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080); \
-               OUTREG(CLOCK_CNTL_DATA, val); \
-       } while(0)
-
-#define OUTPLLP(addr,val,mask)                                         \
-       do {                                                            \
-               unsigned int _tmp = INPLL(addr);                        \
-               _tmp &= (mask);                                         \
-               _tmp |= (val);                                          \
-               OUTPLL(addr, _tmp);                                     \
-       } while (0)
-
-#define OUTREGP(addr,val,mask)                                         \
-       do {                                                            \
-               unsigned int _tmp = INREG(addr);                        \
-               _tmp &= (mask);                                         \
-               _tmp |= (val);                                          \
-               OUTREG(addr, _tmp);                                     \
-       } while (0)
-
-
-static __inline__ u32 _INPLL(struct radeonfb_info *rinfo, u32 addr)
-{
-       OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
-       return (INREG(CLOCK_CNTL_DATA));
-}
-
-#define INPLL(addr)            _INPLL(rinfo, addr)
-
-#define PRIMARY_MONITOR(rinfo) ((rinfo->dviDisp_type != MT_NONE) &&    \
-                                (rinfo->dviDisp_type != MT_STV) &&     \
-                                (rinfo->dviDisp_type != MT_CTV) ?      \
-                                rinfo->dviDisp_type : rinfo->crtDisp_type)
-
-static char *GET_MON_NAME(int type)
-{
-       char *pret = NULL;
-
-       switch (type) {
-               case MT_NONE:
-                       pret = "no";
-                       break;
-               case MT_CRT:
-                       pret = "CRT";
-                       break;
-               case MT_DFP:
-                       pret = "DFP";
-                       break;
-               case MT_LCD:
-                       pret = "LCD";
-                       break;
-               case MT_CTV:
-                       pret = "CTV";
-                       break;
-               case MT_STV:
-                       pret = "STV";
-                       break;
-       }
-
-       return pret;
-}
-
-
-/*
- * 2D engine routines
- */
-
-static __inline__ void radeon_engine_flush (struct radeonfb_info *rinfo)
-{
-       int i;
-
-       /* initiate flush */
-       OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
-               ~RB2D_DC_FLUSH_ALL);
-
-       for (i=0; i < 2000000; i++) {
-               if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
-                       break;
-       }
-}
-
-
-static __inline__ void _radeon_fifo_wait (struct radeonfb_info *rinfo, int entries)
-{
-       int i;
-
-       for (i=0; i<2000000; i++)
-               if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
-                       return;
-}
-
-
-static __inline__ void _radeon_engine_idle (struct radeonfb_info *rinfo)
-{
-       int i;
-
-       /* ensure FIFO is empty before waiting for idle */
-       _radeon_fifo_wait (rinfo, 64);
-
-       for (i=0; i<2000000; i++) {
-               if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
-                       radeon_engine_flush (rinfo);
-                       return;
-               }
-       }
-}
-
-
-#define radeon_engine_idle()           _radeon_engine_idle(rinfo)
-#define radeon_fifo_wait(entries)      _radeon_fifo_wait(rinfo,entries)
-
-
-
-/*
- * helper routines
- */
-
-static __inline__ u32 radeon_get_dstbpp(u16 depth)
-{
-       switch (depth) {
-               case 8:
-                       return DST_8BPP;
-               case 15:
-                       return DST_15BPP;
-               case 16:
-                       return DST_16BPP;
-               case 32:
-                       return DST_32BPP;
-               default:
-                       return 0;
-       }
-}
-
-
-static inline int var_to_depth(const struct fb_var_screeninfo *var)
-{
-       if (var->bits_per_pixel != 16)
-               return var->bits_per_pixel;
-       return (var->green.length == 6) ? 16 : 15;
-}
-
-
-static void _radeon_engine_reset(struct radeonfb_info *rinfo)
-{
-       u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
-
-       radeon_engine_flush (rinfo);
-
-       clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
-       mclk_cntl = INPLL(MCLK_CNTL);
-
-       OUTPLL(MCLK_CNTL, (mclk_cntl |
-                          FORCEON_MCLKA |
-                          FORCEON_MCLKB |
-                          FORCEON_YCLKA |
-                          FORCEON_YCLKB |
-                          FORCEON_MC |
-                          FORCEON_AIC));
-       rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
-
-       OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
-                               SOFT_RESET_CP |
-                               SOFT_RESET_HI |
-                               SOFT_RESET_SE |
-                               SOFT_RESET_RE |
-                               SOFT_RESET_PP |
-                               SOFT_RESET_E2 |
-                               SOFT_RESET_RB);
-       INREG(RBBM_SOFT_RESET);
-       OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32)
-                               ~(SOFT_RESET_CP |
-                                 SOFT_RESET_HI |
-                                 SOFT_RESET_SE |
-                                 SOFT_RESET_RE |
-                                 SOFT_RESET_PP |
-                                 SOFT_RESET_E2 |
-                                 SOFT_RESET_RB));
-       INREG(RBBM_SOFT_RESET);
-
-       OUTPLL(MCLK_CNTL, mclk_cntl);
-       OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
-       OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
-
-       return;
-}
-
-#define radeon_engine_reset()          _radeon_engine_reset(rinfo)
-
-
-static __inline__ int round_div(int num, int den)
-{
-        return (num + (den / 2)) / den;
-}
-
-
-
-static __inline__ int min_bits_req(int val)
-{
-        int bits_req = 0;
-                
-        if (val == 0)
-                bits_req = 1;
-                        
-        while (val) {
-                val >>= 1;
-                bits_req++;
-        }       
-
-        return (bits_req);
-}
-
-
-static __inline__ int _max(int val1, int val2)
-{
-        if (val1 >= val2)
-                return val1;
-        else
-                return val2;
-}                       
-
-
-
-/*
- * globals
- */
-
-#ifndef MODULE
-static char *mode_option;
-#endif
-
-static char noaccel = 0;
-static char mirror = 0;
-static int panel_yres = 0;
-static char force_dfp = 0;
-static struct radeonfb_info *board_list = NULL;
-static char nomtrr = 0;
-
-/*
- * prototypes
- */
-
-static void radeon_save_state (struct radeonfb_info *rinfo,
-                               struct radeon_regs *save);
-static void radeon_engine_init (struct radeonfb_info *rinfo);
-static void radeon_write_mode (struct radeonfb_info *rinfo,
-                               struct radeon_regs *mode);
-static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo);
-static int __devinit radeon_init_disp (struct radeonfb_info *rinfo);
-static int radeon_init_disp_var (struct radeonfb_info *rinfo, struct fb_var_screeninfo *var);
-static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo);
-static void radeon_get_pllinfo(struct radeonfb_info *rinfo, void __iomem *bios_seg);
-static void radeon_get_moninfo (struct radeonfb_info *rinfo);
-static int radeon_get_dfpinfo (struct radeonfb_info *rinfo);
-static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo);
-static void radeon_get_EDID(struct radeonfb_info *rinfo);
-static int radeon_dfp_parse_EDID(struct radeonfb_info *rinfo);
-static void radeon_update_default_var(struct radeonfb_info *rinfo);
-
-#ifdef CONFIG_PPC_OF
-
-static int radeon_read_OF (struct radeonfb_info *rinfo);
-static int radeon_get_EDID_OF(struct radeonfb_info *rinfo);
-extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev);
-
-#ifdef CONFIG_PMAC_PBOOK
-int radeon_sleep_notify(struct pmu_sleep_notifier *self, int when);
-static struct pmu_sleep_notifier radeon_sleep_notifier = {
-       radeon_sleep_notify, SLEEP_LEVEL_VIDEO,
-};
-#endif /* CONFIG_PMAC_PBOOK */
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int radeon_set_backlight_enable(int on, int level, void *data);
-static int radeon_set_backlight_level(int level, void *data);
-static struct backlight_controller radeon_backlight_controller = {
-       radeon_set_backlight_enable,
-       radeon_set_backlight_level
-};
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-#endif /* CONFIG_PPC_OF */
-
-
-static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo)
-{       
-#if defined(__i386__)
-        u32  segstart;
-        char __iomem *rom_base;
-        char __iomem *rom;
-        int  stage;
-        int  i,j;       
-        char aty_rom_sig[] = "761295520";
-        char *radeon_sig[] = {
-          "RG6",
-          "RADEON"
-        };
-                                                
-        for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
-                        
-                stage = 1;
-                
-                rom_base = ioremap(segstart, 0x1000);
-
-                if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
-                        stage = 2;
-                
-                    
-                if (stage != 2) {
-                        iounmap(rom_base);
-                        continue;
-                }
-                                              
-                rom = rom_base;
-                     
-                for (i = 0; (i < 128 - strlen(aty_rom_sig)) && (stage != 3); i++) {
-                        if (aty_rom_sig[0] == *rom)
-                                if (strncmp(aty_rom_sig, rom,
-                                                strlen(aty_rom_sig)) == 0)
-                                        stage = 3;
-                        rom++;
-                }
-                if (stage != 3) {
-                        iounmap(rom_base);
-                        continue;
-                }
-                rom = rom_base;
-        
-                for (i = 0; (i < 512) && (stage != 4); i++) {
-                    for (j = 0; j < ARRAY_SIZE(radeon_sig); j++) {
-                        if (radeon_sig[j][0] == *rom)
-                                if (strncmp(radeon_sig[j], rom,
-                                            strlen(radeon_sig[j])) == 0) {
-                                              stage = 4;
-                                              break;
-                                            }
-                    }                           
-                        rom++;
-                }       
-                if (stage != 4) {
-                        iounmap(rom_base);
-                        continue;
-                }       
-                
-                return rom_base;
-        }
-#endif          
-        return NULL;
-}
-
-
-
-
-static void radeon_get_pllinfo(struct radeonfb_info *rinfo, void __iomem *bios_seg)
-{
-        void __iomem *bios_header;
-        void __iomem *header_ptr;
-        u16 bios_header_offset, pll_info_offset;
-        PLL_BLOCK pll;
-
-       if (bios_seg) {
-               bios_header = bios_seg + 0x48L;
-                       header_ptr  = bios_header;
-        
-               bios_header_offset = readw(header_ptr);
-               bios_header = bios_seg + bios_header_offset;
-               bios_header += 0x30;
-        
-               header_ptr = bios_header;
-               pll_info_offset = readw(header_ptr);
-               header_ptr = bios_seg + pll_info_offset;
-        
-               memcpy_fromio(&pll, header_ptr, 50);
-        
-               rinfo->pll.xclk = (u32)pll.XCLK;
-               rinfo->pll.ref_clk = (u32)pll.PCLK_ref_freq;
-               rinfo->pll.ref_div = (u32)pll.PCLK_ref_divider;
-               rinfo->pll.ppll_min = pll.PCLK_min_freq;
-               rinfo->pll.ppll_max = pll.PCLK_max_freq;
-
-               printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d from BIOS\n",
-                       rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk);
-       } else {
-#ifdef CONFIG_PPC_OF
-               if (radeon_read_OF(rinfo)) {
-                       unsigned int tmp, Nx, M, ref_div, xclk;
-
-                       tmp = INPLL(M_SPLL_REF_FB_DIV);
-                       ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
-
-                       Nx = (tmp & 0xff00) >> 8;
-                       M = (tmp & 0xff);
-                       xclk = ((((2 * Nx * rinfo->pll.ref_clk) + (M)) /
-                               (2 * M)));
-
-                       rinfo->pll.xclk = xclk;
-                       rinfo->pll.ref_div = ref_div;
-                       rinfo->pll.ppll_min = 12000;
-                       rinfo->pll.ppll_max = 35000;
-
-                       printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d from OF\n",
-                               rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk);
-
-                       return;
-               }
-#endif
-               /* no BIOS or BIOS not found, use defaults */
-               switch (rinfo->chipset) {
-                       case PCI_DEVICE_ID_ATI_RADEON_QW:
-                       case PCI_DEVICE_ID_ATI_RADEON_QX:
-                               rinfo->pll.ppll_max = 35000;
-                               rinfo->pll.ppll_min = 12000;
-                               rinfo->pll.xclk = 23000;
-                               rinfo->pll.ref_div = 12;
-                               rinfo->pll.ref_clk = 2700;
-                               break;
-                       case PCI_DEVICE_ID_ATI_RADEON_QL:
-                       case PCI_DEVICE_ID_ATI_RADEON_QN:
-                       case PCI_DEVICE_ID_ATI_RADEON_QO:
-                       case PCI_DEVICE_ID_ATI_RADEON_Ql:
-                       case PCI_DEVICE_ID_ATI_RADEON_BB:
-                               rinfo->pll.ppll_max = 35000;
-                               rinfo->pll.ppll_min = 12000;
-                               rinfo->pll.xclk = 27500;
-                               rinfo->pll.ref_div = 12;
-                               rinfo->pll.ref_clk = 2700;
-                               break;
-                       case PCI_DEVICE_ID_ATI_RADEON_Id:
-                       case PCI_DEVICE_ID_ATI_RADEON_Ie:
-                       case PCI_DEVICE_ID_ATI_RADEON_If:
-                       case PCI_DEVICE_ID_ATI_RADEON_Ig:
-                               rinfo->pll.ppll_max = 35000;
-                               rinfo->pll.ppll_min = 12000;
-                               rinfo->pll.xclk = 25000;
-                               rinfo->pll.ref_div = 12;
-                               rinfo->pll.ref_clk = 2700;
-                               break;
-                       case PCI_DEVICE_ID_ATI_RADEON_ND:
-                       case PCI_DEVICE_ID_ATI_RADEON_NE:
-                       case PCI_DEVICE_ID_ATI_RADEON_NF:
-                       case PCI_DEVICE_ID_ATI_RADEON_NG:
-                               rinfo->pll.ppll_max = 40000;
-                               rinfo->pll.ppll_min = 20000;
-                               rinfo->pll.xclk = 27000;
-                               rinfo->pll.ref_div = 12;
-                               rinfo->pll.ref_clk = 2700;
-                               break;
-                       case PCI_DEVICE_ID_ATI_RADEON_QD:
-                       case PCI_DEVICE_ID_ATI_RADEON_QE:
-                       case PCI_DEVICE_ID_ATI_RADEON_QF:
-                       case PCI_DEVICE_ID_ATI_RADEON_QG:
-                       default:
-                               rinfo->pll.ppll_max = 35000;
-                               rinfo->pll.ppll_min = 12000;
-                               rinfo->pll.xclk = 16600;
-                               rinfo->pll.ref_div = 67;
-                               rinfo->pll.ref_clk = 2700;
-                               break;
-               }
-
-               printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d defaults\n",
-                       rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk);
-       }
-}
-
-
-static void radeon_get_moninfo (struct radeonfb_info *rinfo)
-{
-       unsigned int tmp;
-
-       if (force_dfp) {
-               rinfo->dviDisp_type = MT_DFP;
-               return;
-       }
-
-       tmp = INREG(BIOS_4_SCRATCH);
-       printk(KERN_DEBUG "radeon_get_moninfo: bios 4 scratch = %x\n", tmp);
-       
-       if (rinfo->hasCRTC2) {
-               /* primary DVI port */
-               if (tmp & 0x08)
-                       rinfo->dviDisp_type = MT_DFP;
-               else if (tmp & 0x4)
-                       rinfo->dviDisp_type = MT_LCD;
-               else if (tmp & 0x200)
-                       rinfo->dviDisp_type = MT_CRT;
-               else if (tmp & 0x10)
-                       rinfo->dviDisp_type = MT_CTV;
-               else if (tmp & 0x20)
-                       rinfo->dviDisp_type = MT_STV;
-
-               /* secondary CRT port */
-               if (tmp & 0x2)
-                       rinfo->crtDisp_type = MT_CRT;
-               else if (tmp & 0x800)
-                       rinfo->crtDisp_type = MT_DFP;
-               else if (tmp & 0x400)
-                       rinfo->crtDisp_type = MT_LCD;
-               else if (tmp & 0x1000)
-                       rinfo->crtDisp_type = MT_CTV;
-               else if (tmp & 0x2000)
-                       rinfo->crtDisp_type = MT_STV;
-       } else {
-               rinfo->dviDisp_type = MT_NONE;
-
-               tmp = INREG(FP_GEN_CNTL);
-
-               if (tmp & FP_EN_TMDS)
-                       rinfo->crtDisp_type = MT_DFP;
-               else
-                       rinfo->crtDisp_type = MT_CRT;
-       }
-}
-
-
-
-static void radeon_get_EDID(struct radeonfb_info *rinfo)
-{
-#ifdef CONFIG_PPC_OF
-       if (!radeon_get_EDID_OF(rinfo))
-               RTRACE("radeonfb: could not retrieve EDID from OF\n");
-#else
-       /* XXX use other methods later */
-#endif
-}
-
-
-#ifdef CONFIG_PPC_OF
-static int radeon_get_EDID_OF(struct radeonfb_info *rinfo)
-{
-        struct device_node *dp;
-        unsigned char *pedid = NULL;
-        static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", NULL };
-        int i;  
-
-        dp = pci_device_to_OF_node(rinfo->pdev);
-        while (dp != NULL) {
-                for (i = 0; propnames[i] != NULL; ++i) {
-                        pedid = (unsigned char *)
-                                get_property(dp, propnames[i], NULL);
-                        if (pedid != NULL) {
-                                rinfo->EDID = pedid;
-                                return 1;
-                        }
-                }
-                dp = dp->child;
-        }
-        return 0;
-}
-#endif /* CONFIG_PPC_OF */
-
-
-static int radeon_dfp_parse_EDID(struct radeonfb_info *rinfo)
-{
-       unsigned char *block = rinfo->EDID;
-
-       if (!block)
-               return 0;
-
-       /* jump to the detailed timing block section */
-       block += 54;
-
-       rinfo->clock = (block[0] + (block[1] << 8));
-       rinfo->panel_xres = (block[2] + ((block[4] & 0xf0) << 4));
-       rinfo->hblank = (block[3] + ((block[4] & 0x0f) << 8));
-       rinfo->panel_yres = (block[5] + ((block[7] & 0xf0) << 4));
-       rinfo->vblank = (block[6] + ((block[7] & 0x0f) << 8));
-       rinfo->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2));
-       rinfo->hSync_width = (block[9] + ((block[11] & 0x30) << 4));
-       rinfo->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2));
-       rinfo->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4));
-       rinfo->interlaced = ((block[17] & 0x80) >> 7);
-       rinfo->synct = ((block[17] & 0x18) >> 3);
-       rinfo->misc = ((block[17] & 0x06) >> 1);
-       rinfo->hAct_high = rinfo->vAct_high = 0;
-       if (rinfo->synct == 3) {
-               if (rinfo->misc & 2)
-                       rinfo->hAct_high = 1;
-               if (rinfo->misc & 1)
-                       rinfo->vAct_high = 1;
-       }
-
-       printk("radeonfb: detected DFP panel size from EDID: %dx%d\n",
-               rinfo->panel_xres, rinfo->panel_yres);
-
-       rinfo->got_dfpinfo = 1;
-
-       return 1;
-}
-
-
-static void radeon_update_default_var(struct radeonfb_info *rinfo)
-{
-       struct fb_var_screeninfo *var = &radeonfb_default_var;
-
-       var->xres = rinfo->panel_xres;
-       var->yres = rinfo->panel_yres;
-       var->xres_virtual = rinfo->panel_xres;
-       var->yres_virtual = rinfo->panel_yres;
-       var->xoffset = var->yoffset = 0;
-       var->bits_per_pixel = 8;
-       var->pixclock = 100000000 / rinfo->clock;
-       var->left_margin = (rinfo->hblank - rinfo->hOver_plus - rinfo->hSync_width);
-       var->right_margin = rinfo->hOver_plus;
-       var->upper_margin = (rinfo->vblank - rinfo->vOver_plus - rinfo->vSync_width);
-       var->lower_margin = rinfo->vOver_plus;
-       var->hsync_len = rinfo->hSync_width;
-       var->vsync_len = rinfo->vSync_width;
-       var->sync = 0;
-       if (rinfo->synct == 3) {
-               if (rinfo->hAct_high)
-                       var->sync |= FB_SYNC_HOR_HIGH_ACT;
-               if (rinfo->vAct_high)
-                       var->sync |= FB_SYNC_VERT_HIGH_ACT;
-       }
-
-       var->vmode = 0;
-       if (rinfo->interlaced)
-               var->vmode |= FB_VMODE_INTERLACED;
-
-       rinfo->use_default_var = 1;
-}
-
-
-static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo)
-{
-       char __iomem *fpbiosstart, *tmp, *tmp0;
-       char stmp[30];
-       int i;
-
-       if (!rinfo->bios_seg)
-               return 0;
-
-       if (!(fpbiosstart = rinfo->bios_seg + readw(rinfo->bios_seg + 0x48))) {
-               printk("radeonfb: Failed to detect DFP panel info using BIOS\n");
-               return 0;
-       }
-
-       if (!(tmp = rinfo->bios_seg + readw(fpbiosstart + 0x40))) {
-               printk("radeonfb: Failed to detect DFP panel info using BIOS\n");
-               return 0;
-       }
-
-       for(i=0; i<24; i++)
-               stmp[i] = readb(tmp+i+1);
-       stmp[24] = 0;
-       printk("radeonfb: panel ID string: %s\n", stmp);
-       rinfo->panel_xres = readw(tmp + 25);
-       rinfo->panel_yres = readw(tmp + 27);
-       printk("radeonfb: detected DFP panel size from BIOS: %dx%d\n",
-               rinfo->panel_xres, rinfo->panel_yres);
-
-       for(i=0; i<32; i++) {
-               tmp0 = rinfo->bios_seg + readw(tmp+64+i*2);
-               if (tmp0 == 0)
-                       break;
-               if ((readw(tmp0) == rinfo->panel_xres) &&
-                   (readw(tmp0+2) == rinfo->panel_yres)) {
-                       rinfo->hblank = (readw(tmp0+17) - readw(tmp0+19)) * 8;
-                       rinfo->hOver_plus = ((readw(tmp0+21) - readw(tmp0+19) -1) * 8) & 0x7fff;
-                       rinfo->hSync_width = readb(tmp0+23) * 8;
-                       rinfo->vblank = readw(tmp0+24) - readw(tmp0+26);
-                       rinfo->vOver_plus = (readw(tmp0+28) & 0x7ff) - readw(tmp0+26);
-                       rinfo->vSync_width = (readw(tmp0+28) & 0xf800) >> 11;
-                       rinfo->clock = readw(tmp0+9);
-
-                       rinfo->got_dfpinfo = 1;
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-
-
-static int radeon_get_dfpinfo (struct radeonfb_info *rinfo)
-{
-       unsigned int tmp;
-       unsigned short a, b;
-
-       if (radeon_get_dfpinfo_BIOS(rinfo))
-               radeon_update_default_var(rinfo);
-
-       if (radeon_dfp_parse_EDID(rinfo))
-               radeon_update_default_var(rinfo);
-
-       if (!rinfo->got_dfpinfo) {
-               /*
-                * it seems all else has failed now and we
-                * resort to probing registers for our DFP info
-                */
-               if (panel_yres) {
-                       rinfo->panel_yres = panel_yres;
-               } else {
-                       tmp = INREG(FP_VERT_STRETCH);
-                       tmp &= 0x00fff000;
-                       rinfo->panel_yres = (unsigned short)(tmp >> 0x0c) + 1;
-               }
-
-               switch (rinfo->panel_yres) {
-                       case 480:
-                               rinfo->panel_xres = 640;
-                               break;
-                       case 600:
-                               rinfo->panel_xres = 800;
-                               break;
-                       case 768:
-#if defined(__powerpc__)
-                               if (rinfo->dviDisp_type == MT_LCD)
-                                       rinfo->panel_xres = 1152;
-                               else
-#endif
-                               rinfo->panel_xres = 1024;
-                               break;
-                       case 1024:
-                               rinfo->panel_xres = 1280;
-                               break;
-                       case 1050:
-                               rinfo->panel_xres = 1400;
-                               break;
-                       case 1200:
-                               rinfo->panel_xres = 1600;
-                               break;
-                       default:
-                               printk("radeonfb: Failed to detect DFP panel size\n");
-                               return 0;
-               }
-
-               printk("radeonfb: detected DFP panel size from registers: %dx%d\n",
-                       rinfo->panel_xres, rinfo->panel_yres);
-
-               tmp = INREG(FP_CRTC_H_TOTAL_DISP);
-               a = (tmp & FP_CRTC_H_TOTAL_MASK) + 4;
-               b = (tmp & 0x01ff0000) >> FP_CRTC_H_DISP_SHIFT;
-               rinfo->hblank = (a - b + 1) * 8;
-
-               tmp = INREG(FP_H_SYNC_STRT_WID);
-               rinfo->hOver_plus = (unsigned short) ((tmp & FP_H_SYNC_STRT_CHAR_MASK) >>
-                                       FP_H_SYNC_STRT_CHAR_SHIFT) - b - 1;
-               rinfo->hOver_plus *= 8;
-               rinfo->hSync_width = (unsigned short) ((tmp & FP_H_SYNC_WID_MASK) >>
-                                       FP_H_SYNC_WID_SHIFT);
-               rinfo->hSync_width *= 8;
-               tmp = INREG(FP_CRTC_V_TOTAL_DISP);
-               a = (tmp & FP_CRTC_V_TOTAL_MASK) + 1;
-               b = (tmp & FP_CRTC_V_DISP_MASK) >> FP_CRTC_V_DISP_SHIFT;
-               rinfo->vblank = a - b /* + 24 */ ;
-
-               tmp = INREG(FP_V_SYNC_STRT_WID);
-               rinfo->vOver_plus = (unsigned short) (tmp & FP_V_SYNC_STRT_MASK)
-                                       - b + 1;
-               rinfo->vSync_width = (unsigned short) ((tmp & FP_V_SYNC_WID_MASK) >>
-                                       FP_V_SYNC_WID_SHIFT);
-
-               return 1;
-       }
-
-       return 1;
-}
-
-
-#ifdef CONFIG_PPC_OF
-static int radeon_read_OF (struct radeonfb_info *rinfo)
-{
-       struct device_node *dp;
-       unsigned int *xtal;
-
-       dp = pci_device_to_OF_node(rinfo->pdev);
-
-       xtal = (unsigned int *) get_property(dp, "ATY,RefCLK", NULL);
-
-       rinfo->pll.ref_clk = *xtal / 10;
-
-       if (*xtal)
-               return 1;
-       else
-               return 0;
-}
-#endif 
-
-
-static void radeon_engine_init (struct radeonfb_info *rinfo)
-{
-       u32 temp;
-
-       /* disable 3D engine */
-       OUTREG(RB3D_CNTL, 0);
-
-       radeon_engine_reset ();
-
-       radeon_fifo_wait (1);
-       OUTREG(RB2D_DSTCACHE_MODE, 0);
-
-       radeon_fifo_wait (1);
-       temp = INREG(DEFAULT_PITCH_OFFSET);
-       OUTREG(DEFAULT_PITCH_OFFSET, ((temp & 0xc0000000) | 
-                                     (rinfo->pitch << 0x16)));
-
-       radeon_fifo_wait (1);
-       OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
-
-       radeon_fifo_wait (1);
-       OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
-                                        DEFAULT_SC_BOTTOM_MAX));
-
-       temp = radeon_get_dstbpp(rinfo->depth);
-       rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
-       radeon_fifo_wait (1);
-       OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
-                                   GMC_BRUSH_SOLID_COLOR |
-                                   GMC_SRC_DATATYPE_COLOR));
-
-       radeon_fifo_wait (7);
-
-       /* clear line drawing regs */
-       OUTREG(DST_LINE_START, 0);
-       OUTREG(DST_LINE_END, 0);
-
-       /* set brush color regs */
-       OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
-       OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
-
-       /* set source color regs */
-       OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
-       OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
-
-       /* default write mask */
-       OUTREG(DP_WRITE_MSK, 0xffffffff);
-
-       radeon_engine_idle ();
-}
-
-
-static int __devinit radeon_init_disp (struct radeonfb_info *rinfo)
-{
-        struct fb_info *info = &rinfo->info;
-       struct fb_var_screeninfo var;
-
-        var = radeonfb_default_var;
-        if ((radeon_init_disp_var(rinfo, &var)) < 0)
-                return -1;
-
-       rinfo->depth = var_to_depth(&var);
-       rinfo->bpp = var.bits_per_pixel;
-        
-       info->var = var;
-       fb_alloc_cmap(&info->cmap, 256, 0);
-
-       var.activate = FB_ACTIVATE_NOW;
-        return 0;
-}
-
-
-static int radeon_init_disp_var (struct radeonfb_info *rinfo,
-                                struct fb_var_screeninfo *var)
-{
-#ifndef MODULE
-        if (mode_option)
-                fb_find_mode (var, &rinfo->info, mode_option,
-                              NULL, 0, NULL, 8);
-        else
-#endif
-       if (rinfo->use_default_var)
-               /* We will use the modified default far */
-               *var = radeonfb_default_var;
-       else
-
-                fb_find_mode (var, &rinfo->info, "640x480-8@60",
-                              NULL, 0, NULL, 0);
-
-       if (noaccel)
-               var->accel_flags &= ~FB_ACCELF_TEXT;
-       else
-               var->accel_flags |= FB_ACCELF_TEXT;
-        return 0;
-}
-
-
-static int radeon_do_maximize(struct radeonfb_info *rinfo,
-                                struct fb_var_screeninfo *var,
-                                struct fb_var_screeninfo *v,
-                                int nom, int den)
-{
-        static struct {
-                int xres, yres;
-        } modes[] = {
-                {1600, 1280},
-                {1280, 1024},
-                {1024, 768},
-                {800, 600},
-                {640, 480},
-                {-1, -1}
-        };
-        int i;
-  
-        /* use highest possible virtual resolution */
-        if (v->xres_virtual == -1 && v->yres_virtual == -1) {
-                printk("radeonfb: using max available virtual resolution\n");
-                for (i=0; modes[i].xres != -1; i++) {
-                        if (modes[i].xres * nom / den * modes[i].yres <
-                            rinfo->video_ram / 2)
-                                break;
-                }
-                if (modes[i].xres == -1) {
-                        printk("radeonfb: could not find virtual resolution that fits into video memory!\n");
-                        return -EINVAL;
-                }
-                v->xres_virtual = modes[i].xres;  
-                v->yres_virtual = modes[i].yres;
-                
-                printk("radeonfb: virtual resolution set to max of %dx%d\n",
-                        v->xres_virtual, v->yres_virtual);
-        } else if (v->xres_virtual == -1) {
-                v->xres_virtual = (rinfo->video_ram * den /   
-                                (nom * v->yres_virtual * 2)) & ~15;
-        } else if (v->yres_virtual == -1) {
-                v->xres_virtual = (v->xres_virtual + 15) & ~15;
-                v->yres_virtual = rinfo->video_ram * den /
-                        (nom * v->xres_virtual *2);
-        } else {
-                if (v->xres_virtual * nom / den * v->yres_virtual >
-                        rinfo->video_ram) {
-                        return -EINVAL;
-                }
-        }
-                
-        if (v->xres_virtual * nom / den >= 8192) {
-                v->xres_virtual = 8192 * den / nom - 16;
-        }       
-        
-        if (v->xres_virtual < v->xres)
-                return -EINVAL;
-                
-        if (v->yres_virtual < v->yres)
-                return -EINVAL;
-                                
-        return 0;
-}
-
-
-static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
-{
-        struct radeonfb_info *rinfo = (struct radeonfb_info *) info->par;
-        struct fb_var_screeninfo v;
-        int nom, den;
-
-        memcpy (&v, var, sizeof (v));
-
-        switch (v.bits_per_pixel) {
-               case 0 ... 8:
-                       v.bits_per_pixel = 8;
-                       break;
-               case 9 ... 16:
-                       v.bits_per_pixel = 16;
-                       break;
-               case 17 ... 24:
-#if 0 /* Doesn't seem to work */
-                       v.bits_per_pixel = 24;
-                       break;
-#endif                 
-                       return -EINVAL;
-               case 25 ... 32:
-                       v.bits_per_pixel = 32;
-                       break;
-               default:
-                       return -EINVAL;
-       }
-
-       switch (var_to_depth(&v)) {
-                case 8:
-                        nom = den = 1;
-                        v.red.offset = v.green.offset = v.blue.offset = 0;
-                        v.red.length = v.green.length = v.blue.length = 8;
-                        v.transp.offset = v.transp.length = 0;
-                        break;
-               case 15:
-                       nom = 2;
-                       den = 1;
-                       v.red.offset = 10;
-                       v.green.offset = 5;
-                       v.blue.offset = 0;
-                       v.red.length = v.green.length = v.blue.length = 5;
-                       v.transp.offset = v.transp.length = 0;
-                       break;
-                case 16:
-                        nom = 2;
-                        den = 1;
-                        v.red.offset = 11;
-                        v.green.offset = 5;
-                        v.blue.offset = 0;
-                        v.red.length = 5;
-                        v.green.length = 6;
-                        v.blue.length = 5;
-                        v.transp.offset = v.transp.length = 0;
-                        break;                          
-                case 24:
-                        nom = 4;
-                        den = 1;
-                        v.red.offset = 16;
-                        v.green.offset = 8;
-                        v.blue.offset = 0;
-                        v.red.length = v.blue.length = v.green.length = 8;
-                        v.transp.offset = v.transp.length = 0;
-                        break;
-                case 32:
-                        nom = 4;
-                        den = 1;
-                        v.red.offset = 16;
-                        v.green.offset = 8;
-                        v.blue.offset = 0;
-                        v.red.length = v.blue.length = v.green.length = 8;
-                        v.transp.offset = 24;
-                        v.transp.length = 8;
-                        break;
-                default:
-                        printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n",
-                                var->xres, var->yres, var->bits_per_pixel);
-                        return -EINVAL;
-        }
-
-        if (radeon_do_maximize(rinfo, var, &v, nom, den) < 0)
-                return -EINVAL;  
-                
-        if (v.xoffset < 0)
-                v.xoffset = 0;
-        if (v.yoffset < 0)
-                v.yoffset = 0;
-         
-        if (v.xoffset > v.xres_virtual - v.xres)
-                v.xoffset = v.xres_virtual - v.xres - 1;
-                        
-        if (v.yoffset > v.yres_virtual - v.yres)
-                v.yoffset = v.yres_virtual - v.yres - 1;
-         
-        v.red.msb_right = v.green.msb_right = v.blue.msb_right =
-                          v.transp.offset = v.transp.length =
-                          v.transp.msb_right = 0;
-
-       if (noaccel)
-               v.accel_flags = 0;
-                       
-        memcpy(var, &v, sizeof(v));
-        
-        return 0;
-}
-
-
-static int radeonfb_pan_display (struct fb_var_screeninfo *var,
-                                 struct fb_info *info)
-{
-        struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
-
-        if ((var->xoffset + var->xres > var->xres_virtual)
-           || (var->yoffset + var->yres > var->yres_virtual))
-               return -EINVAL;
-                
-        if (rinfo->asleep)
-               return 0;
-
-        OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
-                            * var->bits_per_pixel / 8) & ~7);
-        return 0;
-}
-
-
-static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
-                           unsigned long arg)
-{
-        struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
-       unsigned int tmp;
-       u32 value = 0;
-       int rc;
-
-       switch (cmd) {
-               /*
-                * TODO:  set mirror accordingly for non-Mobility chipsets with 2 CRTC's
-                */
-               case FBIO_RADEON_SET_MIRROR:
-                       switch (rinfo->arch) {
-                               case RADEON_R100:
-                               case RADEON_RV100:
-                               case RADEON_R200:
-                               case RADEON_RV200:
-                               case RADEON_RV250:
-                               case RADEON_R300:
-                                       return -EINVAL;
-                               default:
-                                       /* RADEON M6, RADEON_M7, RADEON_M9 */
-                                       break;
-                       }
-
-                       rc = get_user(value, (__u32 __user *)arg);
-
-                       if (rc)
-                               return rc;
-
-                       if (value & 0x01) {
-                               tmp = INREG(LVDS_GEN_CNTL);
-
-                               tmp |= (LVDS_ON | LVDS_BLON);
-                       } else {
-                               tmp = INREG(LVDS_GEN_CNTL);
-
-                               tmp &= ~(LVDS_ON | LVDS_BLON);
-                       }
-
-                       OUTREG(LVDS_GEN_CNTL, tmp);
-
-                       if (value & 0x02) {
-                               tmp = INREG(CRTC_EXT_CNTL);
-                               tmp |= CRTC_CRT_ON;
-
-                               mirror = 1;
-                       } else {
-                               tmp = INREG(CRTC_EXT_CNTL);
-                               tmp &= ~CRTC_CRT_ON;
-
-                               mirror = 0;
-                       }
-
-                       OUTREG(CRTC_EXT_CNTL, tmp);
-
-                       break;
-               case FBIO_RADEON_GET_MIRROR:
-                       switch (rinfo->arch) {
-                               case RADEON_R100:
-                               case RADEON_RV100:
-                               case RADEON_R200:
-                               case RADEON_RV200:
-                               case RADEON_RV250:
-                               case RADEON_R300:
-                                       return -EINVAL;
-                               default:
-                                       /* RADEON M6, RADEON_M7, RADEON_M9 */
-                                       break;
-                       }
-
-                       tmp = INREG(LVDS_GEN_CNTL);
-                       if ((LVDS_ON | LVDS_BLON) & tmp)
-                               value |= 0x01;
-
-                       tmp = INREG(CRTC_EXT_CNTL);
-                       if (CRTC_CRT_ON & tmp)
-                               value |= 0x02;
-
-                       return put_user(value, (__u32 __user *)arg);
-               default:
-                       return -EINVAL;
-       }
-
-       return -EINVAL;
-}
-
-
-static int radeonfb_blank (int blank, struct fb_info *info)
-{
-        struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
-        u32 val = INREG(CRTC_EXT_CNTL);
-       u32 val2 = INREG(LVDS_GEN_CNTL);
-
-       if (rinfo->asleep)
-               return 0;
-               
-#ifdef CONFIG_PMAC_BACKLIGHT
-       if (rinfo->dviDisp_type == MT_LCD && machine_is(powermac)) {
-               set_backlight_enable(!blank);
-               return 0;
-       }
-#endif
-                        
-        /* reset it */
-        val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
-                 CRTC_VSYNC_DIS);
-       val2 &= ~(LVDS_DISPLAY_DIS);
-
-        switch (blank) {
-               case FB_BLANK_UNBLANK:
-               case FB_BLANK_NORMAL:
-                        break;
-                case FB_BLANK_VSYNC_SUSPEND:
-                        val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);
-                        break;
-                case FB_BLANK_HSYNC_SUSPEND:
-                        val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS);
-                        break;
-                case FB_BLANK_POWERDOWN:
-                        val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | 
-                                CRTC_HSYNC_DIS);
-                       val2 |= (LVDS_DISPLAY_DIS);
-                        break;
-        }
-
-       switch (rinfo->dviDisp_type) {
-               case MT_LCD:
-                       OUTREG(LVDS_GEN_CNTL, val2);
-                       break;
-               case MT_CRT:
-               default:
-                       OUTREG(CRTC_EXT_CNTL, val);
-                       break;
-       }
-
-       /* let fbcon do a soft blank for us */
-       return (blank == FB_BLANK_NORMAL) ? 1 : 0;
-}
-
-
-static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,
-                             unsigned blue, unsigned transp, struct fb_info *info)
-{
-        struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
-       u32 pindex, vclk_cntl;
-       unsigned int i;
-       
-       if (regno > 255)
-               return 1;
-
-       red >>= 8;
-       green >>= 8;
-       blue >>= 8;
-       rinfo->palette[regno].red = red;
-       rinfo->palette[regno].green = green;
-       rinfo->palette[regno].blue = blue;
-
-        /* default */
-        pindex = regno;
-
-        if (!rinfo->asleep) {
-               vclk_cntl = INPLL(VCLK_ECP_CNTL);
-               OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
-
-               if (rinfo->bpp == 16) {
-                       pindex = regno * 8;
-
-                       if (rinfo->depth == 16 && regno > 63)
-                               return 1;
-                       if (rinfo->depth == 15 && regno > 31)
-                               return 1;
-
-                       /* For 565, the green component is mixed one order below */
-                       if (rinfo->depth == 16) {
-                               OUTREG(PALETTE_INDEX, pindex>>1);
-                               OUTREG(PALETTE_DATA, (rinfo->palette[regno>>1].red << 16) |
-                                       (green << 8) | (rinfo->palette[regno>>1].blue));
-                               green = rinfo->palette[regno<<1].green;
-                       }
-               }
-
-               if (rinfo->depth != 16 || regno < 32) {
-                       OUTREG(PALETTE_INDEX, pindex);
-                       OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue);
-               }
-
-               OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
-       }
-       if (regno < 16) {
-               switch (rinfo->depth) {
-               case 15:
-                       ((u16 *) (info->pseudo_palette))[regno] =
-                           (regno << 10) | (regno << 5) | regno;
-                       break;
-               case 16:
-                       ((u16 *) (info->pseudo_palette))[regno] =
-                           (regno << 11) | (regno << 6) | regno;
-                       break;
-               case 24:
-                       ((u32 *) (info->pseudo_palette))[regno] =
-                           (regno << 16) | (regno << 8) | regno;
-                       break;
-               case 32:
-                       i = (regno << 8) | regno;
-                       ((u32 *) (info->pseudo_palette))[regno] =
-                           (i << 16) | i;
-                       break;
-               }
-        }
-       return 0;
-}
-
-
-
-static void radeon_save_state (struct radeonfb_info *rinfo,
-                               struct radeon_regs *save)
-{
-       /* CRTC regs */
-       save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
-       save->crtc_ext_cntl = INREG(CRTC_EXT_CNTL);
-       save->dac_cntl = INREG(DAC_CNTL);
-        save->crtc_h_total_disp = INREG(CRTC_H_TOTAL_DISP);
-        save->crtc_h_sync_strt_wid = INREG(CRTC_H_SYNC_STRT_WID);
-        save->crtc_v_total_disp = INREG(CRTC_V_TOTAL_DISP);
-        save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID);
-       save->crtc_pitch = INREG(CRTC_PITCH);
-#if defined(__BIG_ENDIAN)
-       save->surface_cntl = INREG(SURFACE_CNTL);
-#endif
-
-       /* FP regs */
-       save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP);
-       save->fp_crtc_v_total_disp = INREG(FP_CRTC_V_TOTAL_DISP);
-       save->fp_gen_cntl = INREG(FP_GEN_CNTL);
-       save->fp_h_sync_strt_wid = INREG(FP_H_SYNC_STRT_WID);
-       save->fp_horz_stretch = INREG(FP_HORZ_STRETCH);
-       save->fp_v_sync_strt_wid = INREG(FP_V_SYNC_STRT_WID);
-       save->fp_vert_stretch = INREG(FP_VERT_STRETCH);
-       save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
-       save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL);
-       save->tmds_crc = INREG(TMDS_CRC);
-       save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL);
-       save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
-}
-
-
-
-static int radeonfb_set_par (struct fb_info *info)
-{
-       struct radeonfb_info *rinfo = (struct radeonfb_info *)info->par;
-       struct fb_var_screeninfo *mode = &info->var;
-       struct radeon_regs newmode;
-       int hTotal, vTotal, hSyncStart, hSyncEnd,
-           hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync;
-       u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5};
-       u8 hsync_fudge_fp[] = {2, 2, 0, 0, 5, 5};
-       u32 dotClock = 1000000000 / mode->pixclock,
-           sync, h_sync_pol, v_sync_pol;
-       int freq = dotClock / 10;  /* x 100 */
-        int xclk_freq, vclk_freq, xclk_per_trans, xclk_per_trans_precise;
-        int useable_precision, roff, ron;
-        int min_bits, format = 0;
-       int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid;
-       int primary_mon = PRIMARY_MONITOR(rinfo);
-       int depth = var_to_depth(mode);
-        int accel = (mode->accel_flags & FB_ACCELF_TEXT) != 0;
-
-       rinfo->xres = mode->xres;
-       rinfo->yres = mode->yres;
-       rinfo->xres_virtual = mode->xres_virtual;
-       rinfo->yres_virtual = mode->yres_virtual;
-       rinfo->pixclock = mode->pixclock;
-
-       hSyncStart = mode->xres + mode->right_margin;
-       hSyncEnd = hSyncStart + mode->hsync_len;
-       hTotal = hSyncEnd + mode->left_margin;
-
-       vSyncStart = mode->yres + mode->lower_margin;
-       vSyncEnd = vSyncStart + mode->vsync_len;
-       vTotal = vSyncEnd + mode->upper_margin;
-
-       if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
-               if (rinfo->panel_xres < mode->xres)
-                       rinfo->xres = mode->xres = rinfo->panel_xres;
-               if (rinfo->panel_yres < mode->yres)
-                       rinfo->yres = mode->yres = rinfo->panel_yres;
-
-               hTotal = mode->xres + rinfo->hblank;
-               hSyncStart = mode->xres + rinfo->hOver_plus;
-               hSyncEnd = hSyncStart + rinfo->hSync_width;
-
-               vTotal = mode->yres + rinfo->vblank;
-               vSyncStart = mode->yres + rinfo->vOver_plus;
-               vSyncEnd = vSyncStart + rinfo->vSync_width;
-       }
-
-       sync = mode->sync;
-       h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
-       v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-
-       RTRACE("hStart = %d, hEnd = %d, hTotal = %d\n",
-               hSyncStart, hSyncEnd, hTotal);
-       RTRACE("vStart = %d, vEnd = %d, vTotal = %d\n",
-               vSyncStart, vSyncEnd, vTotal);
-
-       hsync_wid = (hSyncEnd - hSyncStart) / 8;
-       vsync_wid = vSyncEnd - vSyncStart;
-       if (hsync_wid == 0)
-               hsync_wid = 1;
-       else if (hsync_wid > 0x3f)      /* max */
-               hsync_wid = 0x3f;
-
-       if (vsync_wid == 0)
-               vsync_wid = 1;
-       else if (vsync_wid > 0x1f)      /* max */
-               vsync_wid = 0x1f;
-
-       hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
-       vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-
-       cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
-
-       format = radeon_get_dstbpp(depth);
-       bytpp = mode->bits_per_pixel >> 3;
-
-       if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD))
-               hsync_fudge = hsync_fudge_fp[format-1];
-       else
-               hsync_fudge = hsync_adj_tab[format-1];
-
-       hsync_start = hSyncStart - 8 + hsync_fudge;
-
-       newmode.crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN |
-                               (format << 8);
-
-       if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
-               newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
-               if (mirror)
-                       newmode.crtc_ext_cntl |= CRTC_CRT_ON;
-
-               newmode.crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN |
-                                          CRTC_INTERLACE_EN);
-       } else {
-               newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN |
-                                       CRTC_CRT_ON;
-       }
-
-       newmode.dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN |
-                          DAC_8BIT_EN;
-
-       newmode.crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) |
-                                    (((mode->xres / 8) - 1) << 16));
-
-       newmode.crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |
-                                       (hsync_wid << 16) | (h_sync_pol << 23));
-
-       newmode.crtc_v_total_disp = ((vTotal - 1) & 0xffff) |
-                                   ((mode->yres - 1) << 16);
-
-       newmode.crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) |
-                                        (vsync_wid << 16) | (v_sync_pol  << 23));
-
-       if (accel) {
-               /* We first calculate the engine pitch */
-               rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f)
-                               & ~(0x3f)) >> 6;
-
-               /* Then, re-multiply it to get the CRTC pitch */
-               newmode.crtc_pitch = (rinfo->pitch << 3) / ((mode->bits_per_pixel + 1) / 8);
-       } else
-               newmode.crtc_pitch = (mode->xres_virtual >> 3);
-       newmode.crtc_pitch |= (newmode.crtc_pitch << 16);
-
-#if defined(__BIG_ENDIAN)
-       /*
-        * It looks like recent chips have a problem with SURFACE_CNTL,
-        * setting SURF_TRANSLATION_DIS completely disables the
-        * swapper as well, so we leave it unset now.
-        */
-       newmode.surface_cntl = 0;
-
-       /* Setup swapping on both apertures, though we currently
-        * only use aperture 0, enabling swapper on aperture 1
-        * won't harm
-        */
-       switch (mode->bits_per_pixel) {
-               case 16:
-                       newmode.surface_cntl |= NONSURF_AP0_SWP_16BPP;
-                       newmode.surface_cntl |= NONSURF_AP1_SWP_16BPP;
-                       break;
-               case 24:        
-               case 32:
-                       newmode.surface_cntl |= NONSURF_AP0_SWP_32BPP;
-                       newmode.surface_cntl |= NONSURF_AP1_SWP_32BPP;
-                       break;
-       }
-#endif
-
-       rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f)
-                       & ~(0x3f)) / 64;
-
-       RTRACE("h_total_disp = 0x%x\t   hsync_strt_wid = 0x%x\n",
-               newmode.crtc_h_total_disp, newmode.crtc_h_sync_strt_wid);
-       RTRACE("v_total_disp = 0x%x\t   vsync_strt_wid = 0x%x\n",
-               newmode.crtc_v_total_disp, newmode.crtc_v_sync_strt_wid);
-
-       newmode.xres = mode->xres;
-       newmode.yres = mode->yres;
-
-       rinfo->bpp = mode->bits_per_pixel;
-       rinfo->depth = depth;
-
-       if (freq > rinfo->pll.ppll_max)
-               freq = rinfo->pll.ppll_max;
-       if (freq*12 < rinfo->pll.ppll_min)
-               freq = rinfo->pll.ppll_min / 12;
-
-       {
-               struct {
-                       int divider;
-                       int bitvalue;
-               } *post_div,
-                 post_divs[] = {
-                       { 1,  0 },
-                       { 2,  1 },
-                       { 4,  2 },
-                       { 8,  3 },
-                       { 3,  4 },
-                       { 16, 5 },
-                       { 6,  6 },
-                       { 12, 7 },
-                       { 0,  0 },
-               };
-
-               for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
-                       rinfo->pll_output_freq = post_div->divider * freq;
-                       if (rinfo->pll_output_freq >= rinfo->pll.ppll_min  &&
-                           rinfo->pll_output_freq <= rinfo->pll.ppll_max)
-                               break;
-               }
-
-               rinfo->post_div = post_div->divider;
-               rinfo->fb_div = round_div(rinfo->pll.ref_div*rinfo->pll_output_freq,
-                                         rinfo->pll.ref_clk);
-               newmode.ppll_ref_div = rinfo->pll.ref_div;
-               newmode.ppll_div_3 = rinfo->fb_div | (post_div->bitvalue << 16);
-       }
-       newmode.vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl;
-
-#ifdef CONFIG_PPC_OF
-       /* Gross hack for iBook with M7 until I find out a proper fix */
-       if (machine_is_compatible("PowerBook4,3") && rinfo->arch == RADEON_M7)
-               newmode.ppll_div_3 = 0x000600ad;
-#endif /* CONFIG_PPC_OF */     
-
-       RTRACE("post div = 0x%x\n", rinfo->post_div);
-       RTRACE("fb_div = 0x%x\n", rinfo->fb_div);
-       RTRACE("ppll_div_3 = 0x%x\n", newmode.ppll_div_3);
-
-       /* DDA */
-       vclk_freq = round_div(rinfo->pll.ref_clk * rinfo->fb_div,
-                             rinfo->pll.ref_div * rinfo->post_div);
-       xclk_freq = rinfo->pll.xclk;
-
-       xclk_per_trans = round_div(xclk_freq * 128, vclk_freq * mode->bits_per_pixel);
-
-       min_bits = min_bits_req(xclk_per_trans);
-       useable_precision = min_bits + 1;
-
-       xclk_per_trans_precise = round_div((xclk_freq * 128) << (11 - useable_precision),
-                                          vclk_freq * mode->bits_per_pixel);
-
-       ron = (4 * rinfo->ram.mb + 3 * _max(rinfo->ram.trcd - 2, 0) +
-              2 * rinfo->ram.trp + rinfo->ram.twr + rinfo->ram.cl + rinfo->ram.tr2w +
-              xclk_per_trans) << (11 - useable_precision);
-       roff = xclk_per_trans_precise * (32 - 4);
-
-       RTRACE("ron = %d, roff = %d\n", ron, roff);
-       RTRACE("vclk_freq = %d, per = %d\n", vclk_freq, xclk_per_trans_precise);
-
-       if ((ron + rinfo->ram.rloop) >= roff) {
-               printk("radeonfb: error ron out of range\n");
-               return -EINVAL;
-       }
-
-       newmode.dda_config = (xclk_per_trans_precise |
-                             (useable_precision << 16) |
-                             (rinfo->ram.rloop << 20));
-       newmode.dda_on_off = (ron << 16) | roff;
-
-       if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
-               unsigned int hRatio, vRatio;
-
-               /* We force the pixel clock to be always enabled. Allowing it
-                * to be power managed during blanking would save power, but has
-                * nasty interactions with the 2D engine & sleep code that haven't
-                * been solved yet. --BenH
-                */
-               newmode.vclk_ecp_cntl &= ~PIXCLK_DAC_ALWAYS_ONb;
-               
-               if (mode->xres > rinfo->panel_xres)
-                       mode->xres = rinfo->panel_xres;
-               if (mode->yres > rinfo->panel_yres)
-                       mode->yres = rinfo->panel_yres;
-
-               newmode.fp_horz_stretch = (((rinfo->panel_xres / 8) - 1)
-                                          << HORZ_PANEL_SHIFT);
-               newmode.fp_vert_stretch = ((rinfo->panel_yres - 1)
-                                          << VERT_PANEL_SHIFT);
-
-               if (mode->xres != rinfo->panel_xres) {
-                       hRatio = round_div(mode->xres * HORZ_STRETCH_RATIO_MAX,
-                                          rinfo->panel_xres);
-                       newmode.fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) |
-                                                  (newmode.fp_horz_stretch &
-                                                   (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH |
-                                                    HORZ_AUTO_RATIO_INC)));
-                       newmode.fp_horz_stretch |= (HORZ_STRETCH_BLEND |
-                                                   HORZ_STRETCH_ENABLE);
-               }
-               newmode.fp_horz_stretch &= ~HORZ_AUTO_RATIO;
-
-               if (mode->yres != rinfo->panel_yres) {
-                       vRatio = round_div(mode->yres * VERT_STRETCH_RATIO_MAX,
-                                          rinfo->panel_yres);
-                       newmode.fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) |
-                                                  (newmode.fp_vert_stretch &
-                                                  (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED)));
-                       newmode.fp_vert_stretch |= (VERT_STRETCH_BLEND |
-                                                   VERT_STRETCH_ENABLE);
-               }
-               newmode.fp_vert_stretch &= ~VERT_AUTO_RATIO_EN;
-
-               newmode.fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32)
-                                      ~(FP_SEL_CRTC2 |
-                                        FP_RMX_HVSYNC_CONTROL_EN |
-                                        FP_DFP_SYNC_SEL |
-                                        FP_CRT_SYNC_SEL |
-                                        FP_CRTC_LOCK_8DOT |
-                                        FP_USE_SHADOW_EN |
-                                        FP_CRTC_USE_SHADOW_VEND |
-                                        FP_CRT_SYNC_ALT));
-
-               newmode.fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR |
-                                       FP_CRTC_DONT_SHADOW_HEND);
-
-               newmode.lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl;
-               newmode.lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl;
-               newmode.tmds_crc = rinfo->init_state.tmds_crc;
-               newmode.tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl;
-
-               if (primary_mon == MT_LCD) {
-                       newmode.lvds_gen_cntl |= (LVDS_ON | LVDS_BLON);
-                       newmode.fp_gen_cntl &= ~(FP_FPON | FP_TMDS_EN);
-               } else {
-                       /* DFP */
-                       newmode.fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
-                       newmode.tmds_transmitter_cntl = (TMDS_RAN_PAT_RST |
-                                                        TMDS_ICHCSEL | TMDS_PLL_EN) &
-                                                        ~(TMDS_PLLRST);
-                       newmode.crtc_ext_cntl &= ~CRTC_CRT_ON;
-               }
-
-               newmode.fp_crtc_h_total_disp = (((rinfo->hblank / 8) & 0x3ff) |
-                               (((mode->xres / 8) - 1) << 16));
-               newmode.fp_crtc_v_total_disp = (rinfo->vblank & 0xffff) |
-                               ((mode->yres - 1) << 16);
-               newmode.fp_h_sync_strt_wid = ((rinfo->hOver_plus & 0x1fff) |
-                               (hsync_wid << 16) | (h_sync_pol << 23));
-               newmode.fp_v_sync_strt_wid = ((rinfo->vOver_plus & 0xfff) |
-                               (vsync_wid << 16) | (v_sync_pol  << 23));
-       }
-
-       /* do it! */
-       if (!rinfo->asleep) {
-               radeon_write_mode (rinfo, &newmode);
-               /* (re)initialize the engine */
-               if (noaccel)
-                       radeon_engine_init (rinfo);
-       
-       }
-       /* Update fix */
-       if (accel)
-               info->fix.line_length = rinfo->pitch*64;
-        else
-               info->fix.line_length = mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8);
-        info->fix.visual = rinfo->depth == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-
-#ifdef CONFIG_BOOTX_TEXT
-       /* Update debug text engine */
-       btext_update_display(rinfo->fb_base_phys, mode->xres, mode->yres,
-                            rinfo->depth, info->fix.line_length);
-#endif
-
-       return 0;
-}
-
-
-static void radeon_write_mode (struct radeonfb_info *rinfo,
-                               struct radeon_regs *mode)
-{
-       int i;
-       int primary_mon = PRIMARY_MONITOR(rinfo);
-
-       radeonfb_blank(VESA_POWERDOWN, (struct fb_info *)rinfo);
-
-
-       if (rinfo->arch == RADEON_M6) {
-               for (i=0; i<7; i++)
-                       OUTREG(common_regs_m6[i].reg, common_regs_m6[i].val);
-       } else {
-               for (i=0; i<9; i++)
-                       OUTREG(common_regs[i].reg, common_regs[i].val);
-       }
-
-       OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
-       OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
-               CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS);
-       OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
-       OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
-       OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
-       OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
-       OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
-       OUTREG(CRTC_OFFSET, 0);
-       OUTREG(CRTC_OFFSET_CNTL, 0);
-       OUTREG(CRTC_PITCH, mode->crtc_pitch);
-
-#if defined(__BIG_ENDIAN)
-       OUTREG(SURFACE_CNTL, mode->surface_cntl);
-#endif
-
-       while ((INREG(CLOCK_CNTL_INDEX) & PPLL_DIV_SEL_MASK) !=
-              PPLL_DIV_SEL_MASK) {
-               OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, 0xffff);
-       }
-
-       OUTPLLP(PPLL_CNTL, PPLL_RESET, 0xffff);
-
-       while ((INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK) !=
-              (mode->ppll_ref_div & PPLL_REF_DIV_MASK)) {
-               OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
-       }
-
-       while ((INPLL(PPLL_DIV_3) & PPLL_FB3_DIV_MASK) !=
-              (mode->ppll_div_3 & PPLL_FB3_DIV_MASK)) {
-               OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
-       }
-
-       while ((INPLL(PPLL_DIV_3) & PPLL_POST3_DIV_MASK) !=
-              (mode->ppll_div_3 & PPLL_POST3_DIV_MASK)) {
-               OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
-       }
-
-       OUTPLL(HTOTAL_CNTL, 0);
-
-       OUTPLLP(PPLL_CNTL, 0, ~PPLL_RESET);
-
-//     OUTREG(DDA_CONFIG, mode->dda_config);
-//     OUTREG(DDA_ON_OFF, mode->dda_on_off);
-
-       if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
-               OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
-               OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
-               OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
-               OUTREG(FP_V_SYNC_STRT_WID, mode->fp_v_sync_strt_wid);
-               OUTREG(FP_HORZ_STRETCH, mode->fp_horz_stretch);
-               OUTREG(FP_VERT_STRETCH, mode->fp_vert_stretch);
-               OUTREG(FP_GEN_CNTL, mode->fp_gen_cntl);
-               OUTREG(TMDS_CRC, mode->tmds_crc);
-               OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl);
-
-               if (primary_mon == MT_LCD) {
-                       unsigned int tmp = INREG(LVDS_GEN_CNTL);
-
-                       mode->lvds_gen_cntl &= ~LVDS_STATE_MASK;
-                       mode->lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_STATE_MASK);
-
-                       if ((tmp & (LVDS_ON | LVDS_BLON)) ==
-                           (mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON))) {
-                               OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl);
-                       } else {
-                               if (mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON)) {
-                                       udelay(1000);
-                                       OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl);
-                               } else {
-                                       OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl |
-                                              LVDS_BLON);
-                                       udelay(1000);
-                                       OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl);
-                               }
-                       }
-               }
-       }
-
-       radeonfb_blank(VESA_NO_BLANKING, (struct fb_info *)rinfo);
-
-       OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
-       
-       return;
-}
-
-static struct fb_ops radeonfb_ops = {
-       .owner                  = THIS_MODULE,
-       .fb_check_var           = radeonfb_check_var,
-       .fb_set_par             = radeonfb_set_par,
-       .fb_setcolreg           = radeonfb_setcolreg,
-       .fb_pan_display         = radeonfb_pan_display,
-       .fb_blank               = radeonfb_blank,
-       .fb_ioctl               = radeonfb_ioctl,
-#if 0
-       .fb_fillrect    = radeonfb_fillrect,
-       .fb_copyarea    = radeonfb_copyarea,
-       .fb_imageblit   = radeonfb_imageblit,
-       .fb_rasterimg   = radeonfb_rasterimg,
-#else
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
-       .fb_imageblit   = cfb_imageblit,
-#endif
-};
-
-
-static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
-{
-       struct fb_info *info;
-
-       info = &rinfo->info;
-
-       info->par = rinfo;
-       info->pseudo_palette = rinfo->pseudo_palette;
-        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-        info->fbops = &radeonfb_ops;
-        info->screen_base = rinfo->fb_base;
-
-       /* Fill fix common fields */
-       strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
-        info->fix.smem_start = rinfo->fb_base_phys;
-        info->fix.smem_len = rinfo->video_ram;
-        info->fix.type = FB_TYPE_PACKED_PIXELS;
-        info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-        info->fix.xpanstep = 8;
-        info->fix.ypanstep = 1;
-        info->fix.ywrapstep = 0;
-        info->fix.type_aux = 0;
-        info->fix.mmio_start = rinfo->mmio_base_phys;
-        info->fix.mmio_len = RADEON_REGSIZE;
-       if (noaccel)
-               info->fix.accel = FB_ACCEL_NONE;
-       else
-               info->fix.accel = FB_ACCEL_ATI_RADEON;
-
-        if (radeon_init_disp (rinfo) < 0)
-                return -1;   
-
-        return 0;
-}
-
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-
-/* TODO: Dbl check these tables, we don't go up to full ON backlight
- * in these, possibly because we noticed MacOS doesn't, but I'd prefer
- * having some more official numbers from ATI
- */
-static int backlight_conv_m6[] = {
-       0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
-       0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
-};
-static int backlight_conv_m7[] = {
-       0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81,
-       0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9
-};
-
-#define BACKLIGHT_LVDS_OFF
-#undef BACKLIGHT_DAC_OFF
-
-/* We turn off the LCD completely instead of just dimming the backlight.
- * This provides some greater power saving and the display is useless
- * without backlight anyway.
- */
-
-static int radeon_set_backlight_enable(int on, int level, void *data)
-{
-       struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
-       unsigned int lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
-       int* conv_table;
-
-       /* Pardon me for that hack... maybe some day we can figure
-        * out in what direction backlight should work on a given
-        * panel ?
-        */
-       if ((rinfo->arch == RADEON_M7 || rinfo->arch == RADEON_M9)
-               && !machine_is_compatible("PowerBook4,3"))
-               conv_table = backlight_conv_m7;
-       else
-               conv_table = backlight_conv_m6;
-
-       lvds_gen_cntl |= (LVDS_BL_MOD_EN | LVDS_BLON);
-       if (on && (level > BACKLIGHT_OFF)) {
-               lvds_gen_cntl |= LVDS_DIGON;
-               if (!(lvds_gen_cntl & LVDS_ON)) {
-                       lvds_gen_cntl &= ~LVDS_BLON;
-                       OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-                       (void)INREG(LVDS_GEN_CNTL);
-                       mdelay(10);
-                       lvds_gen_cntl |= LVDS_BLON;
-                       OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-               }
-               lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
-               lvds_gen_cntl |= (conv_table[level] <<
-                                 LVDS_BL_MOD_LEVEL_SHIFT);
-               lvds_gen_cntl |= (LVDS_ON | LVDS_EN);
-               lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
-       } else {
-               lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
-               lvds_gen_cntl |= (conv_table[0] <<
-                                 LVDS_BL_MOD_LEVEL_SHIFT);
-               lvds_gen_cntl |= LVDS_DISPLAY_DIS;
-               OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-               udelay(10);
-               lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGON);
-       }
-
-       OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-       rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-       rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
-
-       return 0;
-}
-
-static int radeon_set_backlight_level(int level, void *data)
-{
-       return radeon_set_backlight_enable(1, level, data);
-}
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-
-#ifdef CONFIG_PMAC_PBOOK
-
-static u32 dbg_clk;
-
-/*
- * Radeon M6 Power Management code. This code currently only supports
- * the mobile chips, it's based from some informations provided by ATI
- * along with hours of tracing of MacOS drivers
- */
-static void radeon_pm_save_regs(struct radeonfb_info *rinfo)
-{
-       rinfo->save_regs[0] = INPLL(PLL_PWRMGT_CNTL);
-       rinfo->save_regs[1] = INPLL(CLK_PWRMGT_CNTL);
-       rinfo->save_regs[2] = INPLL(MCLK_CNTL);
-       rinfo->save_regs[3] = INPLL(SCLK_CNTL);
-       rinfo->save_regs[4] = INPLL(CLK_PIN_CNTL);
-       rinfo->save_regs[5] = INPLL(VCLK_ECP_CNTL);
-       rinfo->save_regs[6] = INPLL(PIXCLKS_CNTL);
-       rinfo->save_regs[7] = INPLL(MCLK_MISC);
-       rinfo->save_regs[8] = INPLL(P2PLL_CNTL);
-       
-       rinfo->save_regs[9] = INREG(DISP_MISC_CNTL);
-       rinfo->save_regs[10] = INREG(DISP_PWR_MAN);
-       rinfo->save_regs[11] = INREG(LVDS_GEN_CNTL);
-       rinfo->save_regs[12] = INREG(LVDS_PLL_CNTL);
-       rinfo->save_regs[13] = INREG(TV_DAC_CNTL);
-       rinfo->save_regs[14] = INREG(BUS_CNTL1);
-       rinfo->save_regs[15] = INREG(CRTC_OFFSET_CNTL);
-       rinfo->save_regs[16] = INREG(AGP_CNTL);
-       rinfo->save_regs[17] = (INREG(CRTC_GEN_CNTL) & 0xfdffffff) | 0x04000000;
-       rinfo->save_regs[18] = (INREG(CRTC2_GEN_CNTL) & 0xfdffffff) | 0x04000000;
-       rinfo->save_regs[19] = INREG(GPIOPAD_A);
-       rinfo->save_regs[20] = INREG(GPIOPAD_EN);
-       rinfo->save_regs[21] = INREG(GPIOPAD_MASK);
-       rinfo->save_regs[22] = INREG(ZV_LCDPAD_A);
-       rinfo->save_regs[23] = INREG(ZV_LCDPAD_EN);
-       rinfo->save_regs[24] = INREG(ZV_LCDPAD_MASK);
-       rinfo->save_regs[25] = INREG(GPIO_VGA_DDC);
-       rinfo->save_regs[26] = INREG(GPIO_DVI_DDC);
-       rinfo->save_regs[27] = INREG(GPIO_MONID);
-       rinfo->save_regs[28] = INREG(GPIO_CRT2_DDC);
-
-       rinfo->save_regs[29] = INREG(SURFACE_CNTL);
-       rinfo->save_regs[30] = INREG(MC_FB_LOCATION);
-       rinfo->save_regs[31] = INREG(DISPLAY_BASE_ADDR);
-       rinfo->save_regs[32] = INREG(MC_AGP_LOCATION);
-       rinfo->save_regs[33] = INREG(CRTC2_DISPLAY_BASE_ADDR);
-}
-
-static void radeon_pm_restore_regs(struct radeonfb_info *rinfo)
-{
-       OUTPLL(P2PLL_CNTL, rinfo->save_regs[8] & 0xFFFFFFFE); /* First */
-       
-       OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]);
-       OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]);
-       OUTPLL(MCLK_CNTL, rinfo->save_regs[2]);
-       OUTPLL(SCLK_CNTL, rinfo->save_regs[3]);
-       OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]);
-       OUTPLL(VCLK_ECP_CNTL, rinfo->save_regs[5]);
-       OUTPLL(PIXCLKS_CNTL, rinfo->save_regs[6]);
-       OUTPLL(MCLK_MISC, rinfo->save_regs[7]);
-       
-       OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
-       OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
-       OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11]);
-       OUTREG(LVDS_PLL_CNTL,rinfo->save_regs[12]);
-       OUTREG(TV_DAC_CNTL, rinfo->save_regs[13]);
-       OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
-       OUTREG(CRTC_OFFSET_CNTL, rinfo->save_regs[15]);
-       OUTREG(AGP_CNTL, rinfo->save_regs[16]);
-       OUTREG(CRTC_GEN_CNTL, rinfo->save_regs[17]);
-       OUTREG(CRTC2_GEN_CNTL, rinfo->save_regs[18]);
-
-       // wait VBL before that one  ?
-       OUTPLL(P2PLL_CNTL, rinfo->save_regs[8]);
-       
-       OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
-       OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
-       OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
-       OUTREG(ZV_LCDPAD_A, rinfo->save_regs[22]);
-       OUTREG(ZV_LCDPAD_EN, rinfo->save_regs[23]);
-       OUTREG(ZV_LCDPAD_MASK, rinfo->save_regs[24]);
-       OUTREG(GPIO_VGA_DDC, rinfo->save_regs[25]);
-       OUTREG(GPIO_DVI_DDC, rinfo->save_regs[26]);
-       OUTREG(GPIO_MONID, rinfo->save_regs[27]);
-       OUTREG(GPIO_CRT2_DDC, rinfo->save_regs[28]);
-}
-
-static void radeon_pm_disable_iopad(struct radeonfb_info *rinfo)
-{              
-       OUTREG(GPIOPAD_MASK, 0x0001ffff);
-       OUTREG(GPIOPAD_EN, 0x00000400);
-       OUTREG(GPIOPAD_A, 0x00000000);          
-        OUTREG(ZV_LCDPAD_MASK, 0x00000000);
-        OUTREG(ZV_LCDPAD_EN, 0x00000000);
-       OUTREG(ZV_LCDPAD_A, 0x00000000);        
-       OUTREG(GPIO_VGA_DDC, 0x00030000);
-       OUTREG(GPIO_DVI_DDC, 0x00000000);
-       OUTREG(GPIO_MONID, 0x00030000);
-       OUTREG(GPIO_CRT2_DDC, 0x00000000);
-}
-
-static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo)
-{
-//
-//     u32 reg;
-//
-//     OUTPLL(P2PLL_REF_DIV, 0x0c);
-//
-//      .../... figure out what macos does here
-}
-
-static void radeon_pm_low_current(struct radeonfb_info *rinfo)
-{
-       u32 reg;
-
-       reg  = INREG(BUS_CNTL1);
-       reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK;
-       reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT);
-       OUTREG(BUS_CNTL1, reg);
-       
-       reg  = INPLL(PLL_PWRMGT_CNTL);
-       reg |= PLL_PWRMGT_CNTL_SPLL_TURNOFF | PLL_PWRMGT_CNTL_PPLL_TURNOFF |
-               PLL_PWRMGT_CNTL_P2PLL_TURNOFF | PLL_PWRMGT_CNTL_TVPLL_TURNOFF;
-       reg &= ~PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK;
-       reg &= ~PLL_PWRMGT_CNTL_MOBILE_SU;
-       OUTPLL(PLL_PWRMGT_CNTL, reg);
-
-//     reg  = INPLL(TV_PLL_CNTL1);
-//     reg |= TV_PLL_CNTL1__TVPLL_RESET | TV_PLL_CNTL1__TVPLL_SLEEP;
-//     OUTPLL(TV_PLL_CNTL1, reg);
-       
-       reg  = INREG(TV_DAC_CNTL);
-       reg &= ~(TV_DAC_CNTL_BGADJ_MASK |TV_DAC_CNTL_DACADJ_MASK);
-       reg |=TV_DAC_CNTL_BGSLEEP | TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD |
-               TV_DAC_CNTL_BDACPD |
-               (8<<TV_DAC_CNTL_BGADJ__SHIFT) | (8<<TV_DAC_CNTL_DACADJ__SHIFT);
-       OUTREG(TV_DAC_CNTL, reg);
-       
-       reg  = INREG(TMDS_TRANSMITTER_CNTL);
-       reg &= ~(TMDS_PLL_EN |TMDS_PLLRST);
-       OUTREG(TMDS_TRANSMITTER_CNTL, reg);
-
-//     lvds_pll_cntl  = regr32(g, LVDS_PLL_CNTL);
-//     lvds_pll_cntl &= ~LVDS_PLL_CNTL__LVDS_PLL_EN;                                                                                   
-//     lvds_pll_cntl |=  LVDS_PLL_CNTL__LVDS_PLL_RESET;        
-//     regw32(g, LVDS_PLL_CNTL, lvds_pll_cntl);
-
-       reg = INREG(DAC_CNTL);
-       reg &= ~DAC_CMP_EN;
-       OUTREG(DAC_CNTL, reg);
-
-       reg = INREG(DAC_CNTL2);
-       reg &= ~DAC2_CMP_EN;
-       OUTREG(DAC_CNTL2, reg);
-       
-       reg  = INREG(TV_DAC_CNTL);
-       reg &= ~TV_DAC_CNTL_DETECT;
-       OUTREG(TV_DAC_CNTL, reg);
-}
-
-static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo)
-{
-       /* This code is disabled. It does what is in the pm_init
-        * function of the MacOS driver code ATI sent me. However,
-        * it doesn't fix my sleep problem, and is causing other issues
-        * on wakeup (bascially the machine dying when switching consoles
-        * I haven't had time to investigate this yet
-        */
-#if 0
-       u32 disp_misc_cntl;
-       u32 disp_pwr_man;
-       u32 temp;
-
-       // set SPLL, MPLL, PPLL, P2PLL, TVPLL, SCLK, MCLK, PCLK, P2CLK,
-       // TCLK and TEST_MODE to 0
-       temp = INPLL(CLK_PWRMGT_CNTL);
-       OUTPLL(CLK_PWRMGT_CNTL , temp & ~0xc00002ff);
-
-       // Turn on Power Management
-       temp = INPLL(CLK_PWRMGT_CNTL);
-       OUTPLL(CLK_PWRMGT_CNTL , temp | 0x00000400);
-
-       // Turn off display clock if using mobile chips
-       temp = INPLL(CLK_PWRMGT_CNTL);
-       OUTREG(CLK_PWRMGT_CNTL , temp | 0x00100000);
-
-       // Force PIXCLK_ALWAYS_ON and PIXCLK_DAC_ALWAYS_ON
-       temp = INPLL(VCLK_ECP_CNTL);
-       OUTPLL(VCLK_ECP_CNTL, temp & ~0x000000c0);
-
-       // Force ECP_FORCE_ON to 1
-       temp = INPLL(VCLK_ECP_CNTL);
-       OUTPLL(VCLK_ECP_CNTL, temp | 0x00040000);
-
-       // Force PIXCLK_BLEND_ALWAYS_ON and PIXCLK_GV_ALWAYS_ON
-       temp = INPLL(PIXCLKS_CNTL);
-               OUTPLL(PIXCLKS_CNTL, temp & ~0x00001800);
-
-       // Forcing SCLK_CNTL to ON
-       OUTPLL(SCLK_CNTL, (INPLL(SCLK_CNTL)& 0x00000007) | 0xffff8000 );
-
-       // Set PM control over XTALIN pad
-       temp = INPLL(CLK_PIN_CNTL);
-       OUTPLL(CLK_PIN_CNTL, temp | 0x00080000);
-
-       // Force MCLK and YCLK and MC as dynamic
-       temp = INPLL(MCLK_CNTL);
-       OUTPLL(MCLK_CNTL, temp & 0xffeaffff);
-
-       // PLL_TURNOFF
-       temp = INPLL(PLL_PWRMGT_CNTL);
-       OUTPLL(PLL_PWRMGT_CNTL, temp | 0x0000001f);
-       // set MOBILE_SU to 1 if M6 or DDR64 is detected
-       temp = INPLL(PLL_PWRMGT_CNTL);
-       OUTPLL(PLL_PWRMGT_CNTL, temp | 0x00010000);
-
-       // select PM access mode (PM_MODE_SEL) (use ACPI mode)
-//      temp = INPLL(PLL_PWRMGT_CNTL);
-//      OUTPLL(PLL_PWRMGT_CNTL, temp | 0x00002000);
-       temp = INPLL(PLL_PWRMGT_CNTL);
-        OUTPLL(PLL_PWRMGT_CNTL, temp & ~0x00002000);
-
-       // set DISP_MISC_CNTL register
-       disp_misc_cntl = INREG(DISP_MISC_CNTL);
-       disp_misc_cntl &= ~(    DISP_MISC_CNTL_SOFT_RESET_GRPH_PP |
-                               DISP_MISC_CNTL_SOFT_RESET_SUBPIC_PP |
-                               DISP_MISC_CNTL_SOFT_RESET_OV0_PP |
-                               DISP_MISC_CNTL_SOFT_RESET_GRPH_SCLK |
-                               DISP_MISC_CNTL_SOFT_RESET_SUBPIC_SCLK |
-                               DISP_MISC_CNTL_SOFT_RESET_OV0_SCLK |
-                               DISP_MISC_CNTL_SOFT_RESET_GRPH2_PP |
-                               DISP_MISC_CNTL_SOFT_RESET_GRPH2_SCLK |
-                               DISP_MISC_CNTL_SOFT_RESET_LVDS |
-                               DISP_MISC_CNTL_SOFT_RESET_TMDS |
-                               DISP_MISC_CNTL_SOFT_RESET_DIG_TMDS |
-                               DISP_MISC_CNTL_SOFT_RESET_TV);
-       OUTREG(DISP_MISC_CNTL, disp_misc_cntl);
-
-       // set DISP_PWR_MAN register
-       disp_pwr_man = INREG(DISP_PWR_MAN);
-       // clau - 9.29.2000 - changes made to bit23:18 to set to 1 as requested by George
-       disp_pwr_man |= (DISP_PWR_MAN_DIG_TMDS_ENABLE_RST |
-                    DISP_PWR_MAN_TV_ENABLE_RST |
- //                 DISP_PWR_MAN_AUTO_PWRUP_EN |
-                    DISP_PWR_MAN_DISP_D3_GRPH_RST |
-                    DISP_PWR_MAN_DISP_D3_SUBPIC_RST |
-                    DISP_PWR_MAN_DISP_D3_OV0_RST |
-                    DISP_PWR_MAN_DISP_D1D2_GRPH_RST |
-                    DISP_PWR_MAN_DISP_D1D2_SUBPIC_RST |
-                    DISP_PWR_MAN_DISP_D1D2_OV0_RST);
-       disp_pwr_man &= ~(DISP_PWR_MAN_DISP_PWR_MAN_D3_CRTC_EN |
-                    DISP_PWR_MAN_DISP2_PWR_MAN_D3_CRTC2_EN|
-                    DISP_PWR_MAN_DISP_D3_RST |
-                    DISP_PWR_MAN_DISP_D3_REG_RST);
-       OUTREG(DISP_PWR_MAN, disp_pwr_man);
-
-       // clau - 10.24.2000
-       // - add in setting for BUS_CNTL1 b27:26 = 0x01 and b31 = 0x1
-       // - add in setting for AGP_CNTL  b7:0 = 0x20
-       // - add in setting for DVI_DDC_DATA_OUT_EN b17:16 = 0x0
-
-       // the following settings (two lines) are applied at a later part of this function, only on mobile platform
-       // requres -mobile flag
-       OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & 0xf3ffffff) | 0x04000000);
-       OUTREG(BUS_CNTL1,  INREG(BUS_CNTL1) | 0x80000000);
-       OUTREG(AGP_CNTL, (INREG(AGP_CNTL) & 0xffffff00) | 0x20);
-       OUTREG(GPIO_DVI_DDC, INREG(GPIO_DVI_DDC) & 0xfffcffff);
-
-       // yulee - 12.12.2000
-       // A12 only
-       // EN_MCLK_TRISTATE_IN_SUSPEND@MCLK_MISC = 1
-       // ACCESS_REGS_IN_SUSPEND@CLK_PIN_CNTL = 0
-       // only on mobile platform
-        OUTPLL(MCLK_MISC, INPLL(MCLK_MISC) | 0x00040000 );
-       
-       // yulee -12.12.2000
-       // AGPCLK_VALID@BUS_CNTL1 = 1
-       // MOBILE_PLATFORM_SEL@BUS_CNTL1 = 01
-       // CRTC_STEREO_SYNC_OUT_EN@CRTC_OFFSET_CNTL = 0
-       // CG_CLK_TO_OUTPIN@CLK_PIN_CNTL = 0
-       // only on mobile platform
-        OUTPLL(CLK_PIN_CNTL, INPLL(CLK_PIN_CNTL ) & 0xFFFFF7FF );
-        OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1 ) & 0xF3FFFFFF) | 0x84000000 );
-        OUTREG(CRTC_OFFSET_CNTL, INREG(CRTC_OFFSET_CNTL ) & 0xFFEFFFFF );
-
-        mdelay(100);
-#endif
-
-       /* Disable CRTCs */
-       OUTREG(CRTC_GEN_CNTL, (INREG(CRTC_GEN_CNTL) & ~CRTC_EN) | CRTC_DISP_REQ_EN_B);
-       OUTREG(CRTC2_GEN_CNTL, (INREG(CRTC2_GEN_CNTL) & ~CRTC2_EN) | CRTC2_DISP_REQ_EN_B);
-       (void)INREG(CRTC2_GEN_CNTL);
-       mdelay(17);
-}
-
-static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
-{
-       u16 pwr_cmd;
-
-       if (!rinfo->pm_reg)
-               return;
-
-       /* Set the chip into appropriate suspend mode (we use D2,
-        * D3 would require a compete re-initialization of the chip,
-        * including PCI config registers, clocks, AGP conf, ...)
-        */
-       if (suspend) {
-               /* According to ATI, we should program V2CLK here, I have
-                * to verify what's up exactly
-                */
-               /* Save some registers */
-               radeon_pm_save_regs(rinfo);
-
-               /* Check that on M7 too, might work might not. M7 may also
-                * need explicit enabling of PM
-                */
-               if (rinfo->arch == RADEON_M6) {
-                       /* Program V2CLK */
-                       radeon_pm_program_v2clk(rinfo);
-               
-                       /* Disable IO PADs */
-                       radeon_pm_disable_iopad(rinfo);
-
-                       /* Set low current */
-                       radeon_pm_low_current(rinfo);
-
-                       /* Prepare chip for power management */
-                       radeon_pm_setup_for_suspend(rinfo);
-
-                       /* Reset the MDLL */
-                       OUTPLL(MDLL_CKO, INPLL(MDLL_CKO) | MCKOA_RESET);
-                       (void)INPLL(MDLL_RDCKA);
-                       OUTPLL(MDLL_CKO, INPLL(MDLL_CKO) & ~MCKOA_RESET);
-                       (void)INPLL(MDLL_RDCKA);
-               }
-
-               /* Switch PCI power managment to D2. */
-               for (;;) {
-                       pci_read_config_word(
-                               rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
-                               &pwr_cmd);
-                       if (pwr_cmd & 2)
-                               break;                  
-                       pci_write_config_word(
-                               rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
-                               (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2);
-                       mdelay(500);
-               }
-       } else {
-               /* Switch back PCI powermanagment to D0 */
-               mdelay(200);
-               pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0);
-               mdelay(500);
-
-               dbg_clk = INPLL(1);
-
-               /* Do we need that on M7 ? */
-               if (rinfo->arch == RADEON_M6) {
-                       /* Restore the MDLL */
-                       OUTPLL(MDLL_CKO, INPLL(MDLL_CKO) & ~MCKOA_RESET);
-                       (void)INPLL(MDLL_CKO);                  
-               }
-               
-               /* Restore some registers */
-               radeon_pm_restore_regs(rinfo);
-       }
-}
-
-/*
- * Save the contents of the framebuffer when we go to sleep,
- * and restore it when we wake up again.
- */
-
-int radeon_sleep_notify(struct pmu_sleep_notifier *self, int when)
-{
-       struct radeonfb_info *rinfo;
-
-       for (rinfo = board_list; rinfo != NULL; rinfo = rinfo->next) {
-               struct fb_fix_screeninfo fix;
-               int nb;
-               struct display *disp;  
-
-               disp = (rinfo->currcon < 0) ? rinfo->info.disp : &fb_display[rinfo->currcon];
-
-               switch (rinfo->arch) {
-                       case RADEON_M6:
-                       case RADEON_M7:
-                       case RADEON_M9:
-                               break;
-                       default:
-                               return PBOOK_SLEEP_REFUSE;
-               }
-
-               radeonfb_get_fix(&fix, fg_console, (struct fb_info *)rinfo);
-               nb = fb_display[fg_console].var.yres * fix.line_length;
-
-               switch (when) {
-                       case PBOOK_SLEEP_NOW:
-                               acquire_console_sem();
-                               disp->dispsw = &fbcon_dummy;
-
-                               if (!noaccel) {
-                                       /* Make sure engine is reset */
-                                       radeon_engine_reset();
-                                       radeon_engine_idle();
-                               }
-
-                               /* Blank display and LCD */
-                               radeonfb_blank(VESA_POWERDOWN+1,
-                                              (struct fb_info *)rinfo);
-
-                               /* Sleep */
-                               rinfo->asleep = 1;
-                               radeon_set_suspend(rinfo, 1);
-                               release_console_sem();
-                               
-                               break;
-                       case PBOOK_WAKE:
-                               acquire_console_sem();
-                               /* Wakeup */
-                               radeon_set_suspend(rinfo, 0);
-
-                               if (!noaccel)
-                                       radeon_engine_init(rinfo);
-                               rinfo->asleep = 0;
-                               radeon_set_dispsw(rinfo, disp);
-                               radeon_load_video_mode(rinfo, &disp->var);
-                               do_install_cmap(rinfo->currcon < 0 ? 0 : rinfo->currcon,
-                                               (struct fb_info *)rinfo);
-
-                               radeonfb_blank(0, (struct fb_info *)rinfo);
-                               release_console_sem();
-                               printk("CLK_PIN_CNTL on wakeup was: %08x\n", dbg_clk);
-                               break;
-               }
-       }
-
-       return PBOOK_SLEEP_OK;
-}
-
-#endif /* CONFIG_PMAC_PBOOK */
-
-static int radeonfb_pci_register (struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
-{
-       struct radeonfb_info *rinfo;
-       struct radeon_chip_info *rci = &radeon_chip_info[ent->driver_data];
-       u32 tmp;
-
-       RTRACE("radeonfb_pci_register BEGIN\n");
-
-       /* Enable device in PCI config */
-       if (pci_enable_device(pdev) != 0) {
-               printk(KERN_ERR "radeonfb: Cannot enable PCI device\n");
-               return -ENODEV;
-       }
-
-       rinfo = kmalloc (sizeof (struct radeonfb_info), GFP_KERNEL);
-       if (!rinfo) {
-               printk ("radeonfb: could not allocate memory\n");
-               return -ENODEV;
-       }
-
-       memset (rinfo, 0, sizeof (struct radeonfb_info));
-       //info = &rinfo->info;
-       rinfo->pdev = pdev;
-       strcpy(rinfo->name, rci->name);
-       rinfo->arch = rci->arch;
-
-       /* Set base addrs */
-       rinfo->fb_base_phys = pci_resource_start (pdev, 0);
-       rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
-
-       /* request the mem regions */
-       if (!request_mem_region (rinfo->fb_base_phys,
-                                pci_resource_len(pdev, 0), "radeonfb")) {
-               printk ("radeonfb: cannot reserve FB region\n");
-               kfree (rinfo);
-               return -ENODEV;
-       }
-
-       if (!request_mem_region (rinfo->mmio_base_phys,
-                                pci_resource_len(pdev, 2), "radeonfb")) {
-               printk ("radeonfb: cannot reserve MMIO region\n");
-               release_mem_region (rinfo->fb_base_phys,
-                                   pci_resource_len(pdev, 0));
-               kfree (rinfo);
-               return -ENODEV;
-       }
-
-       /* map the regions */
-       rinfo->mmio_base = ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);
-       if (!rinfo->mmio_base) {
-               printk ("radeonfb: cannot map MMIO\n");
-               release_mem_region (rinfo->mmio_base_phys,
-                                   pci_resource_len(pdev, 2));
-               release_mem_region (rinfo->fb_base_phys,
-                                   pci_resource_len(pdev, 0));
-               kfree (rinfo);
-               return -ENODEV;
-       }
-
-       rinfo->chipset = pdev->device;
-
-       switch (rinfo->arch) {
-               case RADEON_R100:
-                       rinfo->hasCRTC2 = 0;
-                       break;
-               default:
-                       /* all the rest have it */
-                       rinfo->hasCRTC2 = 1;
-                       break;
-       }
-#if 0
-       if (rinfo->arch == RADEON_M7) {
-               /*
-                * Noticed some errors in accel with M7, will have to work these out...
-                */
-               noaccel = 1;
-       }
-#endif
-       if (mirror)
-               printk("radeonfb: mirroring display to CRT\n");
-
-       /* framebuffer size */
-       tmp = INREG(CONFIG_MEMSIZE);
-
-       /* mem size is bits [28:0], mask off the rest */
-       rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
-
-       /* ram type */
-       tmp = INREG(MEM_SDRAM_MODE_REG);
-       switch ((MEM_CFG_TYPE & tmp) >> 30) {
-               case 0:
-                       /* SDR SGRAM (2:1) */
-                       strcpy(rinfo->ram_type, "SDR SGRAM");
-                       rinfo->ram.ml = 4;
-                       rinfo->ram.mb = 4;
-                       rinfo->ram.trcd = 1;
-                       rinfo->ram.trp = 2;
-                       rinfo->ram.twr = 1;
-                       rinfo->ram.cl = 2;
-                       rinfo->ram.loop_latency = 16;
-                       rinfo->ram.rloop = 16;
-       
-                       break;
-               case 1:
-                       /* DDR SGRAM */
-                       strcpy(rinfo->ram_type, "DDR SGRAM");
-                       rinfo->ram.ml = 4;
-                       rinfo->ram.mb = 4;
-                       rinfo->ram.trcd = 3;
-                       rinfo->ram.trp = 3;
-                       rinfo->ram.twr = 2;
-                       rinfo->ram.cl = 3;
-                       rinfo->ram.tr2w = 1;
-                       rinfo->ram.loop_latency = 16;
-                       rinfo->ram.rloop = 16;
-
-                       break;
-               default:
-                       /* 64-bit SDR SGRAM */
-                       strcpy(rinfo->ram_type, "SDR SGRAM 64");
-                       rinfo->ram.ml = 4;
-                       rinfo->ram.mb = 8;
-                       rinfo->ram.trcd = 3;
-                       rinfo->ram.trp = 3;
-                       rinfo->ram.twr = 1;
-                       rinfo->ram.cl = 3;
-                       rinfo->ram.tr2w = 1;
-                       rinfo->ram.loop_latency = 17;
-                       rinfo->ram.rloop = 17;
-
-                       break;
-       }
-
-       rinfo->bios_seg = radeon_find_rom(rinfo);
-       radeon_get_pllinfo(rinfo, rinfo->bios_seg);
-
-       /*
-        * Hack to get around some busted production M6's
-        * reporting no ram
-        */
-       if (rinfo->video_ram == 0) {
-               switch (pdev->device) {
-                       case PCI_DEVICE_ID_ATI_RADEON_LY:
-                       case PCI_DEVICE_ID_ATI_RADEON_LZ:
-                               rinfo->video_ram = 8192 * 1024;
-                               break;
-                       default:
-                               break;
-               }
-       }
-
-
-       RTRACE("radeonfb: probed %s %dk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024));
-
-#if !defined(__powerpc__)
-       radeon_get_moninfo(rinfo);
-#else
-       switch (pdev->device) {
-               case PCI_DEVICE_ID_ATI_RADEON_LW:
-               case PCI_DEVICE_ID_ATI_RADEON_LX:
-               case PCI_DEVICE_ID_ATI_RADEON_LY:
-               case PCI_DEVICE_ID_ATI_RADEON_LZ:
-                       rinfo->dviDisp_type = MT_LCD;
-                       break;
-               default:
-                       radeon_get_moninfo(rinfo);
-                       break;
-       }
-#endif
-
-       radeon_get_EDID(rinfo);
-
-       if ((rinfo->dviDisp_type == MT_DFP) || (rinfo->dviDisp_type == MT_LCD) ||
-           (rinfo->crtDisp_type == MT_DFP)) {
-               if (!radeon_get_dfpinfo(rinfo)) {
-                       iounmap(rinfo->mmio_base);
-                       release_mem_region (rinfo->mmio_base_phys,
-                                           pci_resource_len(pdev, 2));
-                       release_mem_region (rinfo->fb_base_phys,
-                                           pci_resource_len(pdev, 0));
-                       kfree (rinfo);
-                       return -ENODEV;
-               }
-       }
-
-       rinfo->fb_base = ioremap (rinfo->fb_base_phys, rinfo->video_ram);
-       if (!rinfo->fb_base) {
-               printk ("radeonfb: cannot map FB\n");
-               iounmap(rinfo->mmio_base);
-               release_mem_region (rinfo->mmio_base_phys,
-                                   pci_resource_len(pdev, 2));
-               release_mem_region (rinfo->fb_base_phys,
-                                   pci_resource_len(pdev, 0));
-               kfree (rinfo);
-               return -ENODEV;
-       }
-
-       /* I SHOULD FIX THAT CRAP ! I should probably mimmic XFree DRI
-        * driver setup here.
-        * 
-        * On PPC, OF based cards setup the internal memory
-        * mapping in strange ways. We change it so that the
-        * framebuffer is mapped at 0 and given half of the card's
-        * address space (2Gb). AGP is mapped high (0xe0000000) and
-        * can use up to 512Mb. Once DRI is fully implemented, we
-        * will have to setup the PCI remapper to remap the agp_special_page
-        * memory page somewhere between those regions so that the card
-        * use a normal PCI bus master cycle to access the ring read ptr.
-        * --BenH.
-        */
-#ifdef CONFIG_ALL_PPC
-       if (rinfo->hasCRTC2)
-               OUTREG(CRTC2_GEN_CNTL,
-                       (INREG(CRTC2_GEN_CNTL) & ~CRTC2_EN) | CRTC2_DISP_REQ_EN_B);
-       OUTREG(CRTC_EXT_CNTL, INREG(CRTC_EXT_CNTL) | CRTC_DISPLAY_DIS);
-       OUTREG(MC_FB_LOCATION, 0x7fff0000);
-       OUTREG(MC_AGP_LOCATION, 0xffffe000);
-       OUTREG(DISPLAY_BASE_ADDR, 0x00000000);
-       if (rinfo->hasCRTC2)
-               OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0x00000000);
-       OUTREG(SRC_OFFSET, 0x00000000);
-       OUTREG(DST_OFFSET, 0x00000000);
-       mdelay(10);
-       OUTREG(CRTC_EXT_CNTL, INREG(CRTC_EXT_CNTL) & ~CRTC_DISPLAY_DIS);
-#endif /* CONFIG_ALL_PPC */
-
-       /* save current mode regs before we switch into the new one
-        * so we can restore this upon __exit
-        */
-       radeon_save_state (rinfo, &rinfo->init_state);
-
-       /* set all the vital stuff */
-       radeon_set_fbinfo (rinfo);
-
-       pci_set_drvdata(pdev, rinfo);
-       rinfo->next = board_list;
-       board_list = rinfo;
-       ((struct fb_info *) rinfo)->device = &pdev->dev;
-       if (register_framebuffer ((struct fb_info *) rinfo) < 0) {
-               printk ("radeonfb: could not register framebuffer\n");
-               iounmap(rinfo->fb_base);
-               iounmap(rinfo->mmio_base);
-               release_mem_region (rinfo->mmio_base_phys,
-                                   pci_resource_len(pdev, 2));
-               release_mem_region (rinfo->fb_base_phys,
-                                   pci_resource_len(pdev, 0));
-               kfree (rinfo);
-               return -ENODEV;
-       }
-
-#ifdef CONFIG_MTRR
-       rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys,
-                                                rinfo->video_ram,
-                                                MTRR_TYPE_WRCOMB, 1);
-#endif
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       if (rinfo->dviDisp_type == MT_LCD)
-               register_backlight_controller(&radeon_backlight_controller,
-                                             rinfo, "ati");
-#endif
-
-#ifdef CONFIG_PMAC_PBOOK
-       if (rinfo->dviDisp_type == MT_LCD) {
-               rinfo->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
-               pmu_register_sleep_notifier(&radeon_sleep_notifier);
-       }
-#endif
-
-       printk ("radeonfb: ATI Radeon %s %s %d MB\n", rinfo->name, rinfo->ram_type,
-               (rinfo->video_ram/(1024*1024)));
-
-       if (rinfo->hasCRTC2) {
-               printk("radeonfb: DVI port %s monitor connected\n",
-                       GET_MON_NAME(rinfo->dviDisp_type));
-               printk("radeonfb: CRT port %s monitor connected\n",
-                       GET_MON_NAME(rinfo->crtDisp_type));
-       } else {
-               printk("radeonfb: CRT port %s monitor connected\n",
-                       GET_MON_NAME(rinfo->crtDisp_type));
-       }
-
-       RTRACE("radeonfb_pci_register END\n");
-
-       return 0;
-}
-
-
-
-static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
-{
-        struct radeonfb_info *rinfo = pci_get_drvdata(pdev);
-        if (!rinfo)
-                return;
-       /* restore original state
-        * 
-        * Doesn't quite work yet, possibly because of the PPC hacking
-        * I do on startup, disable for now. --BenH
-        */
-        radeon_write_mode (rinfo, &rinfo->init_state);
-#ifdef CONFIG_MTRR
-       if (rinfo->mtrr_hdl >= 0)
-               mtrr_del(rinfo->mtrr_hdl, 0, 0);
-#endif
-
-        unregister_framebuffer ((struct fb_info *) rinfo);
-                
-        iounmap(rinfo->mmio_base);
-        iounmap(rinfo->fb_base);
-       release_mem_region (rinfo->mmio_base_phys,
-                           pci_resource_len(pdev, 2));
-       release_mem_region (rinfo->fb_base_phys,
-                           pci_resource_len(pdev, 0));
-        
-        kfree (rinfo);
-}
-
-
-static struct pci_driver radeonfb_driver = {
-       .name           = "radeonfb",
-       .id_table       = radeonfb_pci_table,
-       .probe          = radeonfb_pci_register,
-       .remove         = __devexit_p(radeonfb_pci_unregister),
-};
-
-#ifndef MODULE
-static int __init radeonfb_old_setup (char *options)
-{
-        char *this_opt;
-
-        if (!options || !*options)
-                return 0;
-       while ((this_opt = strsep (&options, ",")) != NULL) {
-               if (!*this_opt)
-                       continue;
-                if (!strncmp(this_opt, "noaccel", 7)) {
-                       noaccel = 1;
-                } else if (!strncmp(this_opt, "mirror", 6)) {
-                       mirror = 1;
-               } else if (!strncmp(this_opt, "dfp", 3)) {
-                       force_dfp = 1;
-               } else if (!strncmp(this_opt, "panel_yres:", 11)) {
-                       panel_yres = simple_strtoul((this_opt+11), NULL, 0);
-               } else if (!strncmp(this_opt, "nomtrr", 6)) {
-                       nomtrr = 1;
-                } else
-                       mode_option = this_opt;
-        }
-
-       return 0;
-}
-#endif  /*  MODULE  */
-
-static int __init radeonfb_old_init (void)
-{
-#ifndef MODULE
-       char *option = NULL;
-
-       if (fb_get_options("radeonfb_old", &option))
-               return -ENODEV;
-       radeonfb_old_setup(option);
-#endif
-       return pci_register_driver (&radeonfb_driver);
-}
-
-
-static void __exit radeonfb_old_exit (void)
-{
-       pci_unregister_driver (&radeonfb_driver);
-}
-
-module_init(radeonfb_old_init);
-module_exit(radeonfb_old_exit);
-
-
-MODULE_AUTHOR("Ani Joshi");
-MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset");
-MODULE_LICENSE("GPL");
index dc93336..1a9a60c 100644 (file)
  * for them to fix it and steal their solution.   prumpf
  */
  
-#define STI_WAIT 1
-
-#include <asm/io.h> /* for USE_HPPA_IOREMAP */
-
-#if USE_HPPA_IOREMAP
+#include <asm/io.h>
 
-#define STI_PTR(p)     (p)
-#define PTR_STI(p)     (p)
-static inline int STI_CALL( unsigned long func, 
-               void *flags, void *inptr, void *outptr, void *glob_cfg )
-{
-       int (*f)(void *,void *,void *,void *);
-       f = (void*)func;
-       return f(flags, inptr, outptr, glob_cfg);
-}
-
-#else /* !USE_HPPA_IOREMAP */
+#define STI_WAIT 1
 
 #define STI_PTR(p)     ( virt_to_phys(p) )
-#define PTR_STI(p)     ( phys_to_virt((long)p) )
-#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \
-       ({                                                      \
-               pdc_sti_call( func, (unsigned long)STI_PTR(flags), \
-                                   (unsigned long)STI_PTR(inptr), \
-                                   (unsigned long)STI_PTR(outptr), \
-                                   (unsigned long)STI_PTR(glob_cfg)); \
+#define PTR_STI(p)     ( phys_to_virt((unsigned long)p) )
+#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \
+       ({                                              \
+               pdc_sti_call( func, STI_PTR(flags),     \
+                                  STI_PTR(inptr),      \
+                                  STI_PTR(outptr),     \
+                                  STI_PTR(glob_cfg));  \
        })
 
-#endif /* USE_HPPA_IOREMAP */
-
 
 #define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x)
 #define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y)
@@ -352,8 +336,9 @@ struct sti_struct {
        struct sti_conf_outptr outptr; /* configuration */
        struct sti_conf_outptr_ext outptr_ext;
 
-       /* PCI data structures (pg. 17ff from sti.pdf) */
        struct pci_dev *pd;
+
+       /* PCI data structures (pg. 17ff from sti.pdf) */
        u8 rm_entry[16]; /* pci region mapper array == pci config space offset */
 
        /* pointer to the fb_info where this STI device is used */
index 56d71d6..4a292aa 100644 (file)
@@ -3,7 +3,7 @@
  * Low level Frame buffer driver for HP workstations with 
  * STI (standard text interface) video firmware.
  *
- * Copyright (C) 2001-2005 Helge Deller <deller@gmx.de>
+ * Copyright (C) 2001-2006 Helge Deller <deller@gmx.de>
  * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
  * 
  * Based on:
@@ -514,7 +514,7 @@ rattlerSetupPlanes(struct stifb_info *fb)
        SETUP_HW(fb);
        WRITE_BYTE(1, fb, REG_16b1);
 
-       fb_memset(fb->info.fix.smem_start, 0xff,
+       fb_memset((void*)fb->info.fix.smem_start, 0xff,
                fb->info.var.yres*fb->info.fix.line_length);
     
        CRX24_SET_OVLY_MASK(fb);
@@ -908,83 +908,6 @@ SETUP_HCRX(struct stifb_info *fb)
 
 /* ------------------- driver specific functions --------------------------- */
 
-#define TMPBUFLEN 2048
-
-static ssize_t
-stifb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-{
-       unsigned long p = *ppos;
-       struct inode *inode = file->f_dentry->d_inode;
-       int fbidx = iminor(inode);
-       struct fb_info *info = registered_fb[fbidx];
-       char tmpbuf[TMPBUFLEN];
-
-       if (!info || ! info->screen_base)
-               return -ENODEV;
-
-       if (p >= info->fix.smem_len)
-           return 0;
-       if (count >= info->fix.smem_len)
-           count = info->fix.smem_len;
-       if (count + p > info->fix.smem_len)
-               count = info->fix.smem_len - p;
-       if (count > sizeof(tmpbuf))
-               count = sizeof(tmpbuf);
-       if (count) {
-           char *base_addr;
-
-           base_addr = info->screen_base;
-           memcpy_fromio(&tmpbuf, base_addr+p, count);
-           count -= copy_to_user(buf, &tmpbuf, count);
-           if (!count)
-               return -EFAULT;
-           *ppos += count;
-       }
-       return count;
-}
-
-static ssize_t
-stifb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-       struct inode *inode = file->f_dentry->d_inode;
-       int fbidx = iminor(inode);
-       struct fb_info *info = registered_fb[fbidx];
-       unsigned long p = *ppos;
-       size_t c;
-       int err;
-       char tmpbuf[TMPBUFLEN];
-
-       if (!info || !info->screen_base)
-               return -ENODEV;
-
-       if (p > info->fix.smem_len)
-           return -ENOSPC;
-       if (count >= info->fix.smem_len)
-           count = info->fix.smem_len;
-       err = 0;
-       if (count + p > info->fix.smem_len) {
-           count = info->fix.smem_len - p;
-           err = -ENOSPC;
-       }
-
-       p += (unsigned long)info->screen_base;
-       c = count;
-       while (c) {
-           int len = c > sizeof(tmpbuf) ? sizeof(tmpbuf) : c;
-           err = -EFAULT;
-           if (copy_from_user(&tmpbuf, buf, len))
-                   break;
-           memcpy_toio(p, &tmpbuf, len);
-           c -= len;
-           p += len;
-           buf += len;
-           *ppos += len;
-       }
-       if (count-c)
-               return (count-c);
-       return err;
-}
-
 static int
 stifb_setcolreg(u_int regno, u_int red, u_int green,
              u_int blue, u_int transp, struct fb_info *info)
@@ -1137,8 +1060,6 @@ stifb_init_display(struct stifb_info *fb)
 
 static struct fb_ops stifb_ops = {
        .owner          = THIS_MODULE,
-       .fb_read        = stifb_read,
-       .fb_write       = stifb_write,
        .fb_setcolreg   = stifb_setcolreg,
        .fb_blank       = stifb_blank,
        .fb_fillrect    = cfb_fillrect,
@@ -1162,7 +1083,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
        char *dev_name;
        int bpp, xres, yres;
 
-       fb = kmalloc(sizeof(*fb), GFP_ATOMIC);
+       fb = kzalloc(sizeof(*fb), GFP_ATOMIC);
        if (!fb) {
                printk(KERN_ERR "stifb: Could not allocate stifb structure\n");
                return -ENODEV;
@@ -1171,7 +1092,6 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
        info = &fb->info;
 
        /* set struct to a known state */
-       memset(fb, 0, sizeof(*fb));
        fix = &info->fix;
        var = &info->var;
 
@@ -1234,7 +1154,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
        case S9000_ID_TOMCAT:   /* Dual CRX, behaves else like a CRX */
                /* FIXME: TomCat supports two heads:
                 * fb.iobase = REGION_BASE(fb_info,3);
-                * fb.screen_base = (void*) REGION_BASE(fb_info,2);
+                * fb.screen_base = ioremap_nocache(REGION_BASE(fb_info,2),xxx);
                 * for now we only support the left one ! */
                xres = fb->ngle_rom.x_size_visible;
                yres = fb->ngle_rom.y_size_visible;
@@ -1327,7 +1247,8 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
 
        strcpy(fix->id, "stifb");
        info->fbops = &stifb_ops;
-       info->screen_base = (void*) REGION_BASE(fb,1);
+       info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len);
+       info->screen_size = fix->smem_len;
        info->flags = FBINFO_DEFAULT;
        info->pseudo_palette = &fb->pseudo_palette;
 
@@ -1457,7 +1378,7 @@ stifb_setup(char *options)
        int i;
        
        if (!options || !*options)
-               return 0;
+               return 1;
        
        if (strncmp(options, "off", 3) == 0) {
                stifb_disabled = 1;
@@ -1472,7 +1393,7 @@ stifb_setup(char *options)
                        stifb_bpp_pref[i] = simple_strtoul(options, &options, 10);
                }
        }
-       return 0;
+       return 1;
 }
 
 __setup("stifb=", stifb_setup);
index f6e24ee..5fc86ea 100644 (file)
@@ -4,8 +4,9 @@
  * Frame Buffer Device for ATI Imageon w100 (Wallaby)
  *
  * Copyright (C) 2002, ATI Corp.
- * Copyright (C) 2004-2005 Richard Purdie
+ * Copyright (C) 2004-2006 Richard Purdie
  * Copyright (c) 2005 Ian Molton
+ * Copyright (c) 2006 Alberto Mardegan
  *
  * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
  *
@@ -14,6 +15,9 @@
  *
  * w32xx support by Ian Molton
  *
+ * Hardware acceleration support by Alberto Mardegan
+ * <mardy@users.sourceforge.net>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -47,6 +51,7 @@ static void w100_set_dispregs(struct w100fb_par*);
 static void w100_update_enable(void);
 static void w100_update_disable(void);
 static void calc_hsync(struct w100fb_par *par);
+static void w100_init_graphic_engine(struct w100fb_par *par);
 struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
 
 /* Pseudo palette size */
@@ -248,6 +253,152 @@ static int w100fb_blank(int blank_mode, struct fb_info *info)
 }
 
 
+static void w100_fifo_wait(int entries)
+{
+       union rbbm_status_u status;
+       int i;
+
+       for (i = 0; i < 2000000; i++) {
+               status.val = readl(remapped_regs + mmRBBM_STATUS);
+               if (status.f.cmdfifo_avail >= entries)
+                       return;
+               udelay(1);
+       }
+       printk(KERN_ERR "w100fb: FIFO Timeout!\n");
+}
+
+
+static int w100fb_sync(struct fb_info *info)
+{
+       union rbbm_status_u status;
+       int i;
+
+       for (i = 0; i < 2000000; i++) {
+               status.val = readl(remapped_regs + mmRBBM_STATUS);
+               if (!status.f.gui_active)
+                       return 0;
+               udelay(1);
+       }
+       printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
+       return -EBUSY;
+}
+
+
+static void w100_init_graphic_engine(struct w100fb_par *par)
+{
+       union dp_gui_master_cntl_u gmc;
+       union dp_mix_u dp_mix;
+       union dp_datatype_u dp_datatype;
+       union dp_cntl_u dp_cntl;
+
+       w100_fifo_wait(4);
+       writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
+       writel(par->xres, remapped_regs + mmDST_PITCH);
+       writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
+       writel(par->xres, remapped_regs + mmSRC_PITCH);
+
+       w100_fifo_wait(3);
+       writel(0, remapped_regs + mmSC_TOP_LEFT);
+       writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
+       writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
+
+       w100_fifo_wait(4);
+       dp_cntl.val = 0;
+       dp_cntl.f.dst_x_dir = 1;
+       dp_cntl.f.dst_y_dir = 1;
+       dp_cntl.f.src_x_dir = 1;
+       dp_cntl.f.src_y_dir = 1;
+       dp_cntl.f.dst_major_x = 1;
+       dp_cntl.f.src_major_x = 1;
+       writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
+
+       gmc.val = 0;
+       gmc.f.gmc_src_pitch_offset_cntl = 1;
+       gmc.f.gmc_dst_pitch_offset_cntl = 1;
+       gmc.f.gmc_src_clipping = 1;
+       gmc.f.gmc_dst_clipping = 1;
+       gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
+       gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
+       gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
+       gmc.f.gmc_byte_pix_order = 1;
+       gmc.f.gmc_default_sel = 0;
+       gmc.f.gmc_rop3 = ROP3_SRCCOPY;
+       gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
+       gmc.f.gmc_clr_cmp_fcn_dis = 1;
+       gmc.f.gmc_wr_msk_dis = 1;
+       gmc.f.gmc_dp_op = DP_OP_ROP;
+       writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
+
+       dp_datatype.val = dp_mix.val = 0;
+       dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
+       dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
+       dp_datatype.f.dp_src2_type = 0;
+       dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
+       dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
+       dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
+       writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
+
+       dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
+       dp_mix.f.dp_src2_source = 1;
+       dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
+       dp_mix.f.dp_op = gmc.f.gmc_dp_op;
+       writel(dp_mix.val, remapped_regs + mmDP_MIX);
+}
+
+
+static void w100fb_fillrect(struct fb_info *info,
+                            const struct fb_fillrect *rect)
+{
+       union dp_gui_master_cntl_u gmc;
+
+       if (info->state != FBINFO_STATE_RUNNING)
+               return;
+       if (info->flags & FBINFO_HWACCEL_DISABLED) {
+               cfb_fillrect(info, rect);
+               return;
+       }
+
+       gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
+       gmc.f.gmc_rop3 = ROP3_PATCOPY;
+       gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
+       w100_fifo_wait(2);
+       writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
+       writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
+
+       w100_fifo_wait(2);
+       writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
+       writel((rect->width << 16) | (rect->height & 0xffff),
+              remapped_regs + mmDST_WIDTH_HEIGHT);
+}
+
+
+static void w100fb_copyarea(struct fb_info *info,
+                            const struct fb_copyarea *area)
+{
+       u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
+       u32 h = area->height, w = area->width;
+       union dp_gui_master_cntl_u gmc;
+
+       if (info->state != FBINFO_STATE_RUNNING)
+               return;
+       if (info->flags & FBINFO_HWACCEL_DISABLED) {
+               cfb_copyarea(info, area);
+               return;
+       }
+
+       gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
+       gmc.f.gmc_rop3 = ROP3_SRCCOPY;
+       gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
+       w100_fifo_wait(1);
+       writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
+
+       w100_fifo_wait(3);
+       writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
+       writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
+       writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
+}
+
+
 /*
  *  Change the resolution by calling the appropriate hardware functions
  */
@@ -265,6 +416,7 @@ static void w100fb_activate_var(struct w100fb_par *par)
        w100_init_lcd(par);
        w100_set_dispregs(par);
        w100_update_enable();
+       w100_init_graphic_engine(par);
 
        calc_hsync(par);
 
@@ -394,9 +546,10 @@ static struct fb_ops w100fb_ops = {
        .fb_set_par   = w100fb_set_par,
        .fb_setcolreg = w100fb_setcolreg,
        .fb_blank     = w100fb_blank,
-       .fb_fillrect  = cfb_fillrect,
-       .fb_copyarea  = cfb_copyarea,
+       .fb_fillrect  = w100fb_fillrect,
+       .fb_copyarea  = w100fb_copyarea,
        .fb_imageblit = cfb_imageblit,
+       .fb_sync      = w100fb_sync,
 };
 
 #ifdef CONFIG_PM
@@ -543,7 +696,8 @@ int __init w100fb_probe(struct platform_device *pdev)
        }
 
        info->fbops = &w100fb_ops;
-       info->flags = FBINFO_DEFAULT;
+       info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
+               FBINFO_HWACCEL_FILLRECT;
        info->node = -1;
        info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
        info->screen_size = REMAPPED_FB_LEN;
index 7a58a1e..fffae7b 100644 (file)
 /* Block DISPLAY End: */
 
 /* Block GFX Start: */
+#define mmDST_OFFSET          0x1004
+#define mmDST_PITCH           0x1008
+#define mmDST_Y_X             0x1038
+#define mmDST_WIDTH_HEIGHT    0x1198
+#define mmDP_GUI_MASTER_CNTL  0x106C
 #define mmBRUSH_OFFSET        0x108C
 #define mmBRUSH_Y_X           0x1074
+#define mmDP_BRUSH_FRGD_CLR   0x107C
+#define mmSRC_OFFSET          0x11AC
+#define mmSRC_PITCH           0x11B0
+#define mmSRC_Y_X             0x1034
 #define mmDEFAULT_PITCH_OFFSET      0x10A0
 #define mmDEFAULT_SC_BOTTOM_RIGHT   0x10A8
 #define mmDEFAULT2_SC_BOTTOM_RIGHT  0x10AC
+#define mmSC_TOP_LEFT         0x11BC
+#define mmSC_BOTTOM_RIGHT     0x11C0
+#define mmSRC_SC_BOTTOM_RIGHT 0x11C4
 #define mmGLOBAL_ALPHA        0x1210
 #define mmFILTER_COEF         0x1214
 #define mmMVC_CNTL_START      0x11E0
 #define mmE2_ARITHMETIC_CNTL  0x1220
+#define mmDP_CNTL             0x11C8
+#define mmDP_CNTL_DST_DIR     0x11CC
+#define mmDP_DATATYPE         0x12C4
+#define mmDP_MIX              0x12C8
+#define mmDP_WRITE_MSK        0x12CC
 #define mmENG_CNTL            0x13E8
 #define mmENG_PERF_CNT        0x13F0
 /* Block GFX End: */
 /* Block RBBM Start: */
 #define mmWAIT_UNTIL        0x1400
 #define mmISYNC_CNTL        0x1404
+#define mmRBBM_STATUS       0x0140
 #define mmRBBM_CNTL         0x0144
 #define mmNQWAIT_UNTIL      0x0150
 /* Block RBBM End: */
 /* Register structure definitions */
 
 struct wrap_top_dir_t {
-       unsigned long top_addr  : 23;
-       unsigned long           : 9;
+       u32 top_addr  : 23;
+       u32           : 9;
 } __attribute__((packed));
 
 union wrap_top_dir_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct wrap_top_dir_t f;
 } __attribute__((packed));
 
 struct wrap_start_dir_t {
-       unsigned long start_addr : 23;
-       unsigned long            : 9;
+       u32 start_addr : 23;
+       u32            : 9;
 } __attribute__((packed));
 
 union wrap_start_dir_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct wrap_start_dir_t f;
 } __attribute__((packed));
 
 struct cif_cntl_t {
-       unsigned long swap_reg                 : 2;
-       unsigned long swap_fbuf_1              : 2;
-       unsigned long swap_fbuf_2              : 2;
-       unsigned long swap_fbuf_3              : 2;
-       unsigned long pmi_int_disable          : 1;
-       unsigned long pmi_schmen_disable       : 1;
-       unsigned long intb_oe                  : 1;
-       unsigned long en_wait_to_compensate_dq_prop_dly  : 1;
-       unsigned long compensate_wait_rd_size  : 2;
-       unsigned long wait_asserted_timeout_val  : 2;
-       unsigned long wait_masked_val          : 2;
-       unsigned long en_wait_timeout          : 1;
-       unsigned long en_one_clk_setup_before_wait  : 1;
-       unsigned long interrupt_active_high    : 1;
-       unsigned long en_overwrite_straps      : 1;
-       unsigned long strap_wait_active_hi     : 1;
-       unsigned long lat_busy_count           : 2;
-       unsigned long lat_rd_pm4_sclk_busy     : 1;
-       unsigned long dis_system_bits          : 1;
-       unsigned long dis_mr                   : 1;
-       unsigned long cif_spare_1              : 4;
+       u32 swap_reg                 : 2;
+       u32 swap_fbuf_1              : 2;
+       u32 swap_fbuf_2              : 2;
+       u32 swap_fbuf_3              : 2;
+       u32 pmi_int_disable          : 1;
+       u32 pmi_schmen_disable       : 1;
+       u32 intb_oe                  : 1;
+       u32 en_wait_to_compensate_dq_prop_dly  : 1;
+       u32 compensate_wait_rd_size  : 2;
+       u32 wait_asserted_timeout_val  : 2;
+       u32 wait_masked_val          : 2;
+       u32 en_wait_timeout          : 1;
+       u32 en_one_clk_setup_before_wait  : 1;
+       u32 interrupt_active_high    : 1;
+       u32 en_overwrite_straps      : 1;
+       u32 strap_wait_active_hi     : 1;
+       u32 lat_busy_count           : 2;
+       u32 lat_rd_pm4_sclk_busy     : 1;
+       u32 dis_system_bits          : 1;
+       u32 dis_mr                   : 1;
+       u32 cif_spare_1              : 4;
 } __attribute__((packed));
 
 union cif_cntl_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct cif_cntl_t f;
 } __attribute__((packed));
 
 struct cfgreg_base_t {
-       unsigned long cfgreg_base  : 24;
-       unsigned long              : 8;
+       u32 cfgreg_base  : 24;
+       u32              : 8;
 } __attribute__((packed));
 
 union cfgreg_base_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct cfgreg_base_t f;
 } __attribute__((packed));
 
 struct cif_io_t {
-       unsigned long dq_srp     : 1;
-       unsigned long dq_srn     : 1;
-       unsigned long dq_sp      : 4;
-       unsigned long dq_sn      : 4;
-       unsigned long waitb_srp  : 1;
-       unsigned long waitb_srn  : 1;
-       unsigned long waitb_sp   : 4;
-       unsigned long waitb_sn   : 4;
-       unsigned long intb_srp   : 1;
-       unsigned long intb_srn   : 1;
-       unsigned long intb_sp    : 4;
-       unsigned long intb_sn    : 4;
-       unsigned long            : 2;
+       u32 dq_srp     : 1;
+       u32 dq_srn     : 1;
+       u32 dq_sp      : 4;
+       u32 dq_sn      : 4;
+       u32 waitb_srp  : 1;
+       u32 waitb_srn  : 1;
+       u32 waitb_sp   : 4;
+       u32 waitb_sn   : 4;
+       u32 intb_srp   : 1;
+       u32 intb_srn   : 1;
+       u32 intb_sp    : 4;
+       u32 intb_sn    : 4;
+       u32            : 2;
 } __attribute__((packed));
 
 union cif_io_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct cif_io_t f;
 } __attribute__((packed));
 
 struct cif_read_dbg_t {
-       unsigned long unpacker_pre_fetch_trig_gen  : 2;
-       unsigned long dly_second_rd_fetch_trig     : 1;
-       unsigned long rst_rd_burst_id              : 1;
-       unsigned long dis_rd_burst_id              : 1;
-       unsigned long en_block_rd_when_packer_is_not_emp : 1;
-       unsigned long dis_pre_fetch_cntl_sm        : 1;
-       unsigned long rbbm_chrncy_dis              : 1;
-       unsigned long rbbm_rd_after_wr_lat         : 2;
-       unsigned long dis_be_during_rd             : 1;
-       unsigned long one_clk_invalidate_pulse     : 1;
-       unsigned long dis_chnl_priority            : 1;
-       unsigned long rst_read_path_a_pls          : 1;
-       unsigned long rst_read_path_b_pls          : 1;
-       unsigned long dis_reg_rd_fetch_trig        : 1;
-       unsigned long dis_rd_fetch_trig_from_ind_addr : 1;
-       unsigned long dis_rd_same_byte_to_trig_fetch : 1;
-       unsigned long dis_dir_wrap                 : 1;
-       unsigned long dis_ring_buf_to_force_dec    : 1;
-       unsigned long dis_addr_comp_in_16bit       : 1;
-       unsigned long clr_w                        : 1;
-       unsigned long err_rd_tag_is_3              : 1;
-       unsigned long err_load_when_ful_a          : 1;
-       unsigned long err_load_when_ful_b          : 1;
-       unsigned long                              : 7;
+       u32 unpacker_pre_fetch_trig_gen  : 2;
+       u32 dly_second_rd_fetch_trig     : 1;
+       u32 rst_rd_burst_id              : 1;
+       u32 dis_rd_burst_id              : 1;
+       u32 en_block_rd_when_packer_is_not_emp : 1;
+       u32 dis_pre_fetch_cntl_sm        : 1;
+       u32 rbbm_chrncy_dis              : 1;
+       u32 rbbm_rd_after_wr_lat         : 2;
+       u32 dis_be_during_rd             : 1;
+       u32 one_clk_invalidate_pulse     : 1;
+       u32 dis_chnl_priority            : 1;
+       u32 rst_read_path_a_pls          : 1;
+       u32 rst_read_path_b_pls          : 1;
+       u32 dis_reg_rd_fetch_trig        : 1;
+       u32 dis_rd_fetch_trig_from_ind_addr : 1;
+       u32 dis_rd_same_byte_to_trig_fetch : 1;
+       u32 dis_dir_wrap                 : 1;
+       u32 dis_ring_buf_to_force_dec    : 1;
+       u32 dis_addr_comp_in_16bit       : 1;
+       u32 clr_w                        : 1;
+       u32 err_rd_tag_is_3              : 1;
+       u32 err_load_when_ful_a          : 1;
+       u32 err_load_when_ful_b          : 1;
+       u32                              : 7;
 } __attribute__((packed));
 
 union cif_read_dbg_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct cif_read_dbg_t f;
 } __attribute__((packed));
 
 struct cif_write_dbg_t {
-       unsigned long packer_timeout_count          : 2;
-       unsigned long en_upper_load_cond            : 1;
-       unsigned long en_chnl_change_cond           : 1;
-       unsigned long dis_addr_comp_cond            : 1;
-       unsigned long dis_load_same_byte_addr_cond  : 1;
-       unsigned long dis_timeout_cond              : 1;
-       unsigned long dis_timeout_during_rbbm       : 1;
-       unsigned long dis_packer_ful_during_rbbm_timeout : 1;
-       unsigned long en_dword_split_to_rbbm        : 1;
-       unsigned long en_dummy_val                  : 1;
-       unsigned long dummy_val_sel                 : 1;
-       unsigned long mask_pm4_wrptr_dec            : 1;
-       unsigned long dis_mc_clean_cond             : 1;
-       unsigned long err_two_reqi_during_ful       : 1;
-       unsigned long err_reqi_during_idle_clk      : 1;
-       unsigned long err_global                    : 1;
-       unsigned long en_wr_buf_dbg_load            : 1;
-       unsigned long en_wr_buf_dbg_path            : 1;
-       unsigned long sel_wr_buf_byte               : 3;
-       unsigned long dis_rd_flush_wr               : 1;
-       unsigned long dis_packer_ful_cond           : 1;
-       unsigned long dis_invalidate_by_ops_chnl    : 1;
-       unsigned long en_halt_when_reqi_err         : 1;
-       unsigned long cif_spare_2                   : 5;
-       unsigned long                               : 1;
+       u32 packer_timeout_count          : 2;
+       u32 en_upper_load_cond            : 1;
+       u32 en_chnl_change_cond           : 1;
+       u32 dis_addr_comp_cond            : 1;
+       u32 dis_load_same_byte_addr_cond  : 1;
+       u32 dis_timeout_cond              : 1;
+       u32 dis_timeout_during_rbbm       : 1;
+       u32 dis_packer_ful_during_rbbm_timeout : 1;
+       u32 en_dword_split_to_rbbm        : 1;
+       u32 en_dummy_val                  : 1;
+       u32 dummy_val_sel                 : 1;
+       u32 mask_pm4_wrptr_dec            : 1;
+       u32 dis_mc_clean_cond             : 1;
+       u32 err_two_reqi_during_ful       : 1;
+       u32 err_reqi_during_idle_clk      : 1;
+       u32 err_global                    : 1;
+       u32 en_wr_buf_dbg_load            : 1;
+       u32 en_wr_buf_dbg_path            : 1;
+       u32 sel_wr_buf_byte               : 3;
+       u32 dis_rd_flush_wr               : 1;
+       u32 dis_packer_ful_cond           : 1;
+       u32 dis_invalidate_by_ops_chnl    : 1;
+       u32 en_halt_when_reqi_err         : 1;
+       u32 cif_spare_2                   : 5;
+       u32                               : 1;
 } __attribute__((packed));
 
 union cif_write_dbg_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct cif_write_dbg_t f;
 } __attribute__((packed));
 
@@ -403,327 +421,327 @@ union cpu_defaults_u {
 } __attribute__((packed));
 
 struct crtc_total_t {
-       unsigned long crtc_h_total : 10;
-       unsigned long              : 6;
-       unsigned long crtc_v_total : 10;
-       unsigned long              : 6;
+       u32 crtc_h_total : 10;
+       u32              : 6;
+       u32 crtc_v_total : 10;
+       u32              : 6;
 } __attribute__((packed));
 
 union crtc_total_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct crtc_total_t f;
 } __attribute__((packed));
 
 struct crtc_ss_t {
-       unsigned long ss_start    : 10;
-       unsigned long             : 6;
-       unsigned long ss_end      : 10;
-       unsigned long             : 2;
-       unsigned long ss_align    : 1;
-       unsigned long ss_pol      : 1;
-       unsigned long ss_run_mode : 1;
-       unsigned long ss_en       : 1;
+       u32 ss_start    : 10;
+       u32             : 6;
+       u32 ss_end      : 10;
+       u32             : 2;
+       u32 ss_align    : 1;
+       u32 ss_pol      : 1;
+       u32 ss_run_mode : 1;
+       u32 ss_en       : 1;
 } __attribute__((packed));
 
 union crtc_ss_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct crtc_ss_t f;
 } __attribute__((packed));
 
 struct active_h_disp_t {
-       unsigned long active_h_start  : 10;
-       unsigned long                 : 6;
-       unsigned long active_h_end    : 10;
-       unsigned long                 : 6;
+       u32 active_h_start  : 10;
+       u32                 : 6;
+       u32 active_h_end    : 10;
+       u32                 : 6;
 } __attribute__((packed));
 
 union active_h_disp_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct active_h_disp_t f;
 } __attribute__((packed));
 
 struct active_v_disp_t {
-       unsigned long active_v_start  : 10;
-       unsigned long                 : 6;
-       unsigned long active_v_end    : 10;
-       unsigned long                 : 6;
+       u32 active_v_start  : 10;
+       u32                 : 6;
+       u32 active_v_end    : 10;
+       u32                 : 6;
 } __attribute__((packed));
 
 union active_v_disp_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct active_v_disp_t f;
 } __attribute__((packed));
 
 struct graphic_h_disp_t {
-       unsigned long graphic_h_start : 10;
-       unsigned long                 : 6;
-       unsigned long graphic_h_end   : 10;
-       unsigned long                 : 6;
+       u32 graphic_h_start : 10;
+       u32                 : 6;
+       u32 graphic_h_end   : 10;
+       u32                 : 6;
 } __attribute__((packed));
 
 union graphic_h_disp_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct graphic_h_disp_t f;
 } __attribute__((packed));
 
 struct graphic_v_disp_t {
-       unsigned long graphic_v_start : 10;
-       unsigned long                 : 6;
-       unsigned long graphic_v_end   : 10;
-       unsigned long                 : 6;
+       u32 graphic_v_start : 10;
+       u32                 : 6;
+       u32 graphic_v_end   : 10;
+       u32                 : 6;
 } __attribute__((packed));
 
 union graphic_v_disp_u{
-       unsigned long val : 32;
+       u32 val : 32;
        struct graphic_v_disp_t f;
 } __attribute__((packed));
 
 struct graphic_ctrl_t_w100 {
-       unsigned long color_depth       : 3;
-       unsigned long portrait_mode     : 2;
-       unsigned long low_power_on      : 1;
-       unsigned long req_freq          : 4;
-       unsigned long en_crtc           : 1;
-       unsigned long en_graphic_req    : 1;
-       unsigned long en_graphic_crtc   : 1;
-       unsigned long total_req_graphic : 9;
-       unsigned long lcd_pclk_on       : 1;
-       unsigned long lcd_sclk_on       : 1;
-       unsigned long pclk_running      : 1;
-       unsigned long sclk_running      : 1;
-       unsigned long                   : 6;
+       u32 color_depth       : 3;
+       u32 portrait_mode     : 2;
+       u32 low_power_on      : 1;
+       u32 req_freq          : 4;
+       u32 en_crtc           : 1;
+       u32 en_graphic_req    : 1;
+       u32 en_graphic_crtc   : 1;
+       u32 total_req_graphic : 9;
+       u32 lcd_pclk_on       : 1;
+       u32 lcd_sclk_on       : 1;
+       u32 pclk_running      : 1;
+       u32 sclk_running      : 1;
+       u32                   : 6;
 } __attribute__((packed));
 
 struct graphic_ctrl_t_w32xx {
-       unsigned long color_depth       : 3;
-       unsigned long portrait_mode     : 2;
-       unsigned long low_power_on      : 1;
-       unsigned long req_freq          : 4;
-       unsigned long en_crtc           : 1;
-       unsigned long en_graphic_req    : 1;
-       unsigned long en_graphic_crtc   : 1;
-       unsigned long total_req_graphic : 10;
-       unsigned long lcd_pclk_on       : 1;
-       unsigned long lcd_sclk_on       : 1;
-       unsigned long pclk_running      : 1;
-       unsigned long sclk_running      : 1;
-       unsigned long                   : 5;
+       u32 color_depth       : 3;
+       u32 portrait_mode     : 2;
+       u32 low_power_on      : 1;
+       u32 req_freq          : 4;
+       u32 en_crtc           : 1;
+       u32 en_graphic_req    : 1;
+       u32 en_graphic_crtc   : 1;
+       u32 total_req_graphic : 10;
+       u32 lcd_pclk_on       : 1;
+       u32 lcd_sclk_on       : 1;
+       u32 pclk_running      : 1;
+       u32 sclk_running      : 1;
+       u32                   : 5;
 } __attribute__((packed));
 
 union graphic_ctrl_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct graphic_ctrl_t_w100 f_w100;
        struct graphic_ctrl_t_w32xx f_w32xx;
 } __attribute__((packed));
 
 struct video_ctrl_t {
-       unsigned long video_mode       : 1;
-       unsigned long keyer_en         : 1;
-       unsigned long en_video_req     : 1;
-       unsigned long en_graphic_req_video  : 1;
-       unsigned long en_video_crtc    : 1;
-       unsigned long video_hor_exp    : 2;
-       unsigned long video_ver_exp    : 2;
-       unsigned long uv_combine       : 1;
-       unsigned long total_req_video  : 9;
-       unsigned long video_ch_sel     : 1;
-       unsigned long video_portrait   : 2;
-       unsigned long yuv2rgb_en       : 1;
-       unsigned long yuv2rgb_option   : 1;
-       unsigned long video_inv_hor    : 1;
-       unsigned long video_inv_ver    : 1;
-       unsigned long gamma_sel        : 2;
-       unsigned long dis_limit        : 1;
-       unsigned long en_uv_hblend     : 1;
-       unsigned long rgb_gamma_sel    : 2;
+       u32 video_mode       : 1;
+       u32 keyer_en         : 1;
+       u32 en_video_req     : 1;
+       u32 en_graphic_req_video  : 1;
+       u32 en_video_crtc    : 1;
+       u32 video_hor_exp    : 2;
+       u32 video_ver_exp    : 2;
+       u32 uv_combine       : 1;
+       u32 total_req_video  : 9;
+       u32 video_ch_sel     : 1;
+       u32 video_portrait   : 2;
+       u32 yuv2rgb_en       : 1;
+       u32 yuv2rgb_option   : 1;
+       u32 video_inv_hor    : 1;
+       u32 video_inv_ver    : 1;
+       u32 gamma_sel        : 2;
+       u32 dis_limit        : 1;
+       u32 en_uv_hblend     : 1;
+       u32 rgb_gamma_sel    : 2;
 } __attribute__((packed));
 
 union video_ctrl_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct video_ctrl_t f;
 } __attribute__((packed));
 
 struct disp_db_buf_cntl_rd_t {
-       unsigned long en_db_buf           : 1;
-       unsigned long update_db_buf_done  : 1;
-       unsigned long db_buf_cntl         : 6;
-       unsigned long                     : 24;
+       u32 en_db_buf           : 1;
+       u32 update_db_buf_done  : 1;
+       u32 db_buf_cntl         : 6;
+       u32                     : 24;
 } __attribute__((packed));
 
 union disp_db_buf_cntl_rd_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct disp_db_buf_cntl_rd_t f;
 } __attribute__((packed));
 
 struct disp_db_buf_cntl_wr_t {
-       unsigned long en_db_buf      : 1;
-       unsigned long update_db_buf  : 1;
-       unsigned long db_buf_cntl    : 6;
-       unsigned long                : 24;
+       u32 en_db_buf      : 1;
+       u32 update_db_buf  : 1;
+       u32 db_buf_cntl    : 6;
+       u32                : 24;
 } __attribute__((packed));
 
 union disp_db_buf_cntl_wr_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct disp_db_buf_cntl_wr_t f;
 } __attribute__((packed));
 
 struct gamma_value1_t {
-       unsigned long gamma1   : 8;
-       unsigned long gamma2   : 8;
-       unsigned long gamma3   : 8;
-       unsigned long gamma4   : 8;
+       u32 gamma1   : 8;
+       u32 gamma2   : 8;
+       u32 gamma3   : 8;
+       u32 gamma4   : 8;
 } __attribute__((packed));
 
 union gamma_value1_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct gamma_value1_t f;
 } __attribute__((packed));
 
 struct gamma_value2_t {
-       unsigned long gamma5   : 8;
-       unsigned long gamma6   : 8;
-       unsigned long gamma7   : 8;
-       unsigned long gamma8   : 8;
+       u32 gamma5   : 8;
+       u32 gamma6   : 8;
+       u32 gamma7   : 8;
+       u32 gamma8   : 8;
 } __attribute__((packed));
 
 union gamma_value2_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct gamma_value2_t f;
 } __attribute__((packed));
 
 struct gamma_slope_t {
-       unsigned long slope1   : 3;
-       unsigned long slope2   : 3;
-       unsigned long slope3   : 3;
-       unsigned long slope4   : 3;
-       unsigned long slope5   : 3;
-       unsigned long slope6   : 3;
-       unsigned long slope7   : 3;
-       unsigned long slope8   : 3;
-       unsigned long          : 8;
+       u32 slope1   : 3;
+       u32 slope2   : 3;
+       u32 slope3   : 3;
+       u32 slope4   : 3;
+       u32 slope5   : 3;
+       u32 slope6   : 3;
+       u32 slope7   : 3;
+       u32 slope8   : 3;
+       u32          : 8;
 } __attribute__((packed));
 
 union gamma_slope_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct gamma_slope_t f;
 } __attribute__((packed));
 
 struct mc_ext_mem_location_t {
-       unsigned long mc_ext_mem_start : 16;
-       unsigned long mc_ext_mem_top   : 16;
+       u32 mc_ext_mem_start : 16;
+       u32 mc_ext_mem_top   : 16;
 } __attribute__((packed));
 
 union mc_ext_mem_location_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct mc_ext_mem_location_t f;
 } __attribute__((packed));
 
 struct mc_fb_location_t {
-       unsigned long mc_fb_start      : 16;
-       unsigned long mc_fb_top        : 16;
+       u32 mc_fb_start      : 16;
+       u32 mc_fb_top        : 16;
 } __attribute__((packed));
 
 union mc_fb_location_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct mc_fb_location_t f;
 } __attribute__((packed));
 
 struct clk_pin_cntl_t {
-       unsigned long osc_en           : 1;
-       unsigned long osc_gain         : 5;
-       unsigned long dont_use_xtalin  : 1;
-       unsigned long xtalin_pm_en     : 1;
-       unsigned long xtalin_dbl_en    : 1;
-       unsigned long                  : 7;
-       unsigned long cg_debug         : 16;
+       u32 osc_en           : 1;
+       u32 osc_gain         : 5;
+       u32 dont_use_xtalin  : 1;
+       u32 xtalin_pm_en     : 1;
+       u32 xtalin_dbl_en    : 1;
+       u32                  : 7;
+       u32 cg_debug         : 16;
 } __attribute__((packed));
 
 union clk_pin_cntl_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct clk_pin_cntl_t f;
 } __attribute__((packed));
 
 struct pll_ref_fb_div_t {
-       unsigned long pll_ref_div      : 4;
-       unsigned long                  : 4;
-       unsigned long pll_fb_div_int   : 6;
-       unsigned long                  : 2;
-       unsigned long pll_fb_div_frac  : 3;
-       unsigned long                  : 1;
-       unsigned long pll_reset_time   : 4;
-       unsigned long pll_lock_time    : 8;
+       u32 pll_ref_div      : 4;
+       u32                  : 4;
+       u32 pll_fb_div_int   : 6;
+       u32                  : 2;
+       u32 pll_fb_div_frac  : 3;
+       u32                  : 1;
+       u32 pll_reset_time   : 4;
+       u32 pll_lock_time    : 8;
 } __attribute__((packed));
 
 union pll_ref_fb_div_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct pll_ref_fb_div_t f;
 } __attribute__((packed));
 
 struct pll_cntl_t {
-       unsigned long pll_pwdn        : 1;
-       unsigned long pll_reset       : 1;
-       unsigned long pll_pm_en       : 1;
-       unsigned long pll_mode        : 1;
-       unsigned long pll_refclk_sel  : 1;
-       unsigned long pll_fbclk_sel   : 1;
-       unsigned long pll_tcpoff      : 1;
-       unsigned long pll_pcp         : 3;
-       unsigned long pll_pvg         : 3;
-       unsigned long pll_vcofr       : 1;
-       unsigned long pll_ioffset     : 2;
-       unsigned long pll_pecc_mode   : 2;
-       unsigned long pll_pecc_scon   : 2;
-       unsigned long pll_dactal      : 4;
-       unsigned long pll_cp_clip     : 2;
-       unsigned long pll_conf        : 3;
-       unsigned long pll_mbctrl      : 2;
-       unsigned long pll_ring_off    : 1;
+       u32 pll_pwdn        : 1;
+       u32 pll_reset       : 1;
+       u32 pll_pm_en       : 1;
+       u32 pll_mode        : 1;
+       u32 pll_refclk_sel  : 1;
+       u32 pll_fbclk_sel   : 1;
+       u32 pll_tcpoff      : 1;
+       u32 pll_pcp         : 3;
+       u32 pll_pvg         : 3;
+       u32 pll_vcofr       : 1;
+       u32 pll_ioffset     : 2;
+       u32 pll_pecc_mode   : 2;
+       u32 pll_pecc_scon   : 2;
+       u32 pll_dactal      : 4;
+       u32 pll_cp_clip     : 2;
+       u32 pll_conf        : 3;
+       u32 pll_mbctrl      : 2;
+       u32 pll_ring_off    : 1;
 } __attribute__((packed));
 
 union pll_cntl_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct pll_cntl_t f;
 } __attribute__((packed));
 
 struct sclk_cntl_t {
-       unsigned long sclk_src_sel         : 2;
-       unsigned long                      : 2;
-       unsigned long sclk_post_div_fast   : 4;
-       unsigned long sclk_clkon_hys       : 3;
-       unsigned long sclk_post_div_slow   : 4;
-       unsigned long disp_cg_ok2switch_en : 1;
-       unsigned long sclk_force_reg       : 1;
-       unsigned long sclk_force_disp      : 1;
-       unsigned long sclk_force_mc        : 1;
-       unsigned long sclk_force_extmc     : 1;
-       unsigned long sclk_force_cp        : 1;
-       unsigned long sclk_force_e2        : 1;
-       unsigned long sclk_force_e3        : 1;
-       unsigned long sclk_force_idct      : 1;
-       unsigned long sclk_force_bist      : 1;
-       unsigned long busy_extend_cp       : 1;
-       unsigned long busy_extend_e2       : 1;
-       unsigned long busy_extend_e3       : 1;
-       unsigned long busy_extend_idct     : 1;
-       unsigned long                      : 3;
+       u32 sclk_src_sel         : 2;
+       u32                      : 2;
+       u32 sclk_post_div_fast   : 4;
+       u32 sclk_clkon_hys       : 3;
+       u32 sclk_post_div_slow   : 4;
+       u32 disp_cg_ok2switch_en : 1;
+       u32 sclk_force_reg       : 1;
+       u32 sclk_force_disp      : 1;
+       u32 sclk_force_mc        : 1;
+       u32 sclk_force_extmc     : 1;
+       u32 sclk_force_cp        : 1;
+       u32 sclk_force_e2        : 1;
+       u32 sclk_force_e3        : 1;
+       u32 sclk_force_idct      : 1;
+       u32 sclk_force_bist      : 1;
+       u32 busy_extend_cp       : 1;
+       u32 busy_extend_e2       : 1;
+       u32 busy_extend_e3       : 1;
+       u32 busy_extend_idct     : 1;
+       u32                      : 3;
 } __attribute__((packed));
 
 union sclk_cntl_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct sclk_cntl_t f;
 } __attribute__((packed));
 
 struct pclk_cntl_t {
-       unsigned long pclk_src_sel     : 2;
-       unsigned long                  : 2;
-       unsigned long pclk_post_div    : 4;
-       unsigned long                  : 8;
-       unsigned long pclk_force_disp  : 1;
-       unsigned long                  : 15;
+       u32 pclk_src_sel     : 2;
+       u32                  : 2;
+       u32 pclk_post_div    : 4;
+       u32                  : 8;
+       u32 pclk_force_disp  : 1;
+       u32                  : 15;
 } __attribute__((packed));
 
 union pclk_cntl_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct pclk_cntl_t f;
 } __attribute__((packed));
 
@@ -735,36 +753,176 @@ union pclk_cntl_u {
 #define TESTCLK_SRC_XTAL  0x06
 
 struct clk_test_cntl_t {
-       unsigned long testclk_sel      : 4;
-       unsigned long                  : 3;
-       unsigned long start_check_freq : 1;
-       unsigned long tstcount_rst     : 1;
-       unsigned long                  : 15;
-       unsigned long test_count       : 8;
+       u32 testclk_sel      : 4;
+       u32                  : 3;
+       u32 start_check_freq : 1;
+       u32 tstcount_rst     : 1;
+       u32                  : 15;
+       u32 test_count       : 8;
 } __attribute__((packed));
 
 union clk_test_cntl_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct clk_test_cntl_t f;
 } __attribute__((packed));
 
 struct pwrmgt_cntl_t {
-       unsigned long pwm_enable           : 1;
-       unsigned long                      : 1;
-       unsigned long pwm_mode_req         : 2;
-       unsigned long pwm_wakeup_cond      : 2;
-       unsigned long pwm_fast_noml_hw_en  : 1;
-       unsigned long pwm_noml_fast_hw_en  : 1;
-       unsigned long pwm_fast_noml_cond   : 4;
-       unsigned long pwm_noml_fast_cond   : 4;
-       unsigned long pwm_idle_timer       : 8;
-       unsigned long pwm_busy_timer       : 8;
+       u32 pwm_enable           : 1;
+       u32                      : 1;
+       u32 pwm_mode_req         : 2;
+       u32 pwm_wakeup_cond      : 2;
+       u32 pwm_fast_noml_hw_en  : 1;
+       u32 pwm_noml_fast_hw_en  : 1;
+       u32 pwm_fast_noml_cond   : 4;
+       u32 pwm_noml_fast_cond   : 4;
+       u32 pwm_idle_timer       : 8;
+       u32 pwm_busy_timer       : 8;
 } __attribute__((packed));
 
 union pwrmgt_cntl_u {
-       unsigned long val : 32;
+       u32 val : 32;
        struct pwrmgt_cntl_t f;
 } __attribute__((packed));
 
+#define SRC_DATATYPE_EQU_DST   3
+
+#define ROP3_SRCCOPY   0xcc
+#define ROP3_PATCOPY   0xf0
+
+#define GMC_BRUSH_SOLID_COLOR  13
+#define GMC_BRUSH_NONE                 15
+
+#define DP_SRC_MEM_RECTANGULAR 2
+
+#define DP_OP_ROP      0
+
+struct dp_gui_master_cntl_t {
+       u32 gmc_src_pitch_offset_cntl : 1;
+       u32 gmc_dst_pitch_offset_cntl : 1;
+       u32 gmc_src_clipping          : 1;
+       u32 gmc_dst_clipping          : 1;
+       u32 gmc_brush_datatype        : 4;
+       u32 gmc_dst_datatype          : 4;
+       u32 gmc_src_datatype          : 3;
+       u32 gmc_byte_pix_order        : 1;
+       u32 gmc_default_sel           : 1;
+       u32 gmc_rop3                  : 8;
+       u32 gmc_dp_src_source         : 3;
+       u32 gmc_clr_cmp_fcn_dis       : 1;
+       u32                           : 1;
+       u32 gmc_wr_msk_dis            : 1;
+       u32 gmc_dp_op                 : 1;
+} __attribute__((packed));
+
+union dp_gui_master_cntl_u {
+       u32 val : 32;
+       struct dp_gui_master_cntl_t f;
+} __attribute__((packed));
+
+struct rbbm_status_t {
+       u32 cmdfifo_avail   : 7;
+       u32                 : 1;
+       u32 hirq_on_rbb     : 1;
+       u32 cprq_on_rbb     : 1;
+       u32 cfrq_on_rbb     : 1;
+       u32 hirq_in_rtbuf   : 1;
+       u32 cprq_in_rtbuf   : 1;
+       u32 cfrq_in_rtbuf   : 1;
+       u32 cf_pipe_busy    : 1;
+       u32 eng_ev_busy     : 1;
+       u32 cp_cmdstrm_busy : 1;
+       u32 e2_busy         : 1;
+       u32 rb2d_busy       : 1;
+       u32 rb3d_busy       : 1;
+       u32 se_busy         : 1;
+       u32 re_busy         : 1;
+       u32 tam_busy        : 1;
+       u32 tdm_busy        : 1;
+       u32 pb_busy         : 1;
+       u32                 : 6;
+       u32 gui_active      : 1;
+} __attribute__((packed));
+
+union rbbm_status_u {
+       u32 val : 32;
+       struct rbbm_status_t f;
+} __attribute__((packed));
+
+struct dp_datatype_t {
+       u32 dp_dst_datatype   : 4;
+       u32                   : 4;
+       u32 dp_brush_datatype : 4;
+       u32 dp_src2_type      : 1;
+       u32 dp_src2_datatype  : 3;
+       u32 dp_src_datatype   : 3;
+       u32                   : 11;
+       u32 dp_byte_pix_order : 1;
+       u32                   : 1;
+} __attribute__((packed));
+
+union dp_datatype_u {
+       u32 val : 32;
+       struct dp_datatype_t f;
+} __attribute__((packed));
+
+struct dp_mix_t {
+       u32                : 8;
+       u32 dp_src_source  : 3;
+       u32 dp_src2_source : 3;
+       u32                : 2;
+       u32 dp_rop3        : 8;
+       u32 dp_op          : 1;
+       u32                : 7;
+} __attribute__((packed));
+
+union dp_mix_u {
+       u32 val : 32;
+       struct dp_mix_t f;
+} __attribute__((packed));
+
+struct eng_cntl_t {
+       u32 erc_reg_rd_ws            : 1;
+       u32 erc_reg_wr_ws            : 1;
+       u32 erc_idle_reg_wr          : 1;
+       u32 dis_engine_triggers      : 1;
+       u32 dis_rop_src_uses_dst_w_h : 1;
+       u32 dis_src_uses_dst_dirmaj  : 1;
+       u32                          : 6;
+       u32 force_3dclk_when_2dclk   : 1;
+       u32                          : 19;
+} __attribute__((packed));
+
+union eng_cntl_u {
+       u32 val : 32;
+       struct eng_cntl_t f;
+} __attribute__((packed));
+
+struct dp_cntl_t {
+       u32 dst_x_dir   : 1;
+       u32 dst_y_dir   : 1;
+       u32 src_x_dir   : 1;
+       u32 src_y_dir   : 1;
+       u32 dst_major_x : 1;
+       u32 src_major_x : 1;
+       u32             : 26;
+} __attribute__((packed));
+
+union dp_cntl_u {
+       u32 val : 32;
+       struct dp_cntl_t f;
+} __attribute__((packed));
+
+struct dp_cntl_dst_dir_t {
+       u32           : 15;
+       u32 dst_y_dir : 1;
+       u32           : 15;
+       u32 dst_x_dir : 1;
+} __attribute__((packed));
+
+union dp_cntl_dst_dir_u {
+       u32 val : 32;
+       struct dp_cntl_dst_dir_t f;
+} __attribute__((packed));
+
 #endif
 
index f3a4f70..83bf478 100644 (file)
@@ -10,7 +10,7 @@ obj-y :=      open.o read_write.o file_table.o buffer.o  bio.o super.o \
                ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \
                attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
                seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \
-               ioprio.o pnode.o drop_caches.o splice.o
+               ioprio.o pnode.o drop_caches.o splice.o sync.o
 
 obj-$(CONFIG_INOTIFY)          += inotify.o
 obj-$(CONFIG_EPOLL)            += eventpoll.o
index 4e1b849..f3418f7 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/seq_file.h>
 
 #include <linux/kobject.h>
 #include <linux/kobj_map.h>
@@ -27,8 +28,6 @@
 
 static struct kobj_map *cdev_map;
 
-#define MAX_PROBE_HASH 255     /* random */
-
 static DEFINE_MUTEX(chrdevs_lock);
 
 static struct char_device_struct {
@@ -39,93 +38,29 @@ static struct char_device_struct {
        char name[64];
        struct file_operations *fops;
        struct cdev *cdev;              /* will die */
-} *chrdevs[MAX_PROBE_HASH];
+} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
 
 /* index in the above */
 static inline int major_to_index(int major)
 {
-       return major % MAX_PROBE_HASH;
-}
-
-struct chrdev_info {
-       int index;
-       struct char_device_struct *cd;
-};
-
-void *get_next_chrdev(void *dev)
-{
-       struct chrdev_info *info;
-
-       if (dev == NULL) {
-               info = kmalloc(sizeof(*info), GFP_KERNEL);
-               if (!info)
-                       goto out;
-               info->index=0;
-               info->cd = chrdevs[info->index];
-               if (info->cd)
-                       goto out;
-       } else {
-               info = dev;
-       }
-
-       while (info->index < ARRAY_SIZE(chrdevs)) {
-               if (info->cd)
-                       info->cd = info->cd->next;
-               if (info->cd)
-                       goto out;
-               /*
-                * No devices on this chain, move to the next
-                */
-               info->index++;
-               info->cd = (info->index < ARRAY_SIZE(chrdevs)) ?
-                       chrdevs[info->index] : NULL;
-               if (info->cd)
-                       goto out;
-       }
-
-out:
-       return info;
-}
-
-void *acquire_chrdev_list(void)
-{
-       mutex_lock(&chrdevs_lock);
-       return get_next_chrdev(NULL);
-}
-
-void release_chrdev_list(void *dev)
-{
-       mutex_unlock(&chrdevs_lock);
-       kfree(dev);
+       return major % CHRDEV_MAJOR_HASH_SIZE;
 }
 
+#ifdef CONFIG_PROC_FS
 
-int count_chrdev_list(void)
+void chrdev_show(struct seq_file *f, off_t offset)
 {
        struct char_device_struct *cd;
-       int i, count;
-
-       count = 0;
 
-       for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
-               for (cd = chrdevs[i]; cd; cd = cd->next)
-                       count++;
+       if (offset < CHRDEV_MAJOR_HASH_SIZE) {
+               mutex_lock(&chrdevs_lock);
+               for (cd = chrdevs[offset]; cd; cd = cd->next)
+                       seq_printf(f, "%3d %s\n", cd->major, cd->name);
+               mutex_unlock(&chrdevs_lock);
        }
-
-       return count;
 }
 
-int get_chrdev_info(void *dev, int *major, char **name)
-{
-       struct chrdev_info *info = dev;
-
-       if (info->cd == NULL)
-               return 1;
-
-       *major = info->cd->major;
-       *name = info->cd->name;
-       return 0;
-}
+#endif /* CONFIG_PROC_FS */
 
 /*
  * Register a single major with a specified minor range.
index cb68efb..8a2de03 100644 (file)
@@ -1,3 +1,21 @@
+Version 1.42
+------------
+Fix slow oplock break when mounted to different servers at the same time and
+the tids match and we try to find matching fid on wrong server.
+
+Version 1.41
+------------
+Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can
+configure stronger authentication.  Fix sfu symlinks so they can
+be followed (not just recognized).  Fix wraparound of bcc on
+read responses when buffer size over 64K and also fix wrap of
+max smb buffer size when CIFSMaxBufSize over 64K.  Fix oops in
+cifs_user_read and cifs_readpages (when EAGAIN on send of smb
+on socket is returned over and over).  Add POSIX (advisory) byte range
+locking support (requires server with newest CIFS UNIX Extensions
+to the protocol implemented). Slow down negprot slightly in port 139
+RFC1001 case to give session_init time on buggy servers.
+
 Version 1.40
 ------------
 Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
index 7384947..58c7725 100644 (file)
@@ -3,4 +3,4 @@
 #
 obj-$(CONFIG_CIFS) += cifs.o
 
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o
+cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o
index b0070d1..b2b4d08 100644 (file)
@@ -422,6 +422,13 @@ A partial list of the supported mount options follows:
  nomapchars     Do not translate any of these seven characters (default).
  nocase         Request case insensitive path name matching (case
                sensitive is the default if the server suports it).
+ posixpaths     If CIFS Unix extensions are supported, attempt to
+               negotiate posix path name support which allows certain
+               characters forbidden in typical CIFS filenames, without
+               requiring remapping. (default)
+ noposixpaths   If CIFS Unix extensions are supported, do not request
+               posix path name support (this may cause servers to
+               reject creatingfile with certain reserved characters).
  nobrl          Do not send byte range lock requests to the server.
                This is necessary for certain applications that break
                with cifs style mandatory byte range locks (and most
index a2c2485..e7d6373 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsencrypt.c
  *
- *   Copyright (C) International Business Machines  Corp., 2005
+ *   Copyright (C) International Business Machines  Corp., 2005,2006
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -36,7 +36,8 @@
 extern void mdfour(unsigned char *out, unsigned char *in, int n);
 extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
        
-static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
+static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, 
+                                   const char * key, char * signature)
 {
        struct  MD5Context context;
 
@@ -56,9 +57,6 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
        int rc = 0;
        char smb_signature[20];
 
-       /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
-       /* BB remember to add code to save expected sequence number in midQ entry BB */
-
        if((cifs_pdu == NULL) || (server == NULL))
                return -EINVAL;
 
@@ -85,20 +83,33 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
 static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
                                const char * key, char * signature)
 {
-        struct  MD5Context context;
-
-        if((iov == NULL) || (signature == NULL))
-                return -EINVAL;
+       struct  MD5Context context;
+       int i;
 
-        MD5Init(&context);
-        MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+       if((iov == NULL) || (signature == NULL))
+               return -EINVAL;
 
-/*        MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */
+       MD5Init(&context);
+       MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+       for(i=0;i<n_vec;i++) {
+               if(iov[i].iov_base == NULL) {
+                       cERROR(1,("null iovec entry"));
+                       return -EIO;
+               } else if(iov[i].iov_len == 0)
+                       break; /* bail out if we are sent nothing to sign */
+               /* The first entry includes a length field (which does not get 
+                  signed that occupies the first 4 bytes before the header */
+               if(i==0) {
+                       if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
+                               break; /* nothing to sign or corrupt header */
+                       MD5Update(&context,iov[0].iov_base+4, iov[0].iov_len-4);
+               } else
+                       MD5Update(&context,iov[i].iov_base, iov[i].iov_len);
+       }
 
-        MD5Final(signature,&context);
+       MD5Final(signature,&context);
 
-       return -EOPNOTSUPP;
-/*        return 0; */
+       return 0;
 }
 
 
@@ -259,4 +270,5 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon
 /*     hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
 
        hmac_md5_final(v2_session_response,&context);
+       cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */
 }
index 4bbc544..d4b713e 100644 (file)
@@ -93,13 +93,10 @@ cifs_read_super(struct super_block *sb, void *data,
        int rc = 0;
 
        sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
-       sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
+       sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
        cifs_sb = CIFS_SB(sb);
        if(cifs_sb == NULL)
                return -ENOMEM;
-       else
-               memset(cifs_sb,0,sizeof(struct cifs_sb_info));
-       
 
        rc = cifs_mount(sb, cifs_sb, data, devname);
 
index 74f405a..4e829dc 100644 (file)
@@ -99,5 +99,5 @@ extern ssize_t        cifs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
                       unsigned int command, unsigned long arg);
-#define CIFS_VERSION   "1.40"
+#define CIFS_VERSION   "1.42"
 #endif                         /* _CIFSFS_H */
index 7bed276..006eb33 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsglob.h
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2005
+ *   Copyright (C) International Business Machines  Corp., 2002,2006
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -430,6 +430,15 @@ struct dir_notify_req {
 #define   CIFS_LARGE_BUFFER     2
 #define   CIFS_IOVEC            4    /* array of response buffers */
 
+/* Type of session setup needed */
+#define   CIFS_PLAINTEXT       0
+#define   CIFS_LANMAN          1
+#define   CIFS_NTLM            2
+#define   CIFS_NTLMSSP_NEG     3
+#define   CIFS_NTLMSSP_AUTH    4
+#define   CIFS_SPNEGO_INIT     5
+#define   CIFS_SPNEGO_TARG     6
+
 /*
  *****************************************************************
  * All constants go here
index cc24710..b2233ac 100644 (file)
@@ -859,7 +859,10 @@ typedef struct smb_com_lock_req {
        LOCKING_ANDX_RANGE Locks[1];
 } __attribute__((packed)) LOCK_REQ;
 
-
+/* lock type */
+#define CIFS_RDLCK     0
+#define CIFS_WRLCK     1
+#define CIFS_UNLCK      2
 typedef struct cifs_posix_lock {
        __le16  lock_type;  /* 0 = Read, 1 = Write, 2 = Unlock */
        __le16  lock_flags; /* 1 = Wait (only valid for setlock) */
@@ -1786,7 +1789,13 @@ typedef struct {
 #define CIFS_UNIX_POSIX_ACL_CAP         0x00000002 /* support getfacl/setfacl */
 #define CIFS_UNIX_XATTR_CAP             0x00000004 /* support new namespace   */
 #define CIFS_UNIX_EXTATTR_CAP           0x00000008 /* support chattr/chflag   */
-#define CIFS_UNIX_POSIX_PATHNAMES_CAP   0x00000010 /* Use POSIX pathnames on the wire. */
+#define CIFS_UNIX_POSIX_PATHNAMES_CAP   0x00000010 /* Allow POSIX path chars  */
+#ifdef CONFIG_CIFS_POSIX
+#define CIFS_UNIX_CAP_MASK              0x0000001b
+#else 
+#define CIFS_UNIX_CAP_MASK              0x00000013
+#endif /* CONFIG_CIFS_POSIX */
+
 
 #define CIFS_POSIX_EXTENSIONS           0x00000010 /* support for new QFSInfo */
 
index 7b25463..2879ba3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsproto.h
  *
- *   Copyright (c) International Business Machines  Corp., 2002,2005
+ *   Copyright (c) International Business Machines  Corp., 2002,2006
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -64,6 +64,14 @@ extern int map_smb_to_linux_error(struct smb_hdr *smb);
 extern void header_assemble(struct smb_hdr *, char /* command */ ,
                            const struct cifsTconInfo *, int /* length of
                            fixed section (word count) in two byte units */);
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
+                               struct cifsSesInfo *ses,
+                               void ** request_buf);
+extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
+                            const int stage, int * pNTLMv2_flg,
+                            const struct nls_table *nls_cp);
+#endif
 extern __u16 GetNextMid(struct TCP_Server_Info *server);
 extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, 
                                                 struct cifsTconInfo *);
@@ -257,7 +265,10 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
                        const __u64 offset, const __u32 numUnlock,
                        const __u32 numLock, const __u8 lockType,
                        const int waitFlag);
-
+extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
+                       const __u16 smb_file_id, const int get_flag,
+                       const __u64 len, const __u64 offset, 
+                       const __u16 lock_type, const int waitFlag);
 extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
 extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
 
index a243fe2..d705500 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifssmb.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2005
+ *   Copyright (C) International Business Machines  Corp., 2002,2006
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   Contains the routines for constructing the SMB PDUs themselves
@@ -186,7 +186,35 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                 cifs_stats_inc(&tcon->num_smbs_sent);
 
        return rc;
-}  
+}
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL  
+int
+small_smb_init_no_tc(const int smb_command, const int wct, 
+                    struct cifsSesInfo *ses, void **request_buf)
+{
+       int rc;
+       struct smb_hdr * buffer;
+
+       rc = small_smb_init(smb_command, wct, NULL, request_buf);
+       if(rc)
+               return rc;
+
+       buffer = (struct smb_hdr *)*request_buf;
+       buffer->Mid = GetNextMid(ses->server);
+       if (ses->capabilities & CAP_UNICODE)
+               buffer->Flags2 |= SMBFLG2_UNICODE;
+       if (ses->capabilities & CAP_STATUS32)
+               buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+
+       /* uid, tid can stay at zero as set in header assemble */
+
+       /* BB add support for turning on the signing when 
+       this function is used after 1st of session setup requests */
+
+       return rc;
+}
+#endif  /* CONFIG_CIFS_EXPERIMENTAL */
 
 /* If the return code is zero, this function must fill in request_buf pointer */
 static int
@@ -1042,7 +1070,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
                }
        }
 
-       cifs_small_buf_release(pSMB);
+/*     cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
        if(*buf) {
                if(resp_buf_type == CIFS_SMALL_BUFFER)
                        cifs_small_buf_release(iov[0].iov_base);
@@ -1246,7 +1274,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
                *nbytes += le16_to_cpu(pSMBr->Count);
        } 
 
-       cifs_small_buf_release(pSMB);
+/*     cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
        if(resp_buf_type == CIFS_SMALL_BUFFER)
                cifs_small_buf_release(iov[0].iov_base);
        else if(resp_buf_type == CIFS_LARGE_BUFFER)
@@ -1324,6 +1352,85 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        return rc;
 }
 
+int
+CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
+               const __u16 smb_file_id, const int get_flag, const __u64 len,
+               const __u64 lkoffset, const __u16 lock_type, const int waitFlag)
+{
+       struct smb_com_transaction2_sfi_req *pSMB  = NULL;
+       struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+       char *data_offset;
+       struct cifs_posix_lock *parm_data;
+       int rc = 0;
+       int bytes_returned = 0;
+       __u16 params, param_offset, offset, byte_count, count;
+
+       cFYI(1, ("Posix Lock"));
+       rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+       if (rc)
+               return rc;
+
+       pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
+
+       params = 6; 
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+       offset = param_offset + params;
+
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+
+       count = sizeof(struct cifs_posix_lock);
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       if(get_flag)
+               pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+       else
+               pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+       byte_count = 3 /* pad */  + params + count;
+       pSMB->DataCount = cpu_to_le16(count);
+       pSMB->ParameterCount = cpu_to_le16(params);
+       pSMB->TotalDataCount = pSMB->DataCount;
+       pSMB->TotalParameterCount = pSMB->ParameterCount;
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       parm_data = (struct cifs_posix_lock *) 
+                       (((char *) &pSMB->hdr.Protocol) + offset);
+
+       parm_data->lock_type = cpu_to_le16(lock_type);
+       if(waitFlag)
+               parm_data->lock_flags = 1;
+       parm_data->pid = cpu_to_le32(current->tgid);
+       parm_data->start = lkoffset;
+       parm_data->length = len;  /* normalize negative numbers */
+
+       pSMB->DataOffset = cpu_to_le16(offset);
+       pSMB->Fid = smb_file_id;
+       pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
+       pSMB->Reserved4 = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                       (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (rc) {
+               cFYI(1, ("Send error in Posix Lock = %d", rc));
+       }
+
+       if (pSMB)
+               cifs_small_buf_release(pSMB);
+
+       /* Note: On -EAGAIN error only caller can retry on handle based calls
+          since file handle passed in no longer valid */
+
+       return rc;
+}
+
+
 int
 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
 {
@@ -2578,7 +2685,7 @@ qsec_out:
                cifs_small_buf_release(iov[0].iov_base);
        else if(buf_type == CIFS_LARGE_BUFFER)
                cifs_buf_release(iov[0].iov_base);
-       cifs_small_buf_release(pSMB);
+/*     cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
        return rc;
 }
 
@@ -2954,7 +3061,8 @@ findFirstRetry:
        pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        pSMB->ParameterOffset = cpu_to_le16(
-         offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
+             offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
+               - 4);
        pSMB->DataCount = 0;
        pSMB->DataOffset = 0;
        pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
@@ -2977,12 +3085,12 @@ findFirstRetry:
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_ffirst);
 
-       if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
+       if (rc) {/* BB add logic to retry regular search if Unix search
+                       rejected unexpectedly by server */
                /* BB Add code to handle unsupported level rc */
                cFYI(1, ("Error in FindFirst = %d", rc));
 
-               if (pSMB)
-                       cifs_buf_release(pSMB);
+               cifs_buf_release(pSMB);
 
                /* BB eventually could optimize out free and realloc of buf */
                /*    for this case */
@@ -2998,6 +3106,7 @@ findFirstRetry:
                                psrch_inf->unicode = FALSE;
 
                        psrch_inf->ntwrk_buf_start = (char *)pSMBr;
+                       psrch_inf->smallBuf = 0;
                        psrch_inf->srch_entries_start = 
                                (char *) &pSMBr->hdr.Protocol + 
                                        le16_to_cpu(pSMBr->t2.DataOffset);
@@ -3118,9 +3227,14 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
                        parms = (T2_FNEXT_RSP_PARMS *)response_data;
                        response_data = (char *)&pSMBr->hdr.Protocol +
                                le16_to_cpu(pSMBr->t2.DataOffset);
-                       cifs_buf_release(psrch_inf->ntwrk_buf_start);
+                       if(psrch_inf->smallBuf)
+                               cifs_small_buf_release(
+                                       psrch_inf->ntwrk_buf_start);
+                       else
+                               cifs_buf_release(psrch_inf->ntwrk_buf_start);
                        psrch_inf->srch_entries_start = response_data;
                        psrch_inf->ntwrk_buf_start = (char *)pSMB;
+                       psrch_inf->smallBuf = 0;
                        if(parms->EndofSearch)
                                psrch_inf->endOfSearch = TRUE;
                        else
@@ -3834,6 +3948,7 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
 
        cFYI(1, ("In SETFSUnixInfo"));
 SETFSUnixRetry:
+       /* BB switch to small buf init to save memory */
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
        if (rc)
index 2a0c1f4..0b86d5c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/connect.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2005
+ *   Copyright (C) International Business Machines  Corp., 2002,2006
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -564,7 +564,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
        
 
                dump_smb(smb_buffer, length);
-               if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
+               if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
                        cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
                        continue;
                }
@@ -1476,6 +1476,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
                        rc = smb_send(*csocket, smb_buf, 0x44,
                                (struct sockaddr *)psin_server);
                        kfree(ses_init_buf);
+                       msleep(1); /* RFC1001 layer in at least one server 
+                                     requires very short break before negprot
+                                     presumably because not expecting negprot
+                                     to follow so fast.  This is a simple
+                                     solution that works without 
+                                     complicating the code and causes no
+                                     significant slowing down on mount
+                                     for everyone else */
                }
                /* else the negprot may still work without this 
                even though malloc failed */
@@ -1920,27 +1928,34 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                cifs_sb->tcon = tcon;
                tcon->ses = pSesInfo;
 
-               /* do not care if following two calls succeed - informational only */
+               /* do not care if following two calls succeed - informational */
                CIFSSMBQFSDeviceInfo(xid, tcon);
                CIFSSMBQFSAttributeInfo(xid, tcon);
+
                if (tcon->ses->capabilities & CAP_UNIX) {
                        if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
-                               if(!volume_info.no_psx_acl) {
-                                       if(CIFS_UNIX_POSIX_ACL_CAP & 
-                                          le64_to_cpu(tcon->fsUnixInfo.Capability))
-                                               cFYI(1,("server negotiated posix acl support"));
-                                               sb->s_flags |= MS_POSIXACL;
+                               __u64 cap = 
+                                      le64_to_cpu(tcon->fsUnixInfo.Capability);
+                               cap &= CIFS_UNIX_CAP_MASK;
+                               if(volume_info.no_psx_acl)
+                                       cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
+                               else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
+                                       cFYI(1,("negotiated posix acl support"));
+                                       sb->s_flags |= MS_POSIXACL;
                                }
 
-                               /* Try and negotiate POSIX pathnames if we can. */
-                               if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
-                                   le64_to_cpu(tcon->fsUnixInfo.Capability))) {
-                                       if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP))  {
-                                               cFYI(1,("negotiated posix pathnames support"));
-                                               cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
-                                       } else {
-                                               cFYI(1,("posix pathnames support requested but not supported"));
-                                       }
+                               if(volume_info.posix_paths == 0)
+                                       cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
+                               else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+                                       cFYI(1,("negotiate posix pathnames"));
+                                       cifs_sb->mnt_cifs_flags |= 
+                                               CIFS_MOUNT_POSIX_PATHS;
+                               }
+                                       
+                               cFYI(1,("Negotiate caps 0x%x",(int)cap));
+
+                               if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
+                                       cFYI(1,("setting capabilities failed"));
                                }
                        }
                }
@@ -2278,6 +2293,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        smb_buffer->Mid = GetNextMid(ses->server);
        pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
        pSMB->req.AndXCommand = 0xFF;
+       if(ses->server->maxBuf > 64*1024)
+               ses->server->maxBuf = (64*1023);
        pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
        pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
 
@@ -2525,7 +2542,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
        __u32 negotiate_flags, capabilities;
        __u16 count;
 
-       cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
+       cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
        if(ses == NULL)
                return -EINVAL;
        domain = ses->domainName;
@@ -2575,7 +2592,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
        SecurityBlob->MessageType = NtLmNegotiate;
        negotiate_flags =
            NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
-           NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
+           NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
+           NTLMSSP_NEGOTIATE_56 |
            /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
        if(sign_CIFS_PDUs)
                negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -2588,26 +2606,11 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
        SecurityBlob->WorkstationName.Length = 0;
        SecurityBlob->WorkstationName.MaximumLength = 0;
 
-       if (domain == NULL) {
-               SecurityBlob->DomainName.Buffer = 0;
-               SecurityBlob->DomainName.Length = 0;
-               SecurityBlob->DomainName.MaximumLength = 0;
-       } else {
-               __u16 len;
-               negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
-               strncpy(bcc_ptr, domain, 63);
-               len = strnlen(domain, 64);
-               SecurityBlob->DomainName.MaximumLength =
-                   cpu_to_le16(len);
-               SecurityBlob->DomainName.Buffer =
-                   cpu_to_le32((long) &SecurityBlob->
-                               DomainString -
-                               (long) &SecurityBlob->Signature);
-               bcc_ptr += len;
-               SecurityBlobLength += len;
-               SecurityBlob->DomainName.Length =
-                   cpu_to_le16(len);
-       }
+       /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
+       along with username on auth request (ie the response to challenge) */
+       SecurityBlob->DomainName.Buffer = 0;
+       SecurityBlob->DomainName.Length = 0;
+       SecurityBlob->DomainName.MaximumLength = 0;
        if (ses->capabilities & CAP_UNICODE) {
                if ((long) bcc_ptr % 2) {
                        *bcc_ptr = 0;
@@ -2677,7 +2680,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                              SecurityBlob2->MessageType));
                } else if (ses) {
                        ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ 
-                       cFYI(1, ("UID = %d ", ses->Suid));
+                       cFYI(1, ("UID = %d", ses->Suid));
                        if ((pSMBr->resp.hdr.WordCount == 3)
                            || ((pSMBr->resp.hdr.WordCount == 4)
                                && (blob_len <
@@ -2685,17 +2688,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 
                                if (pSMBr->resp.hdr.WordCount == 4) {
                                        bcc_ptr += blob_len;
-                                       cFYI(1,
-                                            ("Security Blob Length %d ",
+                                       cFYI(1, ("Security Blob Length %d",
                                              blob_len));
                                }
 
-                               cFYI(1, ("NTLMSSP Challenge rcvd "));
+                               cFYI(1, ("NTLMSSP Challenge rcvd"));
 
                                memcpy(ses->server->cryptKey,
                                       SecurityBlob2->Challenge,
                                       CIFS_CRYPTO_KEY_SIZE);
-                               if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
+                               if(SecurityBlob2->NegotiateFlags & 
+                                       cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
                                        *pNTLMv2_flag = TRUE;
 
                                if((SecurityBlob2->NegotiateFlags & 
@@ -2818,7 +2821,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                bcc_ptr++;
                                        } else
                                                cFYI(1,
-                                                    ("Variable field of length %d extends beyond end of smb ",
+                                                    ("Variable field of length %d extends beyond end of smb",
                                                      len));
                                }
                        } else {
@@ -2830,7 +2833,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                }
        } else {
                cERROR(1,
-                      (" Invalid Word count %d: ",
+                      (" Invalid Word count %d:",
                        smb_buffer_response->WordCount));
                rc = -EIO;
        }
@@ -3447,7 +3450,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
                if (extended_security
                                && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
                                && (pSesInfo->server->secType == NTLMSSP)) {
-                       cFYI(1, ("New style sesssetup "));
+                       cFYI(1, ("New style sesssetup"));
                        rc = CIFSSpnegoSessSetup(xid, pSesInfo,
                                NULL /* security blob */, 
                                0 /* blob length */,
@@ -3455,7 +3458,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
                } else if (extended_security
                           && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
                           && (pSesInfo->server->secType == RawNTLMSSP)) {
-                       cFYI(1, ("NTLMSSP sesssetup "));
+                       cFYI(1, ("NTLMSSP sesssetup"));
                        rc = CIFSNTLMSSPNegotiateSessSetup(xid,
                                                pSesInfo,
                                                &ntlmv2_flag,
index 632561d..1d0ca3e 100644 (file)
@@ -48,13 +48,14 @@ build_path_from_dentry(struct dentry *direntry)
        struct dentry *temp;
        int namelen = 0;
        char *full_path;
-       char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
+       char dirsep;
 
        if(direntry == NULL)
                return NULL;  /* not much we can do if dentry is freed and
                we need to reopen the file after it was closed implicitly
                when the server crashed */
 
+       dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
 cifs_bp_rename_retry:
        for (temp = direntry; !IS_ROOT(temp);) {
                namelen += (1 + temp->d_name.len);
@@ -255,12 +256,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                        CIFSSMBClose(xid, pTcon, fileHandle);
                } else if(newinode) {
                        pCifsFile =
-                          kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
+                          kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
                        
                        if(pCifsFile == NULL)
                                goto cifs_create_out;
-                       memset((char *)pCifsFile, 0,
-                              sizeof (struct cifsFileInfo));
                        pCifsFile->netfid = fileHandle;
                        pCifsFile->pid = current->tgid;
                        pCifsFile->pInode = newinode;
index fb49aef..5c497c5 100644 (file)
@@ -555,7 +555,10 @@ int cifs_closedir(struct inode *inode, struct file *file)
                if (ptmp) {
                        cFYI(1, ("closedir free smb buf in srch struct"));
                        pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
-                       cifs_buf_release(ptmp);
+                       if(pCFileStruct->srch_inf.smallBuf)
+                               cifs_small_buf_release(ptmp);
+                       else
+                               cifs_buf_release(ptmp);
                }
                ptmp = pCFileStruct->search_resume_name;
                if (ptmp) {
@@ -574,13 +577,14 @@ int cifs_closedir(struct inode *inode, struct file *file)
 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
 {
        int rc, xid;
-       __u32 lockType = LOCKING_ANDX_LARGE_FILES;
        __u32 numLock = 0;
        __u32 numUnlock = 0;
        __u64 length;
        int wait_flag = FALSE;
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *pTcon;
+       __u16 netfid;
+       __u8 lockType = LOCKING_ANDX_LARGE_FILES;
 
        length = 1 + pfLock->fl_end - pfLock->fl_start;
        rc = -EACCES;
@@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                pfLock->fl_end));
 
        if (pfLock->fl_flags & FL_POSIX)
-               cFYI(1, ("Posix "));
+               cFYI(1, ("Posix"));
        if (pfLock->fl_flags & FL_FLOCK)
-               cFYI(1, ("Flock "));
+               cFYI(1, ("Flock"));
        if (pfLock->fl_flags & FL_SLEEP) {
-               cFYI(1, ("Blocking lock "));
+               cFYI(1, ("Blocking lock"));
                wait_flag = TRUE;
        }
        if (pfLock->fl_flags & FL_ACCESS)
@@ -612,21 +616,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                cFYI(1, ("F_WRLCK "));
                numLock = 1;
        } else if (pfLock->fl_type == F_UNLCK) {
-               cFYI(1, ("F_UNLCK "));
+               cFYI(1, ("F_UNLCK"));
                numUnlock = 1;
+               /* Check if unlock includes more than
+               one lock range */
        } else if (pfLock->fl_type == F_RDLCK) {
-               cFYI(1, ("F_RDLCK "));
+               cFYI(1, ("F_RDLCK"));
                lockType |= LOCKING_ANDX_SHARED_LOCK;
                numLock = 1;
        } else if (pfLock->fl_type == F_EXLCK) {
-               cFYI(1, ("F_EXLCK "));
+               cFYI(1, ("F_EXLCK"));
                numLock = 1;
        } else if (pfLock->fl_type == F_SHLCK) {
-               cFYI(1, ("F_SHLCK "));
+               cFYI(1, ("F_SHLCK"));
                lockType |= LOCKING_ANDX_SHARED_LOCK;
                numLock = 1;
        } else
-               cFYI(1, ("Unknown type of lock "));
+               cFYI(1, ("Unknown type of lock"));
 
        cifs_sb = CIFS_SB(file->f_dentry->d_sb);
        pTcon = cifs_sb->tcon;
@@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                FreeXid(xid);
                return -EBADF;
        }
+       netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
+
 
+       /* BB add code here to normalize offset and length to
+       account for negative length which we can not accept over the
+       wire */
        if (IS_GETLK(cmd)) {
-               rc = CIFSSMBLock(xid, pTcon,
-                                ((struct cifsFileInfo *)file->
-                                 private_data)->netfid,
-                                length,
-                                pfLock->fl_start, 0, 1, lockType,
-                                0 /* wait flag */ );
+               if(experimEnabled && 
+                  (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+                  (CIFS_UNIX_FCNTL_CAP & 
+                       le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
+                       int posix_lock_type;
+                       if(lockType & LOCKING_ANDX_SHARED_LOCK)
+                               posix_lock_type = CIFS_RDLCK;
+                       else
+                               posix_lock_type = CIFS_WRLCK;
+                       rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */,
+                                       length, pfLock->fl_start,
+                                       posix_lock_type, wait_flag);
+                       FreeXid(xid);
+                       return rc;
+               }
+
+               /* BB we could chain these into one lock request BB */
+               rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
+                                0, 1, lockType, 0 /* wait flag */ );
                if (rc == 0) {
-                       rc = CIFSSMBLock(xid, pTcon,
-                                        ((struct cifsFileInfo *) file->
-                                         private_data)->netfid,
-                                        length,
+                       rc = CIFSSMBLock(xid, pTcon, netfid, length, 
                                         pfLock->fl_start, 1 /* numUnlock */ ,
                                         0 /* numLock */ , lockType,
                                         0 /* wait flag */ );
                        pfLock->fl_type = F_UNLCK;
                        if (rc != 0)
                                cERROR(1, ("Error unlocking previously locked "
-                                          "range %d during test of lock ",
-                                          rc));
+                                          "range %d during test of lock", rc));
                        rc = 0;
 
                } else {
@@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                FreeXid(xid);
                return rc;
        }
-
-       rc = CIFSSMBLock(xid, pTcon,
-                        ((struct cifsFileInfo *) file->private_data)->
-                        netfid, length,
-                        pfLock->fl_start, numUnlock, numLock, lockType,
-                        wait_flag);
+       if (experimEnabled &&
+               (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+               (CIFS_UNIX_FCNTL_CAP &
+                        le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
+               int posix_lock_type;
+               if(lockType & LOCKING_ANDX_SHARED_LOCK)
+                       posix_lock_type = CIFS_RDLCK;
+               else
+                       posix_lock_type = CIFS_WRLCK;
+               
+               if(numUnlock == 1)
+                       posix_lock_type = CIFS_UNLCK;
+               else if(numLock == 0) {
+                       /* if no lock or unlock then nothing
+                       to do since we do not know what it is */
+                       FreeXid(xid);
+                       return -EOPNOTSUPP;
+               }
+               rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
+                                     length, pfLock->fl_start,
+                                     posix_lock_type, wait_flag);
+       } else
+               rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
+                               numUnlock, numLock, lockType, wait_flag);
        if (pfLock->fl_flags & FL_POSIX)
                posix_lock_file_wait(file, pfLock);
        FreeXid(xid);
index 598eec9..957ddd1 100644 (file)
@@ -565,11 +565,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
        struct cifsInodeInfo *cifsInode;
        FILE_BASIC_INFO *pinfo_buf;
 
-       cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode));
+       cFYI(1, ("cifs_unlink, inode = 0x%p", inode));
 
        xid = GetXid();
 
-       cifs_sb = CIFS_SB(inode->i_sb);
+       if(inode)
+               cifs_sb = CIFS_SB(inode->i_sb);
+       else
+               cifs_sb = CIFS_SB(direntry->d_sb);
        pTcon = cifs_sb->tcon;
 
        /* Unlink can be called from rename so we can not grab the sem here
@@ -609,9 +612,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
                }
        } else if (rc == -EACCES) {
                /* try only if r/o attribute set in local lookup data? */
-               pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
+               pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
                if (pinfo_buf) {
-                       memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
                        /* ATTRS set to normal clears r/o bit */
                        pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
                        if (!(pTcon->ses->flags & CIFS_SES_NT4))
@@ -693,9 +695,11 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
                                           when needed */
                direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
        }
-       inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
-       cifsInode = CIFS_I(inode);
-       cifsInode->time = 0;    /* force revalidate of dir as well */
+       if(inode) {
+               inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
+               cifsInode = CIFS_I(inode);
+               cifsInode->time = 0;    /* force revalidate of dir as well */
+       }
 
        kfree(full_path);
        FreeXid(xid);
@@ -1167,7 +1171,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                                                nfid, npid, FALSE);
                        atomic_dec(&open_file->wrtPending);
                        cFYI(1,("SetFSize for attrs rc = %d", rc));
-                       if(rc == -EINVAL) {
+                       if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
                                int bytes_written;
                                rc = CIFSSMBWrite(xid, pTcon,
                                                  nfid, 0, attrs->ia_size,
@@ -1189,7 +1193,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                                           cifs_sb->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
                        cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
-                       if(rc == -EINVAL) {
+                       if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
                                __u16 netfid;
                                int oplock = FALSE;
 
index 8d0da7c..9562f5b 100644 (file)
@@ -67,7 +67,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
                                        cifs_sb_target->local_nls, 
                                        cifs_sb_target->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
-               if(rc == -EIO)
+               if((rc == -EIO) || (rc == -EINVAL))
                        rc = -EOPNOTSUPP;  
        }
 
index 432ba15..fafd056 100644 (file)
@@ -72,10 +72,9 @@ sesInfoAlloc(void)
        struct cifsSesInfo *ret_buf;
 
        ret_buf =
-           (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
+           (struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo),
                                           GFP_KERNEL);
        if (ret_buf) {
-               memset(ret_buf, 0, sizeof (struct cifsSesInfo));
                write_lock(&GlobalSMBSeslock);
                atomic_inc(&sesInfoAllocCount);
                ret_buf->status = CifsNew;
@@ -110,10 +109,9 @@ tconInfoAlloc(void)
 {
        struct cifsTconInfo *ret_buf;
        ret_buf =
-           (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
+           (struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo),
                                            GFP_KERNEL);
        if (ret_buf) {
-               memset(ret_buf, 0, sizeof (struct cifsTconInfo));
                write_lock(&GlobalSMBSeslock);
                atomic_inc(&tconInfoAllocCount);
                list_add(&ret_buf->cifsConnectionList,
@@ -423,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
 {
        __u32 len = smb->smb_buf_length;
        __u32 clc_len;  /* calculated length */
-       cFYI(0,
-            ("Entering checkSMB with Length: %x, smb_buf_length: %x",
-             length, len));
+       cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
        if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
            (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
                if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
@@ -433,29 +429,36 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
                                sizeof (struct smb_hdr) - 1)
                            && (smb->Status.CifsError != 0)) {
                                smb->WordCount = 0;
-                               return 0;       /* some error cases do not return wct and bcc */
+                               /* some error cases do not return wct and bcc */
+                               return 0;
                        } else {
                                cERROR(1, ("Length less than smb header size"));
                        }
-
                }
                if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
-                       cERROR(1,
-                              ("smb_buf_length greater than MaxBufSize"));
-               cERROR(1,
-                      ("bad smb detected. Illegal length. mid=%d",
-                       smb->Mid));
+                       cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
+                                  smb->Mid));
                return 1;
        }
 
        if (checkSMBhdr(smb, mid))
                return 1;
        clc_len = smbCalcSize_LE(smb);
-       if ((4 + len != clc_len)
-           || (4 + len != (unsigned int)length)) {
-               cERROR(1, ("Calculated size 0x%x vs actual length 0x%x",
-                               clc_len, 4 + len));
-               cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));
+
+       if(4 + len != (unsigned int)length) {
+               cERROR(1, ("Length read does not match RFC1001 length %d",len));
+               return 1;
+       }
+
+       if (4 + len != clc_len) {
+               /* check if bcc wrapped around for large read responses */
+               if((len > 64 * 1024) && (len > clc_len)) {
+                       /* check if lengths match mod 64K */
+                       if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
+                               return 0; /* bcc wrapped */                     
+               }
+               cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",
+                               clc_len, 4 + len, smb->Mid));
                /* Windows XP can return a few bytes too much, presumably
                an illegal pad, at the end of byte range lock responses 
                so we allow for that three byte pad, as long as actual
@@ -469,8 +472,11 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
                wct and bcc to minimum size and drop the t2 parms and data */
                if((4+len > clc_len) && (len <= clc_len + 512))
                        return 0;
-               else
+               else {
+                       cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
+                                       len, smb->Mid));
                        return 1;
+               }
        }
        return 0;
 }
diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c
new file mode 100644 (file)
index 0000000..78866f9
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ *   fs/cifs/ntlmssp.h
+ *
+ *   Copyright (c) International Business Machines  Corp., 2006
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   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
+ */
+
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "ntlmssp.h"
+#include "nterr.h"
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
+{
+       __u32 capabilities = 0;
+
+       /* init fields common to all four types of SessSetup */
+       /* note that header is initialized to zero in header_assemble */
+       pSMB->req.AndXCommand = 0xFF;
+       pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+       pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+       /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
+
+       /* BB verify whether signing required on neg or just on auth frame 
+          (and NTLM case) */
+
+       capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+                       CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
+
+       if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+               pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+       if (ses->capabilities & CAP_UNICODE) {
+               pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
+               capabilities |= CAP_UNICODE;
+       }
+       if (ses->capabilities & CAP_STATUS32) {
+               pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
+               capabilities |= CAP_STATUS32;
+       }
+       if (ses->capabilities & CAP_DFS) {
+               pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
+               capabilities |= CAP_DFS;
+       }
+
+       /* BB check whether to init vcnum BB */
+       return capabilities;
+}
+int 
+CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type,
+                 int * pNTLMv2_flg, const struct nls_table *nls_cp)
+{
+       int rc = 0;
+       int wct;
+       struct smb_hdr *smb_buffer;
+       char *bcc_ptr;
+       SESSION_SETUP_ANDX *pSMB;
+       __u32 capabilities;
+
+       if(ses == NULL)
+               return -EINVAL;
+
+       cFYI(1,("SStp type: %d",type));
+       if(type < CIFS_NTLM) {
+#ifndef CONFIG_CIFS_WEAK_PW_HASH
+               /* LANMAN and plaintext are less secure and off by default.
+               So we make this explicitly be turned on in kconfig (in the
+               build) and turned on at runtime (changed from the default)
+               in proc/fs/cifs or via mount parm.  Unfortunately this is
+               needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
+               return -EOPNOTSUPP;
+#endif
+               wct = 10; /* lanman 2 style sessionsetup */
+       } else if(type < CIFS_NTLMSSP_NEG)
+               wct = 13; /* old style NTLM sessionsetup */
+       else /* same size for negotiate or auth, NTLMSSP or extended security */
+               wct = 12;
+
+       rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
+                           (void **)&smb_buffer);
+       if(rc)
+               return rc;
+
+       pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
+
+       capabilities = cifs_ssetup_hdr(ses, pSMB);
+       bcc_ptr = pByteArea(smb_buffer);
+       if(type > CIFS_NTLM) {
+               pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+               capabilities |= CAP_EXTENDED_SECURITY;
+               pSMB->req.Capabilities = cpu_to_le32(capabilities);
+               /* BB set password lengths */
+       } else if(type < CIFS_NTLM) /* lanman */ {
+               /* no capabilities flags in old lanman negotiation */
+               /* pSMB->old_req.PasswordLength = */ /* BB fixme BB */
+       } else /* type CIFS_NTLM */ {
+               pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+               pSMB->req_no_secext.CaseInsensitivePasswordLength =
+                       cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+               pSMB->req_no_secext.CaseSensitivePasswordLength =
+                       cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+       }
+
+
+/*     rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */
+       /* SMB request buf freed in SendReceive2 */
+
+       return rc;
+}
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
index 803389b..d39b712 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/ntlmssp.h
  *
- *   Copyright (c) International Business Machines  Corp., 2002
+ *   Copyright (c) International Business Machines  Corp., 2002,2006
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
index 488bd0d..2f6e282 100644 (file)
@@ -604,7 +604,12 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
                cifsFile->search_resume_name = NULL;
                if(cifsFile->srch_inf.ntwrk_buf_start) {
                        cFYI(1,("freeing SMB ff cache buf on search rewind"));
-                       cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start);
+                       if(cifsFile->srch_inf.smallBuf)
+                               cifs_small_buf_release(cifsFile->srch_inf.
+                                               ntwrk_buf_start);
+                       else
+                               cifs_buf_release(cifsFile->srch_inf.
+                                               ntwrk_buf_start);
                }
                rc = initiate_cifs_search(xid,file);
                if(rc) {
index b12cb8a..3da8040 100644 (file)
@@ -309,17 +309,16 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
        
        *pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
 
-       if (ses == NULL) {
-               cERROR(1,("Null smb session"));
-               return -EIO;
-       }
-       if(ses->server == NULL) {
-               cERROR(1,("Null tcp session"));
+       if ((ses == NULL) || (ses->server == NULL)) {
+               cifs_small_buf_release(in_buf);
+               cERROR(1,("Null session"));
                return -EIO;
        }
 
-       if(ses->server->tcpStatus == CifsExiting)
+       if(ses->server->tcpStatus == CifsExiting) {
+               cifs_small_buf_release(in_buf);
                return -ENOENT;
+       }
 
        /* Ensure that we do not send more than 50 overlapping requests 
           to the same server. We may make this configurable later or
@@ -346,6 +345,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
                        } else {
                                if(ses->server->tcpStatus == CifsExiting) {
                                        spin_unlock(&GlobalMid_Lock);
+                                       cifs_small_buf_release(in_buf);
                                        return -ENOENT;
                                }
 
@@ -385,6 +385,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
        midQ = AllocMidQEntry(in_buf, ses);
        if (midQ == NULL) {
                up(&ses->server->tcpSem);
+               cifs_small_buf_release(in_buf);
                /* If not lock req, update # of requests on wire to server */
                if(long_op < 3) {
                        atomic_dec(&ses->server->inFlight); 
@@ -408,14 +409,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
        if(rc < 0) {
                DeleteMidQEntry(midQ);
                up(&ses->server->tcpSem);
+               cifs_small_buf_release(in_buf);
                /* If not lock req, update # of requests on wire to server */
                if(long_op < 3) {
                        atomic_dec(&ses->server->inFlight); 
                        wake_up(&ses->server->request_q);
                }
                return rc;
-       } else
+       } else {
                up(&ses->server->tcpSem);
+               cifs_small_buf_release(in_buf);
+       }
+
        if (long_op == -1)
                goto cifs_no_response_exit2;
        else if (long_op == 2) /* writes past end of file can take loong time */
@@ -543,6 +548,7 @@ cifs_no_response_exit2:
 
 out_unlock2:
        up(&ses->server->tcpSem);
+       cifs_small_buf_release(in_buf);
        /* If not lock req, update # of requests on wire to server */
        if(long_op < 3) {
                atomic_dec(&ses->server->inFlight); 
index 19458d3..940d188 100644 (file)
@@ -1100,6 +1100,32 @@ next:
        return found;
 }
 
+/**
+ * d_hash_and_lookup - hash the qstr then search for a dentry
+ * @dir: Directory to search in
+ * @name: qstr of name we wish to find
+ *
+ * On hash failure or on lookup failure NULL is returned.
+ */
+struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
+{
+       struct dentry *dentry = NULL;
+
+       /*
+        * Check for a fs-specific hash function. Note that we must
+        * calculate the standard hash first, as the d_op->d_hash()
+        * routine may choose to leave the hash value unchanged.
+        */
+       name->hash = full_name_hash(name->name, name->len);
+       if (dir->d_op && dir->d_op->d_hash) {
+               if (dir->d_op->d_hash(dir, name) < 0)
+                       goto out;
+       }
+       dentry = d_lookup(dir, name);
+out:
+       return dentry;
+}
+
 /**
  * d_validate - verify dentry provided from insecure source
  * @dentry: The dentry alleged to be valid child of @dparent
@@ -1172,11 +1198,11 @@ void d_delete(struct dentry * dentry)
        spin_lock(&dentry->d_lock);
        isdir = S_ISDIR(dentry->d_inode->i_mode);
        if (atomic_read(&dentry->d_count) == 1) {
-               /* remove this and other inotify debug checks after 2.6.18 */
-               dentry->d_flags &= ~DCACHE_INOTIFY_PARENT_WATCHED;
-
                dentry_iput(dentry);
                fsnotify_nameremove(dentry, isdir);
+
+               /* remove this and other inotify debug checks after 2.6.18 */
+               dentry->d_flags &= ~DCACHE_INOTIFY_PARENT_WATCHED;
                return;
        }
 
@@ -1616,26 +1642,12 @@ ino_t find_inode_number(struct dentry *dir, struct qstr *name)
        struct dentry * dentry;
        ino_t ino = 0;
 
-       /*
-        * Check for a fs-specific hash function. Note that we must
-        * calculate the standard hash first, as the d_op->d_hash()
-        * routine may choose to leave the hash value unchanged.
-        */
-       name->hash = full_name_hash(name->name, name->len);
-       if (dir->d_op && dir->d_op->d_hash)
-       {
-               if (dir->d_op->d_hash(dir, name) != 0)
-                       goto out;
-       }
-
-       dentry = d_lookup(dir, name);
-       if (dentry)
-       {
+       dentry = d_hash_and_lookup(dir, name);
+       if (dentry) {
                if (dentry->d_inode)
                        ino = dentry->d_inode->i_ino;
                dput(dentry);
        }
-out:
        return ino;
 }
 
index 2ba20cd..5e6363b 100644 (file)
@@ -216,10 +216,10 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
 static struct inode_operations hppfs_file_iops = {
 };
 
-static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
+static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count,
                         loff_t *ppos, int is_user)
 {
-       ssize_t (*read)(struct file *, char *, size_t, loff_t *);
+       ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
        ssize_t n;
 
        read = file->f_dentry->d_inode->i_fop->read;
@@ -236,7 +236,7 @@ static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
        return n;
 }
 
-static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
+static ssize_t hppfs_read_file(int fd, char __user *buf, ssize_t count)
 {
        ssize_t n;
        int cur, err;
@@ -274,7 +274,7 @@ static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
        return n;
 }
 
-static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
+static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count,
                          loff_t *ppos)
 {
        struct hppfs_private *hppfs = file->private_data;
@@ -313,12 +313,12 @@ static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
        return(count);
 }
 
-static ssize_t hppfs_write(struct file *file, const char *buf, size_t len,
+static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len,
                           loff_t *ppos)
 {
        struct hppfs_private *data = file->private_data;
        struct file *proc_file = data->proc_file;
-       ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
+       ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
        int err;
 
        write = proc_file->f_dentry->d_inode->i_fop->write;
@@ -658,7 +658,7 @@ static struct super_operations hppfs_sbops = {
        .statfs         = hppfs_statfs,
 };
 
-static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen)
+static int hppfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 {
        struct file *proc_file;
        struct dentry *proc_dentry;
index 4d9e71d..dda83d6 100644 (file)
@@ -168,18 +168,9 @@ static void locks_release_private(struct file_lock *fl)
 /* Free a lock which is not in use. */
 static void locks_free_lock(struct file_lock *fl)
 {
-       if (fl == NULL) {
-               BUG();
-               return;
-       }
-       if (waitqueue_active(&fl->fl_wait))
-               panic("Attempting to free lock with active wait queue");
-
-       if (!list_empty(&fl->fl_block))
-               panic("Attempting to free lock with active block list");
-
-       if (!list_empty(&fl->fl_link))
-               panic("Attempting to free lock on active lock list");
+       BUG_ON(waitqueue_active(&fl->fl_wait));
+       BUG_ON(!list_empty(&fl->fl_block));
+       BUG_ON(!list_empty(&fl->fl_link));
 
        locks_release_private(fl);
        kmem_cache_free(filelock_cache, fl);
@@ -735,8 +726,9 @@ EXPORT_SYMBOL(posix_locks_deadlock);
  * at the head of the list, but that's secret knowledge known only to
  * flock_lock_file and posix_lock_file.
  */
-static int flock_lock_file(struct file *filp, struct file_lock *new_fl)
+static int flock_lock_file(struct file *filp, struct file_lock *request)
 {
+       struct file_lock *new_fl = NULL;
        struct file_lock **before;
        struct inode * inode = filp->f_dentry->d_inode;
        int error = 0;
@@ -751,17 +743,19 @@ static int flock_lock_file(struct file *filp, struct file_lock *new_fl)
                        continue;
                if (filp != fl->fl_file)
                        continue;
-               if (new_fl->fl_type == fl->fl_type)
+               if (request->fl_type == fl->fl_type)
                        goto out;
                found = 1;
                locks_delete_lock(before);
                break;
        }
-       unlock_kernel();
 
-       if (new_fl->fl_type == F_UNLCK)
-               return 0;
+       if (request->fl_type == F_UNLCK)
+               goto out;
 
+       new_fl = locks_alloc_lock();
+       if (new_fl == NULL)
+               goto out;
        /*
         * If a higher-priority process was blocked on the old file lock,
         * give it the opportunity to lock the file.
@@ -769,26 +763,27 @@ static int flock_lock_file(struct file *filp, struct file_lock *new_fl)
        if (found)
                cond_resched();
 
-       lock_kernel();
        for_each_lock(inode, before) {
                struct file_lock *fl = *before;
                if (IS_POSIX(fl))
                        break;
                if (IS_LEASE(fl))
                        continue;
-               if (!flock_locks_conflict(new_fl, fl))
+               if (!flock_locks_conflict(request, fl))
                        continue;
                error = -EAGAIN;
-               if (new_fl->fl_flags & FL_SLEEP) {
-                       locks_insert_block(fl, new_fl);
-               }
+               if (request->fl_flags & FL_SLEEP)
+                       locks_insert_block(fl, request);
                goto out;
        }
+       locks_copy_lock(new_fl, request);
        locks_insert_lock(&inode->i_flock, new_fl);
-       error = 0;
+       new_fl = NULL;
 
 out:
        unlock_kernel();
+       if (new_fl)
+               locks_free_lock(new_fl);
        return error;
 }
 
@@ -1569,9 +1564,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
                error = flock_lock_file_wait(filp, lock);
 
  out_free:
-       if (list_empty(&lock->fl_link)) {
-               locks_free_lock(lock);
-       }
+       locks_free_lock(lock);
 
  out_putf:
        fput(filp);
index 626a367..5b76ccd 100644 (file)
 #include <linux/msdos_fs.h>
 #include <linux/smp_lock.h>
 
-/* MS-DOS "device special files" */
-static const unsigned char *reserved_names[] = {
-       "CON     ", "PRN     ", "NUL     ", "AUX     ",
-       "LPT1    ", "LPT2    ", "LPT3    ", "LPT4    ",
-       "COM1    ", "COM2    ", "COM3    ", "COM4    ",
-       NULL
-};
-
 /* Characters that are undesirable in an MS-DOS file name */
 static unsigned char bad_chars[] = "*?<>|\"";
 static unsigned char bad_if_strict_pc[] = "+=,; ";
@@ -40,7 +32,6 @@ static int msdos_format_name(const unsigned char *name, int len,
         */
 {
        unsigned char *walk;
-       const unsigned char **reserved;
        unsigned char c;
        int space;
 
@@ -127,11 +118,7 @@ static int msdos_format_name(const unsigned char *name, int len,
        }
        while (walk - res < MSDOS_NAME)
                *walk++ = ' ';
-       if (!opts->atari)
-               /* GEMDOS is less stupid and has no reserved names */
-               for (reserved = reserved_names; *reserved; reserved++)
-                       if (!strncmp(res, *reserved, 8))
-                               return -EINVAL;
+
        return 0;
 }
 
index 22f6e8d..96723ae 100644 (file)
@@ -1254,7 +1254,7 @@ out:
        return dentry;
 }
 
-struct dentry * lookup_hash(struct nameidata *nd)
+static struct dentry *lookup_hash(struct nameidata *nd)
 {
        return __lookup_hash(&nd->last, nd->dentry, nd);
 }
@@ -2697,7 +2697,6 @@ EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
 EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(lock_rename);
-EXPORT_SYMBOL(lookup_hash);
 EXPORT_SYMBOL(lookup_one_len);
 EXPORT_SYMBOL(page_follow_link_light);
 EXPORT_SYMBOL(page_put_link);
index 8f1f49c..a3a3eec 100644 (file)
@@ -534,12 +534,15 @@ static int proc_oom_score(struct task_struct *task, char *buffer)
 
 /* If the process being read is separated by chroot from the reading process,
  * don't let the reader access the threads.
+ *
+ * note: this does dput(root) and mntput(vfsmnt) on exit.
  */
 static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt)
 {
        struct dentry *de, *base;
        struct vfsmount *our_vfsmnt, *mnt;
        int res = 0;
+
        read_lock(&current->fs->lock);
        our_vfsmnt = mntget(current->fs->rootmnt);
        base = dget(current->fs->root);
@@ -549,11 +552,11 @@ static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt)
        de = root;
        mnt = vfsmnt;
 
-       while (vfsmnt != our_vfsmnt) {
-               if (vfsmnt == vfsmnt->mnt_parent)
+       while (mnt != our_vfsmnt) {
+               if (mnt == mnt->mnt_parent)
                        goto out;
-               de = vfsmnt->mnt_mountpoint;
-               vfsmnt = vfsmnt->mnt_parent;
+               de = mnt->mnt_mountpoint;
+               mnt = mnt->mnt_parent;
        }
 
        if (!is_subdir(de, base))
@@ -564,7 +567,7 @@ exit:
        dput(base);
        mntput(our_vfsmnt);
        dput(root);
-       mntput(mnt);
+       mntput(vfsmnt);
        return res;
 out:
        spin_unlock(&vfsmount_lock);
index ef5a332..5c10ea1 100644 (file)
@@ -249,144 +249,60 @@ static int cpuinfo_open(struct inode *inode, struct file *file)
        return seq_open(file, &cpuinfo_op);
 }
 
-enum devinfo_states {
-       CHR_HDR,
-       CHR_LIST,
-       BLK_HDR,
-       BLK_LIST,
-       DEVINFO_DONE
-};
-
-struct devinfo_state {
-       void *chrdev;
-       void *blkdev;
-       unsigned int num_records;
-       unsigned int cur_record;
-       enum devinfo_states state;
+static struct file_operations proc_cpuinfo_operations = {
+       .open           = cpuinfo_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
 };
 
-static void *devinfo_start(struct seq_file *f, loff_t *pos)
+static int devinfo_show(struct seq_file *f, void *v)
 {
-       struct devinfo_state *info = f->private;
+       int i = *(loff_t *) v;
 
-       if (*pos) {
-               if ((info) && (*pos <= info->num_records))
-                       return info;
-               return NULL;
+       if (i < CHRDEV_MAJOR_HASH_SIZE) {
+               if (i == 0)
+                       seq_printf(f, "Character devices:\n");
+               chrdev_show(f, i);
+       } else {
+               i -= CHRDEV_MAJOR_HASH_SIZE;
+               if (i == 0)
+                       seq_printf(f, "\nBlock devices:\n");
+               blkdev_show(f, i);
        }
-       info = kmalloc(sizeof(*info), GFP_KERNEL);
-       f->private = info;
-       info->chrdev = acquire_chrdev_list();
-       info->blkdev = acquire_blkdev_list();
-       info->state = CHR_HDR;
-       info->num_records = count_chrdev_list();
-       info->num_records += count_blkdev_list();
-       info->num_records += 2; /* Character and Block headers */
-       *pos = 1;
-       info->cur_record = *pos;
-       return info;
+       return 0;
 }
 
-static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
+static void *devinfo_start(struct seq_file *f, loff_t *pos)
 {
-       int idummy;
-       char *ndummy;
-       struct devinfo_state *info = f->private;
-
-       switch (info->state) {
-               case CHR_HDR:
-                       info->state = CHR_LIST;
-                       (*pos)++;
-                       /*fallthrough*/
-               case CHR_LIST:
-                       if (get_chrdev_info(info->chrdev,&idummy,&ndummy)) {
-                               /*
-                                * The character dev list is complete
-                                */
-                               info->state = BLK_HDR;
-                       } else {
-                               info->chrdev = get_next_chrdev(info->chrdev);
-                       }
-                       (*pos)++;
-                       break;
-               case BLK_HDR:
-                       info->state = BLK_LIST;
-                       (*pos)++;
-                       /*fallthrough*/
-               case BLK_LIST:
-                       if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) {
-                               /*
-                                * The block dev list is complete
-                                */
-                               info->state = DEVINFO_DONE;
-                       } else {
-                               info->blkdev = get_next_blkdev(info->blkdev);
-                       }
-                       (*pos)++;
-                       break;
-               case DEVINFO_DONE:
-                       (*pos)++;
-                       info->cur_record = *pos;
-                       info = NULL;
-                       break;
-               default:
-                       break;
-       }
-       if (info)
-               info->cur_record = *pos;
-       return info;
+       if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
+               return pos;
+       return NULL;
 }
 
-static void devinfo_stop(struct seq_file *f, void *v)
+static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
 {
-       struct devinfo_state *info = f->private;
-
-       if (info) {
-               release_chrdev_list(info->chrdev);
-               release_blkdev_list(info->blkdev);
-               f->private = NULL;
-               kfree(info);
-       }
+       (*pos)++;
+       if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
+               return NULL;
+       return pos;
 }
 
-static int devinfo_show(struct seq_file *f, void *arg)
-{
-       int major;
-       char *name;
-       struct devinfo_state *info = f->private;
-
-       switch(info->state) {
-               case CHR_HDR:
-                       seq_printf(f,"Character devices:\n");
-                       /* fallthrough */
-               case CHR_LIST:
-                       if (!get_chrdev_info(info->chrdev,&major,&name))
-                               seq_printf(f,"%3d %s\n",major,name);
-                       break;
-               case BLK_HDR:
-                       seq_printf(f,"\nBlock devices:\n");
-                       /* fallthrough */
-               case BLK_LIST:
-                       if (!get_blkdev_info(info->blkdev,&major,&name))
-                               seq_printf(f,"%3d %s\n",major,name);
-                       break;
-               default:
-                       break;
-       }
-
-       return 0;
+static void devinfo_stop(struct seq_file *f, void *v)
+{
+       /* Nothing to do */
 }
 
-static  struct seq_operations devinfo_op = {
-       .start  = devinfo_start,
-       .next   = devinfo_next,
-       .stop   = devinfo_stop,
-       .show   = devinfo_show,
+static struct seq_operations devinfo_ops = {
+       .start = devinfo_start,
+       .next  = devinfo_next,
+       .stop  = devinfo_stop,
+       .show  = devinfo_show
 };
 
-static int devinfo_open(struct inode *inode, struct file *file)
+static int devinfo_open(struct inode *inode, struct file *filp)
 {
-       return seq_open(file, &devinfo_op);
+       return seq_open(filp, &devinfo_ops);
 }
 
 static struct file_operations proc_devinfo_operations = {
@@ -396,13 +312,6 @@ static struct file_operations proc_devinfo_operations = {
        .release        = seq_release,
 };
 
-static struct file_operations proc_cpuinfo_operations = {
-       .open           = cpuinfo_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
-};
-
 extern struct seq_operations vmstat_op;
 static int vmstat_open(struct inode *inode, struct file *file)
 {
index b3a3a13..071660f 100644 (file)
@@ -314,7 +314,7 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
        int ret, size, max_fdset;
        struct fdtable *fdt;
        /* Allocate small arguments on the stack to save memory and be faster */
-       char stack_fds[SELECT_STACK_ALLOC];
+       long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
 
        ret = -EINVAL;
        if (n < 0)
@@ -639,8 +639,10 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
        struct poll_list *walk;
        struct fdtable *fdt;
        int max_fdset;
-       /* Allocate small arguments on the stack to save memory and be faster */
-       char stack_pps[POLL_STACK_ALLOC];
+       /* Allocate small arguments on the stack to save memory and be
+          faster - use long to make sure the buffer is aligned properly
+          on 64 bit archs to avoid unaligned access */
+       long stack_pps[POLL_STACK_ALLOC/sizeof(long)];
        struct poll_list *stack_pp = NULL;
 
        /* Do a sanity check on nfds ... */
index 4a026f9..6081cf7 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/mm_inline.h>
 #include <linux/swap.h>
+#include <linux/module.h>
 
 /*
  * Passed to the actors
@@ -105,7 +106,7 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = {
 
 static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
                            int nr_pages, unsigned long offset,
-                           unsigned long len)
+                           unsigned long len, unsigned int flags)
 {
        struct pipe_inode_info *info;
        int ret, do_wakeup, i;
@@ -158,6 +159,12 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
                        break;
                }
 
+               if (flags & SPLICE_F_NONBLOCK) {
+                       if (!ret)
+                               ret = -EAGAIN;
+                       break;
+               }
+
                if (signal_pending(current)) {
                        if (!ret)
                                ret = -ERESTARTSYS;
@@ -190,7 +197,7 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
 }
 
 static int __generic_file_splice_read(struct file *in, struct inode *pipe,
-                                     size_t len)
+                                     size_t len, unsigned int flags)
 {
        struct address_space *mapping = in->f_mapping;
        unsigned int offset, nr_pages;
@@ -278,7 +285,7 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe,
         * Now we splice them into the pipe..
         */
 splice_them:
-       return move_to_pipe(pipe, pages, i, offset, len);
+       return move_to_pipe(pipe, pages, i, offset, len, flags);
 }
 
 ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
@@ -290,7 +297,7 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
        ret = 0;
        spliced = 0;
        while (len) {
-               ret = __generic_file_splice_read(in, pipe, len);
+               ret = __generic_file_splice_read(in, pipe, len, flags);
 
                if (ret <= 0)
                        break;
@@ -298,6 +305,11 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
                in->f_pos += ret;
                len -= ret;
                spliced += ret;
+
+               if (!(flags & SPLICE_F_NONBLOCK))
+                       continue;
+               ret = -EAGAIN;
+               break;
        }
 
        if (spliced)
@@ -526,6 +538,12 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out,
                                break;
                }
 
+               if (flags & SPLICE_F_NONBLOCK) {
+                       if (!ret)
+                               ret = -EAGAIN;
+                       break;
+               }
+
                if (signal_pending(current)) {
                        if (!ret)
                                ret = -ERESTARTSYS;
@@ -567,6 +585,9 @@ ssize_t generic_splice_sendpage(struct inode *inode, struct file *out,
        return move_from_pipe(inode, out, len, flags, pipe_to_sendpage);
 }
 
+EXPORT_SYMBOL(generic_file_splice_write);
+EXPORT_SYMBOL(generic_file_splice_read);
+
 static long do_splice_from(struct inode *pipe, struct file *out, size_t len,
                           unsigned int flags)
 {
diff --git a/fs/sync.c b/fs/sync.c
new file mode 100644 (file)
index 0000000..8616006
--- /dev/null
+++ b/fs/sync.c
@@ -0,0 +1,164 @@
+/*
+ * High-level sync()-related operations
+ */
+
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/writeback.h>
+#include <linux/syscalls.h>
+#include <linux/linkage.h>
+#include <linux/pagemap.h>
+
+#define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
+                       SYNC_FILE_RANGE_WAIT_AFTER)
+
+/*
+ * sys_sync_file_range() permits finely controlled syncing over a segment of
+ * a file in the range offset .. (offset+nbytes-1) inclusive.  If nbytes is
+ * zero then sys_sync_file_range() will operate from offset out to EOF.
+ *
+ * The flag bits are:
+ *
+ * SYNC_FILE_RANGE_WAIT_BEFORE: wait upon writeout of all pages in the range
+ * before performing the write.
+ *
+ * SYNC_FILE_RANGE_WRITE: initiate writeout of all those dirty pages in the
+ * range which are not presently under writeback.
+ *
+ * SYNC_FILE_RANGE_WAIT_AFTER: wait upon writeout of all pages in the range
+ * after performing the write.
+ *
+ * Useful combinations of the flag bits are:
+ *
+ * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE: ensures that all pages
+ * in the range which were dirty on entry to sys_sync_file_range() are placed
+ * under writeout.  This is a start-write-for-data-integrity operation.
+ *
+ * SYNC_FILE_RANGE_WRITE: start writeout of all dirty pages in the range which
+ * are not presently under writeout.  This is an asynchronous flush-to-disk
+ * operation.  Not suitable for data integrity operations.
+ *
+ * SYNC_FILE_RANGE_WAIT_BEFORE (or SYNC_FILE_RANGE_WAIT_AFTER): wait for
+ * completion of writeout of all pages in the range.  This will be used after an
+ * earlier SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE operation to wait
+ * for that operation to complete and to return the result.
+ *
+ * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER:
+ * a traditional sync() operation.  This is a write-for-data-integrity operation
+ * which will ensure that all pages in the range which were dirty on entry to
+ * sys_sync_file_range() are committed to disk.
+ *
+ *
+ * SYNC_FILE_RANGE_WAIT_BEFORE and SYNC_FILE_RANGE_WAIT_AFTER will detect any
+ * I/O errors or ENOSPC conditions and will return those to the caller, after
+ * clearing the EIO and ENOSPC flags in the address_space.
+ *
+ * It should be noted that none of these operations write out the file's
+ * metadata.  So unless the application is strictly performing overwrites of
+ * already-instantiated disk blocks, there are no guarantees here that the data
+ * will be available after a crash.
+ */
+asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
+                                       int flags)
+{
+       int ret;
+       struct file *file;
+       loff_t endbyte;                 /* inclusive */
+       int fput_needed;
+       umode_t i_mode;
+
+       ret = -EINVAL;
+       if (flags & ~VALID_FLAGS)
+               goto out;
+
+       endbyte = offset + nbytes;
+
+       if ((s64)offset < 0)
+               goto out;
+       if ((s64)endbyte < 0)
+               goto out;
+       if (endbyte < offset)
+               goto out;
+
+       if (sizeof(pgoff_t) == 4) {
+               if (offset >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
+                       /*
+                        * The range starts outside a 32 bit machine's
+                        * pagecache addressing capabilities.  Let it "succeed"
+                        */
+                       ret = 0;
+                       goto out;
+               }
+               if (endbyte >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
+                       /*
+                        * Out to EOF
+                        */
+                       nbytes = 0;
+               }
+       }
+
+       if (nbytes == 0)
+               endbyte = -1;
+       else
+               endbyte--;              /* inclusive */
+
+       ret = -EBADF;
+       file = fget_light(fd, &fput_needed);
+       if (!file)
+               goto out;
+
+       i_mode = file->f_dentry->d_inode->i_mode;
+       ret = -ESPIPE;
+       if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
+                       !S_ISLNK(i_mode))
+               goto out_put;
+
+       ret = do_sync_file_range(file, offset, endbyte, flags);
+out_put:
+       fput_light(file, fput_needed);
+out:
+       return ret;
+}
+
+/*
+ * `endbyte' is inclusive
+ */
+int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte,
+                       int flags)
+{
+       int ret;
+       struct address_space *mapping;
+
+       mapping = file->f_mapping;
+       if (!mapping) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = 0;
+       if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
+               ret = wait_on_page_writeback_range(mapping,
+                                       offset >> PAGE_CACHE_SHIFT,
+                                       endbyte >> PAGE_CACHE_SHIFT);
+               if (ret < 0)
+                       goto out;
+       }
+
+       if (flags & SYNC_FILE_RANGE_WRITE) {
+               ret = __filemap_fdatawrite_range(mapping, offset, endbyte,
+                                               WB_SYNC_NONE);
+               if (ret < 0)
+                       goto out;
+       }
+
+       if (flags & SYNC_FILE_RANGE_WAIT_AFTER) {
+               ret = wait_on_page_writeback_range(mapping,
+                                       offset >> PAGE_CACHE_SHIFT,
+                                       endbyte >> PAGE_CACHE_SHIFT);
+       }
+out:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(do_sync_file_range);
index ef46939..a56cec3 100644 (file)
@@ -185,24 +185,6 @@ static int vfat_valid_longname(const unsigned char *name, unsigned int len)
                return -EINVAL;
        if (len >= 256)
                return -ENAMETOOLONG;
-
-       /* MS-DOS "device special files" */
-       if (len == 3 || (len > 3 && name[3] == '.')) {  /* basename == 3 */
-               if (!strnicmp(name, "aux", 3) ||
-                   !strnicmp(name, "con", 3) ||
-                   !strnicmp(name, "nul", 3) ||
-                   !strnicmp(name, "prn", 3))
-                       return -EINVAL;
-       }
-       if (len == 4 || (len > 4 && name[4] == '.')) {  /* basename == 4 */
-               /* "com1", "com2", ... */
-               if ('1' <= name[3] && name[3] <= '9') {
-                       if (!strnicmp(name, "com", 3) ||
-                           !strnicmp(name, "lpt", 3))
-                               return -EINVAL;
-               }
-       }
-
        return 0;
 }
 
index 2646c01..59e6f44 100644 (file)
@@ -65,6 +65,9 @@
 /* SmartMedia */
 #define AT91_SMARTMEDIA_BASE   0x40000000      /* NCS3: Smartmedia physical base address */
 
+/* Compact Flash */
+#define AT91_CF_BASE           0x50000000      /* NCS4-NCS6: Compact Flash physical base address */
+
 /* Multi-Master Memory controller */
 #define AT91_UHP_BASE          0x00300000      /* USB Host controller */
 
index 62623fa..013575e 100644 (file)
 
 #define UART_BASE      ((volatile u32 *)IXP23XX_UART1_PHYS)
 
-static __inline__ void putc(char c)
+static inline void putc(char c)
 {
        int j;
 
        for (j = 0; j < 0x1000; j++) {
                if (UART_BASE[UART_LSR] & UART_LSR_THRE)
                        break;
+               barrier();
        }
 
        UART_BASE[UART_TX] = c;
 }
 
-static void putstr(const char *s)
+static inline void flush(void)
 {
-       while (*s) {
-               putc(*s);
-               if (*s == '\n')
-                       putc('\r');
-               s++;
-       }
 }
 
 #define arch_decomp_setup()
index 1409c5b..c8f53a7 100644 (file)
 #define SACR1_ENLBF    (1 << 5)        /* Enable Loopback */
 #define SACR1_DRPL     (1 << 4)        /* Disable Replaying Function */
 #define SACR1_DREC     (1 << 3)        /* Disable Recording Function */
-#define SACR1_AMSL     (1 << 1)        /* Specify Alternate Mode */
+#define SACR1_AMSL     (1 << 0)        /* Specify Alternate Mode */
 
 #define SASR0_I2SOFF   (1 << 7)        /* Controller Status */
 #define SASR0_ROR      (1 << 6)        /* Rx FIFO Overrun */
index 0b43495..94cb498 100644 (file)
@@ -27,6 +27,8 @@ struct corgits_machinfo {
  */
 struct corgibl_machinfo {
        int max_intensity;
+       int default_intensity;
+       int limit_mask;
        void (*set_bl_intensity)(int intensity);
 };
 extern void corgibl_limit_intensity(int limit);
index 8f331bb..65ac305 100644 (file)
 #define __NR_mq_notify                 (__NR_SYSCALL_BASE+278)
 #define __NR_mq_getsetattr             (__NR_SYSCALL_BASE+279)
 #define __NR_waitid                    (__NR_SYSCALL_BASE+280)
-
-#if defined(__ARM_EABI__)  /* reserve these for un-muxing socketcall */
 #define __NR_socket                    (__NR_SYSCALL_BASE+281)
 #define __NR_bind                      (__NR_SYSCALL_BASE+282)
 #define __NR_connect                   (__NR_SYSCALL_BASE+283)
 #define __NR_getsockopt                        (__NR_SYSCALL_BASE+295)
 #define __NR_sendmsg                   (__NR_SYSCALL_BASE+296)
 #define __NR_recvmsg                   (__NR_SYSCALL_BASE+297)
-#endif
-
-#if defined(__ARM_EABI__)  /* reserve these for un-muxing ipc */
 #define __NR_semop                     (__NR_SYSCALL_BASE+298)
 #define __NR_semget                    (__NR_SYSCALL_BASE+299)
 #define __NR_semctl                    (__NR_SYSCALL_BASE+300)
 #define __NR_shmdt                     (__NR_SYSCALL_BASE+306)
 #define __NR_shmget                    (__NR_SYSCALL_BASE+307)
 #define __NR_shmctl                    (__NR_SYSCALL_BASE+308)
-#endif
-
 #define __NR_add_key                   (__NR_SYSCALL_BASE+309)
 #define __NR_request_key               (__NR_SYSCALL_BASE+310)
 #define __NR_keyctl                    (__NR_SYSCALL_BASE+311)
-
-#if defined(__ARM_EABI__)  /* reserved for un-muxing ipc */
 #define __NR_semtimedop                        (__NR_SYSCALL_BASE+312)
-#endif
-
 #define __NR_vserver                   (__NR_SYSCALL_BASE+313)
 #define __NR_ioprio_set                        (__NR_SYSCALL_BASE+314)
 #define __NR_ioprio_get                        (__NR_SYSCALL_BASE+315)
index de46148..9291c24 100644 (file)
@@ -7,8 +7,15 @@
 #include <asm/atomic.h>
 #include <asm/types.h>
 
-/* An unsigned long type for operations which are atomic for a single
- * CPU.  Usually used in combination with per-cpu variables. */
+/*
+ * A signed long type for operations which are atomic for a single CPU.
+ * Usually used in combination with per-cpu variables.
+ *
+ * This is the default implementation, which uses atomic_long_t.  Which is
+ * rather pointless.  The whole point behind local_t is that some processors
+ * can perform atomic adds and subtracts in a manner which is atomic wrt IRQs
+ * running on this CPU.  local_t allows exploitation of such capabilities.
+ */
 
 /* Implement in terms of atomics. */
 
@@ -20,7 +27,7 @@ typedef struct
 
 #define LOCAL_INIT(i)  { ATOMIC_LONG_INIT(i) }
 
-#define local_read(l)  ((unsigned long)atomic_long_read(&(l)->a))
+#define local_read(l)  atomic_long_read(&(l)->a)
 #define local_set(l,i) atomic_long_set((&(l)->a),(i))
 #define local_inc(l)   atomic_long_inc(&(l)->a)
 #define local_dec(l)   atomic_long_dec(&(l)->a)
index 40c6d1f..29c6ac3 100644 (file)
  * it wasn't 1 originally. This function MUST leave the value lower than
  * 1 even when the "1" assertion wasn't true.
  */
-#define __mutex_fastpath_lock(count, fail_fn)                          \
-do {                                                                   \
-       if (unlikely(atomic_dec_return(count) < 0))                     \
-               fail_fn(count);                                         \
-       else                                                            \
-               smp_mb();                                               \
-} while (0)
+static inline void
+__mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+       if (unlikely(atomic_dec_return(count) < 0))
+               fail_fn(count);
+       else
+               smp_mb();
+}
 
 /**
  *  __mutex_fastpath_lock_retval - try to take the lock by moving the count
@@ -36,7 +37,7 @@ do {                                                                  \
  * or anything the slow path function returns.
  */
 static inline int
-__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+__mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *))
 {
        if (unlikely(atomic_dec_return(count) < 0))
                return fail_fn(count);
@@ -59,12 +60,13 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
  * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
  * to return 0 otherwise.
  */
-#define __mutex_fastpath_unlock(count, fail_fn)                                \
-do {                                                                   \
-       smp_mb();                                                       \
-       if (unlikely(atomic_inc_return(count) <= 0))                    \
-               fail_fn(count);                                         \
-} while (0)
+static inline void
+__mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+       smp_mb();
+       if (unlikely(atomic_inc_return(count) <= 0))
+               fail_fn(count);
+}
 
 #define __mutex_slowpath_needs_to_unlock()             1
 
index 1d24f47..32a2100 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Generic implementation of the mutex fastpath, based on xchg().
  *
- * NOTE: An xchg based implementation is less optimal than an atomic
+ * NOTE: An xchg based implementation might be less optimal than an atomic
  *       decrement/increment based implementation. If your architecture
  *       has a reasonable atomic dec/inc then you should probably use
  *      asm-generic/mutex-dec.h instead, or you could open-code an
  * wasn't 1 originally. This function MUST leave the value lower than 1
  * even when the "1" assertion wasn't true.
  */
-#define __mutex_fastpath_lock(count, fail_fn)                          \
-do {                                                                   \
-       if (unlikely(atomic_xchg(count, 0) != 1))                       \
-               fail_fn(count);                                         \
-       else                                                            \
-               smp_mb();                                               \
-} while (0)
-
+static inline void
+__mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+       if (unlikely(atomic_xchg(count, 0) != 1))
+               fail_fn(count);
+       else
+               smp_mb();
+}
 
 /**
  *  __mutex_fastpath_lock_retval - try to take the lock by moving the count
@@ -42,7 +42,7 @@ do {                                                                  \
  * or anything the slow path function returns
  */
 static inline int
-__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+__mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *))
 {
        if (unlikely(atomic_xchg(count, 0) != 1))
                return fail_fn(count);
@@ -64,12 +64,13 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
  * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
  * to return 0 otherwise.
  */
-#define __mutex_fastpath_unlock(count, fail_fn)                                \
-do {                                                                   \
-       smp_mb();                                                       \
-       if (unlikely(atomic_xchg(count, 1) != 0))                       \
-               fail_fn(count);                                         \
-} while (0)
+static inline void
+__mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+       smp_mb();
+       if (unlikely(atomic_xchg(count, 1) != 0))
+               fail_fn(count);
+}
 
 #define __mutex_slowpath_needs_to_unlock()             0
 
index 03185ce..5e4a35a 100644 (file)
@@ -37,6 +37,7 @@
 #define                        APIC_SPIV_FOCUS_DISABLED        (1<<9)
 #define                        APIC_SPIV_APIC_ENABLED          (1<<8)
 #define                APIC_ISR        0x100
+#define         APIC_ISR_NR     0x8     /* Number of 32 bit ISR registers. */
 #define                APIC_TMR        0x180
 #define        APIC_IRR        0x200
 #define        APIC_ESR        0x280
index 79727af..0340304 100644 (file)
@@ -56,7 +56,6 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
        register unsigned char st;
 
 #undef TRACE_FLPY_INT
-#define NO_FLOPPY_ASSEMBLER
 
 #ifdef TRACE_FLPY_INT
        static int calls=0;
@@ -71,38 +70,6 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
                bytes = virtual_dma_count;
 #endif
 
-#ifndef NO_FLOPPY_ASSEMBLER
-       __asm__ (
-       "testl %1,%1"
-       "je 3f"
-"1:    inb %w4,%b0"
-       "andb $160,%b0"
-       "cmpb $160,%b0"
-       "jne 2f"
-       "incw %w4"
-       "testl %3,%3"
-       "jne 4f"
-       "inb %w4,%b0"
-       "movb %0,(%2)"
-       "jmp 5f"
-"4:            movb (%2),%0"
-       "outb %b0,%w4"
-"5:    decw %w4"
-       "outb %0,$0x80"
-       "decl %1"
-       "incl %2"
-       "testl %1,%1"
-       "jne 1b"
-"3:    inb %w4,%b0"
-"2:    "
-       : "=a" ((char) st), 
-       "=c" ((long) virtual_dma_count), 
-       "=S" ((long) virtual_dma_addr)
-       : "b" ((long) virtual_dma_mode),
-       "d" ((short) virtual_dma_port+4), 
-       "1" ((long) virtual_dma_count),
-       "2" ((long) virtual_dma_addr));
-#else  
        {
                register int lcount;
                register char *lptr;
@@ -122,7 +89,6 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
                virtual_dma_addr = lptr;
                st = inb(virtual_dma_port+4);
        }
-#endif
 
 #ifdef TRACE_FLPY_INT
        calls++;
index 0177da8..e67fa08 100644 (file)
@@ -5,7 +5,7 @@
 
 typedef struct
 {
-       volatile unsigned long counter;
+       volatile long counter;
 } local_t;
 
 #define LOCAL_INIT(i)  { (i) }
@@ -29,7 +29,7 @@ static __inline__ void local_dec(local_t *v)
                :"m" (v->counter));
 }
 
-static __inline__ void local_add(unsigned long i, local_t *v)
+static __inline__ void local_add(long i, local_t *v)
 {
        __asm__ __volatile__(
                "addl %1,%0"
@@ -37,7 +37,7 @@ static __inline__ void local_add(unsigned long i, local_t *v)
                :"ir" (i), "m" (v->counter));
 }
 
-static __inline__ void local_sub(unsigned long i, local_t *v)
+static __inline__ void local_sub(long i, local_t *v)
 {
        __asm__ __volatile__(
                "subl %1,%0"
index 789e9bd..2e7f3e2 100644 (file)
 #define __NR_set_robust_list   311
 #define __NR_get_robust_list   312
 #define __NR_sys_splice                313
+#define __NR_sys_sync_file_range 314
 
-#define NR_syscalls 314
+#define NR_syscalls 315
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
index 4e7e6f2..37e52a2 100644 (file)
@@ -68,6 +68,7 @@
 #define PAL_SHUTDOWN           40      /* enter processor shutdown state */
 #define PAL_PREFETCH_VISIBILITY        41      /* Make Processor Prefetches Visible */
 #define PAL_LOGICAL_TO_PHYSICAL 42     /* returns information on logical to physical processor mapping */
+#define PAL_CACHE_SHARED_INFO  43      /* returns information on caches shared by logical processor */
 
 #define PAL_COPY_PAL           256     /* relocate PAL procedures and PAL PMI */
 #define PAL_HALT_INFO          257     /* return the low power capabilities of processor */
@@ -130,7 +131,7 @@ typedef u64                         pal_cache_line_state_t;
 #define PAL_CACHE_LINE_STATE_MODIFIED  3       /* Modified */
 
 typedef struct pal_freq_ratio {
-       u64 den : 32, num : 32; /* numerator & denominator */
+       u32 den, num;           /* numerator & denominator */
 } itc_ratio, proc_ratio;
 
 typedef        union  pal_cache_config_info_1_s {
@@ -151,10 +152,10 @@ typedef   union  pal_cache_config_info_1_s {
 
 typedef        union  pal_cache_config_info_2_s {
        struct {
-               u64             cache_size      : 32,   /*cache size in bytes*/
+               u32             cache_size;             /*cache size in bytes*/
 
 
-                               alias_boundary  : 8,    /* 39-32 aliased addr
+               u32             alias_boundary  : 8,    /* 39-32 aliased addr
                                                         * separation for max
                                                         * performance.
                                                         */
@@ -1647,6 +1648,33 @@ ia64_pal_logical_to_phys(u64 proc_number, pal_logical_to_physical_t *mapping)
 
        return iprv.status;
 }
+
+typedef struct pal_cache_shared_info_s
+{
+       u64 num_shared;
+       pal_proc_n_log_info1_t ppli1;
+       pal_proc_n_log_info2_t ppli2;
+} pal_cache_shared_info_t;
+
+/* Get information on logical to physical processor mappings. */
+static inline s64
+ia64_pal_cache_shared_info(u64 level,
+               u64 type,
+               u64 proc_number,
+               pal_cache_shared_info_t *info)
+{
+       struct ia64_pal_retval iprv;
+
+       PAL_CALL(iprv, PAL_CACHE_SHARED_INFO, level, type, proc_number);
+
+       if (iprv.status == PAL_STATUS_SUCCESS) {
+               info->num_shared = iprv.v0;
+               info->ppli1.ppli1_data = iprv.v1;
+               info->ppli2.ppli2_data = iprv.v2;
+       }
+
+       return iprv.status;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_IA64_PAL_H */
index 4dc7253..403ea97 100644 (file)
@@ -210,6 +210,8 @@ static __inline__ int atomic_read(const atomic_t *v)
 
 #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
 
+#define atomic_sub_and_test(i,v)       (atomic_sub_return((i),(v)) == 0)
+
 #define ATOMIC_INIT(i) ((atomic_t) { (i) })
 
 #define smp_mb__before_atomic_dec()    smp_mb()
@@ -267,6 +269,7 @@ atomic64_read(const atomic64_t *v)
 
 #define atomic64_inc_and_test(v)       (atomic64_inc_return(v) == 0)
 #define atomic64_dec_and_test(v)       (atomic64_dec_return(v) == 0)
+#define atomic64_sub_and_test(i,v)     (atomic64_sub_return((i),(v)) == 0)
 
 #endif /* __LP64__ */
 
index ae50f8e..c831665 100644 (file)
@@ -48,7 +48,7 @@ extern void flush_user_icache_range_asm(unsigned long, unsigned long);
 extern void flush_kernel_icache_range_asm(unsigned long, unsigned long);
 extern void flush_user_dcache_range_asm(unsigned long, unsigned long);
 extern void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
-extern void flush_kernel_dcache_page(void *);
+extern void flush_kernel_dcache_page_asm(void *);
 extern void flush_kernel_icache_page(void *);
 extern void disable_sr_hashing(void);   /* turns off space register hashing */
 extern void disable_sr_hashing_asm(int); /* low level support for above */
index c53af9f..76b6b7d 100644 (file)
@@ -62,7 +62,7 @@ extern void flush_dcache_page(struct page *page);
 #define flush_dcache_mmap_unlock(mapping) \
        write_unlock_irq(&(mapping)->tree_lock)
 
-#define flush_icache_page(vma,page)    do { flush_kernel_dcache_page(page_address(page)); flush_kernel_icache_page(page_address(page)); } while (0)
+#define flush_icache_page(vma,page)    do { flush_kernel_dcache_page(page); flush_kernel_icache_page(page_address(page)); } while (0)
 
 #define flush_icache_range(s,e)                do { flush_kernel_dcache_range_asm(s,e); flush_kernel_icache_range_asm(s,e); } while (0)
 
@@ -184,6 +184,21 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
 
 }
 
+static inline void
+flush_anon_page(struct page *page, unsigned long vmaddr)
+{
+       if (PageAnon(page))
+               flush_user_dcache_page(vmaddr);
+}
+#define ARCH_HAS_FLUSH_ANON_PAGE
+
+static inline void
+flush_kernel_dcache_page(struct page *page)
+{
+       flush_kernel_dcache_page_asm(page_address(page));
+}
+#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+
 #ifdef CONFIG_DEBUG_RODATA
 void mark_rodata_ro(void);
 #endif
index be0c723..29da311 100644 (file)
@@ -25,35 +25,11 @@ extern unsigned long parisc_vmerge_max_size;
  *   eg dev->hpa or 0xfee00000.
  */
 
-#ifdef CONFIG_DEBUG_IOREMAP
-#ifdef CONFIG_64BIT
-#define NYBBLE_SHIFT 60
-#else
-#define NYBBLE_SHIFT 28
-#endif
-extern void gsc_bad_addr(unsigned long addr);
-extern void __raw_bad_addr(const volatile void __iomem *addr);
-#define gsc_check_addr(addr)                                   \
-       if ((addr >> NYBBLE_SHIFT) != 0xf) {                    \
-               gsc_bad_addr(addr);                             \
-               addr |= 0xfUL << NYBBLE_SHIFT;                  \
-       }
-#define __raw_check_addr(addr)                                 \
-       if (((unsigned long)addr >> NYBBLE_SHIFT) != 0xe)       \
-               __raw_bad_addr(addr);                   \
-       addr = (void __iomem *)((unsigned long)addr | (0xfUL << NYBBLE_SHIFT));
-#else
-#define gsc_check_addr(addr)
-#define __raw_check_addr(addr)
-#endif
-
 static inline unsigned char gsc_readb(unsigned long addr)
 {
        long flags;
        unsigned char ret;
 
-       gsc_check_addr(addr);
-
        __asm__ __volatile__(
        "       rsm     2,%0\n"
        "       ldbx    0(%2),%1\n"
@@ -68,8 +44,6 @@ static inline unsigned short gsc_readw(unsigned long addr)
        long flags;
        unsigned short ret;
 
-       gsc_check_addr(addr);
-
        __asm__ __volatile__(
        "       rsm     2,%0\n"
        "       ldhx    0(%2),%1\n"
@@ -83,8 +57,6 @@ static inline unsigned int gsc_readl(unsigned long addr)
 {
        u32 ret;
 
-       gsc_check_addr(addr);
-
        __asm__ __volatile__(
        "       ldwax   0(%1),%0\n"
        : "=r" (ret) : "r" (addr) );
@@ -95,7 +67,6 @@ static inline unsigned int gsc_readl(unsigned long addr)
 static inline unsigned long long gsc_readq(unsigned long addr)
 {
        unsigned long long ret;
-       gsc_check_addr(addr);
 
 #ifdef __LP64__
        __asm__ __volatile__(
@@ -112,8 +83,6 @@ static inline unsigned long long gsc_readq(unsigned long addr)
 static inline void gsc_writeb(unsigned char val, unsigned long addr)
 {
        long flags;
-       gsc_check_addr(addr);
-
        __asm__ __volatile__(
        "       rsm     2,%0\n"
        "       stbs    %1,0(%2)\n"
@@ -124,8 +93,6 @@ static inline void gsc_writeb(unsigned char val, unsigned long addr)
 static inline void gsc_writew(unsigned short val, unsigned long addr)
 {
        long flags;
-       gsc_check_addr(addr);
-
        __asm__ __volatile__(
        "       rsm     2,%0\n"
        "       sths    %1,0(%2)\n"
@@ -135,8 +102,6 @@ static inline void gsc_writew(unsigned short val, unsigned long addr)
 
 static inline void gsc_writel(unsigned int val, unsigned long addr)
 {
-       gsc_check_addr(addr);
-
        __asm__ __volatile__(
        "       stwas   %0,0(%1)\n"
        : :  "r" (val), "r" (addr) );
@@ -144,8 +109,6 @@ static inline void gsc_writel(unsigned int val, unsigned long addr)
 
 static inline void gsc_writeq(unsigned long long val, unsigned long addr)
 {
-       gsc_check_addr(addr);
-
 #ifdef __LP64__
        __asm__ __volatile__(
        "       stda    %0,0(%1)\n"
@@ -180,14 +143,7 @@ extern inline void * ioremap_nocache(unsigned long offset, unsigned long size)
 
 extern void iounmap(void __iomem *addr);
 
-/*
- * USE_HPPA_IOREMAP is the magic flag to enable or disable real ioremap()
- * functionality.  It's currently disabled because it may not work on some
- * machines.
- */
-#define USE_HPPA_IOREMAP 0
 
-#if USE_HPPA_IOREMAP
 static inline unsigned char __raw_readb(const volatile void __iomem *addr)
 {
        return (*(volatile unsigned char __force *) (addr));
@@ -221,57 +177,6 @@ static inline void __raw_writeq(unsigned long long b, volatile void __iomem *add
 {
        *(volatile unsigned long long __force *) addr = b;
 }
-#else /* !USE_HPPA_IOREMAP */
-static inline unsigned char __raw_readb(const volatile void __iomem *addr)
-{
-       __raw_check_addr(addr);
-
-       return gsc_readb((unsigned long) addr);
-}
-static inline unsigned short __raw_readw(const volatile void __iomem *addr)
-{
-       __raw_check_addr(addr);
-
-       return gsc_readw((unsigned long) addr);
-}
-static inline unsigned int __raw_readl(const volatile void __iomem *addr)
-{
-       __raw_check_addr(addr);
-
-       return gsc_readl((unsigned long) addr);
-}
-static inline unsigned long long __raw_readq(const volatile void __iomem *addr)
-{
-       __raw_check_addr(addr);
-
-       return gsc_readq((unsigned long) addr);
-}
-
-static inline void __raw_writeb(unsigned char b, volatile void __iomem *addr)
-{
-       __raw_check_addr(addr);
-
-       gsc_writeb(b, (unsigned long) addr);
-}
-static inline void __raw_writew(unsigned short b, volatile void __iomem *addr)
-{
-       __raw_check_addr(addr);
-
-       gsc_writew(b, (unsigned long) addr);
-}
-static inline void __raw_writel(unsigned int b, volatile void __iomem *addr)
-{
-       __raw_check_addr(addr);
-
-       gsc_writel(b, (unsigned long) addr);
-}
-static inline void __raw_writeq(unsigned long long b, volatile void __iomem *addr)
-{
-       __raw_check_addr(addr);
-
-       gsc_writeq(b, (unsigned long) addr);
-}
-#endif /* !USE_HPPA_IOREMAP */
 
 /* readb can never be const, so use __fswab instead of le*_to_cpu */
 #define readb(addr) __raw_readb(addr)
index 892b3b2..d0f5509 100644 (file)
@@ -4,16 +4,16 @@
 #include <linux/percpu.h>
 #include <asm/atomic.h>
 
-typedef atomic_t local_t;
+typedef atomic_long_t local_t;
 
-#define LOCAL_INIT(i)  ATOMIC_INIT(i)
-#define local_read(v)  atomic_read(v)
-#define local_set(v,i) atomic_set(v,i)
+#define LOCAL_INIT(i)  ATOMIC_LONG_INIT(i)
+#define local_read(v)  atomic_long_read(v)
+#define local_set(v,i) atomic_long_set(v,i)
 
-#define local_inc(v)   atomic_inc(v)
-#define local_dec(v)   atomic_dec(v)
-#define local_add(i, v)        atomic_add(i, v)
-#define local_sub(i, v)        atomic_sub(i, v)
+#define local_inc(v)   atomic_long_inc(v)
+#define local_dec(v)   atomic_long_dec(v)
+#define local_add(i, v)        atomic_long_add(i, v)
+#define local_sub(i, v)        atomic_long_sub(i, v)
 
 #define __local_inc(v)         ((v)->counter++)
 #define __local_dec(v)         ((v)->counter--)
index 9f303c0..45e02aa 100644 (file)
@@ -26,7 +26,7 @@ static inline void
 copy_user_page(void *vto, void *vfrom, unsigned long vaddr, struct page *pg)
 {
        copy_user_page_asm(vto, vfrom);
-       flush_kernel_dcache_page(vto);
+       flush_kernel_dcache_page_asm(vto);
        /* XXX: ppc flushes icache too, should we? */
 }
 
@@ -40,14 +40,19 @@ clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 /*
  * These are used to make use of C type-checking..
  */
-#ifdef __LP64__
-typedef struct { unsigned long pte; } pte_t;
-#else
-typedef struct {
-       unsigned long pte;
-       unsigned long flags;
-} pte_t;
+#define STRICT_MM_TYPECHECKS
+#ifdef STRICT_MM_TYPECHECKS
+typedef struct { unsigned long pte;
+#if !defined(CONFIG_64BIT)
+                 unsigned long future_flags;
+ /* XXX: it's possible to remove future_flags and change BITS_PER_PTE_ENTRY
+        to 2, but then strangely the identical 32bit kernel boots on a
+        c3000(pa20), but not any longer on a 715(pa11).
+        Still investigating... HelgeD.
+  */
 #endif
+} pte_t; /* either 32 or 64bit */
+
 /* NOTE: even on 64 bits, these entries are __u32 because we allocate
  * the pmd and pgd in ZONE_DMA (i.e. under 4GB) */
 typedef struct { __u32 pmd; } pmd_t;
@@ -55,25 +60,44 @@ typedef struct { __u32 pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 
 #define pte_val(x)     ((x).pte)
-#ifdef __LP64__
-#define pte_flags(x)   (*(__u32 *)&((x).pte))
-#else
-#define pte_flags(x)   ((x).flags)
-#endif
-
 /* These do not work lvalues, so make sure we don't use them as such. */
 #define pmd_val(x)     ((x).pmd + 0)
 #define pgd_val(x)     ((x).pgd + 0)
 #define pgprot_val(x)  ((x).pgprot)
 
-#define __pmd_val_set(x,n) (x).pmd = (n)
-#define __pgd_val_set(x,n) (x).pgd = (n)
-
 #define __pte(x)       ((pte_t) { (x) } )
 #define __pmd(x)       ((pmd_t) { (x) } )
 #define __pgd(x)       ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
+#define __pmd_val_set(x,n) (x).pmd = (n)
+#define __pgd_val_set(x,n) (x).pgd = (n)
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef         __u32 pmd_t;
+typedef         __u32 pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)      (x)
+#define pmd_val(x)      (x)
+#define pgd_val(x)      (x)
+#define pgprot_val(x)   (x)
+
+#define __pte(x)        (x)
+#define __pmd(x)       (x)
+#define __pgd(x)        (x)
+#define __pgprot(x)     (x)
+
+#define __pmd_val_set(x,n) (x) = (n)
+#define __pgd_val_set(x,n) (x) = (n)
+
+#endif /* STRICT_MM_TYPECHECKS */
+
+
 typedef struct __physmem_range {
        unsigned long start_pfn;
        unsigned long pages;       /* PAGE_SIZE pages */
index fe7f6a2..77bbafb 100644 (file)
@@ -289,4 +289,9 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev)
 {
 }
 
+static inline void pcibios_penalize_isa_irq(int irq, int active)
+{
+       /* We don't need to penalize isa irq's */
+}
+
 #endif /* __ASM_PARISC_PCI_H */
index adac9ac..a609273 100644 (file)
@@ -6,9 +6,8 @@
  *
  *
  *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2, or (at your option)
- *      any later version.
+ *      it under the terms of the GNU General Public License, version 2, as
+ *      published by the Free Software Foundation.
  *      
  *      This program is distributed in the hope that it will be useful,
  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
index 16c2ac0..a93960e 100644 (file)
@@ -134,14 +134,22 @@ static  __inline__ int __raw_write_trylock(raw_rwlock_t *rw)
        return 1;
 }
 
-static __inline__ int __raw_is_read_locked(raw_rwlock_t *rw)
+/*
+ * read_can_lock - would read_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+static __inline__ int __raw_read_can_lock(raw_rwlock_t *rw)
 {
-       return rw->counter > 0;
+       return rw->counter >= 0;
 }
 
-static __inline__ int __raw_is_write_locked(raw_rwlock_t *rw)
+/*
+ * write_can_lock - would write_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+static __inline__ int __raw_write_can_lock(raw_rwlock_t *rw)
 {
-       return rw->counter < 0;
+       return !rw->counter;
 }
 
 #endif /* __ASM_SPINLOCK_H */
index ac32f14..f2f83b0 100644 (file)
@@ -49,7 +49,8 @@ struct thread_info {
 
 #endif /* !__ASSEMBLY */
 
-#define PREEMPT_ACTIVE          0x10000000
+#define PREEMPT_ACTIVE_BIT     28
+#define PREEMPT_ACTIVE         (1 << PREEMPT_ACTIVE_BIT)
 
 /*
  * thread information flags
index 5207758..868c713 100644 (file)
@@ -60,23 +60,9 @@ void __init pci_addr_cache_build(void);
  * device (including config space i/o).  Call eeh_add_device_late
  * to finish the eeh setup for this device.
  */
-void eeh_add_device_early(struct device_node *);
-void eeh_add_device_late(struct pci_dev *dev);
 void eeh_add_device_tree_early(struct device_node *);
 void eeh_add_device_tree_late(struct pci_bus *);
 
-/**
- * eeh_remove_device - undo EEH setup for the indicated pci device
- * @dev: pci device to be removed
- *
- * This routine should be called when a device is removed from
- * a running system (e.g. by hotplug or dlpar).  It unregisters
- * the PCI device from the EEH subsystem.  I/O errors affecting
- * this device will no longer be detected after this call; thus,
- * i/o errors affecting this slot may leave this device unusable.
- */
-void eeh_remove_device(struct pci_dev *);
-
 /**
  * eeh_remove_device_recursive - undo EEH for device & children.
  * @dev: pci device to be removed
@@ -116,12 +102,6 @@ static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *d
 
 static inline void pci_addr_cache_build(void) { }
 
-static inline void eeh_add_device_early(struct device_node *dn) { }
-
-static inline void eeh_add_device_late(struct pci_dev *dev) { }
-
-static inline void eeh_remove_device(struct pci_dev *dev) { }
-
 static inline void eeh_add_device_tree_early(struct device_node *dn) { }
 
 static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
index b72c04f..6cc7e1f 100644 (file)
@@ -4,47 +4,88 @@
 
 #define HVSC                   .long 0x44000022
 
-#define H_Success      0
-#define H_Busy         1       /* Hardware busy -- retry later */
-#define H_Closed       2       /* Resource closed */
-#define H_Constrained  4       /* Resource request constrained to max allowed */
-#define H_InProgress   14      /* Kind of like busy */
-#define H_Pending      17      /* returned from H_POLL_PENDING */
-#define H_Continue     18      /* Returned from H_Join on success */
-#define H_LongBusyStartRange   9900  /* Start of long busy range */
-#define H_LongBusyOrder1msec   9900  /* Long busy, hint that 1msec is a good time to retry */
-#define H_LongBusyOrder10msec  9901  /* Long busy, hint that 10msec is a good time to retry */
-#define H_LongBusyOrder100msec 9902  /* Long busy, hint that 100msec is a good time to retry */
-#define H_LongBusyOrder1sec    9903  /* Long busy, hint that 1sec is a good time to retry */
-#define H_LongBusyOrder10sec   9904  /* Long busy, hint that 10sec is a good time to retry */
-#define H_LongBusyOrder100sec  9905  /* Long busy, hint that 100sec is a good time to retry */
-#define H_LongBusyEndRange     9905  /* End of long busy range */
-#define H_Hardware     -1      /* Hardware error */
-#define H_Function     -2      /* Function not supported */
-#define H_Privilege    -3      /* Caller not privileged */
-#define H_Parameter    -4      /* Parameter invalid, out-of-range or conflicting */
-#define H_Bad_Mode     -5      /* Illegal msr value */
-#define H_PTEG_Full    -6      /* PTEG is full */
-#define H_Not_Found    -7      /* PTE was not found" */
-#define H_Reserved_DABR        -8      /* DABR address is reserved by the hypervisor on this processor" */
-#define H_NoMem                 -9
-#define H_Authority            -10
-#define H_Permission           -11
-#define H_Dropped              -12
-#define H_SourceParm           -13
-#define H_DestParm             -14
-#define H_RemoteParm           -15
-#define H_Resource             -16
+#define H_SUCCESS      0
+#define H_BUSY         1       /* Hardware busy -- retry later */
+#define H_CLOSED       2       /* Resource closed */
+#define H_NOT_AVAILABLE 3
+#define H_CONSTRAINED  4       /* Resource request constrained to max allowed */
+#define H_PARTIAL       5
+#define H_IN_PROGRESS  14      /* Kind of like busy */
+#define H_PAGE_REGISTERED 15
+#define H_PARTIAL_STORE   16
+#define H_PENDING      17      /* returned from H_POLL_PENDING */
+#define H_CONTINUE     18      /* Returned from H_Join on success */
+#define H_LONG_BUSY_START_RANGE                9900  /* Start of long busy range */
+#define H_LONG_BUSY_ORDER_1_MSEC       9900  /* Long busy, hint that 1msec \
+                                                is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_MSEC      9901  /* Long busy, hint that 10msec \
+                                                is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_MSEC     9902  /* Long busy, hint that 100msec \
+                                                is a good time to retry */
+#define H_LONG_BUSY_ORDER_1_SEC                9903  /* Long busy, hint that 1sec \
+                                                is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_SEC       9904  /* Long busy, hint that 10sec \
+                                                is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_SEC      9905  /* Long busy, hint that 100sec \
+                                                is a good time to retry */
+#define H_LONG_BUSY_END_RANGE          9905  /* End of long busy range */
+#define H_HARDWARE     -1      /* Hardware error */
+#define H_FUNCTION     -2      /* Function not supported */
+#define H_PRIVILEGE    -3      /* Caller not privileged */
+#define H_PARAMETER    -4      /* Parameter invalid, out-of-range or conflicting */
+#define H_BAD_MODE     -5      /* Illegal msr value */
+#define H_PTEG_FULL    -6      /* PTEG is full */
+#define H_NOT_FOUND    -7      /* PTE was not found" */
+#define H_RESERVED_DABR        -8      /* DABR address is reserved by the hypervisor on this processor" */
+#define H_NO_MEM       -9
+#define H_AUTHORITY    -10
+#define H_PERMISSION   -11
+#define H_DROPPED      -12
+#define H_SOURCE_PARM  -13
+#define H_DEST_PARM    -14
+#define H_REMOTE_PARM  -15
+#define H_RESOURCE     -16
+#define H_ADAPTER_PARM  -17
+#define H_RH_PARM       -18
+#define H_RCQ_PARM      -19
+#define H_SCQ_PARM      -20
+#define H_EQ_PARM       -21
+#define H_RT_PARM       -22
+#define H_ST_PARM       -23
+#define H_SIGT_PARM     -24
+#define H_TOKEN_PARM    -25
+#define H_MLENGTH_PARM  -27
+#define H_MEM_PARM      -28
+#define H_MEM_ACCESS_PARM -29
+#define H_ATTR_PARM     -30
+#define H_PORT_PARM     -31
+#define H_MCG_PARM      -32
+#define H_VL_PARM       -33
+#define H_TSIZE_PARM    -34
+#define H_TRACE_PARM    -35
+
+#define H_MASK_PARM     -37
+#define H_MCG_FULL      -38
+#define H_ALIAS_EXIST   -39
+#define H_P_COUNTER     -40
+#define H_TABLE_FULL    -41
+#define H_ALT_TABLE     -42
+#define H_MR_CONDITION  -43
+#define H_NOT_ENOUGH_RESOURCES -44
+#define H_R_STATE       -45
+#define H_RESCINDEND    -46
+
 
 /* Long Busy is a condition that can be returned by the firmware
  * when a call cannot be completed now, but the identical call
  * should be retried later.  This prevents calls blocking in the
- * firmware for long periods of time. Annoyingly the firmware can return
+ * firmware for long periods of time.  Annoyingly the firmware can return
  * a range of return codes, hinting at how long we should wait before
  * retrying.  If you don't care for the hint, the macro below is a good
  * way to check for the long_busy return codes
  */
-#define H_isLongBusy(x)  ((x >= H_LongBusyStartRange) && (x <= H_LongBusyEndRange))
+#define H_IS_LONG_BUSY(x)  ((x >= H_LONG_BUSY_START_RANGE) \
+                            && (x <= H_LONG_BUSY_END_RANGE))
 
 /* Flags */
 #define H_LARGE_PAGE           (1UL<<(63-16))
 #define H_DABRX_KERNEL         (1UL<<(63-62))
 #define H_DABRX_USER           (1UL<<(63-63))
 
+/* Each control block has to be on a 4K bondary */
+#define H_CB_ALIGNMENT          4096
+
 /* pSeries hypervisor opcodes */
 #define H_REMOVE               0x04
 #define H_ENTER                        0x08
 #define H_PERFMON              0x7c
 #define H_MIGRATE_DMA          0x78
 #define H_REGISTER_VPA         0xDC
-#define H_CEDE                 0xE0
+#define H_CEDE                 0xE0
 #define H_CONFER               0xE4
-#define H_PROD                 0xE8
+#define H_PROD                 0xE8
 #define H_GET_PPP              0xEC
 #define H_SET_PPP              0xF0
 #define H_PURR                 0xF4
-#define H_PIC                  0xF8
+#define H_PIC                  0xF8
 #define H_REG_CRQ              0xFC
 #define H_FREE_CRQ             0x100
 #define H_VIO_SIGNAL           0x104
 #define H_SEND_CRQ             0x108
-#define H_COPY_RDMA             0x110
+#define H_COPY_RDMA            0x110
 #define H_SET_XDABR            0x134
 #define H_STUFF_TCE            0x138
 #define H_PUT_TCE_INDIRECT     0x13C
 #define H_VTERM_PARTNER_INFO   0x150
 #define H_REGISTER_VTERM       0x154
 #define H_FREE_VTERM           0x158
-#define H_POLL_PENDING         0x1D8
+#define H_RESET_EVENTS          0x15C
+#define H_ALLOC_RESOURCE        0x160
+#define H_FREE_RESOURCE         0x164
+#define H_MODIFY_QP             0x168
+#define H_QUERY_QP              0x16C
+#define H_REREGISTER_PMR        0x170
+#define H_REGISTER_SMR          0x174
+#define H_QUERY_MR              0x178
+#define H_QUERY_MW              0x17C
+#define H_QUERY_HCA             0x180
+#define H_QUERY_PORT            0x184
+#define H_MODIFY_PORT           0x188
+#define H_DEFINE_AQP1           0x18C
+#define H_GET_TRACE_BUFFER      0x190
+#define H_DEFINE_AQP0           0x194
+#define H_RESIZE_MR             0x198
+#define H_ATTACH_MCQP           0x19C
+#define H_DETACH_MCQP           0x1A0
+#define H_CREATE_RPT            0x1A4
+#define H_REMOVE_RPT            0x1A8
+#define H_REGISTER_RPAGES       0x1AC
+#define H_DISABLE_AND_GETC      0x1B0
+#define H_ERROR_DATA            0x1B4
+#define H_GET_HCA_INFO          0x1B8
+#define H_GET_PERF_COUNT        0x1BC
+#define H_MANAGE_TRACE          0x1C0
+#define H_QUERY_INT_STATE       0x1E4
+#define H_POLL_PENDING         0x1D8
 #define H_JOIN                 0x298
 #define H_ENABLE_CRQ           0x2B0
 
@@ -152,7 +223,7 @@ long plpar_hcall_norets(unsigned long opcode, ...);
  */
 long plpar_hcall_8arg_2ret(unsigned long opcode,
                           unsigned long arg1,
-                          unsigned long arg2,
+                          unsigned long arg2,
                           unsigned long arg3,
                           unsigned long arg4,
                           unsigned long arg5,
@@ -176,6 +247,42 @@ long plpar_hcall_4out(unsigned long opcode,
                      unsigned long *out3,
                      unsigned long *out4);
 
+long plpar_hcall_7arg_7ret(unsigned long opcode,
+                          unsigned long arg1,
+                          unsigned long arg2,
+                          unsigned long arg3,
+                          unsigned long arg4,
+                          unsigned long arg5,
+                          unsigned long arg6,
+                          unsigned long arg7,
+                          unsigned long *out1,
+                          unsigned long *out2,
+                          unsigned long *out3,
+                          unsigned long *out4,
+                          unsigned long *out5,
+                          unsigned long *out6,
+                          unsigned long *out7);
+
+long plpar_hcall_9arg_9ret(unsigned long opcode,
+                          unsigned long arg1,
+                          unsigned long arg2,
+                          unsigned long arg3,
+                          unsigned long arg4,
+                          unsigned long arg5,
+                          unsigned long arg6,
+                          unsigned long arg7,
+                          unsigned long arg8,
+                          unsigned long arg9,
+                          unsigned long *out1,
+                          unsigned long *out2,
+                          unsigned long *out3,
+                          unsigned long *out4,
+                          unsigned long *out5,
+                          unsigned long *out6,
+                          unsigned long *out7,
+                          unsigned long *out8,
+                          unsigned long *out9);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */
index 65f5a7b..d075725 100644 (file)
@@ -365,8 +365,11 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
  * powers of 2 writes until it reaches sufficient alignment).
  *
  * Based on this we disable the IP header alignment in network drivers.
+ * We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining
+ * cacheline alignment of buffers.
  */
-#define NET_IP_ALIGN   0
+#define NET_IP_ALIGN   0
+#define NET_SKB_PAD    L1_CACHE_BYTES
 #endif
 
 #define arch_align_stack(x) (x)
index e10ed87..436d216 100644 (file)
@@ -46,7 +46,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
 #define percpu_modcopy(pcpudst, src, size)                     \
 do {                                                           \
        unsigned int __i;                                       \
-       for_each_cpu(__i)                                       \
+       for_each_possible_cpu(__i)                              \
                memcpy((pcpudst)+__per_cpu_offset[__i],         \
                       (src), (size));                          \
 } while (0)
index 64ec640..264f0eb 100644 (file)
 #define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS           */
 #define __NR_getdomainname      162 /* SunOS Specific                              */
 #define __NR_setdomainname      163 /* Common                                      */
-/* #define __NR_ni_syscall     164    ENOSYS under SunOS                          */
+/* #define __NR_utrap_install   164    Linux sparc64 specific                     */
 #define __NR_quotactl           165 /* Common                                      */
 #define __NR_set_tid_address    166 /* Linux specific, exportfs under SunOS        */
 #define __NR_mount              167 /* Common                                      */
 #define __NR_setfsgid           229 /* Linux Specific                              */
 #define __NR__newselect         230 /* Linux Specific                              */
 #define __NR_time               231 /* Linux Specific                              */
-/* #define __NR_oldstat         232    Linux Specific                              */
+#define __NR_sys_splice         232 /* Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
 #define __NR_statfs64           234 /* Linux Specific                              */
 #define __NR_fstatfs64          235 /* Linux Specific                              */
 #define __NR_getsid             252
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
-#define __NR_aplib              255
+#define __NR_sys_sync_file_range 255
 #define __NR_clock_settime     256
 #define __NR_clock_gettime     257
 #define __NR_clock_getres      258
index a284986..d0544b4 100644 (file)
 #ifdef __KERNEL__
 #define __NR_time              231 /* Linux sparc32                               */
 #endif
-/* #define __NR_oldstat         232    Linux Specific                              */
+#define __NR_sys_splice         232 /* Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
 #define __NR_statfs64           234 /* Linux Specific                              */
 #define __NR_fstatfs64          235 /* Linux Specific                              */
 #define __NR_getsid             252
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
-#define __NR_aplib              255
+#define __NR_sys_sync_file_range 255
 #define __NR_clock_settime     256
 #define __NR_clock_gettime     257
 #define __NR_clock_getres      258
index ac1d2a2..4ec34a5 100644 (file)
@@ -1,6 +1,16 @@
 #ifndef __UM_DESC_H
 #define __UM_DESC_H
 
-#include "asm/arch/desc.h"
+/* Taken from asm-i386/desc.h, it's the only thing we need. The rest wouldn't
+ * compile, and has never been used. */
+#define LDT_empty(info) (\
+       (info)->base_addr       == 0    && \
+       (info)->limit           == 0    && \
+       (info)->contents        == 0    && \
+       (info)->read_exec_only  == 1    && \
+       (info)->seg_32bit       == 0    && \
+       (info)->limit_in_pages  == 0    && \
+       (info)->seg_not_present == 1    && \
+       (info)->useable         == 0    )
 
 #endif
diff --git a/include/asm-um/host_ldt-i386.h b/include/asm-um/host_ldt-i386.h
new file mode 100644 (file)
index 0000000..b27cb0a
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __ASM_HOST_LDT_I386_H
+#define __ASM_HOST_LDT_I386_H
+
+#include "asm/arch/ldt.h"
+
+/*
+ * macros stolen from include/asm-i386/desc.h
+ */
+#define LDT_entry_a(info) \
+       ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+
+#define LDT_entry_b(info) \
+       (((info)->base_addr & 0xff000000) | \
+       (((info)->base_addr & 0x00ff0000) >> 16) | \
+       ((info)->limit & 0xf0000) | \
+       (((info)->read_exec_only ^ 1) << 9) | \
+       ((info)->contents << 10) | \
+       (((info)->seg_not_present ^ 1) << 15) | \
+       ((info)->seg_32bit << 22) | \
+       ((info)->limit_in_pages << 23) | \
+       ((info)->useable << 20) | \
+       0x7000)
+
+#define LDT_empty(info) (\
+       (info)->base_addr       == 0    && \
+       (info)->limit           == 0    && \
+       (info)->contents        == 0    && \
+       (info)->read_exec_only  == 1    && \
+       (info)->seg_32bit       == 0    && \
+       (info)->limit_in_pages  == 0    && \
+       (info)->seg_not_present == 1    && \
+       (info)->useable         == 0    )
+
+#endif
diff --git a/include/asm-um/host_ldt-x86_64.h b/include/asm-um/host_ldt-x86_64.h
new file mode 100644 (file)
index 0000000..74a63f7
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __ASM_HOST_LDT_X86_64_H
+#define __ASM_HOST_LDT_X86_64_H
+
+#include "asm/arch/ldt.h"
+
+/*
+ * macros stolen from include/asm-x86_64/desc.h
+ */
+#define LDT_entry_a(info) \
+       ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+
+/* Don't allow setting of the lm bit. It is useless anyways because
+ * 64bit system calls require __USER_CS. */
+#define LDT_entry_b(info) \
+       (((info)->base_addr & 0xff000000) | \
+       (((info)->base_addr & 0x00ff0000) >> 16) | \
+       ((info)->limit & 0xf0000) | \
+       (((info)->read_exec_only ^ 1) << 9) | \
+       ((info)->contents << 10) | \
+       (((info)->seg_not_present ^ 1) << 15) | \
+       ((info)->seg_32bit << 22) | \
+       ((info)->limit_in_pages << 23) | \
+       ((info)->useable << 20) | \
+       /* ((info)->lm << 21) | */ \
+       0x7000)
+
+#define LDT_empty(info) (\
+       (info)->base_addr       == 0    && \
+       (info)->limit           == 0    && \
+       (info)->contents        == 0    && \
+       (info)->read_exec_only  == 1    && \
+       (info)->seg_32bit       == 0    && \
+       (info)->limit_in_pages  == 0    && \
+       (info)->seg_not_present == 1    && \
+       (info)->useable         == 0    && \
+       (info)->lm              == 0)
+
+#endif
diff --git a/include/asm-um/ldt-i386.h b/include/asm-um/ldt-i386.h
deleted file mode 100644 (file)
index 175722a..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Licensed under the GPL
- *
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- */
-
-#ifndef __ASM_LDT_I386_H
-#define __ASM_LDT_I386_H
-
-#include "asm/semaphore.h"
-#include "asm/arch/ldt.h"
-
-struct mmu_context_skas;
-extern void ldt_host_info(void);
-extern long init_new_ldt(struct mmu_context_skas * to_mm,
-                        struct mmu_context_skas * from_mm);
-extern void free_ldt(struct mmu_context_skas * mm);
-
-#define LDT_PAGES_MAX \
-       ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
-#define LDT_ENTRIES_PER_PAGE \
-       (PAGE_SIZE/LDT_ENTRY_SIZE)
-#define LDT_DIRECT_ENTRIES \
-       ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
-
-struct ldt_entry {
-       __u32 a;
-       __u32 b;
-};
-
-typedef struct uml_ldt {
-       int entry_count;
-       struct semaphore semaphore;
-       union {
-               struct ldt_entry * pages[LDT_PAGES_MAX];
-               struct ldt_entry entries[LDT_DIRECT_ENTRIES];
-       } u;
-} uml_ldt_t;
-
-/*
- * macros stolen from include/asm-i386/desc.h
- */
-#define LDT_entry_a(info) \
-       ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-#define LDT_entry_b(info) \
-       (((info)->base_addr & 0xff000000) | \
-       (((info)->base_addr & 0x00ff0000) >> 16) | \
-       ((info)->limit & 0xf0000) | \
-       (((info)->read_exec_only ^ 1) << 9) | \
-       ((info)->contents << 10) | \
-       (((info)->seg_not_present ^ 1) << 15) | \
-       ((info)->seg_32bit << 22) | \
-       ((info)->limit_in_pages << 23) | \
-       ((info)->useable << 20) | \
-       0x7000)
-
-#define LDT_empty(info) (\
-       (info)->base_addr       == 0    && \
-       (info)->limit           == 0    && \
-       (info)->contents        == 0    && \
-       (info)->read_exec_only  == 1    && \
-       (info)->seg_32bit       == 0    && \
-       (info)->limit_in_pages  == 0    && \
-       (info)->seg_not_present == 1    && \
-       (info)->useable         == 0    )
-
-#endif
diff --git a/include/asm-um/ldt-x86_64.h b/include/asm-um/ldt-x86_64.h
deleted file mode 100644 (file)
index 96b35aa..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Licensed under the GPL
- *
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- */
-
-#ifndef __ASM_LDT_X86_64_H
-#define __ASM_LDT_X86_64_H
-
-#include "asm/semaphore.h"
-#include "asm/arch/ldt.h"
-
-struct mmu_context_skas;
-extern void ldt_host_info(void);
-extern long init_new_ldt(struct mmu_context_skas * to_mm,
-                        struct mmu_context_skas * from_mm);
-extern void free_ldt(struct mmu_context_skas * mm);
-
-#define LDT_PAGES_MAX \
-       ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
-#define LDT_ENTRIES_PER_PAGE \
-       (PAGE_SIZE/LDT_ENTRY_SIZE)
-#define LDT_DIRECT_ENTRIES \
-       ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
-
-struct ldt_entry {
-       __u32 a;
-       __u32 b;
-};
-
-typedef struct uml_ldt {
-       int entry_count;
-       struct semaphore semaphore;
-       union {
-               struct ldt_entry * pages[LDT_PAGES_MAX];
-               struct ldt_entry entries[LDT_DIRECT_ENTRIES];
-       } u;
-} uml_ldt_t;
-
-/*
- * macros stolen from include/asm-x86_64/desc.h
- */
-#define LDT_entry_a(info) \
-       ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-/* Don't allow setting of the lm bit. It is useless anyways because
- * 64bit system calls require __USER_CS. */
-#define LDT_entry_b(info) \
-       (((info)->base_addr & 0xff000000) | \
-       (((info)->base_addr & 0x00ff0000) >> 16) | \
-       ((info)->limit & 0xf0000) | \
-       (((info)->read_exec_only ^ 1) << 9) | \
-       ((info)->contents << 10) | \
-       (((info)->seg_not_present ^ 1) << 15) | \
-       ((info)->seg_32bit << 22) | \
-       ((info)->limit_in_pages << 23) | \
-       ((info)->useable << 20) | \
-       /* ((info)->lm << 21) | */ \
-       0x7000)
-
-#define LDT_empty(info) (\
-       (info)->base_addr       == 0    && \
-       (info)->limit           == 0    && \
-       (info)->contents        == 0    && \
-       (info)->read_exec_only  == 1    && \
-       (info)->seg_32bit       == 0    && \
-       (info)->limit_in_pages  == 0    && \
-       (info)->seg_not_present == 1    && \
-       (info)->useable         == 0    && \
-       (info)->lm              == 0)
-
-#endif
diff --git a/include/asm-um/ldt.h b/include/asm-um/ldt.h
new file mode 100644 (file)
index 0000000..96f82a4
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Licensed under the GPL
+ *
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ */
+
+#ifndef __ASM_LDT_H
+#define __ASM_LDT_H
+
+#include "asm/semaphore.h"
+#include "asm/host_ldt.h"
+
+struct mmu_context_skas;
+extern void ldt_host_info(void);
+extern long init_new_ldt(struct mmu_context_skas * to_mm,
+                        struct mmu_context_skas * from_mm);
+extern void free_ldt(struct mmu_context_skas * mm);
+
+#define LDT_PAGES_MAX \
+       ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
+#define LDT_ENTRIES_PER_PAGE \
+       (PAGE_SIZE/LDT_ENTRY_SIZE)
+#define LDT_DIRECT_ENTRIES \
+       ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
+
+struct ldt_entry {
+       __u32 a;
+       __u32 b;
+};
+
+typedef struct uml_ldt {
+       int entry_count;
+       struct semaphore semaphore;
+       union {
+               struct ldt_entry * pages[LDT_PAGES_MAX];
+               struct ldt_entry entries[LDT_DIRECT_ENTRIES];
+       } u;
+} uml_ldt_t;
+
+#endif
index 4108a57..595f1c3 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -6,21 +6,48 @@
 #ifndef __UM_PROCESSOR_I386_H
 #define __UM_PROCESSOR_I386_H
 
+#include "linux/string.h"
+#include "asm/host_ldt.h"
+#include "asm/segment.h"
+
 extern int host_has_xmm;
 extern int host_has_cmov;
 
 /* include faultinfo structure */
 #include "sysdep/faultinfo.h"
 
+struct uml_tls_struct {
+       struct user_desc tls;
+       unsigned flushed:1;
+       unsigned present:1;
+};
+
 struct arch_thread {
+       struct uml_tls_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
        unsigned long debugregs[8];
        int debugregs_seq;
        struct faultinfo faultinfo;
 };
 
-#define INIT_ARCH_THREAD { .debugregs                  = { [ 0 ... 7 ] = 0 }, \
-                           .debugregs_seq      = 0, \
-                           .faultinfo          = { 0, 0, 0 } }
+#define INIT_ARCH_THREAD { \
+       .tls_array              = { [ 0 ... GDT_ENTRY_TLS_ENTRIES - 1 ] = \
+                                   { .present = 0, .flushed = 0 } }, \
+       .debugregs              = { [ 0 ... 7 ] = 0 }, \
+       .debugregs_seq          = 0, \
+       .faultinfo              = { 0, 0, 0 } \
+}
+
+static inline void arch_flush_thread(struct arch_thread *thread)
+{
+       /* Clear any TLS still hanging */
+       memset(&thread->tls_array, 0, sizeof(thread->tls_array));
+}
+
+static inline void arch_copy_thread(struct arch_thread *from,
+                                    struct arch_thread *to)
+{
+        memcpy(&to->tls_array, &from->tls_array, sizeof(from->tls_array));
+}
 
 #include "asm/arch/user.h"
 
index e1e1255..10609af 100644 (file)
@@ -28,6 +28,15 @@ extern inline void rep_nop(void)
                            .debugregs_seq      = 0, \
                            .faultinfo          = { 0, 0, 0 } }
 
+static inline void arch_flush_thread(struct arch_thread *thread)
+{
+}
+
+static inline void arch_copy_thread(struct arch_thread *from,
+                                    struct arch_thread *to)
+{
+}
+
 #include "asm/arch/user.h"
 
 #define current_text_addr() \
index 46599ac..5034843 100644 (file)
@@ -28,7 +28,7 @@ struct pt_regs {
        union uml_pt_regs regs;
 };
 
-#define EMPTY_REGS { regs : EMPTY_UML_PT_REGS }
+#define EMPTY_REGS { .regs = EMPTY_UML_PT_REGS }
 
 #define PT_REGS_IP(r) UPT_IP(&(r)->regs)
 #define PT_REGS_SP(r) UPT_SP(&(r)->regs)
@@ -60,17 +60,9 @@ extern void show_regs(struct pt_regs *regs);
 extern void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs,
                         int error_code);
 
-#endif
+extern int arch_copy_tls(struct task_struct *new);
+extern void clear_flushed_tls(struct task_struct *task);
 
 #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-file-style: "linux"
- * End:
- */
+#endif
index fe882b9..30656c9 100644 (file)
@@ -8,8 +8,11 @@
 
 #define HOST_AUDIT_ARCH AUDIT_ARCH_I386
 
+#include "linux/compiler.h"
 #include "sysdep/ptrace.h"
 #include "asm/ptrace-generic.h"
+#include "asm/host_ldt.h"
+#include "choose-mode.h"
 
 #define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
 #define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
 
 #define user_mode(r) UPT_IS_USER(&(r)->regs)
 
-#endif
+extern int ptrace_get_thread_area(struct task_struct *child, int idx,
+                                  struct user_desc __user *user_desc);
 
-/*
- * 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-file-style: "linux"
- * End:
- */
+extern int ptrace_set_thread_area(struct task_struct *child, int idx,
+                                  struct user_desc __user *user_desc);
+
+extern int do_set_thread_area_skas(struct user_desc *info);
+extern int do_get_thread_area_skas(struct user_desc *info);
+
+extern int do_set_thread_area_tt(struct user_desc *info);
+extern int do_get_thread_area_tt(struct user_desc *info);
+
+extern int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to);
+extern int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to);
+
+static inline int do_get_thread_area(struct user_desc *info)
+{
+       return CHOOSE_MODE_PROC(do_get_thread_area_tt, do_get_thread_area_skas, info);
+}
+
+static inline int do_set_thread_area(struct user_desc *info)
+{
+       return CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, info);
+}
+
+struct task_struct;
+
+#endif
index be51219..c894e68 100644 (file)
@@ -8,6 +8,8 @@
 #define __UM_PTRACE_X86_64_H
 
 #include "linux/compiler.h"
+#include "asm/errno.h"
+#include "asm/host_ldt.h"
 
 #define signal_fault signal_fault_x86_64
 #define __FRAME_OFFSETS /* Needed to get the R* macros */
@@ -63,15 +65,26 @@ void signal_fault(struct pt_regs_subarch *regs, void *frame, char *where);
 
 #define profile_pc(regs) PT_REGS_IP(regs)
 
-#endif
+static inline int ptrace_get_thread_area(struct task_struct *child, int idx,
+                                         struct user_desc __user *user_desc)
+{
+        return -ENOSYS;
+}
 
-/*
- * 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-file-style: "linux"
- * End:
- */
+static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
+                                         struct user_desc __user *user_desc)
+{
+        return -ENOSYS;
+}
+
+static inline void arch_switch_to_tt(struct task_struct *from,
+                                     struct task_struct *to)
+{
+}
+
+static inline void arch_switch_to_skas(struct task_struct *from,
+                                       struct task_struct *to)
+{
+}
+
+#endif
index 55e4030..45183fc 100644 (file)
@@ -1,4 +1,10 @@
 #ifndef __UM_SEGMENT_H
 #define __UM_SEGMENT_H
 
+extern int host_gdt_entry_tls_min;
+
+#define GDT_ENTRY_TLS_ENTRIES 3
+#define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min
+#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
+
 #endif
index 17b6b07..f166b98 100644 (file)
@@ -27,14 +27,14 @@ struct thread_info {
 
 #define INIT_THREAD_INFO(tsk)                  \
 {                                              \
-       task:           &tsk,                   \
-       exec_domain:    &default_exec_domain,   \
-       flags:          0,                      \
-       cpu:            0,                      \
-       preempt_count:  1,                      \
-       addr_limit:     KERNEL_DS,              \
-       restart_block:  {                       \
-               fn:  do_no_restart_syscall,     \
+       .task =         &tsk,                   \
+       .exec_domain =  &default_exec_domain,   \
+       .flags =                0,              \
+       .cpu =          0,                      \
+       .preempt_count =        1,              \
+       .addr_limit =   KERNEL_DS,              \
+       .restart_block =  {                     \
+               .fn =  do_no_restart_syscall,   \
        },                                      \
 }
 
index 4e460d6..bea5a01 100644 (file)
@@ -57,7 +57,7 @@
 ({ \
         const __typeof__((*(ptr))) __user *private_ptr = (ptr); \
         (access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \
-        __get_user(x, private_ptr) : ((x) = 0, -EFAULT)); \
+        __get_user(x, private_ptr) : ((x) = (__typeof__(*ptr))0, -EFAULT)); \
 })
 
 #define __put_user(x, ptr) \
index bf14803..cd17945 100644 (file)
@@ -5,7 +5,7 @@
 
 typedef struct
 {
-       volatile unsigned long counter;
+       volatile long counter;
 } local_t;
 
 #define LOCAL_INIT(i)  { (i) }
@@ -13,7 +13,7 @@ typedef struct
 #define local_read(v)  ((v)->counter)
 #define local_set(v,i) (((v)->counter) = (i))
 
-static __inline__ void local_inc(local_t *v)
+static inline void local_inc(local_t *v)
 {
        __asm__ __volatile__(
                "incq %0"
@@ -21,7 +21,7 @@ static __inline__ void local_inc(local_t *v)
                :"m" (v->counter));
 }
 
-static __inline__ void local_dec(local_t *v)
+static inline void local_dec(local_t *v)
 {
        __asm__ __volatile__(
                "decq %0"
@@ -29,7 +29,7 @@ static __inline__ void local_dec(local_t *v)
                :"m" (v->counter));
 }
 
-static __inline__ void local_add(unsigned int i, local_t *v)
+static inline void local_add(long i, local_t *v)
 {
        __asm__ __volatile__(
                "addq %1,%0"
@@ -37,7 +37,7 @@ static __inline__ void local_add(unsigned int i, local_t *v)
                :"ir" (i), "m" (v->counter));
 }
 
-static __inline__ void local_sub(unsigned int i, local_t *v)
+static inline void local_sub(long i, local_t *v)
 {
        __asm__ __volatile__(
                "subq %1,%0"
index bb9e543..75e91f5 100644 (file)
@@ -19,20 +19,25 @@ struct fb_info;
 struct backlight_properties {
        /* Owner module */
        struct module *owner;
-       /* Get the backlight power status (0: full on, 1..3: power saving
-          modes; 4: full off), see FB_BLANK_XXX */
-       int (*get_power)(struct backlight_device *);
-       /* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */
-       int (*set_power)(struct backlight_device *, int power);
-       /* Maximal value for brightness (read-only) */
-       int max_brightness;
-       /* Get current backlight brightness */
+
+       /* Notify the backlight driver some property has changed */
+       int (*update_status)(struct backlight_device *);
+       /* Return the current backlight brightness (accounting for power,
+          fb_blank etc.) */
        int (*get_brightness)(struct backlight_device *);
-       /* Set backlight brightness (0..max_brightness) */
-       int (*set_brightness)(struct backlight_device *, int brightness);
        /* Check if given framebuffer device is the one bound to this backlight;
           return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */
        int (*check_fb)(struct fb_info *);
+
+       /* Current User requested brightness (0 - max_brightness) */
+       int brightness;
+       /* Maximal value for brightness (read-only) */
+       int max_brightness;
+       /* Current FB Power mode (0: full on, 1..3: power saving
+          modes; 4: full off), see FB_BLANK_XXX */
+       int power;
+       /* FB Blanking active? (values as for power) */
+       int fb_blank;
 };
 
 struct backlight_device {
index d10bd30..836325e 100644 (file)
@@ -275,6 +275,7 @@ extern void d_move(struct dentry *, struct dentry *);
 /* appendix may either be NULL or be used for transname suffixes */
 extern struct dentry * d_lookup(struct dentry *, struct qstr *);
 extern struct dentry * __d_lookup(struct dentry *, struct qstr *);
+extern struct dentry * d_hash_and_lookup(struct dentry *, struct qstr *);
 
 /* validate "insecure" dentry pointer */
 extern int d_validate(struct dentry *, struct dentry *);
index b2913bb..e8e7471 100644 (file)
 #define POSIX_FADV_NOREUSE     5 /* Data will be accessed once.  */
 #endif
 
-/*
- * Linux-specific fadvise() extensions:
- */
-#define LINUX_FADV_ASYNC_WRITE 32      /* Start writeout on range */
-#define LINUX_FADV_WRITE_WAIT  33      /* Wait upon writeout to range */
-
 #endif /* FADVISE_H_INCLUDED */
index d03fadf..315d897 100644 (file)
@@ -839,12 +839,10 @@ struct fb_info {
 #define FB_LEFT_POS(bpp)          (32 - bpp)
 #define FB_SHIFT_HIGH(val, bits)  ((val) >> (bits))
 #define FB_SHIFT_LOW(val, bits)   ((val) << (bits))
-#define FB_BIT_NR(b)              (7 - (b))
 #else
 #define FB_LEFT_POS(bpp)          (0)
 #define FB_SHIFT_HIGH(val, bits)  ((val) << (bits))
 #define FB_SHIFT_LOW(val, bits)   ((val) >> (bits))
-#define FB_BIT_NR(b)              (b)
 #endif
 
     /*
index 20fa5f6..4ed7e60 100644 (file)
@@ -757,6 +757,13 @@ extern void send_sigio(struct fown_struct *fown, int fd, int band);
 extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg);
 extern int fcntl_getlease(struct file *filp);
 
+/* fs/sync.c */
+#define SYNC_FILE_RANGE_WAIT_BEFORE    1
+#define SYNC_FILE_RANGE_WRITE          2
+#define SYNC_FILE_RANGE_WAIT_AFTER     4
+extern int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte,
+                       int flags);
+
 /* fs/locks.c */
 extern void locks_init_lock(struct file_lock *);
 extern void locks_copy_lock(struct file_lock *, struct file_lock *);
@@ -1413,6 +1420,7 @@ extern void bd_release_from_disk(struct block_device *, struct gendisk *);
 #endif
 
 /* fs/char_dev.c */
+#define CHRDEV_MAJOR_HASH_SIZE 255
 extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
 extern int register_chrdev_region(dev_t, unsigned, const char *);
 extern int register_chrdev(unsigned int, const char *,
@@ -1420,25 +1428,17 @@ extern int register_chrdev(unsigned int, const char *,
 extern int unregister_chrdev(unsigned int, const char *);
 extern void unregister_chrdev_region(dev_t, unsigned);
 extern int chrdev_open(struct inode *, struct file *);
-extern int get_chrdev_list(char *);
-extern void *acquire_chrdev_list(void);
-extern int count_chrdev_list(void);
-extern void *get_next_chrdev(void *);
-extern int get_chrdev_info(void *, int *, char **);
-extern void release_chrdev_list(void *);
+extern void chrdev_show(struct seq_file *,off_t);
 
 /* fs/block_dev.c */
+#define BLKDEV_MAJOR_HASH_SIZE 255
 #define BDEVNAME_SIZE  32      /* Largest string for a blockdev identifier */
 extern const char *__bdevname(dev_t, char *buffer);
 extern const char *bdevname(struct block_device *bdev, char *buffer);
 extern struct block_device *lookup_bdev(const char *);
 extern struct block_device *open_bdev_excl(const char *, int, void *);
 extern void close_bdev_excl(struct block_device *);
-extern void *acquire_blkdev_list(void);
-extern int count_blkdev_list(void);
-extern void *get_next_blkdev(void *);
-extern int get_blkdev_info(void *, int *, char **);
-extern void release_blkdev_list(void *);
+extern void blkdev_show(struct seq_file *,off_t);
 
 extern void init_special_inode(struct inode *, umode_t, dev_t);
 
index 9c8e6da..71e7b28 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <asm/io.h>
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/timer.h>
 
@@ -40,7 +41,7 @@ struct gameport {
        struct gameport *parent, *child;
 
        struct gameport_driver *drv;
-       struct semaphore drv_sem;       /* protects serio->drv so attributes can pin driver */
+       struct mutex drv_mutex;         /* protects serio->drv so attributes can pin driver */
 
        struct device dev;
        unsigned int registered;        /* port has been fully registered with driver core */
@@ -137,12 +138,12 @@ static inline void gameport_set_drvdata(struct gameport *gameport, void *data)
  */
 static inline int gameport_pin_driver(struct gameport *gameport)
 {
-       return down_interruptible(&gameport->drv_sem);
+       return mutex_lock_interruptible(&gameport->drv_mutex);
 }
 
 static inline void gameport_unpin_driver(struct gameport *gameport)
 {
-       up(&gameport->drv_sem);
+       mutex_unlock(&gameport->drv_mutex);
 }
 
 void __gameport_register_driver(struct gameport_driver *drv, struct module *owner);
index 9383015..b209392 100644 (file)
@@ -57,6 +57,19 @@ struct hrtimer {
        struct hrtimer_base     *base;
 };
 
+/**
+ * struct hrtimer_sleeper - simple sleeper structure
+ *
+ * @timer:     embedded timer structure
+ * @task:      task to wake up
+ *
+ * task is set to NULL, when the timer expires.
+ */
+struct hrtimer_sleeper {
+       struct hrtimer timer;
+       struct task_struct *task;
+};
+
 /**
  * struct hrtimer_base - the timer base for a specific clock
  *
@@ -127,6 +140,9 @@ extern long hrtimer_nanosleep(struct timespec *rqtp,
                              const enum hrtimer_mode mode,
                              const clockid_t clockid);
 
+extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
+                                struct task_struct *tsk);
+
 /* Soft interrupt function to run the hrtimer queues: */
 extern void hrtimer_run_queues(void);
 
index 1d4e341..b0e612d 100644 (file)
@@ -421,7 +421,7 @@ struct input_absinfo {
 #define BTN_GEAR_UP            0x151
 
 #define KEY_OK                 0x160
-#define KEY_SELECT             0x161
+#define KEY_SELECT             0x161
 #define KEY_GOTO               0x162
 #define KEY_CLEAR              0x163
 #define KEY_POWER2             0x164
@@ -512,6 +512,15 @@ struct input_absinfo {
 #define KEY_FN_S               0x1e3
 #define KEY_FN_B               0x1e4
 
+#define KEY_BRL_DOT1           0x1f1
+#define KEY_BRL_DOT2           0x1f2
+#define KEY_BRL_DOT3           0x1f3
+#define KEY_BRL_DOT4           0x1f4
+#define KEY_BRL_DOT5           0x1f5
+#define KEY_BRL_DOT6           0x1f6
+#define KEY_BRL_DOT7           0x1f7
+#define KEY_BRL_DOT8           0x1f8
+
 /* We avoid low common keys in module aliases so they don't get huge. */
 #define KEY_MIN_INTERESTING    KEY_MUTE
 #define KEY_MAX                        0x1ff
@@ -929,7 +938,7 @@ struct input_dev {
 
        struct input_handle *grab;
 
-       struct semaphore sem;   /* serializes open and close operations */
+       struct mutex mutex;     /* serializes open and close operations */
        unsigned int users;
 
        struct class_device cdev;
@@ -995,11 +1004,6 @@ static inline void init_input_dev(struct input_dev *dev)
 
 struct input_dev *input_allocate_device(void);
 
-static inline void input_free_device(struct input_dev *dev)
-{
-       kfree(dev);
-}
-
 static inline struct input_dev *input_get_device(struct input_dev *dev)
 {
        return to_input_dev(class_device_get(&dev->cdev));
@@ -1010,6 +1014,11 @@ static inline void input_put_device(struct input_dev *dev)
        class_device_put(&dev->cdev);
 }
 
+static inline void input_free_device(struct input_dev *dev)
+{
+       input_put_device(dev);
+}
+
 int input_register_device(struct input_dev *);
 void input_unregister_device(struct input_dev *);
 
index 5357128..6d9c7e4 100644 (file)
@@ -82,6 +82,13 @@ struct ipmi_smi_handlers
 {
        struct module *owner;
 
+       /* The low-level interface cannot start sending messages to
+          the upper layer until this function is called.  This may
+          not be NULL, the lower layer must take the interface from
+          this call. */
+       int (*start_processing)(void       *send_info,
+                               ipmi_smi_t new_intf);
+
        /* Called to enqueue an SMI message to be sent.  This
           operation is not allowed to fail.  If an error occurs, it
           should report back the error in a received message.  It may
@@ -157,13 +164,16 @@ static inline void ipmi_demangle_device_id(unsigned char *data,
 }
 
 /* Add a low-level interface to the IPMI driver.  Note that if the
-   interface doesn't know its slave address, it should pass in zero. */
+   interface doesn't know its slave address, it should pass in zero.
+   The low-level interface should not deliver any messages to the
+   upper layer until the start_processing() function in the handlers
+   is called, and the lower layer must get the interface from that
+   call. */
 int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
                      void                     *send_info,
                      struct ipmi_device_id    *device_id,
                      struct device            *dev,
-                     unsigned char            slave_addr,
-                     ipmi_smi_t               *intf);
+                     unsigned char            slave_addr);
 
 /*
  * Remove a low-level interface from the IPMI driver.  This will
index e87c32a..4eb851e 100644 (file)
@@ -135,6 +135,8 @@ static inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag)
 
 #define U(x) ((x) ^ 0xf000)
 
+#define BRL_UC_ROW 0x2800
+
 /* keyboard.c */
 
 struct console;
index 0848804..de76843 100644 (file)
@@ -44,6 +44,7 @@ extern unsigned short plain_map[NR_KEYS];
 #define KT_ASCII       9
 #define KT_LOCK                10
 #define KT_SLOCK       12
+#define KT_BRL         14
 
 #define K(t,v)         (((t)<<8)|(v))
 #define KTYP(x)                ((x) >> 8)
@@ -427,5 +428,17 @@ extern unsigned short plain_map[NR_KEYS];
 
 #define NR_LOCK                8
 
+#define K_BRL_BLANK     K(KT_BRL, 0)
+#define K_BRL_DOT1      K(KT_BRL, 1)
+#define K_BRL_DOT2      K(KT_BRL, 2)
+#define K_BRL_DOT3      K(KT_BRL, 3)
+#define K_BRL_DOT4      K(KT_BRL, 4)
+#define K_BRL_DOT5      K(KT_BRL, 5)
+#define K_BRL_DOT6      K(KT_BRL, 6)
+#define K_BRL_DOT7      K(KT_BRL, 7)
+#define K_BRL_DOT8      K(KT_BRL, 8)
+
+#define NR_BRL         9
+
 #define MAX_DIACR      256
 #endif
diff --git a/include/linux/leds.h b/include/linux/leds.h
new file mode 100644 (file)
index 0000000..4617e75
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Driver model for leds and led triggers
+ *
+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu>
+ * Copyright (C) 2005 Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __LINUX_LEDS_H_INCLUDED
+#define __LINUX_LEDS_H_INCLUDED
+
+struct device;
+struct class_device;
+/*
+ * LED Core
+ */
+
+enum led_brightness {
+       LED_OFF = 0,
+       LED_HALF = 127,
+       LED_FULL = 255,
+};
+
+struct led_classdev {
+       const char *name;
+       int brightness;
+       int flags;
+#define LED_SUSPENDED       (1 << 0)
+
+       /* A function to set the brightness of the led */
+       void (*brightness_set)(struct led_classdev *led_cdev,
+                               enum led_brightness brightness);
+
+       struct class_device *class_dev;
+       /* LED Device linked list */
+       struct list_head node;
+
+       /* Trigger data */
+       char *default_trigger;
+#ifdef CONFIG_LEDS_TRIGGERS
+       rwlock_t trigger_lock;
+       /* Protects the trigger data below */
+
+       struct led_trigger *trigger;
+       struct list_head trig_list;
+       void *trigger_data;
+#endif
+};
+
+extern int led_classdev_register(struct device *parent,
+                               struct led_classdev *led_cdev);
+extern void led_classdev_unregister(struct led_classdev *led_cdev);
+extern void led_classdev_suspend(struct led_classdev *led_cdev);
+extern void led_classdev_resume(struct led_classdev *led_cdev);
+
+/*
+ * LED Triggers
+ */
+#ifdef CONFIG_LEDS_TRIGGERS
+
+#define TRIG_NAME_MAX 50
+
+struct led_trigger {
+       /* Trigger Properties */
+       const char *name;
+       void (*activate)(struct led_classdev *led_cdev);
+       void (*deactivate)(struct led_classdev *led_cdev);
+
+       /* LEDs under control by this trigger (for simple triggers) */
+       rwlock_t leddev_list_lock;
+       struct list_head led_cdevs;
+
+       /* Link to next registered trigger */
+       struct list_head next_trig;
+};
+
+/* Registration functions for complex triggers */
+extern int led_trigger_register(struct led_trigger *trigger);
+extern void led_trigger_unregister(struct led_trigger *trigger);
+
+/* Registration functions for simple triggers */
+#define DEFINE_LED_TRIGGER(x)          static struct led_trigger *x;
+#define DEFINE_LED_TRIGGER_GLOBAL(x)   struct led_trigger *x;
+extern void led_trigger_register_simple(const char *name,
+                               struct led_trigger **trigger);
+extern void led_trigger_unregister_simple(struct led_trigger *trigger);
+extern void led_trigger_event(struct led_trigger *trigger,
+                               enum led_brightness event);
+
+#else
+
+/* Triggers aren't active - null macros */
+#define DEFINE_LED_TRIGGER(x)
+#define DEFINE_LED_TRIGGER_GLOBAL(x)
+#define led_trigger_register_simple(x, y) do {} while(0)
+#define led_trigger_unregister_simple(x) do {} while(0)
+#define led_trigger_event(x, y) do {} while(0)
+
+#endif
+
+/* Trigger specific functions */
+#ifdef CONFIG_LEDS_TRIGGER_IDE_DISK
+extern void ledtrig_ide_activity(void);
+#else
+#define ledtrig_ide_activity() do {} while(0)
+#endif
+
+#endif         /* __LINUX_LEDS_H_INCLUDED */
index a710bdd..08a450a 100644 (file)
@@ -28,7 +28,7 @@ struct ps2dev {
        struct serio *serio;
 
        /* Ensures that only one command is executing at a time */
-       struct semaphore cmd_sem;
+       struct mutex cmd_mutex;
 
        /* Used to signal completion from interrupt handler */
        wait_queue_head_t wait;
index 7d09962..ff0a640 100644 (file)
@@ -12,7 +12,7 @@ extern void migrate_page_copy(struct page *, struct page *);
 extern int migrate_page_remove_references(struct page *, struct page *, int);
 extern int migrate_pages(struct list_head *l, struct list_head *t,
                struct list_head *moved, struct list_head *failed);
-int migrate_pages_to(struct list_head *pagelist,
+extern int migrate_pages_to(struct list_head *pagelist,
                        struct vm_area_struct *vma, int dest);
 extern int fail_migrate_page(struct page *, struct page *);
 
@@ -26,6 +26,9 @@ static inline int putback_lru_pages(struct list_head *l) { return 0; }
 static inline int migrate_pages(struct list_head *l, struct list_head *t,
        struct list_head *moved, struct list_head *failed) { return -ENOSYS; }
 
+static inline int migrate_pages_to(struct list_head *pagelist,
+                       struct vm_area_struct *vma, int dest) { return 0; }
+
 static inline int migrate_prep(void) { return -ENOSYS; }
 
 /* Possible settings for the migrate_page() method in address_operations */
index f46afec..72fc68c 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef __MTD_TRANS_H__
 #define __MTD_TRANS_H__
 
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 struct hd_geometry;
 struct mtd_info;
@@ -22,7 +22,7 @@ struct mtd_blktrans_dev {
        struct mtd_blktrans_ops *tr;
        struct list_head list;
        struct mtd_info *mtd;
-       struct semaphore sem;
+       struct mutex lock;
        int devnum;
        int blksize;
        unsigned long size;
index 386a52c..9addd07 100644 (file)
@@ -15,7 +15,7 @@
 #define __MTD_DOC2000_H__
 
 #include <linux/mtd/mtd.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 #define DoC_Sig1 0
 #define DoC_Sig2 1
@@ -187,7 +187,7 @@ struct DiskOnChip {
        int numchips;
        struct Nand *chips;
        struct mtd_info *nextdoc;
-       struct semaphore lock;
+       struct mutex lock;
 };
 
 int doc_decode_ecc(unsigned char sector[512], unsigned char ecc1[6]);
index 0268125..d7eaa40 100644 (file)
@@ -52,6 +52,11 @@ struct INFTLrecord {
 int INFTL_mount(struct INFTLrecord *s);
 int INFTL_formatblock(struct INFTLrecord *s, int block);
 
+extern char inftlmountrev[];
+
+void INFTL_dumptables(struct INFTLrecord *s);
+void INFTL_dumpVUchains(struct INFTLrecord *s);
+
 #endif /* __KERNEL__ */
 
 #endif /* __MTD_INFTL_H__ */
index e669801..58cb3d3 100644 (file)
@@ -75,7 +75,6 @@ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
 extern void release_open_intent(struct nameidata *);
 
 extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-extern __deprecated_for_modules struct dentry * lookup_hash(struct nameidata *);
 
 extern int follow_down(struct vfsmount **, struct dentry **);
 extern int follow_up(struct vfsmount **, struct dentry **);
index 950dc55..40ccf8c 100644 (file)
@@ -598,20 +598,7 @@ DECLARE_PER_CPU(struct softnet_data,softnet_data);
 
 #define HAVE_NETIF_QUEUE
 
-static inline void __netif_schedule(struct net_device *dev)
-{
-       if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) {
-               unsigned long flags;
-               struct softnet_data *sd;
-
-               local_irq_save(flags);
-               sd = &__get_cpu_var(softnet_data);
-               dev->next_sched = sd->output_queue;
-               sd->output_queue = dev;
-               raise_softirq_irqoff(NET_TX_SOFTIRQ);
-               local_irq_restore(flags);
-       }
-}
+extern void __netif_schedule(struct net_device *dev);
 
 static inline void netif_schedule(struct net_device *dev)
 {
@@ -675,13 +662,7 @@ static inline void dev_kfree_skb_irq(struct sk_buff *skb)
 /* Use this variant in places where it could be invoked
  * either from interrupt or non-interrupt context.
  */
-static inline void dev_kfree_skb_any(struct sk_buff *skb)
-{
-       if (in_irq() || irqs_disabled())
-               dev_kfree_skb_irq(skb);
-       else
-               dev_kfree_skb(skb);
-}
+extern void dev_kfree_skb_any(struct sk_buff *skb);
 
 #define HAVE_NETIF_RX 1
 extern int             netif_rx(struct sk_buff *skb);
@@ -768,22 +749,9 @@ static inline int netif_device_present(struct net_device *dev)
        return test_bit(__LINK_STATE_PRESENT, &dev->state);
 }
 
-static inline void netif_device_detach(struct net_device *dev)
-{
-       if (test_and_clear_bit(__LINK_STATE_PRESENT, &dev->state) &&
-           netif_running(dev)) {
-               netif_stop_queue(dev);
-       }
-}
+extern void netif_device_detach(struct net_device *dev);
 
-static inline void netif_device_attach(struct net_device *dev)
-{
-       if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) &&
-           netif_running(dev)) {
-               netif_wake_queue(dev);
-               __netdev_watchdog_up(dev);
-       }
-}
+extern void netif_device_attach(struct net_device *dev);
 
 /*
  * Network interface message level settings
@@ -851,20 +819,7 @@ static inline int netif_rx_schedule_prep(struct net_device *dev)
  * already been called and returned 1.
  */
 
-static inline void __netif_rx_schedule(struct net_device *dev)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       dev_hold(dev);
-       list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
-       if (dev->quota < 0)
-               dev->quota += dev->weight;
-       else
-               dev->quota = dev->weight;
-       __raise_softirq_irqoff(NET_RX_SOFTIRQ);
-       local_irq_restore(flags);
-}
+extern void __netif_rx_schedule(struct net_device *dev);
 
 /* Try to reschedule poll. Called by irq handler. */
 
index 1350e47..f6bdef8 100644 (file)
@@ -142,6 +142,12 @@ struct xt_counters_info
 #define ASSERT_WRITE_LOCK(x)
 #include <linux/netfilter_ipv4/listhelp.h>
 
+#ifdef CONFIG_COMPAT
+#define COMPAT_TO_USER         1
+#define COMPAT_FROM_USER       -1
+#define COMPAT_CALC_SIZE       0
+#endif
+
 struct xt_match
 {
        struct list_head list;
@@ -175,6 +181,9 @@ struct xt_match
        void (*destroy)(const struct xt_match *match, void *matchinfo,
                        unsigned int matchinfosize);
 
+       /* Called when userspace align differs from kernel space one */
+       int (*compat)(void *match, void **dstptr, int *size, int convert);
+
        /* Set this to THIS_MODULE if you are a module, otherwise NULL */
        struct module *me;
 
@@ -220,6 +229,9 @@ struct xt_target
        void (*destroy)(const struct xt_target *target, void *targinfo,
                        unsigned int targinfosize);
 
+       /* Called when userspace align differs from kernel space one */
+       int (*compat)(void *target, void **dstptr, int *size, int convert);
+
        /* Set this to THIS_MODULE if you are a module, otherwise NULL */
        struct module *me;
 
@@ -314,6 +326,61 @@ extern void xt_proto_fini(int af);
 extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
 extern void xt_free_table_info(struct xt_table_info *info);
 
+#ifdef CONFIG_COMPAT
+#include <net/compat.h>
+
+struct compat_xt_entry_match
+{
+       union {
+               struct {
+                       u_int16_t match_size;
+                       char name[XT_FUNCTION_MAXNAMELEN - 1];
+                       u_int8_t revision;
+               } user;
+               u_int16_t match_size;
+       } u;
+       unsigned char data[0];
+};
+
+struct compat_xt_entry_target
+{
+       union {
+               struct {
+                       u_int16_t target_size;
+                       char name[XT_FUNCTION_MAXNAMELEN - 1];
+                       u_int8_t revision;
+               } user;
+               u_int16_t target_size;
+       } u;
+       unsigned char data[0];
+};
+
+/* FIXME: this works only on 32 bit tasks
+ * need to change whole approach in order to calculate align as function of
+ * current task alignment */
+
+struct compat_xt_counters
+{
+       u_int32_t cnt[4];
+};
+
+struct compat_xt_counters_info
+{
+       char name[XT_TABLE_MAXNAMELEN];
+       compat_uint_t num_counters;
+       struct compat_xt_counters counters[0];
+};
+
+#define COMPAT_XT_ALIGN(s) (((s) + (__alignof__(struct compat_xt_counters)-1)) \
+               & ~(__alignof__(struct compat_xt_counters)-1))
+
+extern void xt_compat_lock(int af);
+extern void xt_compat_unlock(int af);
+extern int xt_compat_match(void *match, void **dstptr, int *size, int convert);
+extern int xt_compat_target(void *target, void **dstptr, int *size,
+               int convert);
+
+#endif /* CONFIG_COMPAT */
 #endif /* __KERNEL__ */
 
 #endif /* _X_TABLES_H */
diff --git a/include/linux/netfilter/xt_esp.h b/include/linux/netfilter/xt_esp.h
new file mode 100644 (file)
index 0000000..9380fb1
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _XT_ESP_H
+#define _XT_ESP_H
+
+struct xt_esp
+{
+       u_int32_t spis[2];      /* Security Parameter Index */
+       u_int8_t  invflags;     /* Inverse flags */
+};
+
+/* Values for "invflags" field in struct xt_esp. */
+#define XT_ESP_INV_SPI 0x01    /* Invert the sense of spi. */
+#define XT_ESP_INV_MASK        0x01    /* All possible flags. */
+
+#endif /*_XT_ESP_H*/
diff --git a/include/linux/netfilter/xt_multiport.h b/include/linux/netfilter/xt_multiport.h
new file mode 100644 (file)
index 0000000..d49ee41
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _XT_MULTIPORT_H
+#define _XT_MULTIPORT_H
+
+enum xt_multiport_flags
+{
+       XT_MULTIPORT_SOURCE,
+       XT_MULTIPORT_DESTINATION,
+       XT_MULTIPORT_EITHER
+};
+
+#define XT_MULTI_PORTS 15
+
+/* Must fit inside union xt_matchinfo: 16 bytes */
+struct xt_multiport
+{
+       u_int8_t flags;                         /* Type of comparison */
+       u_int8_t count;                         /* Number of ports */
+       u_int16_t ports[XT_MULTI_PORTS];        /* Ports */
+};
+
+struct xt_multiport_v1
+{
+       u_int8_t flags;                         /* Type of comparison */
+       u_int8_t count;                         /* Number of ports */
+       u_int16_t ports[XT_MULTI_PORTS];        /* Ports */
+       u_int8_t pflags[XT_MULTI_PORTS];        /* Port flags */
+       u_int8_t invert;                        /* Invert flag */
+};
+
+#endif /*_XT_MULTIPORT_H*/
index d5b8c0d..c0dac16 100644 (file)
@@ -316,5 +316,23 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb,
                                 void *userdata);
 
 #define IPT_ALIGN(s) XT_ALIGN(s)
+
+#ifdef CONFIG_COMPAT
+#include <net/compat.h>
+
+struct compat_ipt_entry
+{
+       struct ipt_ip ip;
+       compat_uint_t nfcache;
+       u_int16_t target_offset;
+       u_int16_t next_offset;
+       compat_uint_t comefrom;
+       struct compat_xt_counters counters;
+       unsigned char elems[0];
+};
+
+#define COMPAT_IPT_ALIGN(s)    COMPAT_XT_ALIGN(s)
+
+#endif /* CONFIG_COMPAT */
 #endif /*__KERNEL__*/
 #endif /* _IPTABLES_H */
index c782a83..78296e7 100644 (file)
@@ -1,16 +1,10 @@
 #ifndef _IPT_ESP_H
 #define _IPT_ESP_H
 
-struct ipt_esp
-{
-       u_int32_t spis[2];                      /* Security Parameter Index */
-       u_int8_t  invflags;                     /* Inverse flags */
-};
+#include <linux/netfilter/xt_esp.h>
 
-
-
-/* Values for "invflags" field in struct ipt_esp. */
-#define IPT_ESP_INV_SPI                0x01    /* Invert the sense of spi. */
-#define IPT_ESP_INV_MASK       0x01    /* All possible flags. */
+#define ipt_esp xt_esp
+#define IPT_ESP_INV_SPI                XT_ESP_INV_SPI
+#define IPT_ESP_INV_MASK       XT_ESP_INV_MASK
 
 #endif /*_IPT_ESP_H*/
index e6b6fff..55fe85e 100644 (file)
@@ -1,30 +1,15 @@
 #ifndef _IPT_MULTIPORT_H
 #define _IPT_MULTIPORT_H
-#include <linux/netfilter_ipv4/ip_tables.h>
 
-enum ipt_multiport_flags
-{
-       IPT_MULTIPORT_SOURCE,
-       IPT_MULTIPORT_DESTINATION,
-       IPT_MULTIPORT_EITHER
-};
+#include <linux/netfilter/xt_multiport.h>
 
-#define IPT_MULTI_PORTS        15
+#define IPT_MULTIPORT_SOURCE           XT_MULTIPORT_SOURCE
+#define IPT_MULTIPORT_DESTINATION      XT_MULTIPORT_DESTINATION
+#define IPT_MULTIPORT_EITHER           XT_MULTIPORT_EITHER
 
-/* Must fit inside union ipt_matchinfo: 16 bytes */
-struct ipt_multiport
-{
-       u_int8_t flags;                         /* Type of comparison */
-       u_int8_t count;                         /* Number of ports */
-       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
-};
+#define IPT_MULTI_PORTS                        XT_MULTI_PORTS
+
+#define ipt_multiport                  xt_multiport
+#define ipt_multiport_v1               xt_multiport_v1
 
-struct ipt_multiport_v1
-{
-       u_int8_t flags;                         /* Type of comparison */
-       u_int8_t count;                         /* Number of ports */
-       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
-       u_int8_t pflags[IPT_MULTI_PORTS];       /* Port flags */
-       u_int8_t invert;                        /* Invert flag */
-};
 #endif /*_IPT_MULTIPORT_H*/
index a91b6ab..f62eaf5 100644 (file)
@@ -1,14 +1,10 @@
 #ifndef _IP6T_ESP_H
 #define _IP6T_ESP_H
 
-struct ip6t_esp
-{
-       u_int32_t spis[2];                      /* Security Parameter Index */
-       u_int8_t  invflags;                     /* Inverse flags */
-};
+#include <linux/netfilter/xt_esp.h>
 
-/* Values for "invflags" field in struct ip6t_esp. */
-#define IP6T_ESP_INV_SPI               0x01    /* Invert the sense of spi. */
-#define IP6T_ESP_INV_MASK      0x01    /* All possible flags. */
+#define ip6t_esp xt_esp
+#define IP6T_ESP_INV_SPI       XT_ESP_INV_SPI
+#define IP6T_ESP_INV_MASK      XT_ESP_INV_MASK
 
 #endif /*_IP6T_ESP_H*/
index efe4954..042c926 100644 (file)
@@ -1,21 +1,14 @@
 #ifndef _IP6T_MULTIPORT_H
 #define _IP6T_MULTIPORT_H
-#include <linux/netfilter_ipv6/ip6_tables.h>
 
-enum ip6t_multiport_flags
-{
-       IP6T_MULTIPORT_SOURCE,
-       IP6T_MULTIPORT_DESTINATION,
-       IP6T_MULTIPORT_EITHER
-};
+#include <linux/netfilter/xt_multiport.h>
 
-#define IP6T_MULTI_PORTS       15
+#define IP6T_MULTIPORT_SOURCE          XT_MULTIPORT_SOURCE
+#define IP6T_MULTIPORT_DESTINATION     XT_MULTIPORT_DESTINATION
+#define IP6T_MULTIPORT_EITHER          XT_MULTIPORT_EITHER
 
-/* Must fit inside union ip6t_matchinfo: 16 bytes */
-struct ip6t_multiport
-{
-       u_int8_t flags;                         /* Type of comparison */
-       u_int8_t count;                         /* Number of ports */
-       u_int16_t ports[IP6T_MULTI_PORTS];      /* Ports */
-};
-#endif /*_IPT_MULTIPORT_H*/
+#define IP6T_MULTI_PORTS               XT_MULTI_PORTS
+
+#define ip6t_multiport                 xt_multiport
+
+#endif /*_IP6T_MULTIPORT_H*/
index 839f0b3..9539efd 100644 (file)
@@ -72,8 +72,8 @@ extern struct page * find_get_page(struct address_space *mapping,
                                unsigned long index);
 extern struct page * find_lock_page(struct address_space *mapping,
                                unsigned long index);
-extern struct page * find_trylock_page(struct address_space *mapping,
-                               unsigned long index);
+extern __deprecated_for_modules struct page * find_trylock_page(
+                       struct address_space *mapping, unsigned long index);
 extern struct page * find_or_create_page(struct address_space *mapping,
                                unsigned long index, gfp_t gfp_mask);
 unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
index 5b9082c..29960b0 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_PID_H
 #define _LINUX_PID_H
 
+#include <linux/rcupdate.h>
+
 enum pid_type
 {
        PIDTYPE_PID,
@@ -9,45 +11,109 @@ enum pid_type
        PIDTYPE_MAX
 };
 
+/*
+ * What is struct pid?
+ *
+ * A struct pid is the kernel's internal notion of a process identifier.
+ * It refers to individual tasks, process groups, and sessions.  While
+ * there are processes attached to it the struct pid lives in a hash
+ * table, so it and then the processes that it refers to can be found
+ * quickly from the numeric pid value.  The attached processes may be
+ * quickly accessed by following pointers from struct pid.
+ *
+ * Storing pid_t values in the kernel and refering to them later has a
+ * problem.  The process originally with that pid may have exited and the
+ * pid allocator wrapped, and another process could have come along
+ * and been assigned that pid.
+ *
+ * Referring to user space processes by holding a reference to struct
+ * task_struct has a problem.  When the user space process exits
+ * the now useless task_struct is still kept.  A task_struct plus a
+ * stack consumes around 10K of low kernel memory.  More precisely
+ * this is THREAD_SIZE + sizeof(struct task_struct).  By comparison
+ * a struct pid is about 64 bytes.
+ *
+ * Holding a reference to struct pid solves both of these problems.
+ * It is small so holding a reference does not consume a lot of
+ * resources, and since a new struct pid is allocated when the numeric
+ * pid value is reused we don't mistakenly refer to new processes.
+ */
+
 struct pid
 {
+       atomic_t count;
        /* Try to keep pid_chain in the same cacheline as nr for find_pid */
        int nr;
        struct hlist_node pid_chain;
-       /* list of pids with the same nr, only one of them is in the hash */
-       struct list_head pid_list;
+       /* lists of tasks that use this pid */
+       struct hlist_head tasks[PIDTYPE_MAX];
+       struct rcu_head rcu;
 };
 
-#define pid_task(elem, type) \
-       list_entry(elem, struct task_struct, pids[type].pid_list)
+struct pid_link
+{
+       struct hlist_node node;
+       struct pid *pid;
+};
+
+static inline struct pid *get_pid(struct pid *pid)
+{
+       if (pid)
+               atomic_inc(&pid->count);
+       return pid;
+}
+
+extern void FASTCALL(put_pid(struct pid *pid));
+extern struct task_struct *FASTCALL(pid_task(struct pid *pid, enum pid_type));
+extern struct task_struct *FASTCALL(get_pid_task(struct pid *pid,
+                                               enum pid_type));
 
 /*
  * attach_pid() and detach_pid() must be called with the tasklist_lock
  * write-held.
  */
-extern int FASTCALL(attach_pid(struct task_struct *task, enum pid_type type, int nr));
+extern int FASTCALL(attach_pid(struct task_struct *task,
+                               enum pid_type type, int nr));
 
 extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
 
 /*
  * look up a PID in the hash table. Must be called with the tasklist_lock
- * held.
+ * or rcu_read_lock() held.
+ */
+extern struct pid *FASTCALL(find_pid(int nr));
+
+/*
+ * Lookup a PID in the hash table, and return with it's count elevated.
  */
-extern struct pid *FASTCALL(find_pid(enum pid_type, int));
+extern struct pid *find_get_pid(int nr);
 
-extern int alloc_pidmap(void);
-extern void FASTCALL(free_pidmap(int));
+extern struct pid *alloc_pid(void);
+extern void FASTCALL(free_pid(struct pid *pid));
 
+#define pid_next(task, type)                                   \
+       ((task)->pids[(type)].node.next)
+
+#define pid_next_task(task, type)                              \
+       hlist_entry(pid_next(task, type), struct task_struct,   \
+                       pids[(type)].node)
+
+
+/* We could use hlist_for_each_entry_rcu here but it takes more arguments
+ * than the do_each_task_pid/while_each_task_pid.  So we roll our own
+ * to preserve the existing interface.
+ */
 #define do_each_task_pid(who, type, task)                              \
        if ((task = find_task_by_pid_type(type, who))) {                \
-               prefetch((task)->pids[type].pid_list.next);             \
+               prefetch(pid_next(task, type));                         \
                do {
 
 #define while_each_task_pid(who, type, task)                           \
-               } while (task = pid_task((task)->pids[type].pid_list.next,\
-                                               type),                  \
-                       prefetch((task)->pids[type].pid_list.next),     \
-                       hlist_unhashed(&(task)->pids[type].pid_chain)); \
-       }                                                               \
+               } while (pid_next(task, type) &&  ({                    \
+                               task = pid_next_task(task, type);       \
+                               rcu_dereference(task);                  \
+                               prefetch(pid_next(task, type));         \
+                               1; }) );                                \
+       }
 
 #endif /* _LINUX_PID_H */
index 75c7f55..d218fc7 100644 (file)
@@ -60,5 +60,8 @@ void free_pipe_info(struct inode* inode);
  * add the splice flags here.
  */
 #define SPLICE_F_MOVE  (0x01)  /* move pages instead of copying */
+#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
+                                /* we may still block on the fd we splice */
+                                /* from/to, of course */
 
 #endif
index d04186d..541f482 100644 (file)
@@ -100,6 +100,7 @@ DECLARE_PER_CPU(unsigned long, process_counts);
 extern int nr_processes(void);
 extern unsigned long nr_running(void);
 extern unsigned long nr_uninterruptible(void);
+extern unsigned long nr_active(void);
 extern unsigned long nr_iowait(void);
 
 #include <linux/time.h>
@@ -483,6 +484,7 @@ struct signal_struct {
 #define MAX_PRIO               (MAX_RT_PRIO + 40)
 
 #define rt_task(p)             (unlikely((p)->prio < MAX_RT_PRIO))
+#define batch_task(p)          (unlikely((p)->policy == SCHED_BATCH))
 
 /*
  * Some day this will be a full-fledged user tracking system..
@@ -683,6 +685,13 @@ static inline void prefetch_stack(struct task_struct *t) { }
 struct audit_context;          /* See audit.c */
 struct mempolicy;
 
+enum sleep_type {
+       SLEEP_NORMAL,
+       SLEEP_NONINTERACTIVE,
+       SLEEP_INTERACTIVE,
+       SLEEP_INTERRUPTED,
+};
+
 struct task_struct {
        volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
        struct thread_info *thread_info;
@@ -705,7 +714,7 @@ struct task_struct {
        unsigned long sleep_avg;
        unsigned long long timestamp, last_ran;
        unsigned long long sched_time; /* sched_clock time spent running */
-       int activated;
+       enum sleep_type sleep_type;
 
        unsigned long policy;
        cpumask_t cpus_allowed;
@@ -751,7 +760,7 @@ struct task_struct {
        struct task_struct *group_leader;       /* threadgroup leader */
 
        /* PID/PID hash table linkage. */
-       struct pid pids[PIDTYPE_MAX];
+       struct pid_link pids[PIDTYPE_MAX];
        struct list_head thread_group;
 
        struct completion *vfork_done;          /* for vfork() */
@@ -890,18 +899,19 @@ static inline pid_t process_group(struct task_struct *tsk)
  */
 static inline int pid_alive(struct task_struct *p)
 {
-       return p->pids[PIDTYPE_PID].nr != 0;
+       return p->pids[PIDTYPE_PID].pid != NULL;
 }
 
 extern void free_task(struct task_struct *tsk);
 #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
 
 extern void __put_task_struct_cb(struct rcu_head *rhp);
+extern void __put_task_struct(struct task_struct *t);
 
 static inline void put_task_struct(struct task_struct *t)
 {
        if (atomic_dec_and_test(&t->usage))
-               call_rcu(&t->rcu, __put_task_struct_cb);
+               __put_task_struct(t);
 }
 
 /*
index 690aabc..6348e83 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 
@@ -42,7 +43,7 @@ struct serio {
        struct serio *parent, *child;
 
        struct serio_driver *drv;       /* accessed from interrupt, must be protected by serio->lock and serio->sem */
-       struct semaphore drv_sem;       /* protects serio->drv so attributes can pin driver */
+       struct mutex drv_mutex;         /* protects serio->drv so attributes can pin driver */
 
        struct device dev;
        unsigned int registered;        /* port has been fully registered with driver core */
@@ -151,17 +152,17 @@ static inline void serio_continue_rx(struct serio *serio)
  */
 static inline int serio_pin_driver(struct serio *serio)
 {
-       return down_interruptible(&serio->drv_sem);
+       return mutex_lock_interruptible(&serio->drv_mutex);
 }
 
 static inline void serio_pin_driver_uninterruptible(struct serio *serio)
 {
-       down(&serio->drv_sem);
+       mutex_lock(&serio->drv_mutex);
 }
 
 static inline void serio_unpin_driver(struct serio *serio)
 {
-       up(&serio->drv_sem);
+       mutex_unlock(&serio->drv_mutex);
 }
 
 
index 613b951..c4619a4 100644 (file)
@@ -941,6 +941,25 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
 #define NET_IP_ALIGN   2
 #endif
 
+/*
+ * The networking layer reserves some headroom in skb data (via
+ * dev_alloc_skb). This is used to avoid having to reallocate skb data when
+ * the header has to grow. In the default case, if the header has to grow
+ * 16 bytes or less we avoid the reallocation.
+ *
+ * Unfortunately this headroom changes the DMA alignment of the resulting
+ * network packet. As for NET_IP_ALIGN, this unaligned DMA is expensive
+ * on some architectures. An architecture can override this value,
+ * perhaps setting it to a cacheline in size (since that will maintain
+ * cacheline alignment of the DMA). It must be a power of 2.
+ *
+ * Various parts of the networking layer expect at least 16 bytes of
+ * headroom, you should not reduce this.
+ */
+#ifndef NET_SKB_PAD
+#define NET_SKB_PAD    16
+#endif
+
 extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
 
 static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
@@ -1030,9 +1049,9 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
 static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
                                              gfp_t gfp_mask)
 {
-       struct sk_buff *skb = alloc_skb(length + 16, gfp_mask);
+       struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
        if (likely(skb))
-               skb_reserve(skb, 16);
+               skb_reserve(skb, NET_SKB_PAD);
        return skb;
 }
 #else
@@ -1070,13 +1089,15 @@ static inline struct sk_buff *dev_alloc_skb(unsigned int length)
  */
 static inline int skb_cow(struct sk_buff *skb, unsigned int headroom)
 {
-       int delta = (headroom > 16 ? headroom : 16) - skb_headroom(skb);
+       int delta = (headroom > NET_SKB_PAD ? headroom : NET_SKB_PAD) -
+                       skb_headroom(skb);
 
        if (delta < 0)
                delta = 0;
 
        if (delta || skb_cloned(skb))
-               return pskb_expand_head(skb, (delta + 15) & ~15, 0, GFP_ATOMIC);
+               return pskb_expand_head(skb, (delta + (NET_SKB_PAD-1)) &
+                               ~(NET_SKB_PAD-1), 0, GFP_ATOMIC);
        return 0;
 }
 
index e78ffc7..5717147 100644 (file)
@@ -571,5 +571,7 @@ asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
 asmlinkage long sys_unshare(unsigned long unshare_flags);
 asmlinkage long sys_splice(int fdin, int fdout, size_t len,
                                unsigned int flags);
+asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
+                                       int flags);
 
 #endif
index b5caabc..0a485be 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
 
-struct timer_base_s;
+struct tvec_t_base_s;
 
 struct timer_list {
        struct list_head entry;
@@ -15,16 +15,16 @@ struct timer_list {
        void (*function)(unsigned long);
        unsigned long data;
 
-       struct timer_base_s *base;
+       struct tvec_t_base_s *base;
 };
 
-extern struct timer_base_s __init_timer_base;
+extern struct tvec_t_base_s boot_tvec_bases;
 
 #define TIMER_INITIALIZER(_function, _expires, _data) {                \
                .function = (_function),                        \
                .expires = (_expires),                          \
                .data = (_data),                                \
-               .base = &__init_timer_base,                     \
+               .base = &boot_tvec_bases,                       \
        }
 
 #define DEFINE_TIMER(_name, _function, _expires, _data)                \
index 2c9e847..4756862 100644 (file)
@@ -34,5 +34,6 @@ struct tiocl_selection {
 #define TIOCL_SCROLLCONSOLE    13      /* scroll console */
 #define TIOCL_BLANKSCREEN      14      /* keep screen blank even if a key is pressed */
 #define TIOCL_BLANKEDSCREEN    15      /* return which vt was blanked */
+#define TIOCL_GETKMSGREDIRECT  17      /* get the vt the kernel messages are restricted to */
 
 #endif /* _LINUX_TIOCL_H */
index 0ff7ca6..7168302 100644 (file)
@@ -20,7 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
- * 
+ *
  * Changes/Revisions:
  *     0.2     16/10/2004 (Micah Dowty <micah@navi.cx>)
  *             - added force feedback support
@@ -51,7 +51,7 @@ struct uinput_request {
 
 struct uinput_device {
        struct input_dev        *dev;
-       struct semaphore        sem;
+       struct mutex            mutex;
        enum uinput_state       state;
        wait_queue_head_t       waitq;
        unsigned char           ready;
index 9418f4d..3c989db 100644 (file)
@@ -405,9 +405,6 @@ extern int                  tcp_disconnect(struct sock *sk, int flags);
 
 extern void                    tcp_unhash(struct sock *sk);
 
-extern int                     tcp_v4_hash_connecting(struct sock *sk);
-
-
 /* From syncookies.c */
 extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, 
                                    struct ip_options *opt);
index e100291..0d5529c 100644 (file)
@@ -242,7 +242,6 @@ extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
 
 extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
-struct xfrm_decap_state;
 struct xfrm_type
 {
        char                    *description;
@@ -251,7 +250,7 @@ struct xfrm_type
 
        int                     (*init_state)(struct xfrm_state *x);
        void                    (*destructor)(struct xfrm_state *);
-       int                     (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
+       int                     (*input)(struct xfrm_state *, struct sk_buff *skb);
        int                     (*output)(struct xfrm_state *, struct sk_buff *pskb);
        /* Estimate maximal size of result of transformation of a dgram */
        u32                     (*get_max_size)(struct xfrm_state *, int size);
@@ -606,25 +605,11 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
 
 extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
 
-/* Decapsulation state, used by the input to store data during
- * decapsulation procedure, to be used later (during the policy
- * check
- */
-struct xfrm_decap_state {
-       char    decap_data[20];
-       __u16   decap_type;
-};   
-
-struct sec_decap_state {
-       struct xfrm_state       *xvec;
-       struct xfrm_decap_state decap;
-};
-
 struct sec_path
 {
        atomic_t                refcnt;
        int                     len;
-       struct sec_decap_state  x[XFRM_MAX_DEPTH];
+       struct xfrm_state       *xvec[XFRM_MAX_DEPTH];
 };
 
 static inline struct sec_path *
index b53b78d..6bc7472 100644 (file)
@@ -35,7 +35,7 @@ typedef struct region_info_t {
 #define REGION_BAR_MASK                0xe000
 #define REGION_BAR_SHIFT       13
 
-int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn);
-int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn);
+int pcmcia_get_first_region(struct pcmcia_device *handle, region_info_t *rgn);
+int pcmcia_get_next_region(struct pcmcia_device *handle, region_info_t *rgn);
 
 #endif /* _LINUX_BULKMEM_H */
index da19c29..c1da855 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * ciscode.h -- Definitions for bulk memory services
+ * ciscode.h
  *
  * 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
 
 #define MANFID_XIRCOM                  0x0105
 
+#define MANFID_POSSIO                  0x030c
+#define PRODID_POSSIO_GCC              0x0003
+
 #endif /* _LINUX_CISCODE_H */
index c6a0695..d3bbb19 100644 (file)
@@ -586,12 +586,7 @@ typedef struct cisdump_t {
     cisdata_t  Data[CISTPL_MAX_CIS_SIZE];
 } cisdump_t;
 
-int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple);
-int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple);
-int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple);
-int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse);
 
-int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info);
 int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis);
 
 /* don't use outside of PCMCIA core yet */
@@ -602,4 +597,20 @@ int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse);
 
 int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_t *info);
 
+/* ... but use these wrappers instead */
+#define pcmcia_get_first_tuple(p_dev, tuple) \
+               pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple)
+
+#define pcmcia_get_next_tuple(p_dev, tuple) \
+               pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple)
+
+#define pcmcia_get_tuple_data(p_dev, tuple) \
+               pccard_get_tuple_data(p_dev->socket, tuple)
+
+#define pcmcia_parse_tuple(p_dev, tuple, parse) \
+               pccard_parse_tuple(tuple, parse)
+
+#define pcmcia_validate_cis(p_dev, info) \
+               pccard_validate_cis(p_dev->socket, p_dev->func, info)
+
 #endif /* LINUX_CISTPL_H */
index 52660f3..d5838c3 100644 (file)
@@ -109,17 +109,6 @@ typedef struct client_req_t {
 
 #define CLIENT_THIS_SOCKET     0x01
 
-/* For RegisterClient */
-typedef struct client_reg_t {
-    dev_info_t *dev_info;
-    u_int      Attributes;  /* UNUSED */
-    u_int      EventMask;
-    int                (*event_handler)(event_t event, int priority,
-                                event_callback_args_t *);
-    event_callback_args_t event_callback_args;
-    u_int      Version;
-} client_reg_t;
-
 /* ModifyConfiguration */
 typedef struct modconf_t {
     u_int      Attributes;
@@ -127,15 +116,16 @@ typedef struct modconf_t {
 } modconf_t;
 
 /* Attributes for ModifyConfiguration */
-#define CONF_IRQ_CHANGE_VALID  0x100
-#define CONF_VCC_CHANGE_VALID  0x200
-#define CONF_VPP1_CHANGE_VALID 0x400
-#define CONF_VPP2_CHANGE_VALID 0x800
+#define CONF_IRQ_CHANGE_VALID  0x0100
+#define CONF_VCC_CHANGE_VALID  0x0200
+#define CONF_VPP1_CHANGE_VALID 0x0400
+#define CONF_VPP2_CHANGE_VALID 0x0800
+#define CONF_IO_CHANGE_WIDTH   0x1000
 
 /* For RequestConfiguration */
 typedef struct config_req_t {
     u_int      Attributes;
-    u_int      Vcc, Vpp1, Vpp2;
+    u_int      Vpp; /* both Vpp1 and Vpp2 */
     u_int      IntType;
     u_int      ConfigBase;
     u_char     Status, Pin, Copy, ExtStatus;
@@ -389,23 +379,27 @@ int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status);
 int pcmcia_get_mem_page(window_handle_t win, memreq_t *req);
 int pcmcia_map_mem_page(window_handle_t win, memreq_t *req);
 int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
-int pcmcia_release_configuration(struct pcmcia_device *p_dev);
-int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req);
-int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req);
 int pcmcia_release_window(window_handle_t win);
 int pcmcia_request_configuration(struct pcmcia_device *p_dev, config_req_t *req);
 int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req);
 int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req);
 int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh);
-int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req);
 int pcmcia_suspend_card(struct pcmcia_socket *skt);
 int pcmcia_resume_card(struct pcmcia_socket *skt);
 int pcmcia_eject_card(struct pcmcia_socket *skt);
 int pcmcia_insert_card(struct pcmcia_socket *skt);
+int pccard_reset_card(struct pcmcia_socket *skt);
+
+struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *p_dev);
+void pcmcia_disable_device(struct pcmcia_device *p_dev);
 
 struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt);
 void pcmcia_put_socket(struct pcmcia_socket *skt);
 
+/* compatibility functions */
+#define pcmcia_reset_card(p_dev, req) \
+               pccard_reset_card(p_dev->socket)
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_CS_H */
index 8e2a963..8c339f5 100644 (file)
@@ -39,7 +39,7 @@ typedef struct win_info_t {
 typedef struct bind_info_t {
     dev_info_t         dev_info;
     u_char             function;
-    struct dev_link_t  *instance;
+    struct pcmcia_device *instance;
     char               name[DEV_NAME_LEN];
     u_short            major, minor;
     void               *next;
@@ -96,6 +96,7 @@ typedef union ds_ioctl_arg_t {
 
 #ifdef __KERNEL__
 #include <linux/device.h>
+#include <pcmcia/ss.h>
 
 typedef struct dev_node_t {
     char               dev_name[DEV_NAME_LEN];
@@ -103,34 +104,9 @@ typedef struct dev_node_t {
     struct dev_node_t  *next;
 } dev_node_t;
 
-typedef struct dev_link_t {
-    dev_node_t         *dev;
-    u_int              state, open;
-    wait_queue_head_t  pending;
-    client_handle_t    handle;
-    io_req_t           io;
-    irq_req_t          irq;
-    config_req_t       conf;
-    window_handle_t    win;
-    void               *priv;
-    struct dev_link_t  *next;
-} dev_link_t;
-
-/* Flags for device state */
-#define DEV_PRESENT            0x01
-#define DEV_CONFIG             0x02
-#define DEV_STALE_CONFIG       0x04    /* release on close */
-#define DEV_STALE_LINK         0x08    /* detach on release */
-#define DEV_CONFIG_PENDING     0x10
-#define DEV_RELEASE_PENDING    0x20
-#define DEV_SUSPEND            0x40
-#define DEV_BUSY               0x80
-
-#define DEV_OK(l) \
-    ((l) && ((l->state & ~DEV_BUSY) == (DEV_CONFIG|DEV_PRESENT)))
-
 
 struct pcmcia_socket;
+struct config_t;
 
 struct pcmcia_driver {
        int (*probe)            (struct pcmcia_device *dev);
@@ -148,6 +124,7 @@ struct pcmcia_driver {
 int pcmcia_register_driver(struct pcmcia_driver *driver);
 void pcmcia_unregister_driver(struct pcmcia_driver *driver);
 
+
 struct pcmcia_device {
        /* the socket and the device_no [for multifunction devices]
           uniquely define a pcmcia_device */
@@ -160,21 +137,40 @@ struct pcmcia_device {
        /* the hardware "function" device; certain subdevices can
         * share one hardware "function" device. */
        u8                      func;
+       struct config_t*        function_config;
 
        struct list_head        socket_device_list;
 
-       /* deprecated, a cleaned up version will be moved into this
-          struct soon */
-       dev_link_t              *instance;
-       u_int                   state;
+       /* deprecated, will be cleaned up soon */
+       dev_node_t              *dev_node;
+       u_int                   open;
+       io_req_t                io;
+       irq_req_t               irq;
+       config_req_t            conf;
+       window_handle_t         win;
+
+       /* Is the device suspended, or in the process of
+        * being removed? */
+       u16                     suspended:1;
+       u16                     _removed:1;
+
+       /* Flags whether io, irq, win configurations were
+        * requested, and whether the configuration is "locked" */
+       u16                     _irq:1;
+       u16                     _io:1;
+       u16                     _win:4;
+       u16                     _locked:1;
+
+       /* Flag whether a "fuzzy" func_id based match is
+        * allowed. */
+       u16                     allow_func_id_match:1;
 
        /* information about this device */
-       u                     has_manf_id:1;
-       u                     has_card_id:1;
-       u                     has_func_id:1;
+       u16                     has_manf_id:1;
+       u16                     has_card_id:1;
+       u16                     has_func_id:1;
 
-       u8                      allow_func_id_match:1;
-       u8                      reserved:4;
+       u16                     reserved:3;
 
        u8                      func_id;
        u16                     manf_id;
@@ -182,22 +178,24 @@ struct pcmcia_device {
 
        char *                  prod_id[4];
 
+       struct device           dev;
+
+#ifdef CONFIG_PCMCIA_IOCTL
        /* device driver wanted by cardmgr */
        struct pcmcia_driver *  cardmgr;
+#endif
 
-       struct device           dev;
+       /* data private to drivers */
+       void                    *priv;
 };
 
 #define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev)
 #define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv)
 
-#define handle_to_pdev(handle) (handle)
 #define handle_to_dev(handle) (handle->dev)
 
-#define dev_to_instance(dev) (dev->instance)
-
 /* error reporting */
-void cs_error(client_handle_t handle, int func, int ret);
+void cs_error(struct pcmcia_device *handle, int func, int ret);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_DS_H */
index 2889a69..5e0a01a 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/config.h>
 #include <linux/device.h>
 #include <linux/sched.h>       /* task_struct, completion */
+#include <linux/mutex.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
@@ -146,14 +147,15 @@ extern struct pccard_resource_ops pccard_static_ops;
 /* !SS_CAP_STATIC_MAP */
 extern struct pccard_resource_ops pccard_nonstatic_ops;
 
+/* static mem, dynamic IO sockets */
+extern struct pccard_resource_ops pccard_iodyn_ops;
+
 /*
  *  Calls to set up low-level "Socket Services" drivers
  */
 struct pcmcia_socket;
 
 typedef struct io_window_t {
-       u_int                   Attributes;
-       kio_addr_t              BasePort, NumPorts;
        kio_addr_t              InUse, Config;
        struct resource         *res;
 } io_window_t;
@@ -162,7 +164,7 @@ typedef struct io_window_t {
 typedef struct window_t {
        u_short                 magic;
        u_short                 index;
-       client_handle_t         handle;
+       struct pcmcia_device    *handle;
        struct pcmcia_socket    *sock;
        pccard_mem_map          ctl;
 } window_t;
@@ -186,7 +188,6 @@ struct pcmcia_socket {
        u_short                         lock_count;
        pccard_mem_map                  cis_mem;
        void __iomem                    *cis_virt;
-       struct config_t                 *config;
        struct {
                u_int                   AssignedIRQ;
                u_int                   Config;
@@ -241,7 +242,7 @@ struct pcmcia_socket {
 #endif
 
        /* state thread */
-       struct semaphore                skt_sem;        /* protects socket h/w state */
+       struct mutex                    skt_mutex;      /* protects socket h/w state */
 
        struct task_struct              *thread;
        struct completion               thread_done;
index 065d8b4..b327f4d 100644 (file)
@@ -449,8 +449,8 @@ static void do_acct_process(long exitcode, struct file *file)
        /* calculate run_time in nsec*/
        do_posix_clock_monotonic_gettime(&uptime);
        run_time = (u64)uptime.tv_sec*NSEC_PER_SEC + uptime.tv_nsec;
-       run_time -= (u64)current->start_time.tv_sec*NSEC_PER_SEC
-                                       + current->start_time.tv_nsec;
+       run_time -= (u64)current->group_leader->start_time.tv_sec * NSEC_PER_SEC
+                      + current->group_leader->start_time.tv_nsec;
        /* convert nsec -> AHZ */
        elapsed = nsec_to_AHZ(run_time);
 #if ACCT_VERSION==3
@@ -469,10 +469,10 @@ static void do_acct_process(long exitcode, struct file *file)
 #endif
        do_div(elapsed, AHZ);
        ac.ac_btime = xtime.tv_sec - elapsed;
-       jiffies = cputime_to_jiffies(cputime_add(current->group_leader->utime,
+       jiffies = cputime_to_jiffies(cputime_add(current->utime,
                                                 current->signal->utime));
        ac.ac_utime = encode_comp_t(jiffies_to_AHZ(jiffies));
-       jiffies = cputime_to_jiffies(cputime_add(current->group_leader->stime,
+       jiffies = cputime_to_jiffies(cputime_add(current->stime,
                                                 current->signal->stime));
        ac.ac_stime = encode_comp_t(jiffies_to_AHZ(jiffies));
        /* we really need to bite the bullet and change layout */
@@ -522,9 +522,9 @@ static void do_acct_process(long exitcode, struct file *file)
        ac.ac_io = encode_comp_t(0 /* current->io_usage */);    /* %% */
        ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
        ac.ac_minflt = encode_comp_t(current->signal->min_flt +
-                                    current->group_leader->min_flt);
+                                    current->min_flt);
        ac.ac_majflt = encode_comp_t(current->signal->maj_flt +
-                                    current->group_leader->maj_flt);
+                                    current->maj_flt);
        ac.ac_swaps = encode_comp_t(0);
        ac.ac_exitcode = exitcode;
 
index 04fe2e3..c8ccbd0 100644 (file)
@@ -578,7 +578,7 @@ static int __init audit_enable(char *str)
               audit_initialized ? "" : " (after initialization)");
        if (audit_initialized)
                audit_enabled = audit_default;
-       return 0;
+       return 1;
 }
 
 __setup("audit=", audit_enable);
index 18aea1b..72248d1 100644 (file)
@@ -616,12 +616,10 @@ static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
  * current->cpuset if a task has its memory placement changed.
  * Do not call this routine if in_interrupt().
  *
- * Call without callback_mutex or task_lock() held.  May be called
- * with or without manage_mutex held.  Doesn't need task_lock to guard
- * against another task changing a non-NULL cpuset pointer to NULL,
- * as that is only done by a task on itself, and if the current task
- * is here, it is not simultaneously in the exit code NULL'ing its
- * cpuset pointer.  This routine also might acquire callback_mutex and
+ * Call without callback_mutex or task_lock() held.  May be
+ * called with or without manage_mutex held.  Thanks in part to
+ * 'the_top_cpuset_hack', the tasks cpuset pointer will never
+ * be NULL.  This routine also might acquire callback_mutex and
  * current->mm->mmap_sem during call.
  *
  * Reading current->cpuset->mems_generation doesn't need task_lock
@@ -835,6 +833,55 @@ static int update_cpumask(struct cpuset *cs, char *buf)
        return 0;
 }
 
+/*
+ * cpuset_migrate_mm
+ *
+ *    Migrate memory region from one set of nodes to another.
+ *
+ *    Temporarilly set tasks mems_allowed to target nodes of migration,
+ *    so that the migration code can allocate pages on these nodes.
+ *
+ *    Call holding manage_mutex, so our current->cpuset won't change
+ *    during this call, as manage_mutex holds off any attach_task()
+ *    calls.  Therefore we don't need to take task_lock around the
+ *    call to guarantee_online_mems(), as we know no one is changing
+ *    our tasks cpuset.
+ *
+ *    Hold callback_mutex around the two modifications of our tasks
+ *    mems_allowed to synchronize with cpuset_mems_allowed().
+ *
+ *    While the mm_struct we are migrating is typically from some
+ *    other task, the task_struct mems_allowed that we are hacking
+ *    is for our current task, which must allocate new pages for that
+ *    migrating memory region.
+ *
+ *    We call cpuset_update_task_memory_state() before hacking
+ *    our tasks mems_allowed, so that we are assured of being in
+ *    sync with our tasks cpuset, and in particular, callbacks to
+ *    cpuset_update_task_memory_state() from nested page allocations
+ *    won't see any mismatch of our cpuset and task mems_generation
+ *    values, so won't overwrite our hacked tasks mems_allowed
+ *    nodemask.
+ */
+
+static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
+                                                       const nodemask_t *to)
+{
+       struct task_struct *tsk = current;
+
+       cpuset_update_task_memory_state();
+
+       mutex_lock(&callback_mutex);
+       tsk->mems_allowed = *to;
+       mutex_unlock(&callback_mutex);
+
+       do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL);
+
+       mutex_lock(&callback_mutex);
+       guarantee_online_mems(tsk->cpuset, &tsk->mems_allowed);
+       mutex_unlock(&callback_mutex);
+}
+
 /*
  * Handle user request to change the 'mems' memory placement
  * of a cpuset.  Needs to validate the request, update the
@@ -947,10 +994,8 @@ static int update_nodemask(struct cpuset *cs, char *buf)
                struct mm_struct *mm = mmarray[i];
 
                mpol_rebind_mm(mm, &cs->mems_allowed);
-               if (migrate) {
-                       do_migrate_pages(mm, &oldmem, &cs->mems_allowed,
-                                                       MPOL_MF_MOVE_ALL);
-               }
+               if (migrate)
+                       cpuset_migrate_mm(mm, &oldmem, &cs->mems_allowed);
                mmput(mm);
        }
 
@@ -1185,11 +1230,11 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
        mm = get_task_mm(tsk);
        if (mm) {
                mpol_rebind_mm(mm, &to);
+               if (is_memory_migrate(cs))
+                       cpuset_migrate_mm(mm, &from, &to);
                mmput(mm);
        }
 
-       if (is_memory_migrate(cs))
-               do_migrate_pages(tsk->mm, &from, &to, MPOL_MF_MOVE_ALL);
        put_task_struct(tsk);
        synchronize_rcu();
        if (atomic_dec_and_test(&oldcs->count))
index bc0ec67..6c2eeb8 100644 (file)
@@ -127,6 +127,11 @@ static void __exit_signal(struct task_struct *tsk)
        }
 }
 
+static void delayed_put_task_struct(struct rcu_head *rhp)
+{
+       put_task_struct(container_of(rhp, struct task_struct, rcu));
+}
+
 void release_task(struct task_struct * p)
 {
        int zap_leader;
@@ -168,7 +173,7 @@ repeat:
        spin_unlock(&p->proc_lock);
        proc_pid_flush(proc_dentry);
        release_thread(p);
-       put_task_struct(p);
+       call_rcu(&p->rcu, delayed_put_task_struct);
 
        p = leader;
        if (unlikely(zap_leader))
index b3f7a1b..3384eb8 100644 (file)
@@ -108,10 +108,8 @@ void free_task(struct task_struct *tsk)
 }
 EXPORT_SYMBOL(free_task);
 
-void __put_task_struct_cb(struct rcu_head *rhp)
+void __put_task_struct(struct task_struct *tsk)
 {
-       struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
-
        WARN_ON(!(tsk->exit_state & (EXIT_DEAD | EXIT_ZOMBIE)));
        WARN_ON(atomic_read(&tsk->usage));
        WARN_ON(tsk == current);
@@ -126,6 +124,12 @@ void __put_task_struct_cb(struct rcu_head *rhp)
                free_task(tsk);
 }
 
+void __put_task_struct_cb(struct rcu_head *rhp)
+{
+       struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
+       __put_task_struct(tsk);
+}
+
 void __init fork_init(unsigned long mempages)
 {
 #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
@@ -721,7 +725,7 @@ out_release:
        free_fdset (new_fdt->open_fds, new_fdt->max_fdset);
        free_fd_array(new_fdt->fd, new_fdt->max_fds);
        kmem_cache_free(files_cachep, newf);
-       goto out;
+       return NULL;
 }
 
 static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
@@ -1311,17 +1315,19 @@ long do_fork(unsigned long clone_flags,
 {
        struct task_struct *p;
        int trace = 0;
-       long pid = alloc_pidmap();
+       struct pid *pid = alloc_pid();
+       long nr;
 
-       if (pid < 0)
+       if (!pid)
                return -EAGAIN;
+       nr = pid->nr;
        if (unlikely(current->ptrace)) {
                trace = fork_traceflag (clone_flags);
                if (trace)
                        clone_flags |= CLONE_PTRACE;
        }
 
-       p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
+       p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, nr);
        /*
         * Do this prior waking up the new thread - the thread pointer
         * might get invalid after that point, if the thread exits quickly.
@@ -1348,7 +1354,7 @@ long do_fork(unsigned long clone_flags,
                        p->state = TASK_STOPPED;
 
                if (unlikely (trace)) {
-                       current->ptrace_message = pid;
+                       current->ptrace_message = nr;
                        ptrace_notify ((trace << 8) | SIGTRAP);
                }
 
@@ -1358,10 +1364,10 @@ long do_fork(unsigned long clone_flags,
                                ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
                }
        } else {
-               free_pidmap(pid);
-               pid = PTR_ERR(p);
+               free_pid(pid);
+               nr = PTR_ERR(p);
        }
-       return pid;
+       return nr;
 }
 
 #ifndef ARCH_MIN_MMSTRUCT_ALIGN
index 9c9b2b6..5699c51 100644 (file)
@@ -1039,9 +1039,11 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
        unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
        int val2 = 0;
 
-       if ((op == FUTEX_WAIT) && utime) {
+       if (utime && (op == FUTEX_WAIT)) {
                if (copy_from_user(&t, utime, sizeof(t)) != 0)
                        return -EFAULT;
+               if (!timespec_valid(&t))
+                       return -EINVAL;
                timeout = timespec_to_jiffies(&t) + 1;
        }
        /*
index 54274fc..1ab6a0e 100644 (file)
@@ -129,9 +129,11 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
        unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
        int val2 = 0;
 
-       if ((op == FUTEX_WAIT) && utime) {
+       if (utime && (op == FUTEX_WAIT)) {
                if (get_compat_timespec(&t, utime))
                        return -EFAULT;
+               if (!timespec_valid(&t))
+                       return -EINVAL;
                timeout = timespec_to_jiffies(&t) + 1;
        }
        if (op >= FUTEX_REQUEUE)
index 0237a55..f181ff4 100644 (file)
@@ -606,6 +606,9 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base)
 {
        struct rb_node *node;
 
+       if (!base->first)
+               return;
+
        if (base->get_softirq_time)
                base->softirq_time = base->get_softirq_time();
 
@@ -655,29 +658,28 @@ void hrtimer_run_queues(void)
 /*
  * Sleep related functions:
  */
-
-struct sleep_hrtimer {
-       struct hrtimer timer;
-       struct task_struct *task;
-       int expired;
-};
-
-static int nanosleep_wakeup(struct hrtimer *timer)
+static int hrtimer_wakeup(struct hrtimer *timer)
 {
-       struct sleep_hrtimer *t =
-               container_of(timer, struct sleep_hrtimer, timer);
+       struct hrtimer_sleeper *t =
+               container_of(timer, struct hrtimer_sleeper, timer);
+       struct task_struct *task = t->task;
 
-       t->expired = 1;
-       wake_up_process(t->task);
+       t->task = NULL;
+       if (task)
+               wake_up_process(task);
 
        return HRTIMER_NORESTART;
 }
 
-static int __sched do_nanosleep(struct sleep_hrtimer *t, enum hrtimer_mode mode)
+void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, task_t *task)
 {
-       t->timer.function = nanosleep_wakeup;
-       t->task = current;
-       t->expired = 0;
+       sl->timer.function = hrtimer_wakeup;
+       sl->task = task;
+}
+
+static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
+{
+       hrtimer_init_sleeper(t, current);
 
        do {
                set_current_state(TASK_INTERRUPTIBLE);
@@ -685,18 +687,17 @@ static int __sched do_nanosleep(struct sleep_hrtimer *t, enum hrtimer_mode mode)
 
                schedule();
 
-               if (unlikely(!t->expired)) {
-                       hrtimer_cancel(&t->timer);
-                       mode = HRTIMER_ABS;
-               }
-       } while (!t->expired && !signal_pending(current));
+               hrtimer_cancel(&t->timer);
+               mode = HRTIMER_ABS;
+
+       } while (t->task && !signal_pending(current));
 
-       return t->expired;
+       return t->task == NULL;
 }
 
 static long __sched nanosleep_restart(struct restart_block *restart)
 {
-       struct sleep_hrtimer t;
+       struct hrtimer_sleeper t;
        struct timespec __user *rmtp;
        struct timespec tu;
        ktime_t time;
@@ -729,7 +730,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
                       const enum hrtimer_mode mode, const clockid_t clockid)
 {
        struct restart_block *restart;
-       struct sleep_hrtimer t;
+       struct hrtimer_sleeper t;
        struct timespec tu;
        ktime_t rem;
 
index bd088a7..d24deb0 100644 (file)
@@ -1254,6 +1254,7 @@ static inline int license_is_gpl_compatible(const char *license)
                || strcmp(license, "GPL v2") == 0
                || strcmp(license, "GPL and additional rights") == 0
                || strcmp(license, "Dual BSD/GPL") == 0
+               || strcmp(license, "Dual MIT/GPL") == 0
                || strcmp(license, "Dual MPL/GPL") == 0);
 }
 
index a9f2dfd..eeb836b 100644 (file)
@@ -28,8 +28,9 @@
 #include <linux/hash.h>
 
 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
-static struct hlist_head *pid_hash[PIDTYPE_MAX];
+static struct hlist_head *pid_hash;
 static int pidhash_shift;
+static kmem_cache_t *pid_cachep;
 
 int pid_max = PID_MAX_DEFAULT;
 int last_pid;
@@ -60,9 +61,22 @@ typedef struct pidmap {
 static pidmap_t pidmap_array[PIDMAP_ENTRIES] =
         { [ 0 ... PIDMAP_ENTRIES-1 ] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } };
 
+/*
+ * Note: disable interrupts while the pidmap_lock is held as an
+ * interrupt might come in and do read_lock(&tasklist_lock).
+ *
+ * If we don't disable interrupts there is a nasty deadlock between
+ * detach_pid()->free_pid() and another cpu that does
+ * spin_lock(&pidmap_lock) followed by an interrupt routine that does
+ * read_lock(&tasklist_lock);
+ *
+ * After we clean up the tasklist_lock and know there are no
+ * irq handlers that take it we can leave the interrupts enabled.
+ * For now it is easier to be safe than to prove it can't happen.
+ */
 static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock);
 
-fastcall void free_pidmap(int pid)
+static fastcall void free_pidmap(int pid)
 {
        pidmap_t *map = pidmap_array + pid / BITS_PER_PAGE;
        int offset = pid & BITS_PER_PAGE_MASK;
@@ -71,7 +85,7 @@ fastcall void free_pidmap(int pid)
        atomic_inc(&map->nr_free);
 }
 
-int alloc_pidmap(void)
+static int alloc_pidmap(void)
 {
        int i, offset, max_scan, pid, last = last_pid;
        pidmap_t *map;
@@ -89,12 +103,12 @@ int alloc_pidmap(void)
                         * Free the page if someone raced with us
                         * installing it:
                         */
-                       spin_lock(&pidmap_lock);
+                       spin_lock_irq(&pidmap_lock);
                        if (map->page)
                                free_page(page);
                        else
                                map->page = (void *)page;
-                       spin_unlock(&pidmap_lock);
+                       spin_unlock_irq(&pidmap_lock);
                        if (unlikely(!map->page))
                                break;
                }
@@ -131,13 +145,73 @@ int alloc_pidmap(void)
        return -1;
 }
 
-struct pid * fastcall find_pid(enum pid_type type, int nr)
+fastcall void put_pid(struct pid *pid)
+{
+       if (!pid)
+               return;
+       if ((atomic_read(&pid->count) == 1) ||
+            atomic_dec_and_test(&pid->count))
+               kmem_cache_free(pid_cachep, pid);
+}
+
+static void delayed_put_pid(struct rcu_head *rhp)
+{
+       struct pid *pid = container_of(rhp, struct pid, rcu);
+       put_pid(pid);
+}
+
+fastcall void free_pid(struct pid *pid)
+{
+       /* We can be called with write_lock_irq(&tasklist_lock) held */
+       unsigned long flags;
+
+       spin_lock_irqsave(&pidmap_lock, flags);
+       hlist_del_rcu(&pid->pid_chain);
+       spin_unlock_irqrestore(&pidmap_lock, flags);
+
+       free_pidmap(pid->nr);
+       call_rcu(&pid->rcu, delayed_put_pid);
+}
+
+struct pid *alloc_pid(void)
+{
+       struct pid *pid;
+       enum pid_type type;
+       int nr = -1;
+
+       pid = kmem_cache_alloc(pid_cachep, GFP_KERNEL);
+       if (!pid)
+               goto out;
+
+       nr = alloc_pidmap();
+       if (nr < 0)
+               goto out_free;
+
+       atomic_set(&pid->count, 1);
+       pid->nr = nr;
+       for (type = 0; type < PIDTYPE_MAX; ++type)
+               INIT_HLIST_HEAD(&pid->tasks[type]);
+
+       spin_lock_irq(&pidmap_lock);
+       hlist_add_head_rcu(&pid->pid_chain, &pid_hash[pid_hashfn(pid->nr)]);
+       spin_unlock_irq(&pidmap_lock);
+
+out:
+       return pid;
+
+out_free:
+       kmem_cache_free(pid_cachep, pid);
+       pid = NULL;
+       goto out;
+}
+
+struct pid * fastcall find_pid(int nr)
 {
        struct hlist_node *elem;
        struct pid *pid;
 
        hlist_for_each_entry_rcu(pid, elem,
-                       &pid_hash[type][pid_hashfn(nr)], pid_chain) {
+                       &pid_hash[pid_hashfn(nr)], pid_chain) {
                if (pid->nr == nr)
                        return pid;
        }
@@ -146,77 +220,82 @@ struct pid * fastcall find_pid(enum pid_type type, int nr)
 
 int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
 {
-       struct pid *pid, *task_pid;
-
-       task_pid = &task->pids[type];
-       pid = find_pid(type, nr);
-       task_pid->nr = nr;
-       if (pid == NULL) {
-               INIT_LIST_HEAD(&task_pid->pid_list);
-               hlist_add_head_rcu(&task_pid->pid_chain,
-                                  &pid_hash[type][pid_hashfn(nr)]);
-       } else {
-               INIT_HLIST_NODE(&task_pid->pid_chain);
-               list_add_tail_rcu(&task_pid->pid_list, &pid->pid_list);
-       }
+       struct pid_link *link;
+       struct pid *pid;
+
+       WARN_ON(!task->pid); /* to be removed soon */
+       WARN_ON(!nr); /* to be removed soon */
+
+       link = &task->pids[type];
+       link->pid = pid = find_pid(nr);
+       hlist_add_head_rcu(&link->node, &pid->tasks[type]);
 
        return 0;
 }
 
-static fastcall int __detach_pid(task_t *task, enum pid_type type)
+void fastcall detach_pid(task_t *task, enum pid_type type)
 {
-       struct pid *pid, *pid_next;
-       int nr = 0;
+       struct pid_link *link;
+       struct pid *pid;
+       int tmp;
 
-       pid = &task->pids[type];
-       if (!hlist_unhashed(&pid->pid_chain)) {
+       link = &task->pids[type];
+       pid = link->pid;
 
-               if (list_empty(&pid->pid_list)) {
-                       nr = pid->nr;
-                       hlist_del_rcu(&pid->pid_chain);
-               } else {
-                       pid_next = list_entry(pid->pid_list.next,
-                                               struct pid, pid_list);
-                       /* insert next pid from pid_list to hash */
-                       hlist_replace_rcu(&pid->pid_chain,
-                                         &pid_next->pid_chain);
-               }
-       }
+       hlist_del_rcu(&link->node);
+       link->pid = NULL;
 
-       list_del_rcu(&pid->pid_list);
-       pid->nr = 0;
+       for (tmp = PIDTYPE_MAX; --tmp >= 0; )
+               if (!hlist_empty(&pid->tasks[tmp]))
+                       return;
 
-       return nr;
+       free_pid(pid);
 }
 
-void fastcall detach_pid(task_t *task, enum pid_type type)
+struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
 {
-       int tmp, nr;
+       struct task_struct *result = NULL;
+       if (pid) {
+               struct hlist_node *first;
+               first = rcu_dereference(pid->tasks[type].first);
+               if (first)
+                       result = hlist_entry(first, struct task_struct, pids[(type)].node);
+       }
+       return result;
+}
 
-       nr = __detach_pid(task, type);
-       if (!nr)
-               return;
+/*
+ * Must be called under rcu_read_lock() or with tasklist_lock read-held.
+ */
+task_t *find_task_by_pid_type(int type, int nr)
+{
+       return pid_task(find_pid(nr), type);
+}
 
-       for (tmp = PIDTYPE_MAX; --tmp >= 0; )
-               if (tmp != type && find_pid(tmp, nr))
-                       return;
+EXPORT_SYMBOL(find_task_by_pid_type);
 
-       free_pidmap(nr);
+struct task_struct *fastcall get_pid_task(struct pid *pid, enum pid_type type)
+{
+       struct task_struct *result;
+       rcu_read_lock();
+       result = pid_task(pid, type);
+       if (result)
+               get_task_struct(result);
+       rcu_read_unlock();
+       return result;
 }
 
-task_t *find_task_by_pid_type(int type, int nr)
+struct pid *find_get_pid(pid_t nr)
 {
        struct pid *pid;
 
-       pid = find_pid(type, nr);
-       if (!pid)
-               return NULL;
+       rcu_read_lock();
+       pid = get_pid(find_pid(nr));
+       rcu_read_unlock();
 
-       return pid_task(&pid->pid_list, type);
+       return pid;
 }
 
-EXPORT_SYMBOL(find_task_by_pid_type);
-
 /*
  * The pid hash table is scaled according to the amount of memory in the
  * machine.  From a minimum of 16 slots up to 4096 slots at one gigabyte or
@@ -224,7 +303,7 @@ EXPORT_SYMBOL(find_task_by_pid_type);
  */
 void __init pidhash_init(void)
 {
-       int i, j, pidhash_size;
+       int i, pidhash_size;
        unsigned long megabytes = nr_kernel_pages >> (20 - PAGE_SHIFT);
 
        pidhash_shift = max(4, fls(megabytes * 4));
@@ -233,16 +312,13 @@ void __init pidhash_init(void)
 
        printk("PID hash table entries: %d (order: %d, %Zd bytes)\n",
                pidhash_size, pidhash_shift,
-               PIDTYPE_MAX * pidhash_size * sizeof(struct hlist_head));
-
-       for (i = 0; i < PIDTYPE_MAX; i++) {
-               pid_hash[i] = alloc_bootmem(pidhash_size *
-                                       sizeof(*(pid_hash[i])));
-               if (!pid_hash[i])
-                       panic("Could not alloc pidhash!\n");
-               for (j = 0; j < pidhash_size; j++)
-                       INIT_HLIST_HEAD(&pid_hash[i][j]);
-       }
+               pidhash_size * sizeof(struct hlist_head));
+
+       pid_hash = alloc_bootmem(pidhash_size * sizeof(*(pid_hash)));
+       if (!pid_hash)
+               panic("Could not alloc pidhash!\n");
+       for (i = 0; i < pidhash_size; i++)
+               INIT_HLIST_HEAD(&pid_hash[i]);
 }
 
 void __init pidmap_init(void)
@@ -251,4 +327,8 @@ void __init pidmap_init(void)
        /* Reserve PID 0. We never call free_pidmap(0) */
        set_bit(0, pidmap_array->page);
        atomic_dec(&pidmap_array->nr_free);
+
+       pid_cachep = kmem_cache_create("pid", sizeof(struct pid),
+                                       __alignof__(struct pid),
+                                       SLAB_PANIC, NULL, NULL);
 }
index 8ac7c35..b2a5f67 100644 (file)
@@ -26,8 +26,7 @@ static inline int freezeable(struct task_struct * p)
            (p->flags & PF_NOFREEZE) ||
            (p->exit_state == EXIT_ZOMBIE) ||
            (p->exit_state == EXIT_DEAD) ||
-           (p->state == TASK_STOPPED) ||
-           (p->state == TASK_TRACED))
+           (p->state == TASK_STOPPED))
                return 0;
        return 1;
 }
index a9ecac3..dd153d6 100644 (file)
@@ -667,9 +667,13 @@ static int effective_prio(task_t *p)
 /*
  * __activate_task - move a task to the runqueue.
  */
-static inline void __activate_task(task_t *p, runqueue_t *rq)
+static void __activate_task(task_t *p, runqueue_t *rq)
 {
-       enqueue_task(p, rq->active);
+       prio_array_t *target = rq->active;
+
+       if (batch_task(p))
+               target = rq->expired;
+       enqueue_task(p, target);
        rq->nr_running++;
 }
 
@@ -688,7 +692,7 @@ static int recalc_task_prio(task_t *p, unsigned long long now)
        unsigned long long __sleep_time = now - p->timestamp;
        unsigned long sleep_time;
 
-       if (unlikely(p->policy == SCHED_BATCH))
+       if (batch_task(p))
                sleep_time = 0;
        else {
                if (__sleep_time > NS_MAX_SLEEP_AVG)
@@ -700,21 +704,25 @@ static int recalc_task_prio(task_t *p, unsigned long long now)
        if (likely(sleep_time > 0)) {
                /*
                 * User tasks that sleep a long time are categorised as
-                * idle and will get just interactive status to stay active &
-                * prevent them suddenly becoming cpu hogs and starving
-                * other processes.
+                * idle. They will only have their sleep_avg increased to a
+                * level that makes them just interactive priority to stay
+                * active yet prevent them suddenly becoming cpu hogs and
+                * starving other processes.
                 */
-               if (p->mm && p->activated != -1 &&
-                       sleep_time > INTERACTIVE_SLEEP(p)) {
-                               p->sleep_avg = JIFFIES_TO_NS(MAX_SLEEP_AVG -
-                                               DEF_TIMESLICE);
+               if (p->mm && sleep_time > INTERACTIVE_SLEEP(p)) {
+                               unsigned long ceiling;
+
+                               ceiling = JIFFIES_TO_NS(MAX_SLEEP_AVG -
+                                       DEF_TIMESLICE);
+                               if (p->sleep_avg < ceiling)
+                                       p->sleep_avg = ceiling;
                } else {
                        /*
                         * Tasks waking from uninterruptible sleep are
                         * limited in their sleep_avg rise as they
                         * are likely to be waiting on I/O
                         */
-                       if (p->activated == -1 && p->mm) {
+                       if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
                                if (p->sleep_avg >= INTERACTIVE_SLEEP(p))
                                        sleep_time = 0;
                                else if (p->sleep_avg + sleep_time >=
@@ -769,7 +777,7 @@ static void activate_task(task_t *p, runqueue_t *rq, int local)
         * This checks to make sure it's not an uninterruptible task
         * that is now waking up.
         */
-       if (!p->activated) {
+       if (p->sleep_type == SLEEP_NORMAL) {
                /*
                 * Tasks which were woken up by interrupts (ie. hw events)
                 * are most likely of interactive nature. So we give them
@@ -778,13 +786,13 @@ static void activate_task(task_t *p, runqueue_t *rq, int local)
                 * on a CPU, first time around:
                 */
                if (in_interrupt())
-                       p->activated = 2;
+                       p->sleep_type = SLEEP_INTERRUPTED;
                else {
                        /*
                         * Normal first-time wakeups get a credit too for
                         * on-runqueue time, but it will be weighted down:
                         */
-                       p->activated = 1;
+                       p->sleep_type = SLEEP_INTERACTIVE;
                }
        }
        p->timestamp = now;
@@ -1272,19 +1280,19 @@ out_activate:
                 * Tasks on involuntary sleep don't earn
                 * sleep_avg beyond just interactive state.
                 */
-               p->activated = -1;
-       }
+               p->sleep_type = SLEEP_NONINTERACTIVE;
+       } else
 
        /*
         * Tasks that have marked their sleep as noninteractive get
-        * woken up without updating their sleep average. (i.e. their
-        * sleep is handled in a priority-neutral manner, no priority
-        * boost and no penalty.)
+        * woken up with their sleep average not weighted in an
+        * interactive way.
         */
-       if (old_state & TASK_NONINTERACTIVE)
-               __activate_task(p, rq);
-       else
-               activate_task(p, rq, cpu == this_cpu);
+               if (old_state & TASK_NONINTERACTIVE)
+                       p->sleep_type = SLEEP_NONINTERACTIVE;
+
+
+       activate_task(p, rq, cpu == this_cpu);
        /*
         * Sync wakeups (i.e. those types of wakeups where the waker
         * has indicated that it will leave the CPU in short order)
@@ -1658,6 +1666,21 @@ unsigned long nr_iowait(void)
        return sum;
 }
 
+unsigned long nr_active(void)
+{
+       unsigned long i, running = 0, uninterruptible = 0;
+
+       for_each_online_cpu(i) {
+               running += cpu_rq(i)->nr_running;
+               uninterruptible += cpu_rq(i)->nr_uninterruptible;
+       }
+
+       if (unlikely((long)uninterruptible < 0))
+               uninterruptible = 0;
+
+       return running + uninterruptible;
+}
+
 #ifdef CONFIG_SMP
 
 /*
@@ -2860,6 +2883,12 @@ EXPORT_SYMBOL(sub_preempt_count);
 
 #endif
 
+static inline int interactive_sleep(enum sleep_type sleep_type)
+{
+       return (sleep_type == SLEEP_INTERACTIVE ||
+               sleep_type == SLEEP_INTERRUPTED);
+}
+
 /*
  * schedule() is the main scheduler function.
  */
@@ -2983,12 +3012,12 @@ go_idle:
        queue = array->queue + idx;
        next = list_entry(queue->next, task_t, run_list);
 
-       if (!rt_task(next) && next->activated > 0) {
+       if (!rt_task(next) && interactive_sleep(next->sleep_type)) {
                unsigned long long delta = now - next->timestamp;
                if (unlikely((long long)(now - next->timestamp) < 0))
                        delta = 0;
 
-               if (next->activated == 1)
+               if (next->sleep_type == SLEEP_INTERACTIVE)
                        delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
 
                array = next->array;
@@ -2998,10 +3027,9 @@ go_idle:
                        dequeue_task(next, array);
                        next->prio = new_prio;
                        enqueue_task(next, array);
-               } else
-                       requeue_task(next, array);
+               }
        }
-       next->activated = 0;
+       next->sleep_type = SLEEP_NORMAL;
 switch_tasks:
        if (next == rq->idle)
                schedstat_inc(rq, sched_goidle);
index 4922928..92025b1 100644 (file)
@@ -1560,6 +1560,7 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info)
        /* Let the debugger run.  */
        set_current_state(TASK_TRACED);
        spin_unlock_irq(&current->sighand->siglock);
+       try_to_freeze();
        read_lock(&tasklist_lock);
        if (likely(current->ptrace & PT_PTRACED) &&
            likely(current->parent != current->real_parent ||
index 7ef7f60..0b6ec0e 100644 (file)
@@ -1372,18 +1372,29 @@ asmlinkage long sys_getsid(pid_t pid)
 asmlinkage long sys_setsid(void)
 {
        struct task_struct *group_leader = current->group_leader;
-       struct pid *pid;
+       pid_t session;
        int err = -EPERM;
 
        mutex_lock(&tty_mutex);
        write_lock_irq(&tasklist_lock);
 
-       pid = find_pid(PIDTYPE_PGID, group_leader->pid);
-       if (pid)
+       /* Fail if I am already a session leader */
+       if (group_leader->signal->leader)
+               goto out;
+
+       session = group_leader->pid;
+       /* Fail if a process group id already exists that equals the
+        * proposed session id.
+        *
+        * Don't check if session id == 1 because kernel threads use this
+        * session id and so the check will always fail and make it so
+        * init cannot successfully call setsid.
+        */
+       if (session > 1 && find_task_by_pid_type(PIDTYPE_PGID, session))
                goto out;
 
        group_leader->signal->leader = 1;
-       __set_special_pids(group_leader->pid, group_leader->pid);
+       __set_special_pids(session, session);
        group_leader->signal->tty = NULL;
        group_leader->signal->tty_old_pgrp = 0;
        err = process_group(group_leader);
index ab189dd..6b812c0 100644 (file)
@@ -54,7 +54,6 @@ EXPORT_SYMBOL(jiffies_64);
 /*
  * per-CPU timer vector definitions:
  */
-
 #define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
 #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
 #define TVN_SIZE (1 << TVN_BITS)
@@ -62,11 +61,6 @@ EXPORT_SYMBOL(jiffies_64);
 #define TVN_MASK (TVN_SIZE - 1)
 #define TVR_MASK (TVR_SIZE - 1)
 
-struct timer_base_s {
-       spinlock_t lock;
-       struct timer_list *running_timer;
-};
-
 typedef struct tvec_s {
        struct list_head vec[TVN_SIZE];
 } tvec_t;
@@ -76,7 +70,8 @@ typedef struct tvec_root_s {
 } tvec_root_t;
 
 struct tvec_t_base_s {
-       struct timer_base_s t_base;
+       spinlock_t lock;
+       struct timer_list *running_timer;
        unsigned long timer_jiffies;
        tvec_root_t tv1;
        tvec_t tv2;
@@ -87,13 +82,14 @@ struct tvec_t_base_s {
 
 typedef struct tvec_t_base_s tvec_base_t;
 static DEFINE_PER_CPU(tvec_base_t *, tvec_bases);
-static tvec_base_t boot_tvec_bases;
+tvec_base_t boot_tvec_bases;
+EXPORT_SYMBOL(boot_tvec_bases);
 
 static inline void set_running_timer(tvec_base_t *base,
                                        struct timer_list *timer)
 {
 #ifdef CONFIG_SMP
-       base->t_base.running_timer = timer;
+       base->running_timer = timer;
 #endif
 }
 
@@ -139,15 +135,6 @@ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer)
        list_add_tail(&timer->entry, vec);
 }
 
-typedef struct timer_base_s timer_base_t;
-/*
- * Used by TIMER_INITIALIZER, we can't use per_cpu(tvec_bases)
- * at compile time, and we need timer->base to lock the timer.
- */
-timer_base_t __init_timer_base
-       ____cacheline_aligned_in_smp = { .lock = SPIN_LOCK_UNLOCKED };
-EXPORT_SYMBOL(__init_timer_base);
-
 /***
  * init_timer - initialize a timer.
  * @timer: the timer to be initialized
@@ -158,7 +145,7 @@ EXPORT_SYMBOL(__init_timer_base);
 void fastcall init_timer(struct timer_list *timer)
 {
        timer->entry.next = NULL;
-       timer->base = &per_cpu(tvec_bases, raw_smp_processor_id())->t_base;
+       timer->base = per_cpu(tvec_bases, raw_smp_processor_id());
 }
 EXPORT_SYMBOL(init_timer);
 
@@ -174,7 +161,7 @@ static inline void detach_timer(struct timer_list *timer,
 }
 
 /*
- * We are using hashed locking: holding per_cpu(tvec_bases).t_base.lock
+ * We are using hashed locking: holding per_cpu(tvec_bases).lock
  * means that all timers which are tied to this base via timer->base are
  * locked, and the base itself is locked too.
  *
@@ -185,10 +172,10 @@ static inline void detach_timer(struct timer_list *timer,
  * possible to set timer->base = NULL and drop the lock: the timer remains
  * locked.
  */
-static timer_base_t *lock_timer_base(struct timer_list *timer,
+static tvec_base_t *lock_timer_base(struct timer_list *timer,
                                        unsigned long *flags)
 {
-       timer_base_t *base;
+       tvec_base_t *base;
 
        for (;;) {
                base = timer->base;
@@ -205,8 +192,7 @@ static timer_base_t *lock_timer_base(struct timer_list *timer,
 
 int __mod_timer(struct timer_list *timer, unsigned long expires)
 {
-       timer_base_t *base;
-       tvec_base_t *new_base;
+       tvec_base_t *base, *new_base;
        unsigned long flags;
        int ret = 0;
 
@@ -221,7 +207,7 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
 
        new_base = __get_cpu_var(tvec_bases);
 
-       if (base != &new_base->t_base) {
+       if (base != new_base) {
                /*
                 * We are trying to schedule the timer on the local CPU.
                 * However we can't change timer's base while it is running,
@@ -229,21 +215,19 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
                 * handler yet has not finished. This also guarantees that
                 * the timer is serialized wrt itself.
                 */
-               if (unlikely(base->running_timer == timer)) {
-                       /* The timer remains on a former base */
-                       new_base = container_of(base, tvec_base_t, t_base);
-               } else {
+               if (likely(base->running_timer != timer)) {
                        /* See the comment in lock_timer_base() */
                        timer->base = NULL;
                        spin_unlock(&base->lock);
-                       spin_lock(&new_base->t_base.lock);
-                       timer->base = &new_base->t_base;
+                       base = new_base;
+                       spin_lock(&base->lock);
+                       timer->base = base;
                }
        }
 
        timer->expires = expires;
-       internal_add_timer(new_base, timer);
-       spin_unlock_irqrestore(&new_base->t_base.lock, flags);
+       internal_add_timer(base, timer);
+       spin_unlock_irqrestore(&base->lock, flags);
 
        return ret;
 }
@@ -263,10 +247,10 @@ void add_timer_on(struct timer_list *timer, int cpu)
        unsigned long flags;
 
        BUG_ON(timer_pending(timer) || !timer->function);
-       spin_lock_irqsave(&base->t_base.lock, flags);
-       timer->base = &base->t_base;
+       spin_lock_irqsave(&base->lock, flags);
+       timer->base = base;
        internal_add_timer(base, timer);
-       spin_unlock_irqrestore(&base->t_base.lock, flags);
+       spin_unlock_irqrestore(&base->lock, flags);
 }
 
 
@@ -319,7 +303,7 @@ EXPORT_SYMBOL(mod_timer);
  */
 int del_timer(struct timer_list *timer)
 {
-       timer_base_t *base;
+       tvec_base_t *base;
        unsigned long flags;
        int ret = 0;
 
@@ -346,7 +330,7 @@ EXPORT_SYMBOL(del_timer);
  */
 int try_to_del_timer_sync(struct timer_list *timer)
 {
-       timer_base_t *base;
+       tvec_base_t *base;
        unsigned long flags;
        int ret = -1;
 
@@ -410,7 +394,7 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index)
                struct timer_list *tmp;
 
                tmp = list_entry(curr, struct timer_list, entry);
-               BUG_ON(tmp->base != &base->t_base);
+               BUG_ON(tmp->base != base);
                curr = curr->next;
                internal_add_timer(base, tmp);
        }
@@ -432,7 +416,7 @@ static inline void __run_timers(tvec_base_t *base)
 {
        struct timer_list *timer;
 
-       spin_lock_irq(&base->t_base.lock);
+       spin_lock_irq(&base->lock);
        while (time_after_eq(jiffies, base->timer_jiffies)) {
                struct list_head work_list = LIST_HEAD_INIT(work_list);
                struct list_head *head = &work_list;
@@ -458,7 +442,7 @@ static inline void __run_timers(tvec_base_t *base)
 
                        set_running_timer(base, timer);
                        detach_timer(timer, 1);
-                       spin_unlock_irq(&base->t_base.lock);
+                       spin_unlock_irq(&base->lock);
                        {
                                int preempt_count = preempt_count();
                                fn(data);
@@ -471,11 +455,11 @@ static inline void __run_timers(tvec_base_t *base)
                                        BUG();
                                }
                        }
-                       spin_lock_irq(&base->t_base.lock);
+                       spin_lock_irq(&base->lock);
                }
        }
        set_running_timer(base, NULL);
-       spin_unlock_irq(&base->t_base.lock);
+       spin_unlock_irq(&base->lock);
 }
 
 #ifdef CONFIG_NO_IDLE_HZ
@@ -506,7 +490,7 @@ unsigned long next_timer_interrupt(void)
        hr_expires += jiffies;
 
        base = __get_cpu_var(tvec_bases);
-       spin_lock(&base->t_base.lock);
+       spin_lock(&base->lock);
        expires = base->timer_jiffies + (LONG_MAX >> 1);
        list = NULL;
 
@@ -554,7 +538,7 @@ found:
                                expires = nte->expires;
                }
        }
-       spin_unlock(&base->t_base.lock);
+       spin_unlock(&base->lock);
 
        if (time_before(hr_expires, expires))
                return hr_expires;
@@ -841,7 +825,7 @@ void update_process_times(int user_tick)
  */
 static unsigned long count_active_tasks(void)
 {
-       return (nr_running() + nr_uninterruptible()) * FIXED_1;
+       return nr_active() * FIXED_1;
 }
 
 /*
@@ -1262,7 +1246,7 @@ static int __devinit init_timers_cpu(int cpu)
                }
                per_cpu(tvec_bases, cpu) = base;
        }
-       spin_lock_init(&base->t_base.lock);
+       spin_lock_init(&base->lock);
        for (j = 0; j < TVN_SIZE; j++) {
                INIT_LIST_HEAD(base->tv5.vec + j);
                INIT_LIST_HEAD(base->tv4.vec + j);
@@ -1284,7 +1268,7 @@ static void migrate_timer_list(tvec_base_t *new_base, struct list_head *head)
        while (!list_empty(head)) {
                timer = list_entry(head->next, struct timer_list, entry);
                detach_timer(timer, 0);
-               timer->base = &new_base->t_base;
+               timer->base = new_base;
                internal_add_timer(new_base, timer);
        }
 }
@@ -1300,11 +1284,11 @@ static void __devinit migrate_timers(int cpu)
        new_base = get_cpu_var(tvec_bases);
 
        local_irq_disable();
-       spin_lock(&new_base->t_base.lock);
-       spin_lock(&old_base->t_base.lock);
+       spin_lock(&new_base->lock);
+       spin_lock(&old_base->lock);
+
+       BUG_ON(old_base->running_timer);
 
-       if (old_base->t_base.running_timer)
-               BUG();
        for (i = 0; i < TVR_SIZE; i++)
                migrate_timer_list(new_base, old_base->tv1.vec + i);
        for (i = 0; i < TVN_SIZE; i++) {
@@ -1314,8 +1298,8 @@ static void __devinit migrate_timers(int cpu)
                migrate_timer_list(new_base, old_base->tv5.vec + i);
        }
 
-       spin_unlock(&old_base->t_base.lock);
-       spin_unlock(&new_base->t_base.lock);
+       spin_unlock(&old_base->lock);
+       spin_unlock(&new_base->lock);
        local_irq_enable();
        put_cpu_var(tvec_bases);
 }
index 6e8a60f..d57fd91 100644 (file)
@@ -157,19 +157,6 @@ config DEBUG_INFO
 
          If unsure, say N.
 
-config DEBUG_IOREMAP
-       bool "Enable ioremap() debugging"
-       depends on DEBUG_KERNEL && PARISC
-       help
-         Enabling this option will cause the kernel to distinguish between
-         ioremapped and physical addresses.  It will print a backtrace (at
-         most one every 10 seconds), hopefully allowing you to see which
-         drivers need work.  Fixing all these problems is a prerequisite
-         for turning on USE_HPPA_IOREMAP.  The warnings are harmless;
-         the kernel has enough information to fix the broken drivers
-         automatically, but we'd like to make it more efficient by not
-         having to do that.
-
 config DEBUG_FS
        bool "Debug Filesystem"
        depends on SYSFS
index 907c392..0a03357 100644 (file)
  *
  * LINUX_FADV_ASYNC_WRITE: push some or all of the dirty pages at the disk.
  *
- * LINUX_FADV_WRITE_WAIT, LINUX_FADV_ASYNC_WRITE: push all of the currently
- * dirty pages at the disk.
- *
- * LINUX_FADV_WRITE_WAIT, LINUX_FADV_ASYNC_WRITE, LINUX_FADV_WRITE_WAIT: push
- * all of the currently dirty pages at the disk, wait until they have been
- * written.
- *
- * It should be noted that none of these operations write out the file's
- * metadata.  So unless the application is strictly performing overwrites of
- * already-instantiated disk blocks, there are no guarantees here that the data
- * will be available after a crash.
  */
 asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
 {
@@ -129,15 +118,6 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
                        invalidate_mapping_pages(mapping, start_index,
                                                end_index);
                break;
-       case LINUX_FADV_ASYNC_WRITE:
-               ret = __filemap_fdatawrite_range(mapping, offset, endbyte,
-                                               WB_SYNC_NONE);
-               break;
-       case LINUX_FADV_WRITE_WAIT:
-               ret = wait_on_page_writeback_range(mapping,
-                                       offset >> PAGE_CACHE_SHIFT,
-                                       endbyte >> PAGE_CACHE_SHIFT);
-               break;
        default:
                ret = -EINVAL;
        }
index ebad6bb..832f676 100644 (file)
@@ -334,6 +334,7 @@ static unsigned long set_max_huge_pages(unsigned long count)
                return nr_huge_pages;
 
        spin_lock(&hugetlb_lock);
+       count = max(count, reserved_huge_pages);
        try_to_free_low(count);
        while (count < nr_huge_pages) {
                struct page *page = dequeue_huge_page(NULL, 0);
@@ -697,9 +698,10 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                pfn_offset = (vaddr & ~HPAGE_MASK) >> PAGE_SHIFT;
                page = pte_page(*pte);
 same_page:
-               get_page(page);
-               if (pages)
+               if (pages) {
+                       get_page(page);
                        pages[i] = page + pfn_offset;
+               }
 
                if (vmas)
                        vmas[i] = vma;
index 8d8f525..0ec7bc6 100644 (file)
@@ -87,7 +87,7 @@ int randomize_va_space __read_mostly = 1;
 static int __init disable_randmaps(char *s)
 {
        randomize_va_space = 0;
-       return 0;
+       return 1;
 }
 __setup("norandmaps", disable_randmaps);
 
index 39aa9d1..e5fd538 100644 (file)
@@ -397,18 +397,24 @@ void free_swap_and_cache(swp_entry_t entry)
 
        p = swap_info_get(entry);
        if (p) {
-               if (swap_entry_free(p, swp_offset(entry)) == 1)
-                       page = find_trylock_page(&swapper_space, entry.val);
+               if (swap_entry_free(p, swp_offset(entry)) == 1) {
+                       page = find_get_page(&swapper_space, entry.val);
+                       if (page && unlikely(TestSetPageLocked(page))) {
+                               page_cache_release(page);
+                               page = NULL;
+                       }
+               }
                spin_unlock(&swap_lock);
        }
        if (page) {
                int one_user;
 
                BUG_ON(PagePrivate(page));
-               page_cache_get(page);
                one_user = (page_count(page) == 2);
                /* Only cache user (+us), or swap space full? Free it! */
-               if (!PageWriteback(page) && (one_user || vm_swap_full())) {
+               /* Also recheck PageSwapCache after page is locked (above) */
+               if (PageSwapCache(page) && !PageWriteback(page) &&
+                                       (one_user || vm_swap_full())) {
                        delete_from_swap_cache(page);
                        SetPageDirty(page);
                }
index 8fd37cd..d5d69fa 100644 (file)
@@ -476,8 +476,7 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
        int err;
        struct socket *sock;
 
-       /* SO_SET_REPLACE seems to be the same in all levels */
-       if (optname == IPT_SO_SET_REPLACE)
+       if (level == SOL_IPV6 && optname == IPT_SO_SET_REPLACE)
                return do_netfilter_replace(fd, level, optname,
                                            optval, optlen);
 
index a3ab11f..434220d 100644 (file)
@@ -1080,6 +1080,70 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
        rcu_read_unlock();
 }
 
+
+void __netif_schedule(struct net_device *dev)
+{
+       if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) {
+               unsigned long flags;
+               struct softnet_data *sd;
+
+               local_irq_save(flags);
+               sd = &__get_cpu_var(softnet_data);
+               dev->next_sched = sd->output_queue;
+               sd->output_queue = dev;
+               raise_softirq_irqoff(NET_TX_SOFTIRQ);
+               local_irq_restore(flags);
+       }
+}
+EXPORT_SYMBOL(__netif_schedule);
+
+void __netif_rx_schedule(struct net_device *dev)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       dev_hold(dev);
+       list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
+       if (dev->quota < 0)
+               dev->quota += dev->weight;
+       else
+               dev->quota = dev->weight;
+       __raise_softirq_irqoff(NET_RX_SOFTIRQ);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__netif_rx_schedule);
+
+void dev_kfree_skb_any(struct sk_buff *skb)
+{
+       if (in_irq() || irqs_disabled())
+               dev_kfree_skb_irq(skb);
+       else
+               dev_kfree_skb(skb);
+}
+EXPORT_SYMBOL(dev_kfree_skb_any);
+
+
+/* Hot-plugging. */
+void netif_device_detach(struct net_device *dev)
+{
+       if (test_and_clear_bit(__LINK_STATE_PRESENT, &dev->state) &&
+           netif_running(dev)) {
+               netif_stop_queue(dev);
+       }
+}
+EXPORT_SYMBOL(netif_device_detach);
+
+void netif_device_attach(struct net_device *dev)
+{
+       if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) &&
+           netif_running(dev)) {
+               netif_wake_queue(dev);
+               __netdev_watchdog_up(dev);
+       }
+}
+EXPORT_SYMBOL(netif_device_attach);
+
+
 /*
  * Invalidate hardware checksum when packet is to be mangled, and
  * complete checksum manually on outgoing path.
index a96ea7d..ed2afdb 100644 (file)
@@ -385,7 +385,21 @@ set_sndbuf:
                                val = sysctl_rmem_max;
 set_rcvbuf:
                        sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
-                       /* FIXME: is this lower bound the right one? */
+                       /*
+                        * We double it on the way in to account for
+                        * "struct sk_buff" etc. overhead.   Applications
+                        * assume that the SO_RCVBUF setting they make will
+                        * allow that much actual data to be received on that
+                        * socket.
+                        *
+                        * Applications are unaware that "struct sk_buff" and
+                        * other overheads allocate from the receive buffer
+                        * during socket buffer allocation.
+                        *
+                        * And after considering the possible alternatives,
+                        * returning the value we actually used in getsockopt
+                        * is the most desirable behavior.
+                        */
                        if ((val * 2) < SOCK_MIN_RCVBUF)
                                sk->sk_rcvbuf = SOCK_MIN_RCVBUF;
                        else
index e3dd30d..b39e2a5 100644 (file)
@@ -204,7 +204,7 @@ static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt,
        if (rc) {
                kfree(opt->dccpop_sc->dccpoc_val);
                kfree(opt->dccpop_sc);
-               opt->dccpop_sc = 0;
+               opt->dccpop_sc = NULL;
                return rc;
        }
 
@@ -322,7 +322,7 @@ static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk,
        opt->dccpop_type = type == DCCPO_CHANGE_L ? DCCPO_CONFIRM_R :
                                                    DCCPO_CONFIRM_L;
        opt->dccpop_feat = feature;
-       opt->dccpop_val  = 0;
+       opt->dccpop_val  = NULL;
        opt->dccpop_len  = 0;
 
        /* change feature */
@@ -523,7 +523,7 @@ int dccp_feat_clone(struct sock *oldsk, struct sock *newsk)
                 * once...
                 */
                /* the master socket no longer needs to worry about confirms */
-               opt->dccpop_sc = 0; /* it's not a memleak---new socket has it */
+               opt->dccpop_sc = NULL; /* it's not a memleak---new socket has it */
 
                /* reset state for a new socket */
                opt->dccpop_conf = 0;
index d2ae989..a26ff9f 100644 (file)
@@ -620,7 +620,7 @@ int dn_dev_set_default(struct net_device *dev, int force)
        }
        write_unlock(&dndev_lock);
        if (old)
-               dev_put(dev);
+               dev_put(old);
        return rv;
 }
 
index e16d8b4..e2e4771 100644 (file)
@@ -116,7 +116,7 @@ error:
        return err;
 }
 
-static int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
 {
        int ah_hlen;
        struct iphdr *iph;
index bf88c62..9d1881c 100644 (file)
@@ -133,7 +133,7 @@ error:
  * expensive, so we only support truncated data, which is the recommended
  * and common case.
  */
-static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
 {
        struct iphdr *iph;
        struct ip_esp_hdr *esph;
@@ -208,9 +208,6 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
                struct xfrm_encap_tmpl *encap = x->encap;
                struct udphdr *uh;
 
-               if (encap->encap_type != decap->decap_type)
-                       goto out;
-
                uh = (struct udphdr *)(iph + 1);
                encap_len = (void*)esph - (void*)uh;
 
index c95020f..0a1d86a 100644 (file)
@@ -81,8 +81,7 @@ out:
        return err;
 }
 
-static int ipcomp_input(struct xfrm_state *x,
-                        struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
 {
        u8 nexthdr;
        int err = 0;
index 882b842..77855cc 100644 (file)
@@ -221,16 +221,6 @@ config IP_NF_MATCH_IPRANGE
 
          To compile it as a module, choose M here.  If unsure, say N.
 
-config IP_NF_MATCH_MULTIPORT
-       tristate "Multiple port match support"
-       depends on IP_NF_IPTABLES
-       help
-         Multiport matching allows you to match TCP or UDP packets based on
-         a series of source or destination ports: normally a rule can only
-         match a single range of ports.
-
-         To compile it as a module, choose M here.  If unsure, say N.
-
 config IP_NF_MATCH_TOS
        tristate "TOS match support"
        depends on IP_NF_IPTABLES
@@ -272,12 +262,12 @@ config IP_NF_MATCH_DSCP
 
          To compile it as a module, choose M here.  If unsure, say N.
 
-config IP_NF_MATCH_AH_ESP
-       tristate "AH/ESP match support"
+config IP_NF_MATCH_AH
+       tristate "AH match support"
        depends on IP_NF_IPTABLES
        help
-         These two match extensions (`ah' and `esp') allow you to match a
-         range of SPIs inside AH or ESP headers of IPSec packets.
+         This match extension allows you to match a range of SPIs
+         inside AH header of IPSec packets.
 
          To compile it as a module, choose M here.  If unsure, say N.
 
index f2cd9a6..461cb1e 100644 (file)
@@ -53,13 +53,12 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
 # matches
 obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
-obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
 obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
-obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
+obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
 
index 9b6e19b..01bd7ca 100644 (file)
@@ -1658,7 +1658,7 @@ static void __exit ctnetlink_exit(void)
        printk("ctnetlink: unregistering from nfnetlink.\n");
 
 #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
-       ip_conntrack_unregister_notifier(&ctnl_notifier_exp);
+       ip_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
        ip_conntrack_unregister_notifier(&ctnl_notifier);
 #endif
 
index 460fd90..d5b8cdd 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/icmp.h>
 #include <net/ip.h>
+#include <net/compat.h>
 #include <asm/uaccess.h>
 #include <linux/mutex.h>
 #include <linux/proc_fs.h>
@@ -799,17 +800,11 @@ get_counters(const struct xt_table_info *t,
        }
 }
 
-static int
-copy_entries_to_user(unsigned int total_size,
-                    struct ipt_table *table,
-                    void __user *userptr)
+static inline struct xt_counters * alloc_counters(struct ipt_table *table)
 {
-       unsigned int off, num, countersize;
-       struct ipt_entry *e;
+       unsigned int countersize;
        struct xt_counters *counters;
        struct xt_table_info *private = table->private;
-       int ret = 0;
-       void *loc_cpu_entry;
 
        /* We need atomic snapshot of counters: rest doesn't change
           (other than comefrom, which userspace doesn't care
@@ -818,13 +813,32 @@ copy_entries_to_user(unsigned int total_size,
        counters = vmalloc_node(countersize, numa_node_id());
 
        if (counters == NULL)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        /* First, sum counters... */
        write_lock_bh(&table->lock);
        get_counters(private, counters);
        write_unlock_bh(&table->lock);
 
+       return counters;
+}
+
+static int
+copy_entries_to_user(unsigned int total_size,
+                    struct ipt_table *table,
+                    void __user *userptr)
+{
+       unsigned int off, num;
+       struct ipt_entry *e;
+       struct xt_counters *counters;
+       struct xt_table_info *private = table->private;
+       int ret = 0;
+       void *loc_cpu_entry;
+
+       counters = alloc_counters(table);
+       if (IS_ERR(counters))
+               return PTR_ERR(counters);
+
        /* choose the copy that is on our node/cpu, ...
         * This choice is lazy (because current thread is
         * allowed to migrate to another cpu)
@@ -884,44 +898,899 @@ copy_entries_to_user(unsigned int total_size,
        return ret;
 }
 
+#ifdef CONFIG_COMPAT
+struct compat_delta {
+       struct compat_delta *next;
+       u_int16_t offset;
+       short delta;
+};
+
+static struct compat_delta *compat_offsets = NULL;
+
+static int compat_add_offset(u_int16_t offset, short delta)
+{
+       struct compat_delta *tmp;
+
+       tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
+       if (!tmp)
+               return -ENOMEM;
+       tmp->offset = offset;
+       tmp->delta = delta;
+       if (compat_offsets) {
+               tmp->next = compat_offsets->next;
+               compat_offsets->next = tmp;
+       } else {
+               compat_offsets = tmp;
+               tmp->next = NULL;
+       }
+       return 0;
+}
+
+static void compat_flush_offsets(void)
+{
+       struct compat_delta *tmp, *next;
+
+       if (compat_offsets) {
+               for(tmp = compat_offsets; tmp; tmp = next) {
+                       next = tmp->next;
+                       kfree(tmp);
+               }
+               compat_offsets = NULL;
+       }
+}
+
+static short compat_calc_jump(u_int16_t offset)
+{
+       struct compat_delta *tmp;
+       short delta;
+
+       for(tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next)
+               if (tmp->offset < offset)
+                       delta += tmp->delta;
+       return delta;
+}
+
+struct compat_ipt_standard_target
+{
+       struct compat_xt_entry_target target;
+       compat_int_t verdict;
+};
+
+#define IPT_ST_OFFSET  (sizeof(struct ipt_standard_target) - \
+                               sizeof(struct compat_ipt_standard_target))
+
+struct compat_ipt_standard
+{
+       struct compat_ipt_entry entry;
+       struct compat_ipt_standard_target target;
+};
+
+static int compat_ipt_standard_fn(void *target,
+               void **dstptr, int *size, int convert)
+{
+       struct compat_ipt_standard_target compat_st, *pcompat_st;
+       struct ipt_standard_target st, *pst;
+       int ret;
+
+       ret = 0;
+       switch (convert) {
+               case COMPAT_TO_USER:
+                       pst = (struct ipt_standard_target *)target;
+                       memcpy(&compat_st.target, &pst->target,
+                                       sizeof(struct ipt_entry_target));
+                       compat_st.verdict = pst->verdict;
+                       if (compat_st.verdict > 0)
+                               compat_st.verdict -=
+                                       compat_calc_jump(compat_st.verdict);
+                       compat_st.target.u.user.target_size =
+                       sizeof(struct compat_ipt_standard_target);
+                       if (__copy_to_user(*dstptr, &compat_st,
+                               sizeof(struct compat_ipt_standard_target)))
+                               ret = -EFAULT;
+                       *size -= IPT_ST_OFFSET;
+                       *dstptr += sizeof(struct compat_ipt_standard_target);
+                       break;
+               case COMPAT_FROM_USER:
+                       pcompat_st =
+                               (struct compat_ipt_standard_target *)target;
+                       memcpy(&st.target, &pcompat_st->target,
+                                       sizeof(struct ipt_entry_target));
+                       st.verdict = pcompat_st->verdict;
+                       if (st.verdict > 0)
+                               st.verdict += compat_calc_jump(st.verdict);
+                       st.target.u.user.target_size =
+                       sizeof(struct ipt_standard_target);
+                       memcpy(*dstptr, &st,
+                                       sizeof(struct ipt_standard_target));
+                       *size += IPT_ST_OFFSET;
+                       *dstptr += sizeof(struct ipt_standard_target);
+                       break;
+               case COMPAT_CALC_SIZE:
+                       *size += IPT_ST_OFFSET;
+                       break;
+               default:
+                       ret = -ENOPROTOOPT;
+                       break;
+       }
+       return ret;
+}
+
+static inline int
+compat_calc_match(struct ipt_entry_match *m, int * size)
+{
+       if (m->u.kernel.match->compat)
+               m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
+       else
+               xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
+       return 0;
+}
+
+static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
+               void *base, struct xt_table_info *newinfo)
+{
+       struct ipt_entry_target *t;
+       u_int16_t entry_offset;
+       int off, i, ret;
+
+       off = 0;
+       entry_offset = (void *)e - base;
+       IPT_MATCH_ITERATE(e, compat_calc_match, &off);
+       t = ipt_get_target(e);
+       if (t->u.kernel.target->compat)
+               t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
+       else
+               xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
+       newinfo->size -= off;
+       ret = compat_add_offset(entry_offset, off);
+       if (ret)
+               return ret;
+
+       for (i = 0; i< NF_IP_NUMHOOKS; i++) {
+               if (info->hook_entry[i] && (e < (struct ipt_entry *)
+                               (base + info->hook_entry[i])))
+                       newinfo->hook_entry[i] -= off;
+               if (info->underflow[i] && (e < (struct ipt_entry *)
+                               (base + info->underflow[i])))
+                       newinfo->underflow[i] -= off;
+       }
+       return 0;
+}
+
+static int compat_table_info(struct xt_table_info *info,
+               struct xt_table_info *newinfo)
+{
+       void *loc_cpu_entry;
+       int i;
+
+       if (!newinfo || !info)
+               return -EINVAL;
+
+       memset(newinfo, 0, sizeof(struct xt_table_info));
+       newinfo->size = info->size;
+       newinfo->number = info->number;
+       for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+               newinfo->hook_entry[i] = info->hook_entry[i];
+               newinfo->underflow[i] = info->underflow[i];
+       }
+       loc_cpu_entry = info->entries[raw_smp_processor_id()];
+       return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
+                       compat_calc_entry, info, loc_cpu_entry, newinfo);
+}
+#endif
+
+static int get_info(void __user *user, int *len, int compat)
+{
+       char name[IPT_TABLE_MAXNAMELEN];
+       struct ipt_table *t;
+       int ret;
+
+       if (*len != sizeof(struct ipt_getinfo)) {
+               duprintf("length %u != %u\n", *len,
+                       (unsigned int)sizeof(struct ipt_getinfo));
+               return -EINVAL;
+       }
+
+       if (copy_from_user(name, user, sizeof(name)) != 0)
+               return -EFAULT;
+
+       name[IPT_TABLE_MAXNAMELEN-1] = '\0';
+#ifdef CONFIG_COMPAT
+       if (compat)
+               xt_compat_lock(AF_INET);
+#endif
+       t = try_then_request_module(xt_find_table_lock(AF_INET, name),
+                       "iptable_%s", name);
+       if (t && !IS_ERR(t)) {
+               struct ipt_getinfo info;
+               struct xt_table_info *private = t->private;
+
+#ifdef CONFIG_COMPAT
+               if (compat) {
+                       struct xt_table_info tmp;
+                       ret = compat_table_info(private, &tmp);
+                       compat_flush_offsets();
+                       private =  &tmp;
+               }
+#endif
+               info.valid_hooks = t->valid_hooks;
+               memcpy(info.hook_entry, private->hook_entry,
+                               sizeof(info.hook_entry));
+               memcpy(info.underflow, private->underflow,
+                               sizeof(info.underflow));
+               info.num_entries = private->number;
+               info.size = private->size;
+               strcpy(info.name, name);
+
+               if (copy_to_user(user, &info, *len) != 0)
+                       ret = -EFAULT;
+               else
+                       ret = 0;
+
+               xt_table_unlock(t);
+               module_put(t->me);
+       } else
+               ret = t ? PTR_ERR(t) : -ENOENT;
+#ifdef CONFIG_COMPAT
+       if (compat)
+               xt_compat_unlock(AF_INET);
+#endif
+       return ret;
+}
+
+static int
+get_entries(struct ipt_get_entries __user *uptr, int *len)
+{
+       int ret;
+       struct ipt_get_entries get;
+       struct ipt_table *t;
+
+       if (*len < sizeof(get)) {
+               duprintf("get_entries: %u < %d\n", *len,
+                               (unsigned int)sizeof(get));
+               return -EINVAL;
+       }
+       if (copy_from_user(&get, uptr, sizeof(get)) != 0)
+               return -EFAULT;
+       if (*len != sizeof(struct ipt_get_entries) + get.size) {
+               duprintf("get_entries: %u != %u\n", *len,
+                               (unsigned int)(sizeof(struct ipt_get_entries) +
+                               get.size));
+               return -EINVAL;
+       }
+
+       t = xt_find_table_lock(AF_INET, get.name);
+       if (t && !IS_ERR(t)) {
+               struct xt_table_info *private = t->private;
+               duprintf("t->private->number = %u\n",
+                        private->number);
+               if (get.size == private->size)
+                       ret = copy_entries_to_user(private->size,
+                                                  t, uptr->entrytable);
+               else {
+                       duprintf("get_entries: I've got %u not %u!\n",
+                                private->size,
+                                get.size);
+                       ret = -EINVAL;
+               }
+               module_put(t->me);
+               xt_table_unlock(t);
+       } else
+               ret = t ? PTR_ERR(t) : -ENOENT;
+
+       return ret;
+}
+
+static int
+__do_replace(const char *name, unsigned int valid_hooks,
+               struct xt_table_info *newinfo, unsigned int num_counters,
+               void __user *counters_ptr)
+{
+       int ret;
+       struct ipt_table *t;
+       struct xt_table_info *oldinfo;
+       struct xt_counters *counters;
+       void *loc_cpu_old_entry;
+
+       ret = 0;
+       counters = vmalloc(num_counters * sizeof(struct xt_counters));
+       if (!counters) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       t = try_then_request_module(xt_find_table_lock(AF_INET, name),
+                                   "iptable_%s", name);
+       if (!t || IS_ERR(t)) {
+               ret = t ? PTR_ERR(t) : -ENOENT;
+               goto free_newinfo_counters_untrans;
+       }
+
+       /* You lied! */
+       if (valid_hooks != t->valid_hooks) {
+               duprintf("Valid hook crap: %08X vs %08X\n",
+                        valid_hooks, t->valid_hooks);
+               ret = -EINVAL;
+               goto put_module;
+       }
+
+       oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
+       if (!oldinfo)
+               goto put_module;
+
+       /* Update module usage count based on number of rules */
+       duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
+               oldinfo->number, oldinfo->initial_entries, newinfo->number);
+       if ((oldinfo->number > oldinfo->initial_entries) ||
+           (newinfo->number <= oldinfo->initial_entries))
+               module_put(t->me);
+       if ((oldinfo->number > oldinfo->initial_entries) &&
+           (newinfo->number <= oldinfo->initial_entries))
+               module_put(t->me);
+
+       /* Get the old counters. */
+       get_counters(oldinfo, counters);
+       /* Decrease module usage counts and free resource */
+       loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
+       IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
+       xt_free_table_info(oldinfo);
+       if (copy_to_user(counters_ptr, counters,
+                        sizeof(struct xt_counters) * num_counters) != 0)
+               ret = -EFAULT;
+       vfree(counters);
+       xt_table_unlock(t);
+       return ret;
+
+ put_module:
+       module_put(t->me);
+       xt_table_unlock(t);
+ free_newinfo_counters_untrans:
+       vfree(counters);
+ out:
+       return ret;
+}
+
+static int
+do_replace(void __user *user, unsigned int len)
+{
+       int ret;
+       struct ipt_replace tmp;
+       struct xt_table_info *newinfo;
+       void *loc_cpu_entry;
+
+       if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+               return -EFAULT;
+
+       /* Hack: Causes ipchains to give correct error msg --RR */
+       if (len != sizeof(tmp) + tmp.size)
+               return -ENOPROTOOPT;
+
+       /* overflow check */
+       if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+                       SMP_CACHE_BYTES)
+               return -ENOMEM;
+       if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+               return -ENOMEM;
+
+       newinfo = xt_alloc_table_info(tmp.size);
+       if (!newinfo)
+               return -ENOMEM;
+
+       /* choose the copy that is our node/cpu */
+       loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+       if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
+                          tmp.size) != 0) {
+               ret = -EFAULT;
+               goto free_newinfo;
+       }
+
+       ret = translate_table(tmp.name, tmp.valid_hooks,
+                             newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
+                             tmp.hook_entry, tmp.underflow);
+       if (ret != 0)
+               goto free_newinfo;
+
+       duprintf("ip_tables: Translated table\n");
+
+       ret = __do_replace(tmp.name, tmp.valid_hooks,
+                             newinfo, tmp.num_counters,
+                             tmp.counters);
+       if (ret)
+               goto free_newinfo_untrans;
+       return 0;
+
+ free_newinfo_untrans:
+       IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
+ free_newinfo:
+       xt_free_table_info(newinfo);
+       return ret;
+}
+
+/* We're lazy, and add to the first CPU; overflow works its fey magic
+ * and everything is OK. */
+static inline int
+add_counter_to_entry(struct ipt_entry *e,
+                    const struct xt_counters addme[],
+                    unsigned int *i)
+{
+#if 0
+       duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
+                *i,
+                (long unsigned int)e->counters.pcnt,
+                (long unsigned int)e->counters.bcnt,
+                (long unsigned int)addme[*i].pcnt,
+                (long unsigned int)addme[*i].bcnt);
+#endif
+
+       ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
+
+       (*i)++;
+       return 0;
+}
+
+static int
+do_add_counters(void __user *user, unsigned int len, int compat)
+{
+       unsigned int i;
+       struct xt_counters_info tmp;
+       struct xt_counters *paddc;
+       unsigned int num_counters;
+       char *name;
+       int size;
+       void *ptmp;
+       struct ipt_table *t;
+       struct xt_table_info *private;
+       int ret = 0;
+       void *loc_cpu_entry;
+#ifdef CONFIG_COMPAT
+       struct compat_xt_counters_info compat_tmp;
+
+       if (compat) {
+               ptmp = &compat_tmp;
+               size = sizeof(struct compat_xt_counters_info);
+       } else
+#endif
+       {
+               ptmp = &tmp;
+               size = sizeof(struct xt_counters_info);
+       }
+
+       if (copy_from_user(ptmp, user, size) != 0)
+               return -EFAULT;
+
+#ifdef CONFIG_COMPAT
+       if (compat) {
+               num_counters = compat_tmp.num_counters;
+               name = compat_tmp.name;
+       } else
+#endif
+       {
+               num_counters = tmp.num_counters;
+               name = tmp.name;
+       }
+
+       if (len != size + num_counters * sizeof(struct xt_counters))
+               return -EINVAL;
+
+       paddc = vmalloc_node(len - size, numa_node_id());
+       if (!paddc)
+               return -ENOMEM;
+
+       if (copy_from_user(paddc, user + size, len - size) != 0) {
+               ret = -EFAULT;
+               goto free;
+       }
+
+       t = xt_find_table_lock(AF_INET, name);
+       if (!t || IS_ERR(t)) {
+               ret = t ? PTR_ERR(t) : -ENOENT;
+               goto free;
+       }
+
+       write_lock_bh(&t->lock);
+       private = t->private;
+       if (private->number != num_counters) {
+               ret = -EINVAL;
+               goto unlock_up_free;
+       }
+
+       i = 0;
+       /* Choose the copy that is on our node */
+       loc_cpu_entry = private->entries[raw_smp_processor_id()];
+       IPT_ENTRY_ITERATE(loc_cpu_entry,
+                         private->size,
+                         add_counter_to_entry,
+                         paddc,
+                         &i);
+ unlock_up_free:
+       write_unlock_bh(&t->lock);
+       xt_table_unlock(t);
+       module_put(t->me);
+ free:
+       vfree(paddc);
+
+       return ret;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_ipt_replace {
+       char                    name[IPT_TABLE_MAXNAMELEN];
+       u32                     valid_hooks;
+       u32                     num_entries;
+       u32                     size;
+       u32                     hook_entry[NF_IP_NUMHOOKS];
+       u32                     underflow[NF_IP_NUMHOOKS];
+       u32                     num_counters;
+       compat_uptr_t           counters;       /* struct ipt_counters * */
+       struct compat_ipt_entry entries[0];
+};
+
+static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
+               void __user **dstptr, compat_uint_t *size)
+{
+       if (m->u.kernel.match->compat)
+               return m->u.kernel.match->compat(m, dstptr, size,
+                               COMPAT_TO_USER);
+       else
+               return xt_compat_match(m, dstptr, size, COMPAT_TO_USER);
+}
+
+static int compat_copy_entry_to_user(struct ipt_entry *e,
+               void __user **dstptr, compat_uint_t *size)
+{
+       struct ipt_entry_target __user *t;
+       struct compat_ipt_entry __user *ce;
+       u_int16_t target_offset, next_offset;
+       compat_uint_t origsize;
+       int ret;
+
+       ret = -EFAULT;
+       origsize = *size;
+       ce = (struct compat_ipt_entry __user *)*dstptr;
+       if (__copy_to_user(ce, e, sizeof(struct ipt_entry)))
+               goto out;
+
+       *dstptr += sizeof(struct compat_ipt_entry);
+       ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size);
+       target_offset = e->target_offset - (origsize - *size);
+       if (ret)
+               goto out;
+       t = ipt_get_target(e);
+       if (t->u.kernel.target->compat)
+               ret = t->u.kernel.target->compat(t, dstptr, size,
+                               COMPAT_TO_USER);
+       else
+               ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER);
+       if (ret)
+               goto out;
+       ret = -EFAULT;
+       next_offset = e->next_offset - (origsize - *size);
+       if (__put_user(target_offset, &ce->target_offset))
+               goto out;
+       if (__put_user(next_offset, &ce->next_offset))
+               goto out;
+       return 0;
+out:
+       return ret;
+}
+
+static inline int
+compat_check_calc_match(struct ipt_entry_match *m,
+           const char *name,
+           const struct ipt_ip *ip,
+           unsigned int hookmask,
+           int *size, int *i)
+{
+       struct ipt_match *match;
+
+       match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
+                                                  m->u.user.revision),
+                                       "ipt_%s", m->u.user.name);
+       if (IS_ERR(match) || !match) {
+               duprintf("compat_check_calc_match: `%s' not found\n",
+                               m->u.user.name);
+               return match ? PTR_ERR(match) : -ENOENT;
+       }
+       m->u.kernel.match = match;
+
+       if (m->u.kernel.match->compat)
+               m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
+       else
+               xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
+
+       (*i)++;
+       return 0;
+}
+
+static inline int
+check_compat_entry_size_and_hooks(struct ipt_entry *e,
+                          struct xt_table_info *newinfo,
+                          unsigned int *size,
+                          unsigned char *base,
+                          unsigned char *limit,
+                          unsigned int *hook_entries,
+                          unsigned int *underflows,
+                          unsigned int *i,
+                          const char *name)
+{
+       struct ipt_entry_target *t;
+       struct ipt_target *target;
+       u_int16_t entry_offset;
+       int ret, off, h, j;
+
+       duprintf("check_compat_entry_size_and_hooks %p\n", e);
+       if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
+           || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
+               duprintf("Bad offset %p, limit = %p\n", e, limit);
+               return -EINVAL;
+       }
+
+       if (e->next_offset < sizeof(struct compat_ipt_entry) +
+                       sizeof(struct compat_xt_entry_target)) {
+               duprintf("checking: element %p size %u\n",
+                        e, e->next_offset);
+               return -EINVAL;
+       }
+
+       if (!ip_checkentry(&e->ip)) {
+               duprintf("ip_tables: ip check failed %p %s.\n", e, name);
+               return -EINVAL;
+       }
+
+       off = 0;
+       entry_offset = (void *)e - (void *)base;
+       j = 0;
+       ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
+                       e->comefrom, &off, &j);
+       if (ret != 0)
+               goto out;
+
+       t = ipt_get_target(e);
+       target = try_then_request_module(xt_find_target(AF_INET,
+                                                    t->u.user.name,
+                                                    t->u.user.revision),
+                                        "ipt_%s", t->u.user.name);
+       if (IS_ERR(target) || !target) {
+               duprintf("check_entry: `%s' not found\n", t->u.user.name);
+               ret = target ? PTR_ERR(target) : -ENOENT;
+               goto out;
+       }
+       t->u.kernel.target = target;
+
+       if (t->u.kernel.target->compat)
+               t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
+       else
+               xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
+       *size += off;
+       ret = compat_add_offset(entry_offset, off);
+       if (ret)
+               goto out;
+
+       /* Check hooks & underflows */
+       for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+               if ((unsigned char *)e - base == hook_entries[h])
+                       newinfo->hook_entry[h] = hook_entries[h];
+               if ((unsigned char *)e - base == underflows[h])
+                       newinfo->underflow[h] = underflows[h];
+       }
+
+       /* Clear counters and comefrom */
+       e->counters = ((struct ipt_counters) { 0, 0 });
+       e->comefrom = 0;
+
+       (*i)++;
+       return 0;
+out:
+       IPT_MATCH_ITERATE(e, cleanup_match, &j);
+       return ret;
+}
+
+static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
+       void **dstptr, compat_uint_t *size, const char *name,
+       const struct ipt_ip *ip, unsigned int hookmask)
+{
+       struct ipt_entry_match *dm;
+       struct ipt_match *match;
+       int ret;
+
+       dm = (struct ipt_entry_match *)*dstptr;
+       match = m->u.kernel.match;
+       if (match->compat)
+               match->compat(m, dstptr, size, COMPAT_FROM_USER);
+       else
+               xt_compat_match(m, dstptr, size, COMPAT_FROM_USER);
+
+       ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
+                            name, hookmask, ip->proto,
+                            ip->invflags & IPT_INV_PROTO);
+       if (ret)
+               return ret;
+
+       if (m->u.kernel.match->checkentry
+           && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
+                                             dm->u.match_size - sizeof(*dm),
+                                             hookmask)) {
+               duprintf("ip_tables: check failed for `%s'.\n",
+                        m->u.kernel.match->name);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
+       unsigned int *size, const char *name,
+       struct xt_table_info *newinfo, unsigned char *base)
+{
+       struct ipt_entry_target *t;
+       struct ipt_target *target;
+       struct ipt_entry *de;
+       unsigned int origsize;
+       int ret, h;
+
+       ret = 0;
+       origsize = *size;
+       de = (struct ipt_entry *)*dstptr;
+       memcpy(de, e, sizeof(struct ipt_entry));
+
+       *dstptr += sizeof(struct compat_ipt_entry);
+       ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
+                       name, &de->ip, de->comefrom);
+       if (ret)
+               goto out;
+       de->target_offset = e->target_offset - (origsize - *size);
+       t = ipt_get_target(e);
+       target = t->u.kernel.target;
+       if (target->compat)
+               target->compat(t, dstptr, size, COMPAT_FROM_USER);
+       else
+               xt_compat_target(t, dstptr, size, COMPAT_FROM_USER);
+
+       de->next_offset = e->next_offset - (origsize - *size);
+       for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+               if ((unsigned char *)de - base < newinfo->hook_entry[h])
+                       newinfo->hook_entry[h] -= origsize - *size;
+               if ((unsigned char *)de - base < newinfo->underflow[h])
+                       newinfo->underflow[h] -= origsize - *size;
+       }
+
+       t = ipt_get_target(de);
+       target = t->u.kernel.target;
+       ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
+                             name, e->comefrom, e->ip.proto,
+                             e->ip.invflags & IPT_INV_PROTO);
+       if (ret)
+               goto out;
+
+       ret = -EINVAL;
+       if (t->u.kernel.target == &ipt_standard_target) {
+               if (!standard_check(t, *size))
+                       goto out;
+       } else if (t->u.kernel.target->checkentry
+                  && !t->u.kernel.target->checkentry(name, de, target,
+                               t->data, t->u.target_size - sizeof(*t),
+                               de->comefrom)) {
+               duprintf("ip_tables: compat: check failed for `%s'.\n",
+                        t->u.kernel.target->name);
+               goto out;
+       }
+       ret = 0;
+out:
+       return ret;
+}
+
 static int
-get_entries(const struct ipt_get_entries *entries,
-           struct ipt_get_entries __user *uptr)
+translate_compat_table(const char *name,
+               unsigned int valid_hooks,
+               struct xt_table_info **pinfo,
+               void **pentry0,
+               unsigned int total_size,
+               unsigned int number,
+               unsigned int *hook_entries,
+               unsigned int *underflows)
 {
+       unsigned int i;
+       struct xt_table_info *newinfo, *info;
+       void *pos, *entry0, *entry1;
+       unsigned int size;
        int ret;
-       struct ipt_table *t;
 
-       t = xt_find_table_lock(AF_INET, entries->name);
-       if (t && !IS_ERR(t)) {
-               struct xt_table_info *private = t->private;
-               duprintf("t->private->number = %u\n",
-                        private->number);
-               if (entries->size == private->size)
-                       ret = copy_entries_to_user(private->size,
-                                                  t, uptr->entrytable);
-               else {
-                       duprintf("get_entries: I've got %u not %u!\n",
-                                private->size,
-                                entries->size);
-                       ret = -EINVAL;
+       info = *pinfo;
+       entry0 = *pentry0;
+       size = total_size;
+       info->number = number;
+
+       /* Init all hooks to impossible value. */
+       for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+               info->hook_entry[i] = 0xFFFFFFFF;
+               info->underflow[i] = 0xFFFFFFFF;
+       }
+
+       duprintf("translate_compat_table: size %u\n", info->size);
+       i = 0;
+       xt_compat_lock(AF_INET);
+       /* Walk through entries, checking offsets. */
+       ret = IPT_ENTRY_ITERATE(entry0, total_size,
+                               check_compat_entry_size_and_hooks,
+                               info, &size, entry0,
+                               entry0 + total_size,
+                               hook_entries, underflows, &i, name);
+       if (ret != 0)
+               goto out_unlock;
+
+       ret = -EINVAL;
+       if (i != number) {
+               duprintf("translate_compat_table: %u not %u entries\n",
+                        i, number);
+               goto out_unlock;
+       }
+
+       /* Check hooks all assigned */
+       for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+               /* Only hooks which are valid */
+               if (!(valid_hooks & (1 << i)))
+                       continue;
+               if (info->hook_entry[i] == 0xFFFFFFFF) {
+                       duprintf("Invalid hook entry %u %u\n",
+                                i, hook_entries[i]);
+                       goto out_unlock;
                }
-               module_put(t->me);
-               xt_table_unlock(t);
-       } else
-               ret = t ? PTR_ERR(t) : -ENOENT;
+               if (info->underflow[i] == 0xFFFFFFFF) {
+                       duprintf("Invalid underflow %u %u\n",
+                                i, underflows[i]);
+                       goto out_unlock;
+               }
+       }
+
+       ret = -ENOMEM;
+       newinfo = xt_alloc_table_info(size);
+       if (!newinfo)
+               goto out_unlock;
+
+       newinfo->number = number;
+       for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+               newinfo->hook_entry[i] = info->hook_entry[i];
+               newinfo->underflow[i] = info->underflow[i];
+       }
+       entry1 = newinfo->entries[raw_smp_processor_id()];
+       pos = entry1;
+       size =  total_size;
+       ret = IPT_ENTRY_ITERATE(entry0, total_size,
+                       compat_copy_entry_from_user, &pos, &size,
+                       name, newinfo, entry1);
+       compat_flush_offsets();
+       xt_compat_unlock(AF_INET);
+       if (ret)
+               goto free_newinfo;
+
+       ret = -ELOOP;
+       if (!mark_source_chains(newinfo, valid_hooks, entry1))
+               goto free_newinfo;
+
+       /* And one copy for every other CPU */
+       for_each_cpu(i)
+               if (newinfo->entries[i] && newinfo->entries[i] != entry1)
+                       memcpy(newinfo->entries[i], entry1, newinfo->size);
+
+       *pinfo = newinfo;
+       *pentry0 = entry1;
+       xt_free_table_info(info);
+       return 0;
 
+free_newinfo:
+       xt_free_table_info(newinfo);
+out:
        return ret;
+out_unlock:
+       xt_compat_unlock(AF_INET);
+       goto out;
 }
 
 static int
-do_replace(void __user *user, unsigned int len)
+compat_do_replace(void __user *user, unsigned int len)
 {
        int ret;
-       struct ipt_replace tmp;
-       struct ipt_table *t;
-       struct xt_table_info *newinfo, *oldinfo;
-       struct xt_counters *counters;
-       void *loc_cpu_entry, *loc_cpu_old_entry;
+       struct compat_ipt_replace tmp;
+       struct xt_table_info *newinfo;
+       void *loc_cpu_entry;
 
        if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
                return -EFAULT;
@@ -949,151 +1818,201 @@ do_replace(void __user *user, unsigned int len)
                goto free_newinfo;
        }
 
-       counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
-       if (!counters) {
-               ret = -ENOMEM;
+       ret = translate_compat_table(tmp.name, tmp.valid_hooks,
+                             &newinfo, &loc_cpu_entry, tmp.size,
+                             tmp.num_entries, tmp.hook_entry, tmp.underflow);
+       if (ret != 0)
                goto free_newinfo;
-       }
 
-       ret = translate_table(tmp.name, tmp.valid_hooks,
-                             newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
-                             tmp.hook_entry, tmp.underflow);
-       if (ret != 0)
-               goto free_newinfo_counters;
+       duprintf("compat_do_replace: Translated table\n");
 
-       duprintf("ip_tables: Translated table\n");
+       ret = __do_replace(tmp.name, tmp.valid_hooks,
+                             newinfo, tmp.num_counters,
+                             compat_ptr(tmp.counters));
+       if (ret)
+               goto free_newinfo_untrans;
+       return 0;
 
-       t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name),
-                                   "iptable_%s", tmp.name);
-       if (!t || IS_ERR(t)) {
-               ret = t ? PTR_ERR(t) : -ENOENT;
-               goto free_newinfo_counters_untrans;
-       }
+ free_newinfo_untrans:
+       IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
+ free_newinfo:
+       xt_free_table_info(newinfo);
+       return ret;
+}
 
-       /* You lied! */
-       if (tmp.valid_hooks != t->valid_hooks) {
-               duprintf("Valid hook crap: %08X vs %08X\n",
-                        tmp.valid_hooks, t->valid_hooks);
-               ret = -EINVAL;
-               goto put_module;
-       }
+static int
+compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
+               unsigned int len)
+{
+       int ret;
 
-       oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
-       if (!oldinfo)
-               goto put_module;
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
 
-       /* Update module usage count based on number of rules */
-       duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
-               oldinfo->number, oldinfo->initial_entries, newinfo->number);
-       if ((oldinfo->number > oldinfo->initial_entries) || 
-           (newinfo->number <= oldinfo->initial_entries)) 
-               module_put(t->me);
-       if ((oldinfo->number > oldinfo->initial_entries) &&
-           (newinfo->number <= oldinfo->initial_entries))
-               module_put(t->me);
+       switch (cmd) {
+       case IPT_SO_SET_REPLACE:
+               ret = compat_do_replace(user, len);
+               break;
 
-       /* Get the old counters. */
-       get_counters(oldinfo, counters);
-       /* Decrease module usage counts and free resource */
-       loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
-       IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
-       xt_free_table_info(oldinfo);
-       if (copy_to_user(tmp.counters, counters,
-                        sizeof(struct xt_counters) * tmp.num_counters) != 0)
-               ret = -EFAULT;
-       vfree(counters);
-       xt_table_unlock(t);
-       return ret;
+       case IPT_SO_SET_ADD_COUNTERS:
+               ret = do_add_counters(user, len, 1);
+               break;
+
+       default:
+               duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
+               ret = -EINVAL;
+       }
 
- put_module:
-       module_put(t->me);
-       xt_table_unlock(t);
- free_newinfo_counters_untrans:
-       IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
- free_newinfo_counters:
-       vfree(counters);
- free_newinfo:
-       xt_free_table_info(newinfo);
        return ret;
 }
 
-/* We're lazy, and add to the first CPU; overflow works its fey magic
- * and everything is OK. */
-static inline int
-add_counter_to_entry(struct ipt_entry *e,
-                    const struct xt_counters addme[],
-                    unsigned int *i)
+struct compat_ipt_get_entries
 {
-#if 0
-       duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
-                *i,
-                (long unsigned int)e->counters.pcnt,
-                (long unsigned int)e->counters.bcnt,
-                (long unsigned int)addme[*i].pcnt,
-                (long unsigned int)addme[*i].bcnt);
-#endif
+       char name[IPT_TABLE_MAXNAMELEN];
+       compat_uint_t size;
+       struct compat_ipt_entry entrytable[0];
+};
 
-       ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
+static int compat_copy_entries_to_user(unsigned int total_size,
+                    struct ipt_table *table, void __user *userptr)
+{
+       unsigned int off, num;
+       struct compat_ipt_entry e;
+       struct xt_counters *counters;
+       struct xt_table_info *private = table->private;
+       void __user *pos;
+       unsigned int size;
+       int ret = 0;
+       void *loc_cpu_entry;
 
-       (*i)++;
-       return 0;
+       counters = alloc_counters(table);
+       if (IS_ERR(counters))
+               return PTR_ERR(counters);
+
+       /* choose the copy that is on our node/cpu, ...
+        * This choice is lazy (because current thread is
+        * allowed to migrate to another cpu)
+        */
+       loc_cpu_entry = private->entries[raw_smp_processor_id()];
+       pos = userptr;
+       size = total_size;
+       ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
+                       compat_copy_entry_to_user, &pos, &size);
+       if (ret)
+               goto free_counters;
+
+       /* ... then go back and fix counters and names */
+       for (off = 0, num = 0; off < size; off += e.next_offset, num++) {
+               unsigned int i;
+               struct ipt_entry_match m;
+               struct ipt_entry_target t;
+
+               ret = -EFAULT;
+               if (copy_from_user(&e, userptr + off,
+                                       sizeof(struct compat_ipt_entry)))
+                       goto free_counters;
+               if (copy_to_user(userptr + off +
+                       offsetof(struct compat_ipt_entry, counters),
+                        &counters[num], sizeof(counters[num])))
+                       goto free_counters;
+
+               for (i = sizeof(struct compat_ipt_entry);
+                               i < e.target_offset; i += m.u.match_size) {
+                       if (copy_from_user(&m, userptr + off + i,
+                                       sizeof(struct ipt_entry_match)))
+                               goto free_counters;
+                       if (copy_to_user(userptr + off + i +
+                               offsetof(struct ipt_entry_match, u.user.name),
+                               m.u.kernel.match->name,
+                               strlen(m.u.kernel.match->name) + 1))
+                               goto free_counters;
+               }
+
+               if (copy_from_user(&t, userptr + off + e.target_offset,
+                                       sizeof(struct ipt_entry_target)))
+                       goto free_counters;
+               if (copy_to_user(userptr + off + e.target_offset +
+                       offsetof(struct ipt_entry_target, u.user.name),
+                       t.u.kernel.target->name,
+                       strlen(t.u.kernel.target->name) + 1))
+                       goto free_counters;
+       }
+       ret = 0;
+free_counters:
+       vfree(counters);
+       return ret;
 }
 
 static int
-do_add_counters(void __user *user, unsigned int len)
+compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
 {
-       unsigned int i;
-       struct xt_counters_info tmp, *paddc;
+       int ret;
+       struct compat_ipt_get_entries get;
        struct ipt_table *t;
-       struct xt_table_info *private;
-       int ret = 0;
-       void *loc_cpu_entry;
 
-       if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
-               return -EFAULT;
 
-       if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
+       if (*len < sizeof(get)) {
+               duprintf("compat_get_entries: %u < %u\n",
+                               *len, (unsigned int)sizeof(get));
                return -EINVAL;
+       }
 
-       paddc = vmalloc_node(len, numa_node_id());
-       if (!paddc)
-               return -ENOMEM;
+       if (copy_from_user(&get, uptr, sizeof(get)) != 0)
+               return -EFAULT;
 
-       if (copy_from_user(paddc, user, len) != 0) {
-               ret = -EFAULT;
-               goto free;
+       if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
+               duprintf("compat_get_entries: %u != %u\n", *len,
+                       (unsigned int)(sizeof(struct compat_ipt_get_entries) +
+                       get.size));
+               return -EINVAL;
        }
 
-       t = xt_find_table_lock(AF_INET, tmp.name);
-       if (!t || IS_ERR(t)) {
+       xt_compat_lock(AF_INET);
+       t = xt_find_table_lock(AF_INET, get.name);
+       if (t && !IS_ERR(t)) {
+               struct xt_table_info *private = t->private;
+               struct xt_table_info info;
+               duprintf("t->private->number = %u\n",
+                        private->number);
+               ret = compat_table_info(private, &info);
+               if (!ret && get.size == info.size) {
+                       ret = compat_copy_entries_to_user(private->size,
+                                                  t, uptr->entrytable);
+               } else if (!ret) {
+                       duprintf("compat_get_entries: I've got %u not %u!\n",
+                                private->size,
+                                get.size);
+                       ret = -EINVAL;
+               }
+               compat_flush_offsets();
+               module_put(t->me);
+               xt_table_unlock(t);
+       } else
                ret = t ? PTR_ERR(t) : -ENOENT;
-               goto free;
-       }
 
-       write_lock_bh(&t->lock);
-       private = t->private;
-       if (private->number != paddc->num_counters) {
-               ret = -EINVAL;
-               goto unlock_up_free;
-       }
+       xt_compat_unlock(AF_INET);
+       return ret;
+}
 
-       i = 0;
-       /* Choose the copy that is on our node */
-       loc_cpu_entry = private->entries[raw_smp_processor_id()];
-       IPT_ENTRY_ITERATE(loc_cpu_entry,
-                         private->size,
-                         add_counter_to_entry,
-                         paddc->counters,
-                         &i);
- unlock_up_free:
-       write_unlock_bh(&t->lock);
-       xt_table_unlock(t);
-       module_put(t->me);
- free:
-       vfree(paddc);
+static int
+compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+{
+       int ret;
 
+       switch (cmd) {
+       case IPT_SO_GET_INFO:
+               ret = get_info(user, len, 1);
+               break;
+       case IPT_SO_GET_ENTRIES:
+               ret = compat_get_entries(user, len);
+               break;
+       default:
+               duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd);
+               ret = -EINVAL;
+       }
        return ret;
 }
+#endif
 
 static int
 do_ipt_set_ctl(struct sock *sk,        int cmd, void __user *user, unsigned int len)
@@ -1109,7 +2028,7 @@ do_ipt_set_ctl(struct sock *sk,   int cmd, void __user *user, unsigned int len)
                break;
 
        case IPT_SO_SET_ADD_COUNTERS:
-               ret = do_add_counters(user, len);
+               ret = do_add_counters(user, len, 0);
                break;
 
        default:
@@ -1129,65 +2048,13 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
                return -EPERM;
 
        switch (cmd) {
-       case IPT_SO_GET_INFO: {
-               char name[IPT_TABLE_MAXNAMELEN];
-               struct ipt_table *t;
-
-               if (*len != sizeof(struct ipt_getinfo)) {
-                       duprintf("length %u != %u\n", *len,
-                                sizeof(struct ipt_getinfo));
-                       ret = -EINVAL;
-                       break;
-               }
-
-               if (copy_from_user(name, user, sizeof(name)) != 0) {
-                       ret = -EFAULT;
-                       break;
-               }
-               name[IPT_TABLE_MAXNAMELEN-1] = '\0';
-
-               t = try_then_request_module(xt_find_table_lock(AF_INET, name),
-                                           "iptable_%s", name);
-               if (t && !IS_ERR(t)) {
-                       struct ipt_getinfo info;
-                       struct xt_table_info *private = t->private;
-
-                       info.valid_hooks = t->valid_hooks;
-                       memcpy(info.hook_entry, private->hook_entry,
-                              sizeof(info.hook_entry));
-                       memcpy(info.underflow, private->underflow,
-                              sizeof(info.underflow));
-                       info.num_entries = private->number;
-                       info.size = private->size;
-                       memcpy(info.name, name, sizeof(info.name));
-
-                       if (copy_to_user(user, &info, *len) != 0)
-                               ret = -EFAULT;
-                       else
-                               ret = 0;
-                       xt_table_unlock(t);
-                       module_put(t->me);
-               } else
-                       ret = t ? PTR_ERR(t) : -ENOENT;
-       }
-       break;
-
-       case IPT_SO_GET_ENTRIES: {
-               struct ipt_get_entries get;
+       case IPT_SO_GET_INFO:
+               ret = get_info(user, len, 0);
+               break;
 
-               if (*len < sizeof(get)) {
-                       duprintf("get_entries: %u < %u\n", *len, sizeof(get));
-                       ret = -EINVAL;
-               } else if (copy_from_user(&get, user, sizeof(get)) != 0) {
-                       ret = -EFAULT;
-               } else if (*len != sizeof(struct ipt_get_entries) + get.size) {
-                       duprintf("get_entries: %u != %u\n", *len,
-                                sizeof(struct ipt_get_entries) + get.size);
-                       ret = -EINVAL;
-               } else
-                       ret = get_entries(&get, user);
+       case IPT_SO_GET_ENTRIES:
+               ret = get_entries(user, len);
                break;
-       }
 
        case IPT_SO_GET_REVISION_MATCH:
        case IPT_SO_GET_REVISION_TARGET: {
@@ -1336,6 +2203,9 @@ static struct ipt_target ipt_standard_target = {
        .name           = IPT_STANDARD_TARGET,
        .targetsize     = sizeof(int),
        .family         = AF_INET,
+#ifdef CONFIG_COMPAT
+       .compat         = &compat_ipt_standard_fn,
+#endif
 };
 
 static struct ipt_target ipt_error_target = {
@@ -1350,9 +2220,15 @@ static struct nf_sockopt_ops ipt_sockopts = {
        .set_optmin     = IPT_BASE_CTL,
        .set_optmax     = IPT_SO_SET_MAX+1,
        .set            = do_ipt_set_ctl,
+#ifdef CONFIG_COMPAT
+       .compat_set     = compat_do_ipt_set_ctl,
+#endif
        .get_optmin     = IPT_BASE_CTL,
        .get_optmax     = IPT_SO_GET_MAX+1,
        .get            = do_ipt_get_ctl,
+#ifdef CONFIG_COMPAT
+       .compat_get     = compat_do_ipt_get_ctl,
+#endif
 };
 
 static struct ipt_match icmp_matchstruct = {
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
deleted file mode 100644 (file)
index 3840b41..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Kernel module to match ESP parameters. */
-
-/* (C) 1999-2000 Yon Uriarte <yon@astaro.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/ip.h>
-
-#include <linux/netfilter_ipv4/ipt_esp.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
-MODULE_DESCRIPTION("iptables ESP SPI match module");
-
-#ifdef DEBUG_CONNTRACK
-#define duprintf(format, args...) printk(format , ## args)
-#else
-#define duprintf(format, args...)
-#endif
-
-/* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
-{
-       int r=0;
-        duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
-               min,spi,max);
-       r=(spi >= min && spi <= max) ^ invert;
-       duprintf(" result %s\n",r? "PASS" : "FAILED");
-       return r;
-}
-
-static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop)
-{
-       struct ip_esp_hdr _esp, *eh;
-       const struct ipt_esp *espinfo = matchinfo;
-
-       /* Must not be a fragment. */
-       if (offset)
-               return 0;
-
-       eh = skb_header_pointer(skb, protoff,
-                               sizeof(_esp), &_esp);
-       if (eh == NULL) {
-               /* We've been asked to examine this packet, and we
-                * can't.  Hence, no choice but to drop.
-                */
-               duprintf("Dropping evil ESP tinygram.\n");
-               *hotdrop = 1;
-               return 0;
-       }
-
-       return spi_match(espinfo->spis[0], espinfo->spis[1],
-                        ntohl(eh->spi),
-                        !!(espinfo->invflags & IPT_ESP_INV_SPI));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-checkentry(const char *tablename,
-          const void *ip_void,
-          const struct xt_match *match,
-          void *matchinfo,
-          unsigned int matchinfosize,
-          unsigned int hook_mask)
-{
-       const struct ipt_esp *espinfo = matchinfo;
-
-       /* Must specify no unknown invflags */
-       if (espinfo->invflags & ~IPT_ESP_INV_MASK) {
-               duprintf("ipt_esp: unknown flags %X\n", espinfo->invflags);
-               return 0;
-       }
-       return 1;
-}
-
-static struct ipt_match esp_match = {
-       .name           = "esp",
-       .match          = match,
-       .matchsize      = sizeof(struct ipt_esp),
-       .proto          = IPPROTO_ESP,
-       .checkentry     = checkentry,
-       .me             = THIS_MODULE,
-};
-
-static int __init ipt_esp_init(void)
-{
-       return ipt_register_match(&esp_match);
-}
-
-static void __exit ipt_esp_fini(void)
-{
-       ipt_unregister_match(&esp_match);
-}
-
-module_init(ipt_esp_init);
-module_exit(ipt_esp_fini);
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
deleted file mode 100644 (file)
index ac95d83..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/* Kernel module to match one of a list of TCP/UDP ports: ports are in
-   the same place so we can treat them as equal. */
-
-/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/udp.h>
-#include <linux/skbuff.h>
-
-#include <linux/netfilter_ipv4/ipt_multiport.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("iptables multiple port match module");
-
-#if 0
-#define duprintf(format, args...) printk(format , ## args)
-#else
-#define duprintf(format, args...)
-#endif
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match(const u_int16_t *portlist, enum ipt_multiport_flags flags,
-           u_int8_t count, u_int16_t src, u_int16_t dst)
-{
-       unsigned int i;
-       for (i=0; i<count; i++) {
-               if (flags != IPT_MULTIPORT_DESTINATION
-                   && portlist[i] == src)
-                       return 1;
-
-               if (flags != IPT_MULTIPORT_SOURCE
-                   && portlist[i] == dst)
-                       return 1;
-       }
-
-       return 0;
-}
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match_v1(const struct ipt_multiport_v1 *minfo,
-              u_int16_t src, u_int16_t dst)
-{
-       unsigned int i;
-       u_int16_t s, e;
-
-       for (i=0; i < minfo->count; i++) {
-               s = minfo->ports[i];
-
-               if (minfo->pflags[i]) {
-                       /* range port matching */
-                       e = minfo->ports[++i];
-                       duprintf("src or dst matches with %d-%d?\n", s, e);
-
-                       if (minfo->flags == IPT_MULTIPORT_SOURCE
-                           && src >= s && src <= e)
-                               return 1 ^ minfo->invert;
-                       if (minfo->flags == IPT_MULTIPORT_DESTINATION
-                           && dst >= s && dst <= e)
-                               return 1 ^ minfo->invert;
-                       if (minfo->flags == IPT_MULTIPORT_EITHER
-                           && ((dst >= s && dst <= e)
-                               || (src >= s && src <= e)))
-                               return 1 ^ minfo->invert;
-               } else {
-                       /* exact port matching */
-                       duprintf("src or dst matches with %d?\n", s);
-
-                       if (minfo->flags == IPT_MULTIPORT_SOURCE
-                           && src == s)
-                               return 1 ^ minfo->invert;
-                       if (minfo->flags == IPT_MULTIPORT_DESTINATION
-                           && dst == s)
-                               return 1 ^ minfo->invert;
-                       if (minfo->flags == IPT_MULTIPORT_EITHER
-                           && (src == s || dst == s))
-                               return 1 ^ minfo->invert;
-               }
-       }
-       return minfo->invert;
-}
-
-static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop)
-{
-       u16 _ports[2], *pptr;
-       const struct ipt_multiport *multiinfo = matchinfo;
-
-       if (offset)
-               return 0;
-
-       pptr = skb_header_pointer(skb, protoff,
-                                 sizeof(_ports), _ports);
-       if (pptr == NULL) {
-               /* We've been asked to examine this packet, and we
-                * can't.  Hence, no choice but to drop.
-                */
-               duprintf("ipt_multiport:"
-                        " Dropping evil offset=0 tinygram.\n");
-               *hotdrop = 1;
-               return 0;
-       }
-
-       return ports_match(multiinfo->ports,
-                          multiinfo->flags, multiinfo->count,
-                          ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-static int
-match_v1(const struct sk_buff *skb,
-        const struct net_device *in,
-        const struct net_device *out,
-        const struct xt_match *match,
-        const void *matchinfo,
-        int offset,
-        unsigned int protoff,
-        int *hotdrop)
-{
-       u16 _ports[2], *pptr;
-       const struct ipt_multiport_v1 *multiinfo = matchinfo;
-
-       if (offset)
-               return 0;
-
-       pptr = skb_header_pointer(skb, protoff,
-                                 sizeof(_ports), _ports);
-       if (pptr == NULL) {
-               /* We've been asked to examine this packet, and we
-                * can't.  Hence, no choice but to drop.
-                */
-               duprintf("ipt_multiport:"
-                        " Dropping evil offset=0 tinygram.\n");
-               *hotdrop = 1;
-               return 0;
-       }
-
-       return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-static struct ipt_match multiport_match = {
-       .name           = "multiport",
-       .revision       = 0,
-       .match          = match,
-       .matchsize      = sizeof(struct ipt_multiport),
-       .me             = THIS_MODULE,
-};
-
-static struct ipt_match multiport_match_v1 = {
-       .name           = "multiport",
-       .revision       = 1,
-       .match          = match_v1,
-       .matchsize      = sizeof(struct ipt_multiport_v1),
-       .me             = THIS_MODULE,
-};
-
-static int __init ipt_multiport_init(void)
-{
-       int err;
-
-       err = ipt_register_match(&multiport_match);
-       if (!err) {
-               err = ipt_register_match(&multiport_match_v1);
-               if (err)
-                       ipt_unregister_match(&multiport_match);
-       }
-
-       return err;
-}
-
-static void __exit ipt_multiport_fini(void)
-{
-       ipt_unregister_match(&multiport_match);
-       ipt_unregister_match(&multiport_match_v1);
-}
-
-module_init(ipt_multiport_init);
-module_exit(ipt_multiport_fini);
index 850d919..e1b8f4b 100644 (file)
@@ -68,7 +68,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 {
        int err;
        u32 spi, seq;
-       struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
+       struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
        struct xfrm_state *x;
        int xfrm_nr = 0;
        int decaps = 0;
@@ -90,14 +90,16 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
                if (unlikely(x->km.state != XFRM_STATE_VALID))
                        goto drop_unlock;
 
+               if (x->encap->encap_type != encap_type)
+                       goto drop_unlock;
+
                if (x->props.replay_window && xfrm_replay_check(x, seq))
                        goto drop_unlock;
 
                if (xfrm_state_check_expire(x))
                        goto drop_unlock;
 
-               xfrm_vec[xfrm_nr].decap.decap_type = encap_type;
-               if (x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb))
+               if (x->type->input(x, skb))
                        goto drop_unlock;
 
                /* only the first xfrm gets the encap type */
@@ -111,7 +113,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 
                spin_unlock(&x->lock);
 
-               xfrm_vec[xfrm_nr++].xvec = x;
+               xfrm_vec[xfrm_nr++] = x;
 
                iph = skb->nh.iph;
 
@@ -153,7 +155,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
        if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
                goto drop;
 
-       memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
+       memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
+              xfrm_nr * sizeof(xfrm_vec[0]));
        skb->sp->len += xfrm_nr;
 
        nf_reset(skb);
@@ -184,7 +187,7 @@ drop_unlock:
        xfrm_state_put(x);
 drop:
        while (--xfrm_nr >= 0)
-               xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
+               xfrm_state_put(xfrm_vec[xfrm_nr]);
 
        kfree_skb(skb);
        return 0;
index 2d67093..f8ceaa1 100644 (file)
@@ -21,7 +21,7 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
        return 0;
 }
 
-static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
 {
        return 0;
 }
index cf58251..6778173 100644 (file)
@@ -229,7 +229,7 @@ error:
        return err;
 }
 
-static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
 {
        /*
         * Before process AH
index 3dcaac7..22f0460 100644 (file)
@@ -130,7 +130,7 @@ error:
        return err;
 }
 
-static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
 {
        struct ipv6hdr *iph;
        struct ipv6_esp_hdr *esph;
index d4cfec3..00f3fad 100644 (file)
@@ -63,7 +63,7 @@ static void **ipcomp6_scratches;
 static int ipcomp6_scratch_users;
 static LIST_HEAD(ipcomp6_tfms_list);
 
-static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err = 0;
        u8 nexthdr = 0;
index 98f7875..4bc4e5b 100644 (file)
@@ -87,16 +87,6 @@ config IP6_NF_MATCH_HL
 
          To compile it as a module, choose M here.  If unsure, say N.
 
-config IP6_NF_MATCH_MULTIPORT
-       tristate "Multiple port match support"
-       depends on IP6_NF_IPTABLES
-       help
-         Multiport matching allows you to match TCP or UDP packets based on
-         a series of source or destination ports: normally a rule can only
-         match a single range of ports.
-
-         To compile it as a module, choose M here.  If unsure, say N.
-
 config IP6_NF_MATCH_OWNER
        tristate "Owner match support"
        depends on IP6_NF_IPTABLES
@@ -115,11 +105,11 @@ config IP6_NF_MATCH_IPV6HEADER
 
          To compile it as a module, choose M here.  If unsure, say N.
 
-config IP6_NF_MATCH_AHESP
-       tristate "AH/ESP match support"
+config IP6_NF_MATCH_AH
+       tristate "AH match support"
        depends on IP6_NF_IPTABLES
        help
-         This module allows one to match AH and ESP packets.
+         This module allows one to match AH packets.
 
          To compile it as a module, choose M here.  If unsure, say N.
 
index 8436a1a..eeeb57d 100644 (file)
@@ -8,9 +8,8 @@ obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
 obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
-obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
+obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
-obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
deleted file mode 100644 (file)
index 36bedad..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Kernel module to match ESP parameters. */
-/* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/types.h>
-#include <net/checksum.h>
-#include <net/ipv6.h>
-
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_esp.h>
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("IPv6 ESP match");
-MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-/* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
-{
-       int r=0;
-       DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
-              min,spi,max);
-       r=(spi >= min && spi <= max) ^ invert;
-       DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
-       return r;
-}
-
-static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop)
-{
-       struct ip_esp_hdr _esp, *eh;
-       const struct ip6t_esp *espinfo = matchinfo;
-       unsigned int ptr;
-
-       /* Make sure this isn't an evil packet */
-       /*DEBUGP("ipv6_esp entered \n");*/
-
-       if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP, NULL) < 0)
-               return 0;
-
-       eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
-       if (eh == NULL) {
-               *hotdrop = 1;
-               return 0;
-       }
-
-       DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
-
-       return (eh != NULL)
-               && spi_match(espinfo->spis[0], espinfo->spis[1],
-                             ntohl(eh->spi),
-                             !!(espinfo->invflags & IP6T_ESP_INV_SPI));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-checkentry(const char *tablename,
-          const void *ip,
-          const struct xt_match *match,
-          void *matchinfo,
-          unsigned int matchinfosize,
-          unsigned int hook_mask)
-{
-       const struct ip6t_esp *espinfo = matchinfo;
-
-       if (espinfo->invflags & ~IP6T_ESP_INV_MASK) {
-               DEBUGP("ip6t_esp: unknown flags %X\n",
-                        espinfo->invflags);
-               return 0;
-       }
-       return 1;
-}
-
-static struct ip6t_match esp_match = {
-       .name           = "esp",
-       .match          = match,
-       .matchsize      = sizeof(struct ip6t_esp),
-       .checkentry     = checkentry,
-       .me             = THIS_MODULE,
-};
-
-static int __init ip6t_esp_init(void)
-{
-       return ip6t_register_match(&esp_match);
-}
-
-static void __exit ip6t_esp_fini(void)
-{
-       ip6t_unregister_match(&esp_match);
-}
-
-module_init(ip6t_esp_init);
-module_exit(ip6t_esp_fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
deleted file mode 100644 (file)
index 10c48ba..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/* Kernel module to match one of a list of TCP/UDP ports: ports are in
-   the same place so we can treat them as equal. */
-
-/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/udp.h>
-#include <linux/skbuff.h>
-#include <linux/in.h>
-
-#include <linux/netfilter_ipv6/ip6t_multiport.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("ip6tables match for multiple ports");
-
-#if 0
-#define duprintf(format, args...) printk(format , ## args)
-#else
-#define duprintf(format, args...)
-#endif
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match(const u_int16_t *portlist, enum ip6t_multiport_flags flags,
-           u_int8_t count, u_int16_t src, u_int16_t dst)
-{
-       unsigned int i;
-       for (i=0; i<count; i++) {
-               if (flags != IP6T_MULTIPORT_DESTINATION
-                   && portlist[i] == src)
-                       return 1;
-
-               if (flags != IP6T_MULTIPORT_SOURCE
-                   && portlist[i] == dst)
-                       return 1;
-       }
-
-       return 0;
-}
-
-static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop)
-{
-       u16 _ports[2], *pptr;
-       const struct ip6t_multiport *multiinfo = matchinfo;
-
-       /* Must not be a fragment. */
-       if (offset)
-               return 0;
-
-       /* Must be big enough to read ports (both UDP and TCP have
-          them at the start). */
-       pptr = skb_header_pointer(skb, protoff, sizeof(_ports), &_ports[0]);
-       if (pptr == NULL) {
-               /* We've been asked to examine this packet, and we
-                * can't.  Hence, no choice but to drop.
-                */
-               duprintf("ip6t_multiport:"
-                        " Dropping evil offset=0 tinygram.\n");
-               *hotdrop = 1;
-               return 0;
-       }
-
-       return ports_match(multiinfo->ports,
-                          multiinfo->flags, multiinfo->count,
-                          ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-checkentry(const char *tablename,
-          const void *info,
-          const struct xt_match *match,
-          void *matchinfo,
-          unsigned int matchsize,
-          unsigned int hook_mask)
-{
-       const struct ip6t_ip6 *ip = info;
-       const struct ip6t_multiport *multiinfo = matchinfo;
-
-       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
-       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
-               && !(ip->invflags & IP6T_INV_PROTO)
-               && (multiinfo->flags == IP6T_MULTIPORT_SOURCE
-                   || multiinfo->flags == IP6T_MULTIPORT_DESTINATION
-                   || multiinfo->flags == IP6T_MULTIPORT_EITHER)
-               && multiinfo->count <= IP6T_MULTI_PORTS;
-}
-
-static struct ip6t_match multiport_match = {
-       .name           = "multiport",
-       .match          = match,
-       .matchsize      = sizeof(struct ip6t_multiport),
-       .checkentry     = checkentry,
-       .me             = THIS_MODULE,
-};
-
-static int __init ip6t_multiport_init(void)
-{
-       return ip6t_register_match(&multiport_match);
-}
-
-static void __exit ip6t_multiport_fini(void)
-{
-       ip6t_unregister_match(&multiport_match);
-}
-
-module_init(ip6t_multiport_init);
-module_exit(ip6t_multiport_fini);
index cccf8b7..00cfdee 100644 (file)
@@ -32,7 +32,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
 {
        int err;
        u32 seq;
-       struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
+       struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
        struct xfrm_state *x;
        int xfrm_nr = 0;
        int decaps = 0;
@@ -65,7 +65,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
                if (xfrm_state_check_expire(x))
                        goto drop_unlock;
 
-               nexthdr = x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb);
+               nexthdr = x->type->input(x, skb);
                if (nexthdr <= 0)
                        goto drop_unlock;
 
@@ -79,7 +79,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
 
                spin_unlock(&x->lock);
 
-               xfrm_vec[xfrm_nr++].xvec = x;
+               xfrm_vec[xfrm_nr++] = x;
 
                if (x->props.mode) { /* XXX */
                        if (nexthdr != IPPROTO_IPV6)
@@ -118,7 +118,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
        if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
                goto drop;
 
-       memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
+       memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
+              xfrm_nr * sizeof(xfrm_vec[0]));
        skb->sp->len += xfrm_nr;
        skb->ip_summed = CHECKSUM_NONE;
 
@@ -149,7 +150,7 @@ drop_unlock:
        xfrm_state_put(x);
 drop:
        while (--xfrm_nr >= 0)
-               xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
+               xfrm_state_put(xfrm_vec[xfrm_nr]);
        kfree_skb(skb);
        return -1;
 }
index a8f6776..d37768e 100644 (file)
@@ -351,7 +351,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
        return 0;
 }
 
-static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 {
        return 0;
 }
index 332acb3..e2893ef 100644 (file)
@@ -231,6 +231,15 @@ config NETFILTER_XT_MATCH_DCCP
          If you want to compile it as a module, say M here and read
          <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_MATCH_ESP
+       tristate '"ESP" match support'
+       depends on NETFILTER_XTABLES
+       help
+         This match extension allows you to match a range of SPIs
+         inside ESP header of IPSec packets.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_HELPER
        tristate '"helper" match support'
        depends on NETFILTER_XTABLES
@@ -289,6 +298,16 @@ config NETFILTER_XT_MATCH_POLICY
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_MULTIPORT
+       tristate "Multiple port match support"
+       depends on NETFILTER_XTABLES
+       help
+         Multiport matching allows you to match TCP or UDP packets based on
+         a series of source or destination ports: normally a rule can only
+         match a single range of ports.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_PHYSDEV
        tristate '"physdev" match support'
        depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
index 9558727..95b7e41 100644 (file)
@@ -35,11 +35,13 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
index 0e0e9d7..bd10eb9 100644 (file)
@@ -1022,7 +1022,7 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[])
                        return err;
        }
 
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+#if defined(CONFIG_NF_CONNTRACK_MARK)
        if (cda[CTA_MARK-1])
                ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
@@ -1062,7 +1062,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
                        return err;
        }
 
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+#if defined(CONFIG_NF_CONNTRACK_MARK)
        if (cda[CTA_MARK-1])
                ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
@@ -1687,7 +1687,7 @@ static void __exit ctnetlink_exit(void)
        printk("ctnetlink: unregistering from nfnetlink.\n");
 
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
-       nf_conntrack_unregister_notifier(&ctnl_notifier_exp);
+       nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
        nf_conntrack_unregister_notifier(&ctnl_notifier);
 #endif
 
index a657ab5..feb8a9e 100644 (file)
@@ -38,6 +38,7 @@ struct xt_af {
        struct list_head match;
        struct list_head target;
        struct list_head tables;
+       struct mutex compat_mutex;
 };
 
 static struct xt_af *xt;
@@ -272,6 +273,54 @@ int xt_check_match(const struct xt_match *match, unsigned short family,
 }
 EXPORT_SYMBOL_GPL(xt_check_match);
 
+#ifdef CONFIG_COMPAT
+int xt_compat_match(void *match, void **dstptr, int *size, int convert)
+{
+       struct xt_match *m;
+       struct compat_xt_entry_match *pcompat_m;
+       struct xt_entry_match *pm;
+       u_int16_t msize;
+       int off, ret;
+
+       ret = 0;
+       m = ((struct xt_entry_match *)match)->u.kernel.match;
+       off = XT_ALIGN(m->matchsize) - COMPAT_XT_ALIGN(m->matchsize);
+       switch (convert) {
+               case COMPAT_TO_USER:
+                       pm = (struct xt_entry_match *)match;
+                       msize = pm->u.user.match_size;
+                       if (__copy_to_user(*dstptr, pm, msize)) {
+                               ret = -EFAULT;
+                               break;
+                       }
+                       msize -= off;
+                       if (put_user(msize, (u_int16_t *)*dstptr))
+                               ret = -EFAULT;
+                       *size -= off;
+                       *dstptr += msize;
+                       break;
+               case COMPAT_FROM_USER:
+                       pcompat_m = (struct compat_xt_entry_match *)match;
+                       pm = (struct xt_entry_match *)*dstptr;
+                       msize = pcompat_m->u.user.match_size;
+                       memcpy(pm, pcompat_m, msize);
+                       msize += off;
+                       pm->u.user.match_size = msize;
+                       *size += off;
+                       *dstptr += msize;
+                       break;
+               case COMPAT_CALC_SIZE:
+                       *size += off;
+                       break;
+               default:
+                       ret = -ENOPROTOOPT;
+                       break;
+       }
+       return ret;
+}
+EXPORT_SYMBOL_GPL(xt_compat_match);
+#endif
+
 int xt_check_target(const struct xt_target *target, unsigned short family,
                    unsigned int size, const char *table, unsigned int hook_mask,
                    unsigned short proto, int inv_proto)
@@ -301,6 +350,54 @@ int xt_check_target(const struct xt_target *target, unsigned short family,
 }
 EXPORT_SYMBOL_GPL(xt_check_target);
 
+#ifdef CONFIG_COMPAT
+int xt_compat_target(void *target, void **dstptr, int *size, int convert)
+{
+       struct xt_target *t;
+       struct compat_xt_entry_target *pcompat;
+       struct xt_entry_target *pt;
+       u_int16_t tsize;
+       int off, ret;
+
+       ret = 0;
+       t = ((struct xt_entry_target *)target)->u.kernel.target;
+       off = XT_ALIGN(t->targetsize) - COMPAT_XT_ALIGN(t->targetsize);
+       switch (convert) {
+               case COMPAT_TO_USER:
+                       pt = (struct xt_entry_target *)target;
+                       tsize = pt->u.user.target_size;
+                       if (__copy_to_user(*dstptr, pt, tsize)) {
+                               ret = -EFAULT;
+                               break;
+                       }
+                       tsize -= off;
+                       if (put_user(tsize, (u_int16_t *)*dstptr))
+                               ret = -EFAULT;
+                       *size -= off;
+                       *dstptr += tsize;
+                       break;
+               case COMPAT_FROM_USER:
+                       pcompat = (struct compat_xt_entry_target *)target;
+                       pt = (struct xt_entry_target *)*dstptr;
+                       tsize = pcompat->u.user.target_size;
+                       memcpy(pt, pcompat, tsize);
+                       tsize += off;
+                       pt->u.user.target_size = tsize;
+                       *size += off;
+                       *dstptr += tsize;
+                       break;
+               case COMPAT_CALC_SIZE:
+                       *size += off;
+                       break;
+               default:
+                       ret = -ENOPROTOOPT;
+                       break;
+       }
+       return ret;
+}
+EXPORT_SYMBOL_GPL(xt_compat_target);
+#endif
+
 struct xt_table_info *xt_alloc_table_info(unsigned int size)
 {
        struct xt_table_info *newinfo;
@@ -371,6 +468,19 @@ void xt_table_unlock(struct xt_table *table)
 }
 EXPORT_SYMBOL_GPL(xt_table_unlock);
 
+#ifdef CONFIG_COMPAT
+void xt_compat_lock(int af)
+{
+       mutex_lock(&xt[af].compat_mutex);
+}
+EXPORT_SYMBOL_GPL(xt_compat_lock);
+
+void xt_compat_unlock(int af)
+{
+       mutex_unlock(&xt[af].compat_mutex);
+}
+EXPORT_SYMBOL_GPL(xt_compat_unlock);
+#endif
 
 struct xt_table_info *
 xt_replace_table(struct xt_table *table,
@@ -671,6 +781,9 @@ static int __init xt_init(void)
 
        for (i = 0; i < NPROTO; i++) {
                mutex_init(&xt[i].mutex);
+#ifdef CONFIG_COMPAT
+               mutex_init(&xt[i].compat_mutex);
+#endif
                INIT_LIST_HEAD(&xt[i].target);
                INIT_LIST_HEAD(&xt[i].match);
                INIT_LIST_HEAD(&xt[i].tables);
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
new file mode 100644 (file)
index 0000000..9dad628
--- /dev/null
@@ -0,0 +1,136 @@
+/* Kernel module to match ESP parameters. */
+
+/* (C) 1999-2000 Yon Uriarte <yon@astaro.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+
+#include <linux/netfilter/xt_esp.h>
+#include <linux/netfilter/x_tables.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
+MODULE_DESCRIPTION("x_tables ESP SPI match module");
+MODULE_ALIAS("ipt_esp");
+MODULE_ALIAS("ip6t_esp");
+
+#if 0
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+/* Returns 1 if the spi is matched by the range, 0 otherwise */
+static inline int
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+{
+       int r = 0;
+       duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
+                min, spi, max);
+       r = (spi >= min && spi <= max) ^ invert;
+       duprintf(" result %s\n", r ? "PASS" : "FAILED");
+       return r;
+}
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const struct xt_match *match,
+      const void *matchinfo,
+      int offset,
+      unsigned int protoff,
+      int *hotdrop)
+{
+       struct ip_esp_hdr _esp, *eh;
+       const struct xt_esp *espinfo = matchinfo;
+
+       /* Must not be a fragment. */
+       if (offset)
+               return 0;
+
+       eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp);
+       if (eh == NULL) {
+               /* We've been asked to examine this packet, and we
+                * can't.  Hence, no choice but to drop.
+                */
+               duprintf("Dropping evil ESP tinygram.\n");
+               *hotdrop = 1;
+               return 0;
+       }
+
+       return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi),
+                        !!(espinfo->invflags & XT_ESP_INV_SPI));
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+checkentry(const char *tablename,
+          const void *ip_void,
+          const struct xt_match *match,
+          void *matchinfo,
+          unsigned int matchinfosize,
+          unsigned int hook_mask)
+{
+       const struct xt_esp *espinfo = matchinfo;
+
+       if (espinfo->invflags & ~XT_ESP_INV_MASK) {
+               duprintf("xt_esp: unknown flags %X\n", espinfo->invflags);
+               return 0;
+       }
+
+       return 1;
+}
+
+static struct xt_match esp_match = {
+       .name           = "esp",
+       .family         = AF_INET,
+       .proto          = IPPROTO_ESP,
+       .match          = &match,
+       .matchsize      = sizeof(struct xt_esp),
+       .checkentry     = &checkentry,
+       .me             = THIS_MODULE,
+};
+
+static struct xt_match esp6_match = {
+       .name           = "esp",
+       .family         = AF_INET6,
+       .proto          = IPPROTO_ESP,
+       .match          = &match,
+       .matchsize      = sizeof(struct xt_esp),
+       .checkentry     = &checkentry,
+       .me             = THIS_MODULE,
+};
+
+static int __init xt_esp_init(void)
+{
+       int ret;
+       ret = xt_register_match(&esp_match);
+       if (ret)
+               return ret;
+
+       ret = xt_register_match(&esp6_match);
+       if (ret)
+               xt_unregister_match(&esp_match);
+
+       return ret;
+}
+
+static void __exit xt_esp_cleanup(void)
+{
+       xt_unregister_match(&esp_match);
+       xt_unregister_match(&esp6_match);
+}
+
+module_init(xt_esp_init);
+module_exit(xt_esp_cleanup);
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
new file mode 100644 (file)
index 0000000..b56cd2b
--- /dev/null
@@ -0,0 +1,314 @@
+/* Kernel module to match one of a list of TCP/UDP ports: ports are in
+   the same place so we can treat them as equal. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+
+#include <linux/netfilter/xt_multiport.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
+MODULE_DESCRIPTION("x_tables multiple port match module");
+MODULE_ALIAS("ipt_multiport");
+MODULE_ALIAS("ip6t_multiport");
+
+#if 0
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+/* Returns 1 if the port is matched by the test, 0 otherwise. */
+static inline int
+ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags,
+           u_int8_t count, u_int16_t src, u_int16_t dst)
+{
+       unsigned int i;
+       for (i = 0; i < count; i++) {
+               if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src)
+                       return 1;
+
+               if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst)
+                       return 1;
+       }
+
+       return 0;
+}
+
+/* Returns 1 if the port is matched by the test, 0 otherwise. */
+static inline int
+ports_match_v1(const struct xt_multiport_v1 *minfo,
+              u_int16_t src, u_int16_t dst)
+{
+       unsigned int i;
+       u_int16_t s, e;
+
+       for (i = 0; i < minfo->count; i++) {
+               s = minfo->ports[i];
+
+               if (minfo->pflags[i]) {
+                       /* range port matching */
+                       e = minfo->ports[++i];
+                       duprintf("src or dst matches with %d-%d?\n", s, e);
+
+                       if (minfo->flags == XT_MULTIPORT_SOURCE
+                           && src >= s && src <= e)
+                               return 1 ^ minfo->invert;
+                       if (minfo->flags == XT_MULTIPORT_DESTINATION
+                           && dst >= s && dst <= e)
+                               return 1 ^ minfo->invert;
+                       if (minfo->flags == XT_MULTIPORT_EITHER
+                           && ((dst >= s && dst <= e)
+                               || (src >= s && src <= e)))
+                               return 1 ^ minfo->invert;
+               } else {
+                       /* exact port matching */
+                       duprintf("src or dst matches with %d?\n", s);
+
+                       if (minfo->flags == XT_MULTIPORT_SOURCE
+                           && src == s)
+                               return 1 ^ minfo->invert;
+                       if (minfo->flags == XT_MULTIPORT_DESTINATION
+                           && dst == s)
+                               return 1 ^ minfo->invert;
+                       if (minfo->flags == XT_MULTIPORT_EITHER
+                           && (src == s || dst == s))
+                               return 1 ^ minfo->invert;
+               }
+       }
+
+       return minfo->invert;
+}
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const struct xt_match *match,
+      const void *matchinfo,
+      int offset,
+      unsigned int protoff,
+      int *hotdrop)
+{
+       u16 _ports[2], *pptr;
+       const struct xt_multiport *multiinfo = matchinfo;
+
+       if (offset)
+               return 0;
+
+       pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
+       if (pptr == NULL) {
+               /* We've been asked to examine this packet, and we
+                * can't.  Hence, no choice but to drop.
+                */
+               duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
+               *hotdrop = 1;
+               return 0;
+       }
+
+       return ports_match(multiinfo->ports,
+                          multiinfo->flags, multiinfo->count,
+                          ntohs(pptr[0]), ntohs(pptr[1]));
+}
+
+static int
+match_v1(const struct sk_buff *skb,
+        const struct net_device *in,
+        const struct net_device *out,
+        const struct xt_match *match,
+        const void *matchinfo,
+        int offset,
+        unsigned int protoff,
+        int *hotdrop)
+{
+       u16 _ports[2], *pptr;
+       const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+       if (offset)
+               return 0;
+
+       pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
+       if (pptr == NULL) {
+               /* We've been asked to examine this packet, and we
+                * can't.  Hence, no choice but to drop.
+                */
+               duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
+               *hotdrop = 1;
+               return 0;
+       }
+
+       return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
+}
+
+static inline int
+check(u_int16_t proto,
+      u_int8_t ip_invflags,
+      u_int8_t match_flags,
+      u_int8_t count)
+{
+       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
+       return (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
+               && !(ip_invflags & XT_INV_PROTO)
+               && (match_flags == XT_MULTIPORT_SOURCE
+                   || match_flags == XT_MULTIPORT_DESTINATION
+                   || match_flags == XT_MULTIPORT_EITHER)
+               && count <= XT_MULTI_PORTS;
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+checkentry(const char *tablename,
+          const void *info,
+          const struct xt_match *match,
+          void *matchinfo,
+          unsigned int matchsize,
+          unsigned int hook_mask)
+{
+       const struct ipt_ip *ip = info;
+       const struct xt_multiport *multiinfo = matchinfo;
+
+       return check(ip->proto, ip->invflags, multiinfo->flags,
+                    multiinfo->count);
+}
+
+static int
+checkentry_v1(const char *tablename,
+             const void *info,
+             const struct xt_match *match,
+             void *matchinfo,
+             unsigned int matchsize,
+             unsigned int hook_mask)
+{
+       const struct ipt_ip *ip = info;
+       const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+       return check(ip->proto, ip->invflags, multiinfo->flags,
+                    multiinfo->count);
+}
+
+static int
+checkentry6(const char *tablename,
+           const void *info,
+           const struct xt_match *match,
+           void *matchinfo,
+           unsigned int matchsize,
+           unsigned int hook_mask)
+{
+       const struct ip6t_ip6 *ip = info;
+       const struct xt_multiport *multiinfo = matchinfo;
+
+       return check(ip->proto, ip->invflags, multiinfo->flags,
+                    multiinfo->count);
+}
+
+static int
+checkentry6_v1(const char *tablename,
+              const void *info,
+              const struct xt_match *match,
+              void *matchinfo,
+              unsigned int matchsize,
+              unsigned int hook_mask)
+{
+       const struct ip6t_ip6 *ip = info;
+       const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+       return check(ip->proto, ip->invflags, multiinfo->flags,
+                    multiinfo->count);
+}
+
+static struct xt_match multiport_match = {
+       .name           = "multiport",
+       .revision       = 0,
+       .matchsize      = sizeof(struct xt_multiport),
+       .match          = &match,
+       .checkentry     = &checkentry,
+       .family         = AF_INET,
+       .me             = THIS_MODULE,
+};
+
+static struct xt_match multiport_match_v1 = {
+       .name           = "multiport",
+       .revision       = 1,
+       .matchsize      = sizeof(struct xt_multiport_v1),
+       .match          = &match_v1,
+       .checkentry     = &checkentry_v1,
+       .family         = AF_INET,
+       .me             = THIS_MODULE,
+};
+
+static struct xt_match multiport6_match = {
+       .name           = "multiport",
+       .revision       = 0,
+       .matchsize      = sizeof(struct xt_multiport),
+       .match          = &match,
+       .checkentry     = &checkentry6,
+       .family         = AF_INET6,
+       .me             = THIS_MODULE,
+};
+
+static struct xt_match multiport6_match_v1 = {
+       .name           = "multiport",
+       .revision       = 1,
+       .matchsize      = sizeof(struct xt_multiport_v1),
+       .match          = &match_v1,
+       .checkentry     = &checkentry6_v1,
+       .family         = AF_INET6,
+       .me             = THIS_MODULE,
+};
+
+static int __init xt_multiport_init(void)
+{
+       int ret;
+
+       ret = xt_register_match(&multiport_match);
+       if (ret)
+               goto out;
+
+       ret = xt_register_match(&multiport_match_v1);
+       if (ret)
+               goto out_unreg_multi_v0;
+
+       ret = xt_register_match(&multiport6_match);
+       if (ret)
+               goto out_unreg_multi_v1;
+
+       ret = xt_register_match(&multiport6_match_v1);
+       if (ret)
+               goto out_unreg_multi6_v0;
+
+       return ret;
+
+out_unreg_multi6_v0:
+       xt_unregister_match(&multiport6_match);
+out_unreg_multi_v1:
+       xt_unregister_match(&multiport_match_v1);
+out_unreg_multi_v0:
+       xt_unregister_match(&multiport_match);
+out:
+       return ret;
+}
+
+static void __exit xt_multiport_fini(void)
+{
+       xt_unregister_match(&multiport_match);
+       xt_unregister_match(&multiport_match_v1);
+       xt_unregister_match(&multiport6_match);
+       xt_unregister_match(&multiport6_match_v1);
+}
+
+module_init(xt_multiport_init);
+module_exit(xt_multiport_fini);
index 1099cb0..a3aa62f 100644 (file)
@@ -71,7 +71,7 @@ match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info,
                        return 0;
                e = &info->pol[pos];
 
-               if (match_xfrm_state(sp->x[i].xvec, e, family)) {
+               if (match_xfrm_state(sp->xvec[i], e, family)) {
                        if (!strict)
                                return 1;
                } else if (strict)
index b13042f..b807f36 100644 (file)
@@ -1418,7 +1418,8 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
        newfd = sock_alloc_fd(&newfile);
        if (unlikely(newfd < 0)) {
                err = newfd;
-               goto out_release;
+               sock_release(newsock);
+               goto out_put;
        }
 
        err = sock_attach_fd(newsock, newfile);
@@ -1455,10 +1456,8 @@ out_put:
 out:
        return err;
 out_fd:
-       put_filp(newfile);
+       fput(newfile);
        put_unused_fd(newfd);
-out_release:
-       sock_release(newsock);
        goto out_put;
 }
 
index 2407a70..b549710 100644 (file)
@@ -18,7 +18,7 @@ void __secpath_destroy(struct sec_path *sp)
 {
        int i;
        for (i = 0; i < sp->len; i++)
-               xfrm_state_put(sp->x[i].xvec);
+               xfrm_state_put(sp->xvec[i]);
        kmem_cache_free(secpath_cachep, sp);
 }
 EXPORT_SYMBOL(__secpath_destroy);
@@ -37,7 +37,7 @@ struct sec_path *secpath_dup(struct sec_path *src)
 
                memcpy(sp, src, sizeof(*sp));
                for (i = 0; i < sp->len; i++)
-                       xfrm_state_hold(sp->x[i].xvec);
+                       xfrm_state_hold(sp->xvec[i]);
        }
        atomic_set(&sp->refcnt, 1);
        return sp;
index f5eae9f..c3725fe 100644 (file)
@@ -943,9 +943,9 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
        } else
                start = -1;
        for (; idx < sp->len; idx++) {
-               if (xfrm_state_ok(tmpl, sp->x[idx].xvec, family))
+               if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
                        return ++idx;
-               if (sp->x[idx].xvec->props.mode)
+               if (sp->xvec[idx]->props.mode)
                        break;
        }
        return start;
@@ -968,7 +968,7 @@ EXPORT_SYMBOL(xfrm_decode_session);
 static inline int secpath_has_tunnel(struct sec_path *sp, int k)
 {
        for (; k < sp->len; k++) {
-               if (sp->x[k].xvec->props.mode)
+               if (sp->xvec[k]->props.mode)
                        return 1;
        }
 
@@ -994,8 +994,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                int i;
 
                for (i=skb->sp->len-1; i>=0; i--) {
-                       struct sec_decap_state *xvec = &(skb->sp->x[i]);
-                       if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
+                       struct xfrm_state *x = skb->sp->xvec[i];
+                       if (!xfrm_selector_match(&x->sel, &fl, family))
                                return 0;
                }
        }
index 77caf43..adfdce7 100644 (file)
@@ -57,18 +57,12 @@ static struct snd_card *card_list[SNDRV_CARDS];
 /*
  * prototypes
  */
-static void pdacf_config(dev_link_t *link);
+static int pdacf_config(struct pcmcia_device *link);
 static void snd_pdacf_detach(struct pcmcia_device *p_dev);
 
-static void pdacf_release(dev_link_t *link)
+static void pdacf_release(struct pcmcia_device *link)
 {
-       if (link->state & DEV_CONFIG) {
-               /* release cs resources */
-               pcmcia_release_configuration(link->handle);
-               pcmcia_release_io(link->handle, &link->io);
-               pcmcia_release_irq(link->handle, &link->irq);
-               link->state &= ~DEV_CONFIG;
-       }
+       pcmcia_disable_device(link);
 }
 
 /*
@@ -76,7 +70,7 @@ static void pdacf_release(dev_link_t *link)
  */
 static int snd_pdacf_free(struct snd_pdacf *pdacf)
 {
-       dev_link_t *link = &pdacf->link;
+       struct pcmcia_device *link = pdacf->p_dev;
 
        pdacf_release(link);
 
@@ -96,10 +90,9 @@ static int snd_pdacf_dev_free(struct snd_device *device)
 /*
  * snd_pdacf_attach - attach callback for cs
  */
-static int snd_pdacf_attach(struct pcmcia_device *p_dev)
+static int snd_pdacf_probe(struct pcmcia_device *link)
 {
        int i;
-       dev_link_t *link;               /* Info for cardmgr */
        struct snd_pdacf *pdacf;
        struct snd_card *card;
        static struct snd_device_ops ops = {
@@ -139,7 +132,7 @@ static int snd_pdacf_attach(struct pcmcia_device *p_dev)
        pdacf->index = i;
        card_list[i] = card;
 
-       link = &pdacf->link;
+       pdacf->p_dev = link;
        link->priv = pdacf;
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -156,13 +149,7 @@ static int snd_pdacf_attach(struct pcmcia_device *p_dev)
        link->conf.ConfigIndex = 1;
        link->conf.Present = PRESENT_OPTION;
 
-       /* Chain drivers */
-       link->next = NULL;
-
-       link->handle = p_dev;
-       pdacf_config(link);
-
-       return 0;
+       return pdacf_config(link);
 }
 
 
@@ -209,9 +196,8 @@ static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq
 /*
  * snd_pdacf_detach - detach callback for cs
  */
-static void snd_pdacf_detach(struct pcmcia_device *p_dev)
+static void snd_pdacf_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct snd_pdacf *chip = link->priv;
 
        snd_printdd(KERN_DEBUG "pdacf_detach called\n");
@@ -230,13 +216,11 @@ static void snd_pdacf_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void pdacf_config(dev_link_t *link)
+static int pdacf_config(struct pcmcia_device *link)
 {
-       client_handle_t handle = link->handle;
        struct snd_pdacf *pdacf = link->priv;
        tuple_t tuple;
        cisparse_t *parse = NULL;
-       config_info_t conf;
        u_short buf[32];
        int last_fn, last_ret;
 
@@ -244,7 +228,7 @@ static void pdacf_config(dev_link_t *link)
        parse = kmalloc(sizeof(*parse), GFP_KERNEL);
        if (! parse) {
                snd_printk(KERN_ERR "pdacf_config: cannot allocate\n");
-               return;
+               return -ENOMEM;
        }
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
        tuple.Attributes = 0;
@@ -252,71 +236,51 @@ static void pdacf_config(dev_link_t *link)
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
        tuple.DesiredTuple = CISTPL_CONFIG;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
        link->conf.ConfigBase = parse->config.base;
        link->conf.ConfigIndex = 0x5;
        kfree(parse);
 
-       CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-       link->conf.Vcc = conf.Vcc;
-
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
-       CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
-       CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+       CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+       CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
        if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
                goto failed;
 
-       link->dev = &pdacf->node;
-       link->state &= ~DEV_CONFIG_PENDING;
-       return;
+       link->dev_node = &pdacf->node;
+       return 0;
 
 cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 failed:
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
+       pcmcia_disable_device(link);
+       return -ENODEV;
 }
 
 #ifdef CONFIG_PM
 
-static int pdacf_suspend(struct pcmcia_device *dev)
+static int pdacf_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        struct snd_pdacf *chip = link->priv;
 
        snd_printdd(KERN_DEBUG "SUSPEND\n");
-       link->state |= DEV_SUSPEND;
        if (chip) {
                snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
                snd_pdacf_suspend(chip, PMSG_SUSPEND);
        }
 
-       snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
-
        return 0;
 }
 
-static int pdacf_resume(struct pcmcia_device *dev)
+static int pdacf_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        struct snd_pdacf *chip = link->priv;
 
        snd_printdd(KERN_DEBUG "RESUME\n");
-       link->state &= ~DEV_SUSPEND;
-
-       snd_printdd(KERN_DEBUG "CARD_RESET\n");
-       if (DEV_OK(link)) {
-               snd_printdd(KERN_DEBUG "requestconfig...\n");
-               pcmcia_request_configuration(link->handle, &link->conf);
+       if (pcmcia_dev_present(link)) {
                if (chip) {
                        snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
                        snd_pdacf_resume(chip);
@@ -343,7 +307,7 @@ static struct pcmcia_driver pdacf_cs_driver = {
        .drv            = {
                .name   = "snd-pdaudiocf",
        },
-       .probe          = snd_pdacf_attach,
+       .probe          = snd_pdacf_probe,
        .remove         = snd_pdacf_detach,
        .id_table       = snd_pdacf_ids,
 #ifdef CONFIG_PM
index 2744f18..9a14a4f 100644 (file)
@@ -116,7 +116,7 @@ struct snd_pdacf {
        void *pcm_area;
        
        /* pcmcia stuff */
-       dev_link_t link;
+       struct pcmcia_device    *p_dev;
        dev_node_t node;
 };
 
index 66900d2..7e0cda2 100644 (file)
@@ -59,15 +59,9 @@ static unsigned int card_alloc;
 
 /*
  */
-static void vxpocket_release(dev_link_t *link)
+static void vxpocket_release(struct pcmcia_device *link)
 {
-       if (link->state & DEV_CONFIG) {
-               /* release cs resources */
-               pcmcia_release_configuration(link->handle);
-               pcmcia_release_io(link->handle, &link->io);
-               pcmcia_release_irq(link->handle, &link->irq);
-               link->state &= ~DEV_CONFIG;
-       }
+       pcmcia_disable_device(link);
 }
 
 /*
@@ -132,9 +126,9 @@ static struct snd_vx_hardware vxp440_hw = {
 /*
  * create vxpocket instance
  */
-static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
+static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl,
+                                            struct pcmcia_device *link)
 {
-       dev_link_t *link;               /* Info for cardmgr */
        struct vx_core *chip;
        struct snd_vxpocket *vxp;
        static struct snd_device_ops ops = {
@@ -154,7 +148,7 @@ static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
 
        vxp = (struct snd_vxpocket *)chip;
 
-       link = &vxp->link;
+       vxp->p_dev = link;
        link->priv = chip;
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -167,7 +161,6 @@ static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
        link->irq.Instance = chip;
 
        link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.Vcc = 50;
        link->conf.IntType = INT_MEMORY_AND_IO;
        link->conf.ConfigIndex = 1;
        link->conf.Present = PRESENT_OPTION;
@@ -215,9 +208,8 @@ static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void vxpocket_config(dev_link_t *link)
+static int vxpocket_config(struct pcmcia_device *link)
 {
-       client_handle_t handle = link->handle;
        struct vx_core *chip = link->priv;
        struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
        tuple_t tuple;
@@ -229,24 +221,24 @@ static void vxpocket_config(dev_link_t *link)
        parse = kmalloc(sizeof(*parse), GFP_KERNEL);
        if (! parse) {
                snd_printk(KERN_ERR "vx: cannot allocate\n");
-               return;
+               return -ENOMEM;
        }
        tuple.Attributes = 0;
        tuple.TupleData = (cisdata_t *)buf;
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
        tuple.DesiredTuple = CISTPL_CONFIG;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
        link->conf.ConfigBase = parse->config.base;
        link->conf.Present = parse->config.rmask[0];
 
        /* redefine hardware record according to the VERSION1 string */
        tuple.DesiredTuple = CISTPL_VERS_1;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
        if (! strcmp(parse->version_1.str + parse->version_1.ofs[1], "VX-POCKET")) {
                snd_printdd("VX-pocket is detected\n");
        } else {
@@ -257,67 +249,50 @@ static void vxpocket_config(dev_link_t *link)
                strcpy(chip->card->driver, vxp440_hw.name);
        }
 
-       /* Configure card */
-       link->state |= DEV_CONFIG;
-
-       CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
-       CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+       CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+       CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
-       chip->dev = &handle_to_dev(link->handle);
+       chip->dev = &handle_to_dev(link);
        snd_card_set_dev(chip->card, chip->dev);
 
        if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
                goto failed;
 
-       link->dev = &vxp->node;
-       link->state &= ~DEV_CONFIG_PENDING;
+       link->dev_node = &vxp->node;
        kfree(parse);
-       return;
+       return 9;
 
 cs_failed:
-       cs_error(link->handle, last_fn, last_ret);
+       cs_error(link, last_fn, last_ret);
 failed:
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
-       pcmcia_release_irq(link->handle, &link->irq);
-       link->state &= ~DEV_CONFIG;
+       pcmcia_disable_device(link);
        kfree(parse);
+       return -ENODEV;
 }
 
 #ifdef CONFIG_PM
 
-static int vxp_suspend(struct pcmcia_device *dev)
+static int vxp_suspend(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        struct vx_core *chip = link->priv;
 
        snd_printdd(KERN_DEBUG "SUSPEND\n");
-       link->state |= DEV_SUSPEND;
        if (chip) {
                snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
                snd_vx_suspend(chip, PMSG_SUSPEND);
        }
-       snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
 
        return 0;
 }
 
-static int vxp_resume(struct pcmcia_device *dev)
+static int vxp_resume(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(dev);
        struct vx_core *chip = link->priv;
 
        snd_printdd(KERN_DEBUG "RESUME\n");
-       link->state &= ~DEV_SUSPEND;
-
-       snd_printdd(KERN_DEBUG "CARD_RESET\n");
-       if (DEV_OK(link)) {
+       if (pcmcia_dev_present(link)) {
                //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
-               snd_printdd(KERN_DEBUG "requestconfig...\n");
-               pcmcia_request_configuration(link->handle, &link->conf);
                if (chip) {
                        snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
                        snd_vx_resume(chip);
@@ -333,7 +308,7 @@ static int vxp_resume(struct pcmcia_device *dev)
 
 /*
  */
-static int vxpocket_attach(struct pcmcia_device *p_dev)
+static int vxpocket_probe(struct pcmcia_device *p_dev)
 {
        struct snd_card *card;
        struct snd_vxpocket *vxp;
@@ -358,7 +333,7 @@ static int vxpocket_attach(struct pcmcia_device *p_dev)
                return -ENOMEM;
        }
 
-       vxp = snd_vxpocket_new(card, ibl[i]);
+       vxp = snd_vxpocket_new(card, ibl[i], p_dev);
        if (! vxp) {
                snd_card_free(card);
                return -ENODEV;
@@ -368,20 +343,13 @@ static int vxpocket_attach(struct pcmcia_device *p_dev)
        vxp->index = i;
        card_alloc |= 1 << i;
 
-       /* Chain drivers */
-       vxp->link.next = NULL;
-
-       vxp->link.handle = p_dev;
-       vxp->link.state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-       p_dev->instance = &vxp->link;
-       vxpocket_config(&vxp->link);
+       vxp->p_dev = p_dev;
 
-       return 0;
+       return vxpocket_config(p_dev);
 }
 
-static void vxpocket_detach(struct pcmcia_device *p_dev)
+static void vxpocket_detach(struct pcmcia_device *link)
 {
-       dev_link_t *link = dev_to_instance(p_dev);
        struct snd_vxpocket *vxp;
        struct vx_core *chip;
 
@@ -413,7 +381,7 @@ static struct pcmcia_driver vxp_cs_driver = {
        .drv            = {
                .name   = "snd-vxpocket",
        },
-       .probe          = vxpocket_attach,
+       .probe          = vxpocket_probe,
        .remove         = vxpocket_detach,
        .id_table       = vxp_ids,
 #ifdef CONFIG_PM
index 67efae3..27ea002 100644 (file)
@@ -42,7 +42,7 @@ struct snd_vxpocket {
        int index;      /* card index */
 
        /* pcmcia stuff */
-       dev_link_t link;
+       struct pcmcia_device    *p_dev;
        dev_node_t node;
 };