aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/SubmittingDrivers7
-rw-r--r--Documentation/cpusets.txt8
-rw-r--r--Documentation/kernel-docs.txt7
-rw-r--r--Documentation/oops-tracing.txt32
-rw-r--r--Documentation/power/devices.txt2
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl22
-rw-r--r--Documentation/sysrq.txt2
-rw-r--r--Documentation/usb/usbmon.txt156
-rw-r--r--MAINTAINERS16
-rw-r--r--arch/arm/kernel/vmlinux.lds.S4
-rw-r--r--arch/arm/mach-footbridge/cats-hw.c1
-rw-r--r--arch/arm/mach-omap/usb.c4
-rw-r--r--arch/frv/Kconfig146
-rw-r--r--arch/frv/Kconfig.debug74
-rw-r--r--arch/frv/kernel/setup.c3
-rw-r--r--arch/frv/kernel/signal.c1
-rw-r--r--arch/i386/kernel/cpu/common.c11
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c456
-rw-r--r--arch/i386/kernel/entry.S130
-rw-r--r--arch/i386/kernel/head.S2
-rw-r--r--arch/i386/kernel/kprobes.c19
-rw-r--r--arch/i386/kernel/process.c29
-rw-r--r--arch/i386/kernel/smp.c2
-rw-r--r--arch/i386/kernel/traps.c45
-rw-r--r--arch/m32r/kernel/setup.c31
-rw-r--r--arch/m32r/mm/discontig.c1
-rw-r--r--arch/ppc/Kconfig2
-rw-r--r--arch/ppc/boot/simple/mpc52xx_tty.c30
-rw-r--r--arch/ppc/kernel/entry.S91
-rw-r--r--arch/ppc/kernel/head_44x.S77
-rw-r--r--arch/ppc/kernel/head_4xx.S44
-rw-r--r--arch/ppc/kernel/head_booke.h139
-rw-r--r--arch/ppc/kernel/head_e500.S81
-rw-r--r--arch/ppc/platforms/85xx/mpc8560_ads.c18
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.c19
-rw-r--r--arch/ppc/platforms/85xx/stx_gp3.c21
-rw-r--r--arch/ppc/platforms/Makefile2
-rw-r--r--arch/ppc/platforms/lite5200.c87
-rw-r--r--arch/ppc/platforms/lite5200.h2
-rw-r--r--arch/ppc/platforms/pmac_backlight.c80
-rw-r--r--arch/ppc/syslib/Makefile3
-rw-r--r--arch/ppc/syslib/cpm2_pic.c94
-rw-r--r--arch/ppc/syslib/cpm2_pic.h3
-rw-r--r--arch/ppc/syslib/m8260_setup.c8
-rw-r--r--arch/ppc/syslib/mpc52xx_devices.c318
-rw-r--r--arch/ppc/syslib/mpc52xx_pci.c2
-rw-r--r--arch/ppc/syslib/mpc52xx_pic.c4
-rw-r--r--arch/ppc/syslib/mpc52xx_setup.c42
-rw-r--r--arch/ppc/syslib/mpc52xx_sys.c38
-rw-r--r--arch/ppc/syslib/mpc85xx_sys.c8
-rw-r--r--arch/ppc64/Kconfig17
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c40
-rw-r--r--arch/ppc64/kernel/kprobes.c15
-rw-r--r--arch/ppc64/kernel/lmb.c26
-rw-r--r--arch/ppc64/kernel/prom.c15
-rw-r--r--arch/ppc64/kernel/prom_init.c137
-rw-r--r--arch/ppc64/kernel/ptrace.c3
-rw-r--r--arch/ppc64/kernel/setup.c20
-rw-r--r--arch/ppc64/mm/hash_utils.c23
-rw-r--r--arch/ppc64/mm/numa.c46
-rw-r--r--arch/s390/mm/fault.c2
-rw-r--r--arch/sparc64/kernel/kprobes.c18
-rw-r--r--arch/um/Kconfig.debug2
-rw-r--r--arch/um/drivers/chan_kern.c5
-rw-r--r--arch/um/drivers/line.c2
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h16
-rw-r--r--arch/um/include/sysdep-i386/syscalls.h16
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h6
-rw-r--r--arch/um/include/sysdep-x86_64/syscalls.h5
-rw-r--r--arch/um/kernel/sigio_user.c29
-rw-r--r--arch/um/kernel/skas/uaccess.c3
-rw-r--r--arch/um/kernel/sys_call_table.c15
-rw-r--r--arch/um/kernel/um_arch.c2
-rw-r--r--arch/x86_64/ia32/sys_ia32.c1
-rw-r--r--arch/x86_64/kernel/kprobes.c160
-rw-r--r--arch/x86_64/kernel/process.c41
-rw-r--r--arch/x86_64/kernel/smp.c5
-rw-r--r--arch/x86_64/kernel/sys_x86_64.c1
-rw-r--r--drivers/base/power/suspend.c2
-rw-r--r--drivers/block/ll_rw_blk.c2
-rw-r--r--drivers/block/rd.c4
-rw-r--r--drivers/block/ub.c81
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/agp/via-agp.c6
-rw-r--r--drivers/char/mem.c31
-rw-r--r--drivers/char/rio/riocmd.c67
-rw-r--r--drivers/char/sx.c60
-rw-r--r--drivers/char/sysrq.c23
-rw-r--r--drivers/char/vt.c18
-rw-r--r--drivers/ide/ide-disk.c2
-rw-r--r--drivers/macintosh/via-pmu.c2
-rw-r--r--drivers/media/dvb/frontends/cx24110.c28
-rw-r--r--drivers/media/video/cpia_usb.c4
-rw-r--r--drivers/media/video/zr36050.c2
-rw-r--r--drivers/message/fusion/mptbase.h4
-rw-r--r--drivers/message/fusion/mptscsih.c92
-rw-r--r--drivers/message/fusion/mptscsih.h8
-rw-r--r--drivers/mmc/mmc_block.c2
-rw-r--r--drivers/mmc/mmc_sysfs.c2
-rw-r--r--drivers/net/b44.c36
-rw-r--r--drivers/net/b44.h3
-rw-r--r--drivers/net/e1000/e1000.h1
-rw-r--r--drivers/net/e1000/e1000_main.c21
-rw-r--r--drivers/net/macsonic.c1
-rw-r--r--drivers/net/pcnet32.c3
-rw-r--r--drivers/net/s2io-regs.h2
-rw-r--r--drivers/net/s2io.c245
-rw-r--r--drivers/net/s2io.h119
-rw-r--r--drivers/parport/parport_pc.c8
-rw-r--r--drivers/pci/pci.c12
-rw-r--r--drivers/pcmcia/cs.c2
-rw-r--r--drivers/pcmcia/i82092.c2
-rw-r--r--drivers/pcmcia/i82365.c2
-rw-r--r--drivers/pcmcia/pd6729.c2
-rw-r--r--drivers/pcmcia/tcic.c2
-rw-r--r--drivers/pcmcia/yenta_socket.c2
-rw-r--r--drivers/scsi/3w-9xxx.c512
-rw-r--r--drivers/scsi/3w-9xxx.h88
-rw-r--r--drivers/scsi/3w-xxxx.c366
-rw-r--r--drivers/scsi/3w-xxxx.h3
-rw-r--r--drivers/scsi/53c700.c25
-rw-r--r--drivers/scsi/53c700.h4
-rw-r--r--drivers/scsi/NCR_D700.c41
-rw-r--r--drivers/scsi/NCR_Q720.c2
-rw-r--r--drivers/scsi/aacraid/aachba.c149
-rw-r--r--drivers/scsi/aacraid/aacraid.h193
-rw-r--r--drivers/scsi/aacraid/commctrl.c12
-rw-r--r--drivers/scsi/aacraid/comminit.c2
-rw-r--r--drivers/scsi/aacraid/commsup.c25
-rw-r--r--drivers/scsi/aacraid/rkt.c21
-rw-r--r--drivers/scsi/aacraid/rx.c18
-rw-r--r--drivers/scsi/aacraid/sa.c28
-rw-r--r--drivers/scsi/atp870u.c341
-rw-r--r--drivers/scsi/hosts.c17
-rw-r--r--drivers/scsi/lasi700.c17
-rw-r--r--drivers/scsi/ncr53c8xx.c508
-rw-r--r--drivers/scsi/osst.c7
-rw-r--r--drivers/scsi/scsi_error.c6
-rw-r--r--drivers/scsi/scsi_lib.c36
-rw-r--r--drivers/scsi/scsi_scan.c3
-rw-r--r--drivers/scsi/scsi_sysfs.c22
-rw-r--r--drivers/scsi/scsi_transport_fc.c8
-rw-r--r--drivers/scsi/scsi_transport_spi.c9
-rw-r--r--drivers/scsi/sim710.c12
-rw-r--r--drivers/scsi/sym53c8xx_defs.h54
-rw-r--r--drivers/scsi/zalon.c23
-rw-r--r--drivers/serial/8250.c2
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/serial/imx.c7
-rw-r--r--drivers/serial/mpc52xx_uart.c189
-rw-r--r--drivers/usb/Makefile2
-rw-r--r--drivers/usb/class/usb-midi.c6
-rw-r--r--drivers/usb/core/buffer.c2
-rw-r--r--drivers/usb/core/config.c6
-rw-r--r--drivers/usb/core/devices.c7
-rw-r--r--drivers/usb/core/hcd-pci.c14
-rw-r--r--drivers/usb/core/hcd.c112
-rw-r--r--drivers/usb/core/hcd.h38
-rw-r--r--drivers/usb/core/hub.c55
-rw-r--r--drivers/usb/core/hub.h2
-rw-r--r--drivers/usb/core/message.c10
-rw-r--r--drivers/usb/core/usb.c41
-rw-r--r--drivers/usb/core/usb.h8
-rw-r--r--drivers/usb/gadget/Kconfig77
-rw-r--r--drivers/usb/gadget/config.c1
-rw-r--r--drivers/usb/gadget/dummy_hcd.c6
-rw-r--r--drivers/usb/gadget/ether.c252
-rw-r--r--drivers/usb/gadget/file_storage.c63
-rw-r--r--drivers/usb/gadget/gadget_chips.h7
-rw-r--r--drivers/usb/gadget/inode.c29
-rw-r--r--drivers/usb/gadget/net2280.c2
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c279
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.h29
-rw-r--r--drivers/usb/gadget/rndis.c169
-rw-r--r--drivers/usb/gadget/rndis.h162
-rw-r--r--drivers/usb/gadget/serial.c3
-rw-r--r--drivers/usb/gadget/usbstring.c4
-rw-r--r--drivers/usb/gadget/zero.c50
-rw-r--r--drivers/usb/host/ehci-hcd.c26
-rw-r--r--drivers/usb/host/ehci-hub.c10
-rw-r--r--drivers/usb/host/ehci-q.c23
-rw-r--r--drivers/usb/host/ehci-sched.c43
-rw-r--r--drivers/usb/host/ehci.h2
-rw-r--r--drivers/usb/host/ohci-dbg.c6
-rw-r--r--drivers/usb/host/ohci-hcd.c24
-rw-r--r--drivers/usb/host/ohci-hub.c19
-rw-r--r--drivers/usb/host/ohci-omap.c123
-rw-r--r--drivers/usb/host/ohci-q.c12
-rw-r--r--drivers/usb/host/ohci.h10
-rw-r--r--drivers/usb/host/sl811-hcd.c16
-rw-r--r--drivers/usb/host/uhci-debug.c4
-rw-r--r--drivers/usb/host/uhci-hcd.c140
-rw-r--r--drivers/usb/host/uhci-hcd.h37
-rw-r--r--drivers/usb/host/uhci-hub.c46
-rw-r--r--drivers/usb/host/uhci-q.c107
-rw-r--r--drivers/usb/image/Kconfig11
-rw-r--r--drivers/usb/image/Makefile1
-rw-r--r--drivers/usb/image/hpusbscsi.c523
-rw-r--r--drivers/usb/image/hpusbscsi.h73
-rw-r--r--drivers/usb/image/microtek.c8
-rw-r--r--drivers/usb/input/aiptek.c2
-rw-r--r--drivers/usb/media/ibmcam.c3
-rw-r--r--drivers/usb/media/pwc/pwc-ctrl.c10
-rw-r--r--drivers/usb/media/pwc/pwc-dec23.c4
-rw-r--r--drivers/usb/media/pwc/pwc-if.c43
-rw-r--r--drivers/usb/media/usbvideo.c6
-rw-r--r--drivers/usb/misc/emi26.c2
-rw-r--r--drivers/usb/misc/rio500.c12
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c17
-rw-r--r--drivers/usb/misc/usblcd.c528
-rw-r--r--drivers/usb/misc/usbtest.c2
-rw-r--r--drivers/usb/mon/mon_text.c14
-rw-r--r--drivers/usb/net/catc.c3
-rw-r--r--drivers/usb/net/kaweth.c2
-rw-r--r--drivers/usb/net/kawethfw.h8
-rw-r--r--drivers/usb/net/pegasus.c304
-rw-r--r--drivers/usb/net/pegasus.h4
-rw-r--r--drivers/usb/net/usbnet.c407
-rw-r--r--drivers/usb/net/zd1201.c4
-rw-r--r--drivers/usb/net/zd1201.h4
-rw-r--r--drivers/usb/serial/Kconfig10
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/cp2101.c591
-rw-r--r--drivers/usb/serial/digi_acceleport.c29
-rw-r--r--drivers/usb/serial/ftdi_sio.c55
-rw-r--r--drivers/usb/serial/garmin_gps.c4
-rw-r--r--drivers/usb/serial/ipw.c4
-rw-r--r--drivers/usb/serial/kl5kusb105.c2
-rw-r--r--drivers/usb/serial/mct_u232.c22
-rw-r--r--drivers/usb/serial/usb-serial.c10
-rw-r--r--drivers/usb/serial/visor.c41
-rw-r--r--drivers/usb/serial/visor.h3
-rw-r--r--drivers/usb/storage/Kconfig22
-rw-r--r--drivers/usb/storage/datafab.c2
-rw-r--r--drivers/usb/storage/debug.h2
-rw-r--r--drivers/usb/storage/dpcm.c2
-rw-r--r--drivers/usb/storage/freecom.c2
-rw-r--r--drivers/usb/storage/initializers.c2
-rw-r--r--drivers/usb/storage/isd200.c2
-rw-r--r--drivers/usb/storage/jumpshot.c2
-rw-r--r--drivers/usb/storage/protocol.c3
-rw-r--r--drivers/usb/storage/protocol.h3
-rw-r--r--drivers/usb/storage/scsiglue.c111
-rw-r--r--drivers/usb/storage/scsiglue.h6
-rw-r--r--drivers/usb/storage/sddr09.c2
-rw-r--r--drivers/usb/storage/sddr55.c2
-rw-r--r--drivers/usb/storage/shuttle_usbat.c15
-rw-r--r--drivers/usb/storage/shuttle_usbat.h4
-rw-r--r--drivers/usb/storage/transport.c13
-rw-r--r--drivers/usb/storage/transport.h8
-rw-r--r--drivers/usb/storage/unusual_devs.h52
-rw-r--r--drivers/usb/storage/usb.c174
-rw-r--r--drivers/usb/storage/usb.h60
-rw-r--r--drivers/video/Kconfig31
-rw-r--r--drivers/video/Makefile14
-rw-r--r--drivers/video/asiliantfb.c2
-rw-r--r--drivers/video/aty/aty128fb.c8
-rw-r--r--drivers/video/aty/atyfb_base.c31
-rw-r--r--drivers/video/aty/radeon_accel.c28
-rw-r--r--drivers/video/aty/radeon_base.c67
-rw-r--r--drivers/video/aty/radeon_i2c.c6
-rw-r--r--drivers/video/aty/radeon_monitor.c33
-rw-r--r--drivers/video/aty/radeon_pm.c45
-rw-r--r--drivers/video/aty/radeonfb.h148
-rw-r--r--drivers/video/chipsfb.c2
-rw-r--r--drivers/video/cirrusfb.c2
-rw-r--r--drivers/video/console/bitblit.c11
-rw-r--r--drivers/video/console/fbcon.c86
-rw-r--r--drivers/video/console/fbcon.h8
-rw-r--r--drivers/video/console/mdacon.c4
-rw-r--r--drivers/video/console/sticore.c9
-rw-r--r--drivers/video/cyber2000fb.c4
-rw-r--r--drivers/video/fbmem.c9
-rw-r--r--drivers/video/fbmon.c23
-rw-r--r--drivers/video/i810/i810_main.c6
-rw-r--r--drivers/video/i810/i810_main.h2
-rw-r--r--drivers/video/igafb.c3
-rw-r--r--drivers/video/imsttfb.c2
-rw-r--r--drivers/video/intelfb/intelfbdrv.c2
-rw-r--r--drivers/video/kyro/fbdev.c2
-rw-r--r--drivers/video/macmodes.c9
-rw-r--r--drivers/video/matrox/matroxfb_accel.c14
-rw-r--r--drivers/video/matrox/matroxfb_base.h4
-rw-r--r--drivers/video/modedb.c4
-rw-r--r--drivers/video/neofb.c38
-rw-r--r--drivers/video/nvidia/nv_accel.c72
-rw-r--r--drivers/video/nvidia/nv_dma.h10
-rw-r--r--drivers/video/nvidia/nv_hw.c11
-rw-r--r--drivers/video/nvidia/nv_i2c.c2
-rw-r--r--drivers/video/nvidia/nv_local.h13
-rw-r--r--drivers/video/nvidia/nv_of.c1
-rw-r--r--drivers/video/nvidia/nv_proto.h2
-rw-r--r--drivers/video/nvidia/nv_setup.c10
-rw-r--r--drivers/video/nvidia/nvidia.c35
-rw-r--r--drivers/video/pm2fb.c4
-rw-r--r--drivers/video/pvr2fb.c2
-rw-r--r--drivers/video/pxafb.c3
-rw-r--r--drivers/video/radeonfb.c2
-rw-r--r--drivers/video/riva/fbdev.c6
-rw-r--r--drivers/video/s1d13xxxfb.c772
-rw-r--r--drivers/video/sa1100fb.c3
-rw-r--r--drivers/video/savage/savagefb_driver.c3
-rw-r--r--drivers/video/sis/sis_main.c4
-rw-r--r--drivers/video/sstfb.c2
-rw-r--r--drivers/video/tdfxfb.c2
-rw-r--r--drivers/video/tgafb.c2
-rw-r--r--drivers/video/tridentfb.c4
-rw-r--r--drivers/video/vga16fb.c24
-rw-r--r--drivers/video/w100fb.c6
-rw-r--r--fs/buffer.c2
-rw-r--r--fs/cifs/CHANGES16
-rw-r--r--fs/cifs/cifs_debug.c8
-rw-r--r--fs/cifs/cifsencrypt.h2
-rw-r--r--fs/cifs/cifsfs.c69
-rw-r--r--fs/cifs/cifsfs.h12
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/cifspdu.h19
-rw-r--r--fs/cifs/cifsproto.h7
-rw-r--r--fs/cifs/cifssmb.c156
-rw-r--r--fs/cifs/connect.c54
-rw-r--r--fs/cifs/file.c1104
-rw-r--r--fs/cifs/inode.c728
-rw-r--r--fs/cifs/misc.c10
-rw-r--r--fs/cifs/ntlmssp.h2
-rw-r--r--fs/cifs/readdir.c157
-rw-r--r--fs/fs-writeback.c4
-rw-r--r--fs/hostfs/hostfs_kern.c20
-rw-r--r--fs/hugetlbfs/inode.c2
-rw-r--r--fs/inode.c7
-rw-r--r--fs/nfs/dir.c2
-rw-r--r--fs/nfsd/nfs4acl.c40
-rw-r--r--fs/nfsd/nfs4callback.c2
-rw-r--r--fs/nfsd/nfs4proc.c60
-rw-r--r--fs/nfsd/nfs4state.c103
-rw-r--r--fs/nfsd/nfs4xdr.c5
-rw-r--r--fs/nfsd/vfs.c7
-rw-r--r--fs/ramfs/inode.c4
-rw-r--r--fs/sysfs/inode.c2
-rw-r--r--include/asm-arm/arch-s3c2410/regs-gpio.h7
-rw-r--r--include/asm-arm/atomic.h1
-rw-r--r--include/asm-arm/ipc.h30
-rw-r--r--include/asm-arm26/ipc.h29
-rw-r--r--include/asm-cris/ipc.h36
-rw-r--r--include/asm-frv/ipc.h34
-rw-r--r--include/asm-frv/tlbflush.h3
-rw-r--r--include/asm-generic/ipc.h31
-rw-r--r--include/asm-h8300/ipc.h32
-rw-r--r--include/asm-i386/desc.h4
-rw-r--r--include/asm-i386/ipc.h33
-rw-r--r--include/asm-i386/processor.h12
-rw-r--r--include/asm-i386/seccomp.h16
-rw-r--r--include/asm-i386/segment.h5
-rw-r--r--include/asm-m32r/ipc.h36
-rw-r--r--include/asm-m32r/spinlock.h6
-rw-r--r--include/asm-m68k/ipc.h32
-rw-r--r--include/asm-m68knommu/ipc.h2
-rw-r--r--include/asm-mips/ipc.h34
-rw-r--r--include/asm-ppc/cpm2.h2
-rw-r--r--include/asm-ppc/ipc.h30
-rw-r--r--include/asm-ppc/irq.h169
-rw-r--r--include/asm-ppc/mpc52xx.h113
-rw-r--r--include/asm-ppc/mpc85xx.h49
-rw-r--r--include/asm-ppc/ppc_sys.h2
-rw-r--r--include/asm-ppc64/ipc.h35
-rw-r--r--include/asm-ppc64/lmb.h1
-rw-r--r--include/asm-ppc64/seccomp.h21
-rw-r--r--include/asm-ppc64/thread_info.h4
-rw-r--r--include/asm-s390/ipc.h41
-rw-r--r--include/asm-sh/ipc.h33
-rw-r--r--include/asm-sh64/ipc.h7
-rw-r--r--include/asm-sparc/ipc.h33
-rw-r--r--include/asm-sparc64/ipc.h34
-rw-r--r--include/asm-v850/ipc.h32
-rw-r--r--include/asm-x86_64/ipc.h6
-rw-r--r--include/asm-x86_64/msr.h12
-rw-r--r--include/asm-x86_64/seccomp.h24
-rw-r--r--include/asm-x86_64/unistd.h2
-rw-r--r--include/linux/backing-dev.h41
-rw-r--r--include/linux/console.h1
-rw-r--r--include/linux/device.h2
-rw-r--r--include/linux/fb.h4
-rw-r--r--include/linux/mmc/card.h2
-rw-r--r--include/linux/pci_ids.h2
-rw-r--r--include/linux/seccomp.h1
-rw-r--r--include/linux/sunrpc/svcauth.h14
-rw-r--r--include/linux/usb.h4
-rw-r--r--include/linux/usb_cdc.h34
-rw-r--r--include/pcmcia/ss.h2
-rw-r--r--include/scsi/scsi_device.h1
-rw-r--r--include/scsi/scsi_host.h1
-rw-r--r--include/scsi/scsi_transport_fc.h3
-rw-r--r--include/sound/ac97_codec.h1
-rw-r--r--include/sound/asound.h1
-rw-r--r--include/sound/asoundef.h2
-rw-r--r--include/sound/core.h9
-rw-r--r--include/sound/emu10k1.h69
-rw-r--r--include/sound/rawmidi.h5
-rw-r--r--include/sound/seq_midi_emul.h4
-rw-r--r--include/sound/version.h4
-rw-r--r--include/video/s1d13xxxfb.h166
-rw-r--r--include/video/trident.h2
-rw-r--r--kernel/cpuset.c4
-rw-r--r--kernel/printk.c18
-rw-r--r--kernel/rcupdate.c6
-rw-r--r--kernel/sched.c2
-rw-r--r--kernel/seccomp.c32
-rw-r--r--lib/Kconfig.debug4
-rw-r--r--mm/filemap.c6
-rw-r--r--mm/nommu.c7
-rw-r--r--mm/page-writeback.c6
-rw-r--r--mm/page_alloc.c5
-rw-r--r--mm/readahead.c1
-rw-r--r--mm/shmem.c4
-rw-r--r--mm/swap_state.c2
-rw-r--r--sound/core/control.c25
-rw-r--r--sound/core/info.c9
-rw-r--r--sound/core/misc.c8
-rw-r--r--sound/core/oss/mixer_oss.c38
-rw-r--r--sound/core/oss/pcm_oss.c2
-rw-r--r--sound/core/pcm.c36
-rw-r--r--sound/core/pcm_native.c31
-rw-r--r--sound/core/rawmidi.c64
-rw-r--r--sound/core/seq/oss/seq_oss_init.c46
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c37
-rw-r--r--sound/core/seq/seq_midi.c96
-rw-r--r--sound/core/seq/seq_midi_emul.c12
-rw-r--r--sound/core/seq/seq_system.c62
-rw-r--r--sound/core/seq/seq_virmidi.c54
-rw-r--r--sound/core/timer.c72
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c15
-rw-r--r--sound/drivers/mtpav.c5
-rw-r--r--sound/drivers/serial-u16550.c7
-rw-r--r--sound/i2c/other/ak4114.c4
-rw-r--r--sound/i2c/other/ak4xxx-adda.c134
-rw-r--r--sound/isa/Kconfig45
-rw-r--r--sound/isa/gus/gus_synth.c21
-rw-r--r--sound/isa/wavefront/wavefront_synth.c131
-rw-r--r--sound/oss/ali5455.c2
-rw-r--r--sound/oss/cs4281/cs4281_wrapper-24.c2
-rw-r--r--sound/oss/cs46xx.c4
-rw-r--r--sound/oss/cs46xxpm-24.h2
-rw-r--r--sound/oss/esssolo1.c2
-rw-r--r--sound/oss/i810_audio.c2
-rw-r--r--sound/oss/maestro3.c6
-rw-r--r--sound/oss/trident.c4
-rw-r--r--sound/oss/ymfpci.c2
-rw-r--r--sound/pci/ac97/ac97_codec.c38
-rw-r--r--sound/pci/ac97/ac97_patch.c2
-rw-r--r--sound/pci/als4000.c6
-rw-r--r--sound/pci/atiixp.c20
-rw-r--r--sound/pci/au88x0/au88x0_game.c12
-rw-r--r--sound/pci/au88x0/au88x0_mixer.c1
-rw-r--r--sound/pci/azt3328.c6
-rw-r--r--sound/pci/ca0106/ca0106_main.c10
-rw-r--r--sound/pci/cmipci.c6
-rw-r--r--sound/pci/cs4281.c34
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c31
-rw-r--r--sound/pci/emu10k1/Makefile2
-rw-r--r--sound/pci/emu10k1/emu10k1.c41
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c173
-rw-r--r--sound/pci/emu10k1/emu10k1x.c6
-rw-r--r--sound/pci/emu10k1/emufx.c154
-rw-r--r--sound/pci/emu10k1/emumixer.c39
-rw-r--r--sound/pci/emu10k1/emumpu401.c5
-rw-r--r--sound/pci/emu10k1/emupcm.c94
-rw-r--r--sound/pci/emu10k1/emuproc.c14
-rw-r--r--sound/pci/emu10k1/io.c32
-rw-r--r--sound/pci/emu10k1/irq.c19
-rw-r--r--sound/pci/emu10k1/p16v.c736
-rw-r--r--sound/pci/emu10k1/p16v.h299
-rw-r--r--sound/pci/emu10k1/timer.c4
-rw-r--r--sound/pci/emu10k1/voice.c14
-rw-r--r--sound/pci/ens1370.c41
-rw-r--r--sound/pci/es1938.c2
-rw-r--r--sound/pci/es1968.c24
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_codec.c6
-rw-r--r--sound/pci/hda/hda_generic.c13
-rw-r--r--sound/pci/hda/hda_patch.h3
-rw-r--r--sound/pci/hda/patch_analog.c445
-rw-r--r--sound/pci/hda/patch_cmedia.c11
-rw-r--r--sound/pci/hda/patch_realtek.c11
-rw-r--r--sound/pci/mixart/mixart.c6
-rw-r--r--sound/pci/mixart/mixart.h2
-rw-r--r--sound/pci/mixart/mixart_hwdep.c91
-rw-r--r--sound/pci/rme32.c5
-rw-r--r--sound/pci/rme9652/hdsp.c7
-rw-r--r--sound/pci/sonicvibes.c2
-rw-r--r--sound/pci/trident/trident_main.c12
-rw-r--r--sound/pci/via82xx.c16
-rw-r--r--sound/pci/via82xx_modem.c11
-rw-r--r--sound/pci/ymfpci/ymfpci.c5
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c12
-rw-r--r--sound/usb/usbaudio.c46
-rw-r--r--sound/usb/usbmidi.c2
495 files changed, 13241 insertions, 8168 deletions
diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers
index 2630629d7ab56..de3b252e717d0 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/SubmittingDrivers
@@ -118,13 +118,18 @@ Linux kernel mailing list:
linux-kernel@vger.kernel.org
[mail majordomo@vger.kernel.org to subscribe]
+Linux Device Drivers, Third Edition (covers 2.6.10):
+ http://lwn.net/Kernel/LDD3/ (free version)
+
Kernel traffic:
Weekly summary of kernel list activity (much easier to read)
http://www.kerneltraffic.org/kernel-traffic/
LWN.net:
Weekly summary of kernel development activity - http://lwn.net/
- 2.6 driver porting information:
+ 2.6 API changes:
+ http://lwn.net/Articles/2.6-kernel-api/
+ Porting drivers from prior kernels to 2.6:
http://lwn.net/Articles/driver-porting/
KernelTrap:
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
index 488792243d15b..1ad26d2c20ae6 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -261,6 +261,14 @@ that has had all its allowed CPUs or Memory Nodes taken offline. User
code should reconfigure cpusets to only refer to online CPUs and Memory
Nodes when using hotplug to add or remove such resources.
+There is a second exception to the above. GFP_ATOMIC requests are
+kernel internal allocations that must be satisfied, immediately.
+The kernel may drop some request, in rare cases even panic, if a
+GFP_ATOMIC alloc fails. If the request cannot be satisfied within
+the current tasks cpuset, then we relax the cpuset, and look for
+memory anywhere we can find it. It's better to violate the cpuset
+than stress the kernel.
+
To start a new job that is to be contained within a cpuset, the steps are:
1) mkdir /dev/cpuset
diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt
index cffca06ad4cef..cb89fb3b61efd 100644
--- a/Documentation/kernel-docs.txt
+++ b/Documentation/kernel-docs.txt
@@ -39,6 +39,13 @@
ON-LINE DOCS:
+ * Title: "Linux Device Drivers, Third Edition"
+ Author: Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman
+ URL: http://lwn.net/Kernel/LDD3/
+ Description: A 600-page book covering the (2.6.10) driver
+ programming API and kernel hacking in general. Available under the
+ Creative Commons Attribution-ShareAlike 2.0 license.
+
* Title: "The Linux Kernel"
Author: David A. Rusling.
URL: http://www.tldp.org/LDP/tlk/tlk.html
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index 53b58a6ace67e..da711028e5f71 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -1,23 +1,22 @@
+NOTE: ksymoops is useless on 2.6. Please use the Oops in its original format
+(from dmesg, etc). Ignore any references in this or other docs to "decoding
+the Oops" or "running it through ksymoops". If you post an Oops fron 2.6 that
+has been run through ksymoops, people will just tell you to repost it.
+
Quick Summary
-------------
-Install ksymoops from
-ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops
-Read the ksymoops man page.
-ksymoops < the_oops.txt
-
-and send the output the maintainer of the kernel area that seems to be
-involved with the problem, not to the ksymoops maintainer. Don't worry
-too much about getting the wrong person. If you are unsure send it to
-the person responsible for the code relevant to what you were doing.
-If it occurs repeatably try and describe how to recreate it. Thats
-worth even more than the oops
+Find the Oops and send it to the maintainer of the kernel area that seems to be
+involved with the problem. Don't worry too much about getting the wrong person.
+If you are unsure send it to the person responsible for the code relevant to
+what you were doing. If it occurs repeatably try and describe how to recreate
+it. That's worth even more than the oops.
If you are totally stumped as to whom to send the report, send it to
linux-kernel@vger.kernel.org. Thanks for your help in making Linux as
stable as humanly possible.
-Where is the_oops.txt?
+Where is the Oops?
----------------------
Normally the Oops text is read from the kernel buffers by klogd and
@@ -43,15 +42,14 @@ the disk is not available then you have three options :-
them yourself. Search kernel archives for kmsgdump, lkcd and
oops+smram.
-No matter how you capture the log output, feed the resulting file to
-ksymoops along with /proc/ksyms and /proc/modules that applied at the
-time of the crash. /var/log/ksymoops can be useful to capture the
-latter, man ksymoops for details.
-
Full Information
----------------
+NOTE: the message from Linus below applies to 2.4 kernel. I have preserved it
+for historical reasons, and because some of the information in it still
+applies. Especially, please ignore any references to ksymoops.
+
From: Linus Torvalds <torvalds@osdl.org>
How to track down an Oops.. [originally a mail to linux-kernel]
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 2e7eccd13e706..5d4ae9a39f1d5 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -15,7 +15,7 @@ The methods to suspend and resume devices reside in struct bus_type:
struct bus_type {
...
- int (*suspend)(struct device * dev, u32 state);
+ int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 0e71f436b3550..e789475304b6e 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -3011,6 +3011,9 @@ struct _snd_pcm_runtime {
current appl_ptr for the internal buffer, and this callback
is useful only for such a purpose.
</para>
+ <para>
+ This callback is atomic.
+ </para>
</section>
<section id="pcm-interface-operators-page-callback">
@@ -3208,6 +3211,11 @@ struct _snd_pcm_runtime {
<function>udelay()</function> or <function>mdelay()</function>.
</para>
+ <para>
+ All three atomic callbacks (trigger, pointer, and ack) are
+ called with local interrupts disabled.
+ </para>
+
</section>
<section id="pcm-interface-constraints">
<title>Constraints</title>
@@ -4596,14 +4604,6 @@ struct _snd_pcm_runtime {
zero <parameter>up</parameter> parameter when the transmission
of data should be aborted.
</para>
-
- <para>
- The <function>trigger</function> callback may be called from
- another hardware interrupt handler. This means that all
- spinlocks taken in the <function>trigger</function> callback
- must be taken with <function>spin_lock_irqsave</function>
- everywhere.
- </para>
</section>
<section id="rawmidi-interface-op-trigger-in">
@@ -4625,6 +4625,12 @@ struct _snd_pcm_runtime {
</para>
<para>
+ The <function>trigger</function> callback must not sleep; the
+ actual reading of data from the device is usually done in an
+ interrupt handler.
+ </para>
+
+ <para>
When data reception is enabled, your interrupt handler should
call <function>snd_rawmidi_receive</function> for all received
data:
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index a1d3ec6292a99..f98c2e31c143e 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -92,6 +92,8 @@ On all - write a character to /proc/sysrq-trigger. eg:
it so that only emergency messages like PANICs or OOPSes would
make it to your console.)
+'f' - Will call oom_kill to kill a memory hog process
+
'e' - Send a SIGTERM to all processes, except for init.
'i' - Send a SIGKILL to all processes, except for init.
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
new file mode 100644
index 0000000000000..2f8431f92b77f
--- /dev/null
+++ b/Documentation/usb/usbmon.txt
@@ -0,0 +1,156 @@
+* Introduction
+
+The name "usbmon" in lowercase refers to a facility in kernel which is
+used to collect traces of I/O on the USB bus. This function is analogous
+to a packet socket used by network monitoring tools such as tcpdump(1)
+or Ethereal. Similarly, it is expected that a tool such as usbdump or
+USBMon (with uppercase letters) is used to examine raw traces produced
+by usbmon.
+
+The usbmon reports requests made by peripheral-specific drivers to Host
+Controller Drivers (HCD). So, if HCD is buggy, the traces reported by
+usbmon may not correspond to bus transactions precisely. This is the same
+situation as with tcpdump.
+
+* How to use usbmon to collect raw text traces
+
+Unlike the packet socket, usbmon has an interface which provides traces
+in a text format. This is used for two purposes. First, it serves as a
+common trace exchange format for tools while most sophisticated formats
+are finalized. Second, humans can read it in case tools are not available.
+
+To collect a raw text trace, execute following steps.
+
+1. Prepare
+
+Mount debugfs (it has to be enabled in your kernel configuration), and
+load the usbmon module (if built as module). The second step is skipped
+if usbmon is built into the kernel.
+
+# mount -t debugfs none_debugs /sys/kernel/debug
+# modprobe usbmon
+
+Verify that bus sockets are present.
+
+[root@lembas zaitcev]# ls /sys/kernel/debug/usbmon
+1s 1t 2s 2t 3s 3t 4s 4t
+[root@lembas zaitcev]#
+
+# ls /sys/kernel
+
+2. Find which bus connects to the desired device
+
+Run "cat /proc/bus/usb/devices", and find the T-line which corresponds to
+the device. Usually you do it by looking for the vendor string. If you have
+many similar devices, unplug one and compare two /proc/bus/usb/devices outputs.
+The T-line will have a bus number. Example:
+
+T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
+D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
+P: Vendor=0557 ProdID=2004 Rev= 1.00
+S: Manufacturer=ATEN
+S: Product=UC100KM V2.00
+
+Bus=03 means it's bus 3.
+
+3. Start 'cat'
+
+# cat /sys/kernel/debug/usbmon/3t > /tmp/1.mon.out
+
+This process will be reading until killed. Naturally, the output can be
+redirected to a desirable location. This is preferred, because it is going
+to be quite long.
+
+4. Perform the desired operation on the USB bus
+
+This is where you do something that creates the traffic: plug in a flash key,
+copy files, control a webcam, etc.
+
+5. Kill cat
+
+Usually it's done with a keyboard interrupt (Control-C).
+
+At this point the output file (/tmp/1.mon.out in this example) can be saved,
+sent by e-mail, or inspected with a text editor. In the last case make sure
+that the file size is not excessive for your favourite editor.
+
+* Raw text data format
+
+The '0t' type data consists of a stream of events, such as URB submission,
+URB callback, submission error. Every event is a text line, which consists
+of whitespace separated words. The number of position of words may depend
+on the event type, but there is a set of words, common for all types.
+
+Here is the list of words, from left to right:
+- URB Tag. This is used to identify URBs is normally a kernel mode address
+ of the URB structure in hexadecimal.
+- Timestamp in microseconds, a decimal number. The timestamp's resolution
+ depends on available clock, and so it can be much worse than a microsecond
+ (if the implementation uses jiffies, for example).
+- Event Type. This type refers to the format of the event, not URB type.
+ Available types are: S - submission, C - callback, E - submission error.
+- "Pipe". The pipe concept is deprecated. This is a composite word, used to
+ be derived from information in pipes. It consists of three fields, separated
+ by colons: URB type and direction, Device address, Endpoint number.
+ Type and direction are encoded with two bytes in the following manner:
+ Ci Co Control input and output
+ Zi Zo Isochronous input and output
+ Ii Io Interrupt input and output
+ Bi Bo Bulk input and output
+ Device address and Endpoint number are decimal numbers with leading zeroes
+ or 3 and 2 positions, correspondingly.
+- URB Status. This field makes no sense for submissions, but is present
+ to help scripts with parsing. In error case, it contains the error code.
+- Data Length. This is the actual length in the URB.
+- Data tag. The usbmon may not always capture data, even if length is nonzero.
+ Only if tag is '=', the data words are present.
+- Data words follow, in big endian hexadecimal format. Notice that they are
+ not machine words, but really just a byte stream split into words to make
+ it easier to read. Thus, the last word may contain from one to four bytes.
+ The length of collected data is limited and can be less than the data length
+ report in Data Length word.
+
+Here is an example of code to read the data stream in a well known programming
+language:
+
+class ParsedLine {
+ int data_len; /* Available length of data */
+ byte data[];
+
+ void parseData(StringTokenizer st) {
+ int availwords = st.countTokens();
+ data = new byte[availwords * 4];
+ data_len = 0;
+ while (st.hasMoreTokens()) {
+ String data_str = st.nextToken();
+ int len = data_str.length() / 2;
+ int i;
+ for (i = 0; i < len; i++) {
+ data[data_len] = Byte.parseByte(
+ data_str.substring(i*2, i*2 + 2),
+ 16);
+ data_len++;
+ }
+ }
+ }
+}
+
+This format is obviously deficient. For example, the setup packet for control
+transfers is not delivered. This will change in the future.
+
+Examples:
+
+An input control transfer to get a port status:
+
+d74ff9a0 2640288196 S Ci:001:00 -115 4 <
+d74ff9a0 2640288202 C Ci:001:00 0 4 = 01010100
+
+An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper
+to a storage device at address 5:
+
+dd65f0e8 4128379752 S Bo:005:02 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000
+dd65f0e8 4128379808 C Bo:005:02 0 31 >
+
+* Raw binary format and API
+
+TBD
diff --git a/MAINTAINERS b/MAINTAINERS
index d824a0b79a07e..2d0fd20388cef 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -984,11 +984,6 @@ M: mikulas@artax.karlin.mff.cuni.cz
W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
S: Maintained
-HPUSBSCSI
-P: Oliver Neukum
-M: oliver@neukum.name
-S: Maintained
-
HUGETLB FILESYSTEM
P: William Irwin
M: wli@holomorphy.com
@@ -2314,6 +2309,13 @@ L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
+USB BLOCK DRIVER (UB ub)
+P: Pete Zaitcev
+M: zaitcev@redhat.com
+L: linux-kernel@vger.kernel.org
+L: linux-usb-devel@lists.sourceforge.net
+S: Supported
+
USB BLUETOOTH TTY CONVERTER DRIVER
P: Greg Kroah-Hartman
M: greg@kroah.com
@@ -2663,11 +2665,11 @@ M: jpr@f6fbb.org
L: linux-hams@vger.kernel.org
S: Maintained
-YMFPCI YAMAHA PCI SOUND
+YMFPCI YAMAHA PCI SOUND (Use ALSA instead)
P: Pete Zaitcev
M: zaitcev@yahoo.com
L: linux-kernel@vger.kernel.org
-S: Maintained
+S: Obsolete
Z8530 DRIVER FOR AX.25
P: Joerg Reuter
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index b885d32d1ca3b..a39c6a42d68ad 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -160,3 +160,7 @@ SECTIONS
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}
+
+/* those must never be empty */
+ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
+ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index f94d176c3201d..d1ced86c379c4 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -8,6 +8,7 @@
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/tty.h>
#include <asm/hardware/dec21285.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c
index 4a53d1e307bc3..6e805d451d0e7 100644
--- a/arch/arm/mach-omap/usb.c
+++ b/arch/arm/mach-omap/usb.c
@@ -326,8 +326,8 @@ static u64 ohci_dmamask = ~(u32)0;
static struct resource ohci_resources[] = {
{
- .start = IO_ADDRESS(OMAP_OHCI_BASE),
- .end = IO_ADDRESS(OMAP_OHCI_BASE + 4096),
+ .start = OMAP_OHCI_BASE,
+ .end = OMAP_OHCI_BASE + 4096,
.flags = IORESOURCE_MEM,
},
{
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 78e55051f98f1..2b19372767eb8 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -348,151 +348,7 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
- bool "Kernel debugging"
- help
- Say Y here if you are developing drivers or trying to debug and
- identify kernel problems.
-
-config EARLY_PRINTK
- bool "Early printk"
- depends on EMBEDDED && DEBUG_KERNEL
- default n
- help
- Write kernel log output directly into the VGA buffer or to a serial
- port.
-
- This is useful for kernel debugging when your machine crashes very
- early before the console code is initialized. For normal operation
- it is not recommended because it looks ugly and doesn't cooperate
- with klogd/syslogd or the X server. You should normally N here,
- unless you want to debug such a crash.
-
-config DEBUG_STACKOVERFLOW
- bool "Check for stack overflows"
- depends on DEBUG_KERNEL
-
-config DEBUG_SLAB
- bool "Debug memory allocations"
- depends on DEBUG_KERNEL
- help
- Say Y here to have the kernel do limited verification on memory
- allocation as well as poisoning memory on free to catch use of freed
- memory.
-
-config MAGIC_SYSRQ
- bool "Magic SysRq key"
- depends on DEBUG_KERNEL
- help
- If you say Y here, you will have some control over the system even
- if the system crashes for example during kernel debugging (e.g., you
- will be able to flush the buffer cache to disk, reboot the system
- immediately or dump some status information). This is accomplished
- by pressing various keys while holding SysRq (Alt+PrintScreen). It
- also works on a serial console (on PC hardware at least), if you
- send a BREAK and then within 5 seconds a command keypress. The
- keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
- unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
- bool "Spinlock debugging"
- depends on DEBUG_KERNEL
- help
- Say Y here and build SMP to catch missing spinlock initialization
- and certain other kinds of spinlock errors commonly made. This is
- best used in conjunction with the NMI watchdog so that spinlock
- deadlocks are also debuggable.
-
-config DEBUG_SPINLOCK_SLEEP
- bool "Sleep-inside-spinlock checking"
- depends on DEBUG_KERNEL
- help
- If you say Y here, various routines which may sleep will become very
- noisy if they are called with a spinlock held.
-
-config DEBUG_PAGEALLOC
- bool "Page alloc debugging"
- depends on DEBUG_KERNEL
- help
- Unmap pages from the kernel linear mapping after free_pages().
- This results in a large slowdown, but helps to find certain types
- of memory corruptions.
-
-config DEBUG_HIGHMEM
- bool "Highmem debugging"
- depends on DEBUG_KERNEL && HIGHMEM
- help
- This options enables addition error checking for high memory systems.
- Disable for production systems.
-
-config DEBUG_INFO
- bool "Compile the kernel with debug info"
- depends on DEBUG_KERNEL
- help
- If you say Y here the resulting kernel image will include
- debugging info resulting in a larger kernel image.
- Say Y here only if you plan to use gdb to debug the kernel.
- If you don't debug the kernel, you can say N.
-
-config DEBUG_BUGVERBOSE
- bool "Verbose BUG() reporting"
- depends on DEBUG_KERNEL
-
-config FRAME_POINTER
- bool "Compile the kernel with frame pointers"
- depends on DEBUG_KERNEL
- help
- If you say Y here the resulting kernel image will be slightly larger
- and slower, but it will give very useful debugging information.
- If you don't debug the kernel, you can say N, but we may not be able
- to solve problems without frame pointers.
-
-config GDBSTUB
- bool "Remote GDB kernel debugging"
- depends on DEBUG_KERNEL
- select DEBUG_INFO
- select FRAME_POINTER
- help
- If you say Y here, it will be possible to remotely debug the kernel
- using gdb. This enlarges your kernel ELF image disk size by several
- megabytes and requires a machine with more than 16 MB, better 32 MB
- RAM to avoid excessive linking time. This is only useful for kernel
- hackers. If unsure, say N.
-
-choice
- prompt "GDB stub port"
- default GDBSTUB_UART1
- depends on GDBSTUB
- help
- Select the on-CPU port used for GDB-stub
-
-config GDBSTUB_UART0
- bool "/dev/ttyS0"
-
-config GDBSTUB_UART1
- bool "/dev/ttyS1"
-
-endchoice
-
-config GDBSTUB_IMMEDIATE
- bool "Break into GDB stub immediately"
- depends on GDBSTUB
- help
- If you say Y here, GDB stub will break into the program as soon as
- possible, leaving the program counter at the beginning of
- start_kernel() in init/main.c.
-
-config GDB_CONSOLE
- bool "Console output to GDB"
- depends on KGDB
- help
- If you are using GDB for remote debugging over a serial port and
- would like kernel messages to be formatted into GDB $O packets so
- that GDB prints them as program output, say 'Y'.
-
-endmenu
+source "arch/frv/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/frv/Kconfig.debug b/arch/frv/Kconfig.debug
new file mode 100644
index 0000000000000..0034b654995df
--- /dev/null
+++ b/arch/frv/Kconfig.debug
@@ -0,0 +1,74 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+ bool "Early printk"
+ depends on EMBEDDED && DEBUG_KERNEL
+ default n
+ help
+ Write kernel log output directly into the VGA buffer or to a serial
+ port.
+
+ This is useful for kernel debugging when your machine crashes very
+ early before the console code is initialized. For normal operation
+ it is not recommended because it looks ugly and doesn't cooperate
+ with klogd/syslogd or the X server. You should normally N here,
+ unless you want to debug such a crash.
+
+config DEBUG_STACKOVERFLOW
+ bool "Check for stack overflows"
+ depends on DEBUG_KERNEL
+
+config DEBUG_PAGEALLOC
+ bool "Page alloc debugging"
+ depends on DEBUG_KERNEL
+ help
+ Unmap pages from the kernel linear mapping after free_pages().
+ This results in a large slowdown, but helps to find certain types
+ of memory corruptions.
+
+config GDBSTUB
+ bool "Remote GDB kernel debugging"
+ depends on DEBUG_KERNEL
+ select DEBUG_INFO
+ select FRAME_POINTER
+ help
+ If you say Y here, it will be possible to remotely debug the kernel
+ using gdb. This enlarges your kernel ELF image disk size by several
+ megabytes and requires a machine with more than 16 MB, better 32 MB
+ RAM to avoid excessive linking time. This is only useful for kernel
+ hackers. If unsure, say N.
+
+choice
+ prompt "GDB stub port"
+ default GDBSTUB_UART1
+ depends on GDBSTUB
+ help
+ Select the on-CPU port used for GDB-stub
+
+config GDBSTUB_UART0
+ bool "/dev/ttyS0"
+
+config GDBSTUB_UART1
+ bool "/dev/ttyS1"
+
+endchoice
+
+config GDBSTUB_IMMEDIATE
+ bool "Break into GDB stub immediately"
+ depends on GDBSTUB
+ help
+ If you say Y here, GDB stub will break into the program as soon as
+ possible, leaving the program counter at the beginning of
+ start_kernel() in init/main.c.
+
+config GDB_CONSOLE
+ bool "Console output to GDB"
+ depends on GDBSTUB
+ help
+ If you are using GDB for remote debugging over a serial port and
+ would like kernel messages to be formatted into GDB $O packets so
+ that GDB prints them as program output, say 'Y'.
+
+endmenu
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 9ba4979188a82..ef6865f0b9792 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -65,9 +65,6 @@ static void __init setup_uclinux_memory(void);
#ifdef CONFIG_CONSOLE
extern struct consw *conswitchp;
-#ifdef CONFIG_FRAMEBUFFER
-extern struct consw fb_con;
-#endif
#endif
#ifdef CONFIG_MB93090_MB00
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index ae8e099e1daed..d8d8f3d4304d9 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -225,7 +225,6 @@ asmlinkage int sys_rt_sigreturn(void)
{
struct rt_sigframe __user *frame = (struct rt_sigframe __user *) __frame->sp;
sigset_t set;
- stack_t st;
int gr8;
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 190e3feeba6d5..ebd5d8247faae 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -21,6 +21,9 @@
DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
+DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
+EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
+
static int cachesize_override __initdata = -1;
static int disable_x86_fxsr __initdata = 0;
static int disable_x86_serial_nr __initdata = 1;
@@ -546,6 +549,7 @@ void __init cpu_init (void)
int cpu = smp_processor_id();
struct tss_struct * t = &per_cpu(init_tss, cpu);
struct thread_struct *thread = &current->thread;
+ __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
if (cpu_test_and_set(cpu, cpu_initialized)) {
printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
@@ -568,6 +572,13 @@ void __init cpu_init (void)
*/
memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table,
GDT_SIZE);
+
+ /* Set up GDT entry for 16bit stack */
+ *(__u64 *)&(per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_ESPFIX_SS]) |=
+ ((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) |
+ ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
+ (CPU_16BIT_STACK_SIZE - 1);
+
cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
cpu_gdt_descr[cpu].address =
(unsigned long)&per_cpu(cpu_gdt_table, cpu);
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index d7c8f7b9f72a5..7d1d350bf87e8 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -1,5 +1,18 @@
+/*
+ * Routines to indentify caches on Intel CPU.
+ *
+ * Changes:
+ * Venkatesh Pallipadi : Adding cache identification through cpuid(4)
+ */
+
#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/compiler.h>
+#include <linux/cpu.h>
+
#include <asm/processor.h>
+#include <asm/smp.h>
#define LVL_1_INST 1
#define LVL_1_DATA 2
@@ -58,10 +71,142 @@ static struct _cache_table cache_table[] __initdata =
{ 0x00, 0, 0}
};
+
+enum _cache_type
+{
+ CACHE_TYPE_NULL = 0,
+ CACHE_TYPE_DATA = 1,
+ CACHE_TYPE_INST = 2,
+ CACHE_TYPE_UNIFIED = 3
+};
+
+union _cpuid4_leaf_eax {
+ struct {
+ enum _cache_type type:5;
+ unsigned int level:3;
+ unsigned int is_self_initializing:1;
+ unsigned int is_fully_associative:1;
+ unsigned int reserved:4;
+ unsigned int num_threads_sharing:12;
+ unsigned int num_cores_on_die:6;
+ } split;
+ u32 full;
+};
+
+union _cpuid4_leaf_ebx {
+ struct {
+ unsigned int coherency_line_size:12;
+ unsigned int physical_line_partition:10;
+ unsigned int ways_of_associativity:10;
+ } split;
+ u32 full;
+};
+
+union _cpuid4_leaf_ecx {
+ struct {
+ unsigned int number_of_sets:32;
+ } split;
+ u32 full;
+};
+
+struct _cpuid4_info {
+ union _cpuid4_leaf_eax eax;
+ union _cpuid4_leaf_ebx ebx;
+ union _cpuid4_leaf_ecx ecx;
+ unsigned long size;
+ cpumask_t shared_cpu_map;
+};
+
+#define MAX_CACHE_LEAVES 4
+static unsigned short __devinitdata num_cache_leaves;
+
+static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
+{
+ unsigned int eax, ebx, ecx, edx;
+ union _cpuid4_leaf_eax cache_eax;
+
+ cpuid_count(4, index, &eax, &ebx, &ecx, &edx);
+ cache_eax.full = eax;
+ if (cache_eax.split.type == CACHE_TYPE_NULL)
+ return -1;
+
+ this_leaf->eax.full = eax;
+ this_leaf->ebx.full = ebx;
+ this_leaf->ecx.full = ecx;
+ this_leaf->size = (this_leaf->ecx.split.number_of_sets + 1) *
+ (this_leaf->ebx.split.coherency_line_size + 1) *
+ (this_leaf->ebx.split.physical_line_partition + 1) *
+ (this_leaf->ebx.split.ways_of_associativity + 1);
+ return 0;
+}
+
+static int __init find_num_cache_leaves(void)
+{
+ unsigned int eax, ebx, ecx, edx;
+ union _cpuid4_leaf_eax cache_eax;
+ int i;
+ int retval;
+
+ retval = MAX_CACHE_LEAVES;
+ /* Do cpuid(4) loop to find out num_cache_leaves */
+ for (i = 0; i < MAX_CACHE_LEAVES; i++) {
+ cpuid_count(4, i, &eax, &ebx, &ecx, &edx);
+ cache_eax.full = eax;
+ if (cache_eax.split.type == CACHE_TYPE_NULL) {
+ retval = i;
+ break;
+ }
+ }
+ return retval;
+}
+
unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
{
unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
+ unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
+ unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
+
+ if (c->cpuid_level > 4) {
+ static int is_initialized;
+
+ if (is_initialized == 0) {
+ /* Init num_cache_leaves from boot CPU */
+ num_cache_leaves = find_num_cache_leaves();
+ is_initialized++;
+ }
+
+ /*
+ * Whenever possible use cpuid(4), deterministic cache
+ * parameters cpuid leaf to find the cache details
+ */
+ for (i = 0; i < num_cache_leaves; i++) {
+ struct _cpuid4_info this_leaf;
+
+ int retval;
+ retval = cpuid4_cache_lookup(i, &this_leaf);
+ if (retval >= 0) {
+ switch(this_leaf.eax.split.level) {
+ case 1:
+ if (this_leaf.eax.split.type ==
+ CACHE_TYPE_DATA)
+ new_l1d = this_leaf.size/1024;
+ else if (this_leaf.eax.split.type ==
+ CACHE_TYPE_INST)
+ new_l1i = this_leaf.size/1024;
+ break;
+ case 2:
+ new_l2 = this_leaf.size/1024;
+ break;
+ case 3:
+ new_l3 = this_leaf.size/1024;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
if (c->cpuid_level > 1) {
/* supports eax=2 call */
int i, j, n;
@@ -114,6 +259,18 @@ unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
}
}
+ if (new_l1d)
+ l1d = new_l1d;
+
+ if (new_l1i)
+ l1i = new_l1i;
+
+ if (new_l2)
+ l2 = new_l2;
+
+ if (new_l3)
+ l3 = new_l3;
+
if ( trace )
printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
else if ( l1i )
@@ -138,3 +295,302 @@ unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
return l2;
}
+
+/* pointer to _cpuid4_info array (for each cache leaf) */
+static struct _cpuid4_info *cpuid4_info[NR_CPUS];
+#define CPUID4_INFO_IDX(x,y) (&((cpuid4_info[x])[y]))
+
+#ifdef CONFIG_SMP
+static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+{
+ struct _cpuid4_info *this_leaf;
+ unsigned long num_threads_sharing;
+
+ this_leaf = CPUID4_INFO_IDX(cpu, index);
+ num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
+
+ if (num_threads_sharing == 1)
+ cpu_set(cpu, this_leaf->shared_cpu_map);
+ else if (num_threads_sharing == smp_num_siblings)
+ this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
+ else
+ printk(KERN_INFO "Number of CPUs sharing cache didn't match "
+ "any known set of CPUs\n");
+}
+#else
+static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
+#endif
+
+static void free_cache_attributes(unsigned int cpu)
+{
+ kfree(cpuid4_info[cpu]);
+ cpuid4_info[cpu] = NULL;
+}
+
+static int __devinit detect_cache_attributes(unsigned int cpu)
+{
+ struct _cpuid4_info *this_leaf;
+ unsigned long j;
+ int retval;
+
+ if (num_cache_leaves == 0)
+ return -ENOENT;
+
+ cpuid4_info[cpu] = kmalloc(
+ sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
+ if (unlikely(cpuid4_info[cpu] == NULL))
+ return -ENOMEM;
+ memset(cpuid4_info[cpu], 0,
+ sizeof(struct _cpuid4_info) * num_cache_leaves);
+
+ /* Do cpuid and store the results */
+ for (j = 0; j < num_cache_leaves; j++) {
+ this_leaf = CPUID4_INFO_IDX(cpu, j);
+ retval = cpuid4_cache_lookup(j, this_leaf);
+ if (unlikely(retval < 0))
+ goto err_out;
+ cache_shared_cpu_map_setup(cpu, j);
+ }
+ return 0;
+
+err_out:
+ free_cache_attributes(cpu);
+ return -ENOMEM;
+}
+
+#ifdef CONFIG_SYSFS
+
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
+
+/* pointer to kobject for cpuX/cache */
+static struct kobject * cache_kobject[NR_CPUS];
+
+struct _index_kobject {
+ struct kobject kobj;
+ unsigned int cpu;
+ unsigned short index;
+};
+
+/* pointer to array of kobjects for cpuX/cache/indexY */
+static struct _index_kobject *index_kobject[NR_CPUS];
+#define INDEX_KOBJECT_PTR(x,y) (&((index_kobject[x])[y]))
+
+#define show_one_plus(file_name, object, val) \
+static ssize_t show_##file_name \
+ (struct _cpuid4_info *this_leaf, char *buf) \
+{ \
+ return sprintf (buf, "%lu\n", (unsigned long)this_leaf->object + val); \
+}
+
+show_one_plus(level, eax.split.level, 0);
+show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1);
+show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
+show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
+show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
+
+static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
+{
+ return sprintf (buf, "%luK\n", this_leaf->size / 1024);
+}
+
+static ssize_t show_shared_cpu_map(struct _cpuid4_info *this_leaf, char *buf)
+{
+ char mask_str[NR_CPUS];
+ cpumask_scnprintf(mask_str, NR_CPUS, this_leaf->shared_cpu_map);
+ return sprintf(buf, "%s\n", mask_str);
+}
+
+static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) {
+ switch(this_leaf->eax.split.type) {
+ case CACHE_TYPE_DATA:
+ return sprintf(buf, "Data\n");
+ break;
+ case CACHE_TYPE_INST:
+ return sprintf(buf, "Instruction\n");
+ break;
+ case CACHE_TYPE_UNIFIED:
+ return sprintf(buf, "Unified\n");
+ break;
+ default:
+ return sprintf(buf, "Unknown\n");
+ break;
+ }
+}
+
+struct _cache_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct _cpuid4_info *, char *);
+ ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
+};
+
+#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(physical_line_partition);
+define_one_ro(ways_of_associativity);
+define_one_ro(number_of_sets);
+define_one_ro(size);
+define_one_ro(shared_cpu_map);
+
+static struct attribute * default_attrs[] = {
+ &type.attr,
+ &level.attr,
+ &coherency_line_size.attr,
+ &physical_line_partition.attr,
+ &ways_of_associativity.attr,
+ &number_of_sets.attr,
+ &size.attr,
+ &shared_cpu_map.attr,
+ NULL
+};
+
+#define to_object(k) container_of(k, struct _index_kobject, kobj)
+#define to_attr(a) container_of(a, struct _cache_attr, attr)
+
+static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf)
+{
+ struct _cache_attr *fattr = to_attr(attr);
+ struct _index_kobject *this_leaf = to_object(kobj);
+ ssize_t ret;
+
+ ret = fattr->show ?
+ fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
+ buf) :
+ 0;
+ return ret;
+}
+
+static ssize_t store(struct kobject * kobj, struct attribute * attr,
+ const char * buf, size_t count)
+{
+ return 0;
+}
+
+static struct sysfs_ops sysfs_ops = {
+ .show = show,
+ .store = store,
+};
+
+static struct kobj_type ktype_cache = {
+ .sysfs_ops = &sysfs_ops,
+ .default_attrs = default_attrs,
+};
+
+static struct kobj_type ktype_percpu_entry = {
+ .sysfs_ops = &sysfs_ops,
+};
+
+static void cpuid4_cache_sysfs_exit(unsigned int cpu)
+{
+ kfree(cache_kobject[cpu]);
+ kfree(index_kobject[cpu]);
+ cache_kobject[cpu] = NULL;
+ index_kobject[cpu] = NULL;
+ free_cache_attributes(cpu);
+}
+
+static int __devinit cpuid4_cache_sysfs_init(unsigned int cpu)
+{
+
+ if (num_cache_leaves == 0)
+ return -ENOENT;
+
+ detect_cache_attributes(cpu);
+ if (cpuid4_info[cpu] == NULL)
+ return -ENOENT;
+
+ /* Allocate all required memory */
+ cache_kobject[cpu] = kmalloc(sizeof(struct kobject), GFP_KERNEL);
+ if (unlikely(cache_kobject[cpu] == NULL))
+ goto err_out;
+ memset(cache_kobject[cpu], 0, sizeof(struct kobject));
+
+ index_kobject[cpu] = kmalloc(
+ sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL);
+ if (unlikely(index_kobject[cpu] == NULL))
+ goto err_out;
+ memset(index_kobject[cpu], 0,
+ sizeof(struct _index_kobject) * num_cache_leaves);
+
+ return 0;
+
+err_out:
+ cpuid4_cache_sysfs_exit(cpu);
+ return -ENOMEM;
+}
+
+/* Add/Remove cache interface for CPU device */
+static int __devinit cache_add_dev(struct sys_device * sys_dev)
+{
+ unsigned int cpu = sys_dev->id;
+ unsigned long i, j;
+ struct _index_kobject *this_object;
+ int retval = 0;
+
+ retval = cpuid4_cache_sysfs_init(cpu);
+ if (unlikely(retval < 0))
+ return retval;
+
+ cache_kobject[cpu]->parent = &sys_dev->kobj;
+ kobject_set_name(cache_kobject[cpu], "%s", "cache");
+ cache_kobject[cpu]->ktype = &ktype_percpu_entry;
+ retval = kobject_register(cache_kobject[cpu]);
+
+ for (i = 0; i < num_cache_leaves; i++) {
+ this_object = INDEX_KOBJECT_PTR(cpu,i);
+ this_object->cpu = cpu;
+ this_object->index = i;
+ this_object->kobj.parent = cache_kobject[cpu];
+ kobject_set_name(&(this_object->kobj), "index%1lu", i);
+ this_object->kobj.ktype = &ktype_cache;
+ retval = kobject_register(&(this_object->kobj));
+ if (unlikely(retval)) {
+ for (j = 0; j < i; j++) {
+ kobject_unregister(
+ &(INDEX_KOBJECT_PTR(cpu,j)->kobj));
+ }
+ kobject_unregister(cache_kobject[cpu]);
+ cpuid4_cache_sysfs_exit(cpu);
+ break;
+ }
+ }
+ return retval;
+}
+
+static int __devexit cache_remove_dev(struct sys_device * sys_dev)
+{
+ unsigned int cpu = sys_dev->id;
+ unsigned long i;
+
+ for (i = 0; i < num_cache_leaves; i++)
+ kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
+ kobject_unregister(cache_kobject[cpu]);
+ cpuid4_cache_sysfs_exit(cpu);
+ return 0;
+}
+
+static struct sysdev_driver cache_sysdev_driver = {
+ .add = cache_add_dev,
+ .remove = __devexit_p(cache_remove_dev),
+};
+
+/* Register/Unregister the cpu_cache driver */
+static int __devinit cache_register_driver(void)
+{
+ if (num_cache_leaves == 0)
+ return 0;
+
+ return sysdev_driver_register(&cpu_sysdev_class,&cache_sysdev_driver);
+}
+
+device_initcall(cache_register_driver);
+
+#endif
+
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 87aad70d37302..1e45ff292bc99 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -47,6 +47,7 @@
#include <asm/segment.h>
#include <asm/smp.h>
#include <asm/page.h>
+#include <asm/desc.h>
#include "irq_vectors.h"
#define nr_syscalls ((syscall_table_size)/4)
@@ -78,7 +79,7 @@ VM_MASK = 0x00020000
#define preempt_stop cli
#else
#define preempt_stop
-#define resume_kernel restore_all
+#define resume_kernel restore_nocheck
#endif
#define SAVE_ALL \
@@ -122,24 +123,6 @@ VM_MASK = 0x00020000
.previous
-#define RESTORE_ALL \
- RESTORE_REGS \
- addl $4, %esp; \
-1: iret; \
-.section .fixup,"ax"; \
-2: sti; \
- movl $(__USER_DS), %edx; \
- movl %edx, %ds; \
- movl %edx, %es; \
- movl $11,%eax; \
- call do_exit; \
-.previous; \
-.section __ex_table,"a";\
- .align 4; \
- .long 1b,2b; \
-.previous
-
-
ENTRY(ret_from_fork)
pushl %eax
call schedule_tail
@@ -163,7 +146,7 @@ ret_from_intr:
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
movb CS(%esp), %al
testl $(VM_MASK | 3), %eax
- jz resume_kernel # returning to kernel or vm86-space
+ jz resume_kernel
ENTRY(resume_userspace)
cli # make sure we don't miss an interrupt
# setting need_resched or sigpending
@@ -178,7 +161,7 @@ ENTRY(resume_userspace)
ENTRY(resume_kernel)
cli
cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
- jnz restore_all
+ jnz restore_nocheck
need_resched:
movl TI_flags(%ebp), %ecx # need_resched set ?
testb $_TIF_NEED_RESCHED, %cl
@@ -259,8 +242,56 @@ syscall_exit:
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx # current->work
jne syscall_exit_work
+
restore_all:
- RESTORE_ALL
+ movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
+ movb OLDSS(%esp), %ah
+ movb CS(%esp), %al
+ andl $(VM_MASK | (4 << 8) | 3), %eax
+ cmpl $((4 << 8) | 3), %eax
+ je ldt_ss # returning to user-space with LDT SS
+restore_nocheck:
+ RESTORE_REGS
+ addl $4, %esp
+1: iret
+.section .fixup,"ax"
+iret_exc:
+ sti
+ movl $__USER_DS, %edx
+ movl %edx, %ds
+ movl %edx, %es
+ movl $11,%eax
+ call do_exit
+.previous
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
+
+ldt_ss:
+ larl OLDSS(%esp), %eax
+ jnz restore_nocheck
+ testl $0x00400000, %eax # returning to 32bit stack?
+ jnz restore_nocheck # allright, normal return
+ /* If returning to userspace with 16bit stack,
+ * try to fix the higher word of ESP, as the CPU
+ * won't restore it.
+ * This is an "official" bug of all the x86-compatible
+ * CPUs, which we can try to work around to make
+ * dosemu and wine happy. */
+ subl $8, %esp # reserve space for switch16 pointer
+ cli
+ movl %esp, %eax
+ /* Set up the 16bit stack frame with switch32 pointer on top,
+ * and a switch16 pointer on top of the current frame. */
+ call setup_x86_bogus_stack
+ RESTORE_REGS
+ lss 20+4(%esp), %esp # switch to 16bit stack
+1: iret
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
# perform work that needs to be done immediately before resumption
ALIGN
@@ -336,6 +367,27 @@ syscall_badsys:
movl $-ENOSYS,EAX(%esp)
jmp resume_userspace
+#define FIXUP_ESPFIX_STACK \
+ movl %esp, %eax; \
+ /* switch to 32bit stack using the pointer on top of 16bit stack */ \
+ lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \
+ /* copy data from 16bit stack to 32bit stack */ \
+ call fixup_x86_bogus_stack; \
+ /* put ESP to the proper location */ \
+ movl %eax, %esp;
+#define UNWIND_ESPFIX_STACK \
+ pushl %eax; \
+ movl %ss, %eax; \
+ /* see if on 16bit stack */ \
+ cmpw $__ESPFIX_SS, %ax; \
+ jne 28f; \
+ movl $__KERNEL_DS, %edx; \
+ movl %edx, %ds; \
+ movl %edx, %es; \
+ /* switch to 32bit stack */ \
+ FIXUP_ESPFIX_STACK \
+28: popl %eax;
+
/*
* Build the entry stubs and pointer table with
* some assembler magic.
@@ -390,7 +442,9 @@ error_code:
pushl %ecx
pushl %ebx
cld
- movl %es, %ecx
+ pushl %es
+ UNWIND_ESPFIX_STACK
+ popl %ecx
movl ES(%esp), %edi # get the function address
movl ORIG_EAX(%esp), %edx # get the error code
movl %eax, ORIG_EAX(%esp)
@@ -472,6 +526,11 @@ debug_stack_correct:
* fault happened on the sysenter path.
*/
ENTRY(nmi)
+ pushl %eax
+ movl %ss, %eax
+ cmpw $__ESPFIX_SS, %ax
+ popl %eax
+ je nmi_16bit_stack
cmpl $sysenter_entry,(%esp)
je nmi_stack_fixup
pushl %eax
@@ -491,7 +550,7 @@ nmi_stack_correct:
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
call do_nmi
- RESTORE_ALL
+ jmp restore_all
nmi_stack_fixup:
FIX_STACK(12,nmi_stack_correct, 1)
@@ -507,6 +566,29 @@ nmi_debug_stack_fixup:
FIX_STACK(24,nmi_stack_correct, 1)
jmp nmi_stack_correct
+nmi_16bit_stack:
+ /* create the pointer to lss back */
+ pushl %ss
+ pushl %esp
+ movzwl %sp, %esp
+ addw $4, (%esp)
+ /* copy the iret frame of 12 bytes */
+ .rept 3
+ pushl 16(%esp)
+ .endr
+ pushl %eax
+ SAVE_ALL
+ FIXUP_ESPFIX_STACK # %eax == %esp
+ xorl %edx,%edx # zero error code
+ call do_nmi
+ RESTORE_REGS
+ lss 12+4(%esp), %esp # back to 16bit stack
+1: iret
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
+
ENTRY(int3)
pushl $-1 # mark this as an int
SAVE_ALL
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index ea1ef3a32ec5b..d273fd7461921 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -512,7 +512,7 @@ ENTRY(cpu_gdt_table)
.quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */
.quad 0x0040920000000000 /* 0xc8 APM DS data */
- .quad 0x0000000000000000 /* 0xd0 - unused */
+ .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */
.quad 0x0000000000000000 /* 0xd8 - unused */
.quad 0x0000000000000000 /* 0xe0 - unused */
.quad 0x0000000000000000 /* 0xe8 - unused */
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index f74b755704c4c..6716816592434 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -84,7 +84,11 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
- regs->eip = (unsigned long)&p->ainsn.insn;
+ /*single step inline if the instruction is an int3*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
+ regs->eip = (unsigned long)p->addr;
+ else
+ regs->eip = (unsigned long)&p->ainsn.insn;
}
/*
@@ -117,6 +121,12 @@ static int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->eflags &= ~TF_MASK;
+ regs->eflags |= kprobe_saved_eflags;
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -159,17 +169,16 @@ static int kprobe_handler(struct pt_regs *regs)
if (is_IF_modifier(p->opcode))
kprobe_saved_eflags &= ~IF_MASK;
- if (p->pre_handler(p, regs)) {
+ if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
return 1;
- }
- ss_probe:
+ss_probe:
prepare_singlestep(p, regs);
kprobe_status = KPROBE_HIT_SS;
return 1;
- no_kprobe:
+no_kprobe:
preempt_enable_no_resched();
return ret;
}
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 90cfff176251e..c36fedf40e958 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -73,7 +73,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
* Powermanagement idle function, if any..
*/
void (*pm_idle)(void);
-static cpumask_t cpu_idle_map;
+static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
void disable_hlt(void)
{
@@ -146,15 +146,14 @@ static void poll_idle (void)
*/
void cpu_idle (void)
{
- int cpu = _smp_processor_id();
-
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
void (*idle)(void);
- if (cpu_isset(cpu, cpu_idle_map))
- cpu_clear(cpu, cpu_idle_map);
+ if (__get_cpu_var(cpu_idle_state))
+ __get_cpu_var(cpu_idle_state) = 0;
+
rmb();
idle = pm_idle;
@@ -170,16 +169,28 @@ void cpu_idle (void)
void cpu_idle_wait(void)
{
- int cpu;
+ unsigned int cpu, this_cpu = get_cpu();
cpumask_t map;
- for_each_online_cpu(cpu)
- cpu_set(cpu, cpu_idle_map);
+ set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+ put_cpu();
+
+ cpus_clear(map);
+ for_each_online_cpu(cpu) {
+ per_cpu(cpu_idle_state, cpu) = 1;
+ cpu_set(cpu, map);
+ }
+
+ __get_cpu_var(cpu_idle_state) = 0;
wmb();
do {
ssleep(1);
- cpus_and(map, cpu_idle_map, cpu_online_map);
+ for_each_online_cpu(cpu) {
+ if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
+ cpu_clear(cpu, map);
+ }
+ cpus_and(map, map, cpu_online_map);
} while (!cpus_empty(map));
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 0ac1d19c7739f..6223c33ac91cc 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -188,7 +188,7 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
local_irq_restore(flags);
}
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
+void send_IPI_mask_sequence(cpumask_t mask, int vector)
{
unsigned long cfg, flags;
unsigned int query_cpu;
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 7b5b97f209b7f..6c0e383915b6a 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -887,6 +887,51 @@ fastcall void do_spurious_interrupt_bug(struct pt_regs * regs,
#endif
}
+fastcall void setup_x86_bogus_stack(unsigned char * stk)
+{
+ unsigned long *switch16_ptr, *switch32_ptr;
+ struct pt_regs *regs;
+ unsigned long stack_top, stack_bot;
+ unsigned short iret_frame16_off;
+ int cpu = smp_processor_id();
+ /* reserve the space on 32bit stack for the magic switch16 pointer */
+ memmove(stk, stk + 8, sizeof(struct pt_regs));
+ switch16_ptr = (unsigned long *)(stk + sizeof(struct pt_regs));
+ regs = (struct pt_regs *)stk;
+ /* now the switch32 on 16bit stack */
+ stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
+ stack_top = stack_bot + CPU_16BIT_STACK_SIZE;
+ switch32_ptr = (unsigned long *)(stack_top - 8);
+ iret_frame16_off = CPU_16BIT_STACK_SIZE - 8 - 20;
+ /* copy iret frame on 16bit stack */
+ memcpy((void *)(stack_bot + iret_frame16_off), &regs->eip, 20);
+ /* fill in the switch pointers */
+ switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off;
+ switch16_ptr[1] = __ESPFIX_SS;
+ switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) +
+ 8 - CPU_16BIT_STACK_SIZE;
+ switch32_ptr[1] = __KERNEL_DS;
+}
+
+fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
+{
+ unsigned long *switch32_ptr;
+ unsigned char *stack16, *stack32;
+ unsigned long stack_top, stack_bot;
+ int len;
+ int cpu = smp_processor_id();
+ stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
+ stack_top = stack_bot + CPU_16BIT_STACK_SIZE;
+ switch32_ptr = (unsigned long *)(stack_top - 8);
+ /* copy the data from 16bit stack to 32bit stack */
+ len = CPU_16BIT_STACK_SIZE - 8 - sp;
+ stack16 = (unsigned char *)(stack_bot + sp);
+ stack32 = (unsigned char *)
+ (switch32_ptr[0] + CPU_16BIT_STACK_SIZE - 8 - len);
+ memcpy(stack32, stack16, len);
+ return stack32;
+}
+
/*
* 'math_state_restore()' saves the current math information in the
* old math state array, and gets the new ones from the current task
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index fb03be1a0c94c..4826cd6e40e8e 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -7,8 +7,6 @@
* Hitoshi Yamamoto
*/
-/* $Id$ */
-
#include <linux/config.h>
#include <linux/init.h>
#include <linux/stddef.h>
@@ -24,6 +22,9 @@
#include <linux/seq_file.h>
#include <linux/timex.h>
#include <linux/tty.h>
+#include <linux/cpu.h>
+#include <linux/nodemask.h>
+
#include <asm/processor.h>
#include <asm/pgtable.h>
#include <asm/io.h>
@@ -52,7 +53,7 @@ struct cpuinfo_m32r boot_cpu_data;
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
-extern int rd_image_start; /* starting block # of image */
+extern int rd_image_start; /* starting block # of image */
#endif
#if defined(CONFIG_VGA_CONSOLE)
@@ -273,6 +274,21 @@ void __init setup_arch(char **cmdline_p)
paging_init();
}
+static struct cpu cpu[NR_CPUS];
+
+static int __init topology_init(void)
+{
+ int cpu_id;
+
+ for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
+ if (cpu_possible(cpu_id))
+ register_cpu(&cpu[cpu_id], cpu_id, NULL);
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
+
#ifdef CONFIG_PROC_FS
/*
* Get CPU information for use by the procfs.
@@ -285,7 +301,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
#ifdef CONFIG_SMP
if (!cpu_online(cpu))
return 0;
-#endif /* CONFIG_SMP */
+#endif /* CONFIG_SMP */
seq_printf(m, "processor\t: %ld\n", cpu);
@@ -359,7 +375,7 @@ struct seq_operations cpuinfo_op = {
stop: c_stop,
show: show_cpuinfo,
};
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_PROC_FS */
unsigned long cpu_initialized __initdata = 0;
@@ -399,7 +415,6 @@ void __init cpu_init (void)
#endif
/* Set up ICUIMASK */
- outl(0x00070000, M32R_ICU_IMASK_PORTL); /* imask=111 */
+ outl(0x00070000, M32R_ICU_IMASK_PORTL); /* imask=111 */
}
-#endif /* defined(CONFIG_CHIP_VDEC2) ... */
-
+#endif /* defined(CONFIG_CHIP_VDEC2) ... */
diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c
index bf3104a159087..1d1a01e54b3fa 100644
--- a/arch/m32r/mm/discontig.c
+++ b/arch/m32r/mm/discontig.c
@@ -11,6 +11,7 @@
#include <linux/bootmem.h>
#include <linux/mmzone.h>
#include <linux/initrd.h>
+#include <linux/nodemask.h>
#include <asm/setup.h>
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 930103cf2b339..59995a4308683 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -816,7 +816,7 @@ config MPC10X_BRIDGE
config FSL_OCP
bool
- depends on MPC10X_BRIDGE || PPC_MPC52xx
+ depends on MPC10X_BRIDGE
default y
config MPC10X_OPENPIC
diff --git a/arch/ppc/boot/simple/mpc52xx_tty.c b/arch/ppc/boot/simple/mpc52xx_tty.c
index 5bf4f0c793223..3acc6b7c0727c 100644
--- a/arch/ppc/boot/simple/mpc52xx_tty.c
+++ b/arch/ppc/boot/simple/mpc52xx_tty.c
@@ -20,32 +20,31 @@
#include <asm/io.h>
#include <asm/time.h>
-#if MPC52xx_PF_CONSOLE_PORT == 0
-#define MPC52xx_CONSOLE MPC52xx_PSC1
-#define MPC52xx_PSC_CONFIG_SHIFT 0
-#elif MPC52xx_PF_CONSOLE_PORT == 1
-#define MPC52xx_CONSOLE MPC52xx_PSC2
-#define MPC52xx_PSC_CONFIG_SHIFT 4
-#elif MPC52xx_PF_CONSOLE_PORT == 2
-#define MPC52xx_CONSOLE MPC52xx_PSC3
-#define MPC52xx_PSC_CONFIG_SHIFT 8
+
+#ifdef MPC52xx_PF_CONSOLE_PORT
+#define MPC52xx_CONSOLE MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT)
+#define MPC52xx_PSC_CONFIG_SHIFT ((MPC52xx_PF_CONSOLE_PORT-1)<<2)
#else
#error "MPC52xx_PF_CONSOLE_PORT not defined"
#endif
static struct mpc52xx_psc __iomem *psc =
- (struct mpc52xx_psc __iomem *) MPC52xx_CONSOLE;
+ (struct mpc52xx_psc __iomem *) MPC52xx_PA(MPC52xx_CONSOLE);
/* The decrementer counts at the system bus clock frequency
* divided by four. The most accurate time base is connected to the
- * rtc. We read the decrementer change during one rtc tick (one second)
- * and multiply by 4 to get the system bus clock frequency.
+ * rtc. We read the decrementer change during one rtc tick
+ * and multiply by 4 to get the system bus clock frequency. Since a
+ * rtc tick is one seconds, and that's pretty long, we change the rtc
+ * dividers temporarly to set them 64x faster ;)
*/
static int
mpc52xx_ipbfreq(void)
{
- struct mpc52xx_rtc __iomem *rtc = (struct mpc52xx_rtc __iomem *)MPC52xx_RTC;
- struct mpc52xx_cdm __iomem *cdm = (struct mpc52xx_cdm __iomem *)MPC52xx_CDM;
+ struct mpc52xx_rtc __iomem *rtc =
+ (struct mpc52xx_rtc __iomem *) MPC52xx_PA(MPC52xx_RTC_OFFSET);
+ struct mpc52xx_cdm __iomem *cdm =
+ (struct mpc52xx_cdm __iomem *) MPC52xx_PA(MPC52xx_CDM_OFFSET);
int current_time, previous_time;
int tbl_start, tbl_end;
int xlbfreq, ipbfreq;
@@ -68,7 +67,8 @@ mpc52xx_ipbfreq(void)
unsigned long
serial_init(int ignored, void *ignored2)
{
- struct mpc52xx_gpio __iomem *gpio = (struct mpc52xx_gpio __iomem *)MPC52xx_GPIO;
+ struct mpc52xx_gpio __iomem *gpio =
+ (struct mpc52xx_gpio __iomem *) MPC52xx_PA(MPC52xx_GPIO_OFFSET);
int divisor;
int mode1;
int mode2;
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 370ee2a59c1f5..035217d6c0f11 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -45,40 +45,37 @@
#endif
#ifdef CONFIG_BOOKE
-#define COR r8 /* Critical Offset Register (COR) */
-#define BOOKE_LOAD_COR lis COR,crit_save@ha
-#define BOOKE_REST_COR mfspr COR,SPRN_SPRG2
-#define BOOKE_SAVE_COR mtspr SPRN_SPRG2,COR
-#else
-#define COR 0
-#define BOOKE_LOAD_COR
-#define BOOKE_REST_COR
-#define BOOKE_SAVE_COR
-#endif
-
-#ifdef CONFIG_BOOKE
+#include "head_booke.h"
.globl mcheck_transfer_to_handler
mcheck_transfer_to_handler:
- mtspr SPRN_SPRG6W,r8
- lis r8,mcheck_save@ha
- lwz r0,mcheck_r10@l(r8)
+ mtspr MCHECK_SPRG,r8
+ BOOKE_LOAD_MCHECK_STACK
+ lwz r0,GPR10-INT_FRAME_SIZE(r8)
stw r0,GPR10(r11)
- lwz r0,mcheck_r11@l(r8)
+ lwz r0,GPR11-INT_FRAME_SIZE(r8)
stw r0,GPR11(r11)
- mfspr r8,SPRN_SPRG6R
+ mfspr r8,MCHECK_SPRG
b transfer_to_handler_full
+
+ .globl crit_transfer_to_handler
+crit_transfer_to_handler:
+ mtspr CRIT_SPRG,r8
+ BOOKE_LOAD_CRIT_STACK
+ lwz r0,GPR10-INT_FRAME_SIZE(r8)
+ stw r0,GPR10(r11)
+ lwz r0,GPR11-INT_FRAME_SIZE(r8)
+ stw r0,GPR11(r11)
+ mfspr r8,CRIT_SPRG
+ /* fall through */
#endif
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_40x
.globl crit_transfer_to_handler
crit_transfer_to_handler:
- BOOKE_SAVE_COR
- BOOKE_LOAD_COR
- lwz r0,crit_r10@l(COR)
+ lwz r0,crit_r10@l(0)
stw r0,GPR10(r11)
- lwz r0,crit_r11@l(COR)
+ lwz r0,crit_r11@l(0)
stw r0,GPR11(r11)
- BOOKE_REST_COR
/* fall through */
#endif
@@ -724,8 +721,6 @@ exc_exit_restart_end:
* We have to restore various SPRs that may have been in use at the
* time of the critical interrupt.
*
- * Note that SPRG6 is used for machine check on CONFIG_BOOKE parts and
- * thus not saved in the critical handler
*/
.globl ret_from_crit_exc
ret_from_crit_exc:
@@ -770,32 +765,9 @@ ret_from_crit_exc:
mtspr SPRN_CSRR1,r12
lwz r9,GPR9(r1)
lwz r12,GPR12(r1)
- BOOKE_SAVE_COR
- BOOKE_LOAD_COR
- lwz r10,crit_sprg0@l(COR)
- mtspr SPRN_SPRG0,r10
- lwz r10,crit_sprg1@l(COR)
- mtspr SPRN_SPRG1,r10
- lwz r10,crit_sprg4@l(COR)
- mtspr SPRN_SPRG4,r10
- lwz r10,crit_sprg5@l(COR)
- mtspr SPRN_SPRG5,r10
-#ifdef CONFIG_40x
- lwz r10,crit_sprg6@l(COR)
- mtspr SPRN_SPRG6,r10
-#endif
- lwz r10,crit_sprg7@l(COR)
- mtspr SPRN_SPRG7,r10
- lwz r10,crit_srr0@l(COR)
- mtspr SPRN_SRR0,r10
- lwz r10,crit_srr1@l(COR)
- mtspr SPRN_SRR1,r10
- lwz r10,crit_pid@l(COR)
- mtspr SPRN_PID,r10
lwz r10,GPR10(r1)
lwz r11,GPR11(r1)
lwz r1,GPR1(r1)
- BOOKE_REST_COR
PPC405_ERR77_SYNC
rfci
b . /* prevent prefetch past rfci */
@@ -839,32 +811,9 @@ ret_from_mcheck_exc:
mtspr SPRN_MCSRR1,r12
lwz r9,GPR9(r1)
lwz r12,GPR12(r1)
- mtspr SPRN_SPRG6W,r8
- lis r8,mcheck_save@ha
- lwz r10,mcheck_sprg0@l(r8)
- mtspr SPRN_SPRG0,r10
- lwz r10,mcheck_sprg1@l(r8)
- mtspr SPRN_SPRG1,r10
- lwz r10,mcheck_sprg4@l(r8)
- mtspr SPRN_SPRG4,r10
- lwz r10,mcheck_sprg5@l(r8)
- mtspr SPRN_SPRG5,r10
- lwz r10,mcheck_sprg7@l(r8)
- mtspr SPRN_SPRG7,r10
- lwz r10,mcheck_srr0@l(r8)
- mtspr SPRN_SRR0,r10
- lwz r10,mcheck_srr1@l(r8)
- mtspr SPRN_SRR1,r10
- lwz r10,mcheck_csrr0@l(r8)
- mtspr SPRN_CSRR0,r10
- lwz r10,mcheck_csrr1@l(r8)
- mtspr SPRN_CSRR1,r10
- lwz r10,mcheck_pid@l(r8)
- mtspr SPRN_PID,r10
lwz r10,GPR10(r1)
lwz r11,GPR11(r1)
lwz r1,GPR1(r1)
- mfspr r8,SPRN_SPRG6R
RFMCI
#endif /* CONFIG_BOOKE */
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index e61f3be049feb..9ed8165a3d6c6 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -728,78 +728,13 @@ _GLOBAL(empty_zero_page)
_GLOBAL(swapper_pg_dir)
.space 8192
+/* Reserved 4k for the critical exception stack & 4k for the machine
+ * check stack per CPU for kernel mode exceptions */
.section .bss
-/* Stack for handling critical exceptions from kernel mode */
-critical_stack_bottom:
- .space 4096
-critical_stack_top:
- .previous
-
-/* Stack for handling machine check exceptions from kernel mode */
-mcheck_stack_bottom:
- .space 4096
-mcheck_stack_top:
- .previous
-
-/*
- * This area is used for temporarily saving registers during the
- * critical and machine check exception prologs. It must always
- * follow the page aligned allocations, so it starts on a page
- * boundary, ensuring that all crit_save areas are in a single
- * page.
- */
-
-/* crit_save */
-_GLOBAL(crit_save)
- .space 4
-_GLOBAL(crit_r10)
- .space 4
-_GLOBAL(crit_r11)
- .space 4
-_GLOBAL(crit_sprg0)
- .space 4
-_GLOBAL(crit_sprg1)
- .space 4
-_GLOBAL(crit_sprg4)
- .space 4
-_GLOBAL(crit_sprg5)
- .space 4
-_GLOBAL(crit_sprg7)
- .space 4
-_GLOBAL(crit_pid)
- .space 4
-_GLOBAL(crit_srr0)
- .space 4
-_GLOBAL(crit_srr1)
- .space 4
-
-/* mcheck_save */
-_GLOBAL(mcheck_save)
- .space 4
-_GLOBAL(mcheck_r10)
- .space 4
-_GLOBAL(mcheck_r11)
- .space 4
-_GLOBAL(mcheck_sprg0)
- .space 4
-_GLOBAL(mcheck_sprg1)
- .space 4
-_GLOBAL(mcheck_sprg4)
- .space 4
-_GLOBAL(mcheck_sprg5)
- .space 4
-_GLOBAL(mcheck_sprg7)
- .space 4
-_GLOBAL(mcheck_pid)
- .space 4
-_GLOBAL(mcheck_srr0)
- .space 4
-_GLOBAL(mcheck_srr1)
- .space 4
-_GLOBAL(mcheck_csrr0)
- .space 4
-_GLOBAL(mcheck_csrr1)
- .space 4
+ .align 12
+exception_stack_bottom:
+ .space BOOKE_EXCEPTION_STACK_SIZE
+_GLOBAL(exception_stack_top)
/*
* This space gets a copy of optional info passed to us by the bootstrap
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
index dd23e90ac8166..6f5d380e23450 100644
--- a/arch/ppc/kernel/head_4xx.S
+++ b/arch/ppc/kernel/head_4xx.S
@@ -95,24 +95,6 @@ _GLOBAL(crit_r10)
.space 4
_GLOBAL(crit_r11)
.space 4
-_GLOBAL(crit_sprg0)
- .space 4
-_GLOBAL(crit_sprg1)
- .space 4
-_GLOBAL(crit_sprg4)
- .space 4
-_GLOBAL(crit_sprg5)
- .space 4
-_GLOBAL(crit_sprg6)
- .space 4
-_GLOBAL(crit_sprg7)
- .space 4
-_GLOBAL(crit_pid)
- .space 4
-_GLOBAL(crit_srr0)
- .space 4
-_GLOBAL(crit_srr1)
- .space 4
/*
* Exception vector entry code. This code runs with address translation
@@ -165,24 +147,6 @@ _GLOBAL(crit_srr1)
#define CRITICAL_EXCEPTION_PROLOG \
stw r10,crit_r10@l(0); /* save two registers to work with */\
stw r11,crit_r11@l(0); \
- mfspr r10,SPRN_SPRG0; \
- stw r10,crit_sprg0@l(0); \
- mfspr r10,SPRN_SPRG1; \
- stw r10,crit_sprg1@l(0); \
- mfspr r10,SPRN_SPRG4; \
- stw r10,crit_sprg4@l(0); \
- mfspr r10,SPRN_SPRG5; \
- stw r10,crit_sprg5@l(0); \
- mfspr r10,SPRN_SPRG6; \
- stw r10,crit_sprg6@l(0); \
- mfspr r10,SPRN_SPRG7; \
- stw r10,crit_sprg7@l(0); \
- mfspr r10,SPRN_PID; \
- stw r10,crit_pid@l(0); \
- mfspr r10,SPRN_SRR0; \
- stw r10,crit_srr0@l(0); \
- mfspr r10,SPRN_SRR1; \
- stw r10,crit_srr1@l(0); \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_SRR3; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
@@ -221,9 +185,6 @@ _GLOBAL(crit_srr1)
* r11 saved in crit_r11 and in stack frame,
* now phys stack/exception frame pointer
* r12 saved in stack frame, now saved SRR2
- * SPRG0,1,4,5,6,7 saved in crit_sprg0,1,4,5,6,7
- * PID saved in crit_pid
- * SRR0,1 saved in crit_srr0,1
* CR saved in stack frame, CR0.EQ = !SRR3.PR
* LR, DEAR, ESR in stack frame
* r1 saved in stack frame, now virt stack/excframe pointer
@@ -1030,10 +991,11 @@ _GLOBAL(swapper_pg_dir)
/* Stack for handling critical exceptions from kernel mode */
.section .bss
-critical_stack_bottom:
+ .align 12
+exception_stack_bottom:
.space 4096
critical_stack_top:
- .previous
+_GLOBAL(exception_stack_top)
/* This space gets a copy of optional info passed to us by the bootstrap
* which is used to pass parameters into the kernel like root=/dev/sda1, etc.
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
index b69813a9f9e93..884dac916bce7 100644
--- a/arch/ppc/kernel/head_booke.h
+++ b/arch/ppc/kernel/head_booke.h
@@ -22,7 +22,7 @@
lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
addi r1,r1,THREAD_SIZE; \
1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
- tophys(r11,r1); \
+ mr r11,r1; \
stw r10,_CCR(r11); /* save various registers */\
stw r12,GPR12(r11); \
stw r9,GPR9(r11); \
@@ -42,45 +42,71 @@
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
+/* To handle the additional exception priority levels on 40x and Book-E
+ * processors we allocate a 4k stack per additional priority level. The various
+ * head_xxx.S files allocate space (exception_stack_top) for each priority's
+ * stack times the number of CPUs
+ *
+ * On 40x critical is the only additional level
+ * On 44x/e500 we have critical and machine check
+ *
+ * Additionally we reserve a SPRG for each priority level so we can free up a
+ * GPR to use as the base for indirect access to the exception stacks. This
+ * is necessary since the MMU is always on, for Book-E parts, and the stacks
+ * are offset from KERNELBASE.
+ *
+ */
+#define BOOKE_EXCEPTION_STACK_SIZE (8192)
+
+/* CRIT_SPRG only used in critical exception handling */
+#define CRIT_SPRG SPRN_SPRG2
+/* MCHECK_SPRG only used in critical exception handling */
+#define MCHECK_SPRG SPRN_SPRG6W
+
+#define MCHECK_STACK_TOP (exception_stack_top - 4096)
+#define CRIT_STACK_TOP (exception_stack_top)
+
+#ifdef CONFIG_SMP
+#define BOOKE_LOAD_CRIT_STACK \
+ mfspr r8,SPRN_PIR; \
+ mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
+ neg r8,r8; \
+ addis r8,r8,CRIT_STACK_TOP@ha; \
+ addi r8,r8,CRIT_STACK_TOP@l
+#define BOOKE_LOAD_MCHECK_STACK \
+ mfspr r8,SPRN_PIR; \
+ mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
+ neg r8,r8; \
+ addis r8,r8,MCHECK_STACK_TOP@ha; \
+ addi r8,r8,MCHECK_STACK_TOP@l
+#else
+#define BOOKE_LOAD_CRIT_STACK \
+ lis r8,CRIT_STACK_TOP@h; \
+ ori r8,r8,CRIT_STACK_TOP@l
+#define BOOKE_LOAD_MCHECK_STACK \
+ lis r8,MCHECK_STACK_TOP@h; \
+ ori r8,r8,MCHECK_STACK_TOP@l
+#endif
+
/*
* Exception prolog for critical exceptions. This is a little different
* from the normal exception prolog above since a critical exception
* can potentially occur at any point during normal exception processing.
* Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a couple of words of memory at low physical addresses.
- * This is OK since we don't support SMP on these processors. For Book E
- * processors, we also have a reserved register (SPRG2) that is only used
- * in critical exceptions so we can free up a GPR to use as the base for
- * indirect access to the critical exception save area. This is necessary
- * since the MMU is always on and the save area is offset from KERNELBASE.
+ * Instead we use a portion of the critical exception stack at low physical
+ * addresses.
*/
+
#define CRITICAL_EXCEPTION_PROLOG \
- mtspr SPRN_SPRG2,r8; /* SPRG2 only used in criticals */ \
- lis r8,crit_save@ha; \
- stw r10,crit_r10@l(r8); \
- stw r11,crit_r11@l(r8); \
- mfspr r10,SPRN_SPRG0; \
- stw r10,crit_sprg0@l(r8); \
- mfspr r10,SPRN_SPRG1; \
- stw r10,crit_sprg1@l(r8); \
- mfspr r10,SPRN_SPRG4R; \
- stw r10,crit_sprg4@l(r8); \
- mfspr r10,SPRN_SPRG5R; \
- stw r10,crit_sprg5@l(r8); \
- mfspr r10,SPRN_SPRG7R; \
- stw r10,crit_sprg7@l(r8); \
- mfspr r10,SPRN_PID; \
- stw r10,crit_pid@l(r8); \
- mfspr r10,SPRN_SRR0; \
- stw r10,crit_srr0@l(r8); \
- mfspr r10,SPRN_SRR1; \
- stw r10,crit_srr1@l(r8); \
- mfspr r8,SPRN_SPRG2; /* SPRG2 only used in criticals */ \
+ mtspr CRIT_SPRG,r8; \
+ BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
+ stw r10,GPR10-INT_FRAME_SIZE(r8); \
+ stw r11,GPR11-INT_FRAME_SIZE(r8); \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
- lis r11,critical_stack_top@h; \
- ori r11,r11,critical_stack_top@l; \
+ mr r11,r8; \
+ mfspr r8,CRIT_SPRG; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
@@ -100,7 +126,7 @@
stw r1,GPR1(r11); \
mfspr r9,SPRN_CSRR1; \
stw r1,0(r11); \
- tovirt(r1,r11); \
+ mr r1,r11; \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
@@ -109,43 +135,18 @@
/*
* Exception prolog for machine check exceptions. This is similar to
* the critical exception prolog, except that machine check exceptions
- * have their own save area. For Book E processors, we also have a
- * reserved register (SPRG6) that is only used in machine check exceptions
- * so we can free up a GPR to use as the base for indirect access to the
- * machine check exception save area. This is necessary since the MMU
- * is always on and the save area is offset from KERNELBASE.
+ * have their stack.
*/
#define MCHECK_EXCEPTION_PROLOG \
- mtspr SPRN_SPRG6W,r8; /* SPRG6 used in machine checks */ \
- lis r8,mcheck_save@ha; \
- stw r10,mcheck_r10@l(r8); \
- stw r11,mcheck_r11@l(r8); \
- mfspr r10,SPRN_SPRG0; \
- stw r10,mcheck_sprg0@l(r8); \
- mfspr r10,SPRN_SPRG1; \
- stw r10,mcheck_sprg1@l(r8); \
- mfspr r10,SPRN_SPRG4R; \
- stw r10,mcheck_sprg4@l(r8); \
- mfspr r10,SPRN_SPRG5R; \
- stw r10,mcheck_sprg5@l(r8); \
- mfspr r10,SPRN_SPRG7R; \
- stw r10,mcheck_sprg7@l(r8); \
- mfspr r10,SPRN_PID; \
- stw r10,mcheck_pid@l(r8); \
- mfspr r10,SPRN_SRR0; \
- stw r10,mcheck_srr0@l(r8); \
- mfspr r10,SPRN_SRR1; \
- stw r10,mcheck_srr1@l(r8); \
- mfspr r10,SPRN_CSRR0; \
- stw r10,mcheck_csrr0@l(r8); \
- mfspr r10,SPRN_CSRR1; \
- stw r10,mcheck_csrr1@l(r8); \
- mfspr r8,SPRN_SPRG6R; /* SPRG6 used in machine checks */ \
+ mtspr MCHECK_SPRG,r8; \
+ BOOKE_LOAD_MCHECK_STACK; /* r8 points to the mcheck stack */\
+ stw r10,GPR10-INT_FRAME_SIZE(r8); \
+ stw r11,GPR11-INT_FRAME_SIZE(r8); \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
- lis r11,mcheck_stack_top@h; \
- ori r11,r11,mcheck_stack_top@l; \
+ mr r11,r8; \
+ mfspr r8,MCHECK_SPRG; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
@@ -165,7 +166,7 @@
stw r1,GPR1(r11); \
mfspr r9,SPRN_MCSRR1; \
stw r1,0(r11); \
- tovirt(r1,r11); \
+ mr r1,r11; \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
@@ -289,11 +290,11 @@ label:
mtspr SPRN_CSRR1,r9; \
lwz r9,GPR9(r11); \
lwz r12,GPR12(r11); \
- mtspr SPRN_SPRG2,r8; /* SPRG2 only used in criticals */ \
- lis r8,crit_save@ha; \
- lwz r10,crit_r10@l(r8); \
- lwz r11,crit_r11@l(r8); \
- mfspr r8,SPRN_SPRG2; \
+ mtspr CRIT_SPRG,r8; \
+ BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
+ lwz r10,GPR10-INT_FRAME_SIZE(r8); \
+ lwz r11,GPR11-INT_FRAME_SIZE(r8); \
+ mfspr r8,CRIT_SPRG; \
\
rfci; \
b .; \
diff --git a/arch/ppc/kernel/head_e500.S b/arch/ppc/kernel/head_e500.S
index d83353d5eab56..e478de5a92d32 100644
--- a/arch/ppc/kernel/head_e500.S
+++ b/arch/ppc/kernel/head_e500.S
@@ -33,6 +33,7 @@
*/
#include <linux/config.h>
+#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
@@ -789,8 +790,6 @@ load_up_spe:
SYNC
rfi
-
-
/*
* SPE unavailable trap from kernel - print a message, but let
* the task use SPE in the kernel until it returns to user mode.
@@ -929,78 +928,13 @@ _GLOBAL(empty_zero_page)
_GLOBAL(swapper_pg_dir)
.space 4096
+/* Reserved 4k for the critical exception stack & 4k for the machine
+ * check stack per CPU for kernel mode exceptions */
.section .bss
-/* Stack for handling critical exceptions from kernel mode */
-critical_stack_bottom:
- .space 4096
-critical_stack_top:
- .previous
-
-/* Stack for handling machine check exceptions from kernel mode */
-mcheck_stack_bottom:
- .space 4096
-mcheck_stack_top:
- .previous
-
-/*
- * This area is used for temporarily saving registers during the
- * critical and machine check exception prologs. It must always
- * follow the page aligned allocations, so it starts on a page
- * boundary, ensuring that all crit_save areas are in a single
- * page.
- */
-
-/* crit_save */
-_GLOBAL(crit_save)
- .space 4
-_GLOBAL(crit_r10)
- .space 4
-_GLOBAL(crit_r11)
- .space 4
-_GLOBAL(crit_sprg0)
- .space 4
-_GLOBAL(crit_sprg1)
- .space 4
-_GLOBAL(crit_sprg4)
- .space 4
-_GLOBAL(crit_sprg5)
- .space 4
-_GLOBAL(crit_sprg7)
- .space 4
-_GLOBAL(crit_pid)
- .space 4
-_GLOBAL(crit_srr0)
- .space 4
-_GLOBAL(crit_srr1)
- .space 4
-
-/* mcheck_save */
-_GLOBAL(mcheck_save)
- .space 4
-_GLOBAL(mcheck_r10)
- .space 4
-_GLOBAL(mcheck_r11)
- .space 4
-_GLOBAL(mcheck_sprg0)
- .space 4
-_GLOBAL(mcheck_sprg1)
- .space 4
-_GLOBAL(mcheck_sprg4)
- .space 4
-_GLOBAL(mcheck_sprg5)
- .space 4
-_GLOBAL(mcheck_sprg7)
- .space 4
-_GLOBAL(mcheck_pid)
- .space 4
-_GLOBAL(mcheck_srr0)
- .space 4
-_GLOBAL(mcheck_srr1)
- .space 4
-_GLOBAL(mcheck_csrr0)
- .space 4
-_GLOBAL(mcheck_csrr1)
- .space 4
+ .align 12
+exception_stack_bottom:
+ .space BOOKE_EXCEPTION_STACK_SIZE * NR_CPUS
+_GLOBAL(exception_stack_top)
/*
* This space gets a copy of optional info passed to us by the bootstrap
@@ -1016,4 +950,3 @@ _GLOBAL(cmd_line)
abatron_pteptrs:
.space 8
-
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index 513c5ecdcd4f5..761b8c7b25d27 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -135,25 +135,11 @@ static struct irqaction cpm2_irqaction = {
static void __init
mpc8560_ads_init_IRQ(void)
{
- int i;
- volatile cpm2_map_t *immap = cpm2_immr;
-
/* Setup OpenPIC */
mpc85xx_ads_init_IRQ();
- /* disable all CPM interupts */
- immap->im_intctl.ic_simrh = 0x0;
- immap->im_intctl.ic_simrl = 0x0;
-
- for (i = CPM_IRQ_OFFSET; i < (NR_CPM_INTS + CPM_IRQ_OFFSET); i++)
- irq_desc[i].handler = &cpm2_pic;
-
- /* Initialize the default interrupt mapping priorities,
- * in case the boot rom changed something on us.
- */
- immap->im_intctl.ic_sicr = 0;
- immap->im_intctl.ic_scprrh = 0x05309770;
- immap->im_intctl.ic_scprrl = 0x05309770;
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index 5e80b9dc4ed4f..6c020d67ad704 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -181,10 +181,6 @@ void __init
mpc85xx_cds_init_IRQ(void)
{
bd_t *binfo = (bd_t *) __res;
-#ifdef CONFIG_CPM2
- volatile cpm2_map_t *immap = cpm2_immr;
- int i;
-#endif
/* Determine the Physical Address of the OpenPIC regs */
phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
@@ -203,19 +199,8 @@ mpc85xx_cds_init_IRQ(void)
openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
#ifdef CONFIG_CPM2
- /* disable all CPM interupts */
- immap->im_intctl.ic_simrh = 0x0;
- immap->im_intctl.ic_simrl = 0x0;
-
- for (i = CPM_IRQ_OFFSET; i < (NR_CPM_INTS + CPM_IRQ_OFFSET); i++)
- irq_desc[i].handler = &cpm2_pic;
-
- /* Initialize the default interrupt mapping priorities,
- * in case the boot rom changed something on us.
- */
- immap->im_intctl.ic_sicr = 0;
- immap->im_intctl.ic_scprrh = 0x05309770;
- immap->im_intctl.ic_scprrl = 0x05309770;
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
#endif
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index 6184b533035a1..bc95836e417c5 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -201,7 +201,6 @@ static void __init
gp3_init_IRQ(void)
{
int i;
- volatile cpm2_map_t *immap = cpm2_immr;
bd_t *binfo = (bd_t *) __res;
/*
@@ -227,24 +226,8 @@ gp3_init_IRQ(void)
*/
openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
- /*
- * Setup CPM2 PIC
- */
-
- /* disable all CPM interupts */
- immap->im_intctl.ic_simrh = 0x0;
- immap->im_intctl.ic_simrl = 0x0;
-
- for (i = CPM_IRQ_OFFSET; i < (NR_CPM_INTS + CPM_IRQ_OFFSET); i++)
- irq_desc[i].handler = &cpm2_pic;
-
- /*
- * Initialize the default interrupt mapping priorities,
- * in case the boot rom changed something on us.
- */
- immap->im_intctl.ic_sicr = 0;
- immap->im_intctl.ic_scprrh = 0x05309770;
- immap->im_intctl.ic_scprrl = 0x05309770;
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index 7bc10c88c8240..5488a053f4155 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -45,7 +45,7 @@ obj-$(CONFIG_RADSTONE_PPC7D) += radstone_ppc7d.o
obj-$(CONFIG_SANDPOINT) += sandpoint.o
obj-$(CONFIG_SBC82xx) += sbc82xx.o
obj-$(CONFIG_SPRUCE) += spruce.o
-obj-$(CONFIG_LITE5200) += lite5200.o mpc5200.o
+obj-$(CONFIG_LITE5200) += lite5200.o
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
index 77fa7545bb0a5..b604cf8b3cae9 100644
--- a/arch/ppc/platforms/lite5200.c
+++ b/arch/ppc/platforms/lite5200.c
@@ -13,7 +13,7 @@
* Dale Farnsworth <dale.farnsworth@mvista.com> and
* Wolfgang Denk <wd@denx.de>
*
- * Copyright 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright 2003 Motorola Inc.
* Copyright 2003 MontaVista Software Inc.
* Copyright 2003 DENX Software Engineering (wd@denx.de)
@@ -29,11 +29,12 @@
#include <linux/kdev_t.h>
#include <linux/root_dev.h>
#include <linux/console.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
-#include <asm/ocp.h>
#include <asm/mpc52xx.h>
+#include <asm/ppc_sys.h>
#include <syslib/mpc52xx_pci.h>
@@ -46,33 +47,19 @@ EXPORT_SYMBOL(__res); /* For modules */
/* ======================================================================== */
-/* OCP device definition */
-/* For board/shared resources like PSCs */
+/* Platform specific code */
/* ======================================================================== */
-/* Be sure not to load conficting devices : e.g. loading the UART drivers for
- * PSC1 and then also loading a AC97 for this same PSC.
- * For details about how to create an entry, look in the doc of the concerned
- * driver ( eg drivers/serial/mpc52xx_uart.c for the PSC in uart mode )
- */
-
-static struct ocp_def board_ocp[] = {
- {
- .vendor = OCP_VENDOR_FREESCALE,
- .function = OCP_FUNC_PSC_UART,
- .index = 0,
- .paddr = MPC52xx_PSC1,
- .irq = MPC52xx_PSC1_IRQ,
- .pm = OCP_CPM_NA,
- },
- { /* Terminating entry */
- .vendor = OCP_VENDOR_INVALID
- }
-};
+/* Supported PSC function in "preference" order */
+struct mpc52xx_psc_func mpc52xx_psc_functions[] = {
+ { .id = 0,
+ .func = "uart",
+ },
+ { .id = -1, /* End entry */
+ .func = NULL,
+ }
+ };
-/* ======================================================================== */
-/* Platform specific code */
-/* ======================================================================== */
static int
lite5200_show_cpuinfo(struct seq_file *m)
@@ -92,21 +79,47 @@ lite5200_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
static void __init
lite5200_setup_cpu(void)
{
+ struct mpc52xx_cdm __iomem *cdm;
+ struct mpc52xx_gpio __iomem *gpio;
struct mpc52xx_intr __iomem *intr;
struct mpc52xx_xlb __iomem *xlb;
+ u32 port_config;
u32 intr_ctrl;
/* Map zones */
- xlb = ioremap(MPC52xx_XLB,sizeof(struct mpc52xx_xlb));
- intr = ioremap(MPC52xx_INTR,sizeof(struct mpc52xx_intr));
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+ gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
+ xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
+ intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
- if (!xlb || !intr) {
- printk("lite5200.c: Error while mapping XLB/INTR during "
+ if (!cdm || !gpio || !xlb || !intr) {
+ printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during"
"lite5200_setup_cpu\n");
goto unmap_regs;
}
+ /* Use internal 48 Mhz */
+ out_8(&cdm->ext_48mhz_en, 0x00);
+ out_8(&cdm->fd_enable, 0x01);
+ if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
+ out_be16(&cdm->fd_counters, 0x0001);
+ else
+ out_be16(&cdm->fd_counters, 0x5555);
+
+ /* Get port mux config */
+ port_config = in_be32(&gpio->port_config);
+
+ /* 48Mhz internal, pin is GPIO */
+ port_config &= ~0x00800000;
+
+ /* USB port */
+ port_config &= ~0x00007000; /* Differential mode - USB1 only */
+ port_config |= 0x00001000;
+
+ /* Commit port config */
+ out_be32(&gpio->port_config, port_config);
+
/* Configure the XLB Arbiter */
out_be32(&xlb->master_pri_enable, 0xff);
out_be32(&xlb->master_priority, 0x11111111);
@@ -124,6 +137,8 @@ lite5200_setup_cpu(void)
/* Unmap reg zone */
unmap_regs:
+ if (cdm) iounmap(cdm);
+ if (gpio) iounmap(gpio);
if (xlb) iounmap(xlb);
if (intr) iounmap(intr);
}
@@ -131,9 +146,6 @@ unmap_regs:
static void __init
lite5200_setup_arch(void)
{
- /* Add board OCP definitions */
- mpc52xx_add_board_devices(board_ocp);
-
/* CPU & Port mux setup */
lite5200_setup_cpu();
@@ -176,6 +188,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
}
}
+ /* PPC Sys identification */
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
/* BAT setup */
mpc52xx_set_bat();
@@ -184,7 +199,11 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
isa_mem_base = 0;
/* Powersave */
- powersave_nap = 1; /* We allow this platform to NAP */
+ /* This is provided as an example on how to do it. But you
+ need to be aware that NAP disable bus snoop and that may
+ be required for some devices to work properly, like USB ... */
+ /* powersave_nap = 1; */
+
/* Setup the ppc_md struct */
ppc_md.setup_arch = lite5200_setup_arch;
diff --git a/arch/ppc/platforms/lite5200.h b/arch/ppc/platforms/lite5200.h
index 833134b19c791..c1de2aa47175f 100644
--- a/arch/ppc/platforms/lite5200.h
+++ b/arch/ppc/platforms/lite5200.h
@@ -17,7 +17,7 @@
#define __PLATFORMS_LITE5200_H__
/* Serial port used for low-level debug */
-#define MPC52xx_PF_CONSOLE_PORT 0 /* PSC1 */
+#define MPC52xx_PF_CONSOLE_PORT 1 /* PSC1 */
#endif /* __PLATFORMS_LITE5200_H__ */
diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c
index e0c797f59ac99..ed2b1cebc19ae 100644
--- a/arch/ppc/platforms/pmac_backlight.c
+++ b/arch/ppc/platforms/pmac_backlight.c
@@ -12,6 +12,7 @@
#include <linux/stddef.h>
#include <linux/reboot.h>
#include <linux/nvram.h>
+#include <linux/console.h>
#include <asm/sections.h>
#include <asm/ptrace.h>
#include <asm/io.h>
@@ -25,14 +26,19 @@
#include <linux/adb.h>
#include <linux/pmu.h>
-static struct backlight_controller *backlighter = NULL;
-static void* backlighter_data = NULL;
-static int backlight_autosave = 0;
+static struct backlight_controller *backlighter;
+static void* backlighter_data;
+static int backlight_autosave;
static int backlight_level = BACKLIGHT_MAX;
static int backlight_enabled = 1;
+static int backlight_req_level = -1;
+static int backlight_req_enable = -1;
-void __pmac
-register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type)
+static void backlight_callback(void *);
+static DECLARE_WORK(backlight_work, backlight_callback, NULL);
+
+void __pmac register_backlight_controller(struct backlight_controller *ctrler,
+ void *data, char *type)
{
struct device_node* bk_node;
char *prop;
@@ -83,16 +89,18 @@ register_backlight_controller(struct backlight_controller *ctrler, void *data, c
backlight_level = req.reply[0] >> 4;
}
#endif
+ acquire_console_sem();
if (!backlighter->set_enable(1, backlight_level, data))
backlight_enabled = 1;
+ release_console_sem();
- printk(KERN_INFO "Registered \"%s\" backlight controller, level: %d/15\n",
- type, backlight_level);
+ printk(KERN_INFO "Registered \"%s\" backlight controller,"
+ "level: %d/15\n", type, backlight_level);
}
EXPORT_SYMBOL(register_backlight_controller);
-void __pmac
-unregister_backlight_controller(struct backlight_controller *ctrler, void *data)
+void __pmac unregister_backlight_controller(struct backlight_controller
+ *ctrler, void *data)
{
/* We keep the current backlight level (for now) */
if (ctrler == backlighter && data == backlighter_data)
@@ -100,22 +108,32 @@ unregister_backlight_controller(struct backlight_controller *ctrler, void *data)
}
EXPORT_SYMBOL(unregister_backlight_controller);
-int __pmac
-set_backlight_enable(int enable)
+static int __pmac __set_backlight_enable(int enable)
{
int rc;
if (!backlighter)
return -ENODEV;
- rc = backlighter->set_enable(enable, backlight_level, backlighter_data);
+ acquire_console_sem();
+ rc = backlighter->set_enable(enable, backlight_level,
+ backlighter_data);
if (!rc)
backlight_enabled = enable;
+ release_console_sem();
return rc;
}
+int __pmac set_backlight_enable(int enable)
+{
+ if (!backlighter)
+ return -ENODEV;
+ backlight_req_enable = enable;
+ schedule_work(&backlight_work);
+ return 0;
+}
+
EXPORT_SYMBOL(set_backlight_enable);
-int __pmac
-get_backlight_enable(void)
+int __pmac get_backlight_enable(void)
{
if (!backlighter)
return -ENODEV;
@@ -123,8 +141,7 @@ get_backlight_enable(void)
}
EXPORT_SYMBOL(get_backlight_enable);
-int __pmac
-set_backlight_level(int level)
+static int __pmac __set_backlight_level(int level)
{
int rc = 0;
@@ -134,10 +151,12 @@ set_backlight_level(int level)
level = BACKLIGHT_OFF;
if (level > BACKLIGHT_MAX)
level = BACKLIGHT_MAX;
+ acquire_console_sem();
if (backlight_enabled)
rc = backlighter->set_level(level, backlighter_data);
if (!rc)
backlight_level = level;
+ release_console_sem();
if (!rc && !backlight_autosave) {
level <<=1;
if (level & 0x10)
@@ -146,13 +165,38 @@ set_backlight_level(int level)
}
return rc;
}
+int __pmac set_backlight_level(int level)
+{
+ if (!backlighter)
+ return -ENODEV;
+ backlight_req_level = level;
+ schedule_work(&backlight_work);
+ return 0;
+}
+
EXPORT_SYMBOL(set_backlight_level);
-int __pmac
-get_backlight_level(void)
+int __pmac get_backlight_level(void)
{
if (!backlighter)
return -ENODEV;
return backlight_level;
}
EXPORT_SYMBOL(get_backlight_level);
+
+static void backlight_callback(void *dummy)
+{
+ int level, enable;
+
+ do {
+ level = backlight_req_level;
+ enable = backlight_req_enable;
+ mb();
+
+ if (level >= 0)
+ __set_backlight_level(level);
+ if (enable >= 0)
+ __set_backlight_enable(enable);
+ } while(cmpxchg(&backlight_req_level, level, -1) != level ||
+ cmpxchg(&backlight_req_enable, enable, -1) != enable);
+}
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 830d00da5db0b..dd418ea3426c7 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -108,7 +108,8 @@ ifeq ($(CONFIG_83xx),y)
obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
endif
obj-$(CONFIG_MPC8555_CDS) += todc_time.o
-obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_setup.o mpc52xx_pic.o
+obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_setup.o mpc52xx_pic.o \
+ mpc52xx_sys.o mpc52xx_devices.o ppc_sys.o
ifeq ($(CONFIG_PPC_MPC52xx),y)
obj-$(CONFIG_PCI) += mpc52xx_pci.o
endif
diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c
index bd8335b84d93a..954b07fc1df39 100644
--- a/arch/ppc/syslib/cpm2_pic.c
+++ b/arch/ppc/syslib/cpm2_pic.c
@@ -32,15 +32,17 @@ static u_char irq_to_siureg[] = {
0, 0, 0, 0, 0, 0, 0, 0
};
+/* bit numbers do not match the docs, these are precomputed so the bit for
+ * a given irq is (1 << irq_to_siubit[irq]) */
static u_char irq_to_siubit[] = {
- 31, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 27, 28, 29, 30,
- 29, 30, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 27, 28, 31,
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 15, 14, 13, 12, 11, 10, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 0
+ 0, 15, 14, 13, 12, 11, 10, 9,
+ 8, 7, 6, 5, 4, 3, 2, 1,
+ 2, 1, 15, 14, 13, 12, 11, 10,
+ 9, 8, 7, 6, 5, 4, 3, 0,
+ 31, 30, 29, 28, 27, 26, 25, 24,
+ 23, 22, 21, 20, 19, 18, 17, 16,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
};
static void cpm2_mask_irq(unsigned int irq_nr)
@@ -48,11 +50,13 @@ static void cpm2_mask_irq(unsigned int irq_nr)
int bit, word;
volatile uint *simr;
+ irq_nr -= CPM_IRQ_OFFSET;
+
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
- ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ ppc_cached_irq_mask[word] &= ~(1 << bit);
simr[word] = ppc_cached_irq_mask[word];
}
@@ -61,11 +65,13 @@ static void cpm2_unmask_irq(unsigned int irq_nr)
int bit, word;
volatile uint *simr;
+ irq_nr -= CPM_IRQ_OFFSET;
+
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
- ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ ppc_cached_irq_mask[word] |= 1 << bit;
simr[word] = ppc_cached_irq_mask[word];
}
@@ -74,14 +80,16 @@ static void cpm2_mask_and_ack(unsigned int irq_nr)
int bit, word;
volatile uint *simr, *sipnr;
+ irq_nr -= CPM_IRQ_OFFSET;
+
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
sipnr = &(cpm2_immr->im_intctl.ic_sipnrh);
- ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ ppc_cached_irq_mask[word] &= ~(1 << bit);
simr[word] = ppc_cached_irq_mask[word];
- sipnr[word] = 1 << (31 - bit);
+ sipnr[word] = 1 << bit;
}
static void cpm2_end_irq(unsigned int irq_nr)
@@ -92,29 +100,25 @@ static void cpm2_end_irq(unsigned int irq_nr)
if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
&& irq_desc[irq_nr].action) {
+ irq_nr -= CPM_IRQ_OFFSET;
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
- ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ ppc_cached_irq_mask[word] |= 1 << bit;
simr[word] = ppc_cached_irq_mask[word];
}
}
-struct hw_interrupt_type cpm2_pic = {
- " CPM2 SIU ",
- NULL,
- NULL,
- cpm2_unmask_irq,
- cpm2_mask_irq,
- cpm2_mask_and_ack,
- cpm2_end_irq,
- 0
+static struct hw_interrupt_type cpm2_pic = {
+ .typename = " CPM2 SIU ",
+ .enable = cpm2_unmask_irq,
+ .disable = cpm2_mask_irq,
+ .ack = cpm2_mask_and_ack,
+ .end = cpm2_end_irq,
};
-
-int
-cpm2_get_irq(struct pt_regs *regs)
+int cpm2_get_irq(struct pt_regs *regs)
{
int irq;
unsigned long bits;
@@ -126,5 +130,43 @@ cpm2_get_irq(struct pt_regs *regs)
if (irq == 0)
return(-1);
- return irq;
+ return irq+CPM_IRQ_OFFSET;
+}
+
+void cpm2_init_IRQ(void)
+{
+ int i;
+
+ /* Clear the CPM IRQ controller, in case it has any bits set
+ * from the bootloader
+ */
+
+ /* Mask out everything */
+ cpm2_immr->im_intctl.ic_simrh = 0x00000000;
+ cpm2_immr->im_intctl.ic_simrl = 0x00000000;
+ wmb();
+
+ /* Ack everything */
+ cpm2_immr->im_intctl.ic_sipnrh = 0xffffffff;
+ cpm2_immr->im_intctl.ic_sipnrl = 0xffffffff;
+ wmb();
+
+ /* Dummy read of the vector */
+ i = cpm2_immr->im_intctl.ic_sivec;
+ rmb();
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ cpm2_immr->im_intctl.ic_sicr = 0;
+ cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
+ cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
+
+
+ /* Enable chaining to OpenPIC, and make everything level
+ */
+ for (i = 0; i < NR_CPM_INTS; i++) {
+ irq_desc[i+CPM_IRQ_OFFSET].handler = &cpm2_pic;
+ irq_desc[i+CPM_IRQ_OFFSET].status |= IRQ_LEVEL;
+ }
}
diff --git a/arch/ppc/syslib/cpm2_pic.h b/arch/ppc/syslib/cpm2_pic.h
index d05003b091f53..97cab8f13a1a0 100644
--- a/arch/ppc/syslib/cpm2_pic.h
+++ b/arch/ppc/syslib/cpm2_pic.h
@@ -1,7 +1,8 @@
#ifndef _PPC_KERNEL_CPM2_H
#define _PPC_KERNEL_CPM2_H
-extern struct hw_interrupt_type cpm2_pic;
extern int cpm2_get_irq(struct pt_regs *regs);
+extern void cpm2_init_IRQ(void);
+
#endif /* _PPC_KERNEL_CPM2_H */
diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
index f3c12a51bf3e0..23ea3f694de20 100644
--- a/arch/ppc/syslib/m8260_setup.c
+++ b/arch/ppc/syslib/m8260_setup.c
@@ -167,18 +167,12 @@ m8260_show_cpuinfo(struct seq_file *m)
static void __init
m8260_init_IRQ(void)
{
- int i;
-
- for ( i = 0 ; i < NR_SIU_INTS ; i++ )
- irq_desc[i].handler = &cpm2_pic;
+ cpm2_init_IRQ();
/* Initialize the default interrupt mapping priorities,
* in case the boot rom changed something on us.
*/
- cpm2_immr->im_intctl.ic_sicr = 0;
cpm2_immr->im_intctl.ic_siprr = 0x05309770;
- cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
- cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
}
/*
diff --git a/arch/ppc/syslib/mpc52xx_devices.c b/arch/ppc/syslib/mpc52xx_devices.c
new file mode 100644
index 0000000000000..ad5182efca1dd
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_devices.c
@@ -0,0 +1,318 @@
+/*
+ * arch/ppc/syslib/mpc52xx_devices.c
+ *
+ * Freescale MPC52xx device descriptions
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/fsl_devices.h>
+#include <linux/resource.h>
+#include <asm/mpc52xx.h>
+#include <asm/ppc_sys.h>
+
+
+static u64 mpc52xx_dma_mask = 0xffffffffULL;
+
+static struct fsl_i2c_platform_data mpc52xx_fsl_i2c_pdata = {
+ .device_flags = FSL_I2C_DEV_CLOCK_5200,
+};
+
+
+/* We use relative offsets for IORESOURCE_MEM to be independent from the
+ * MBAR location at compile time
+ */
+
+/* TODO Add the BestComm initiator channel to the device definitions,
+ possibly using IORESOURCE_DMA. But that's when BestComm is ready ... */
+
+struct platform_device ppc_sys_platform_devices[] = {
+ [MPC52xx_MSCAN1] = {
+ .name = "mpc52xx-mscan",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0900,
+ .end = 0x097f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_MSCAN1_IRQ,
+ .end = MPC52xx_MSCAN1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_MSCAN2] = {
+ .name = "mpc52xx-mscan",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0980,
+ .end = 0x09ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_MSCAN2_IRQ,
+ .end = MPC52xx_MSCAN2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_SPI] = {
+ .name = "mpc52xx-spi",
+ .id = -1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0f00,
+ .end = 0x0f1f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "modf",
+ .start = MPC52xx_SPI_MODF_IRQ,
+ .end = MPC52xx_SPI_MODF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "spif",
+ .start = MPC52xx_SPI_SPIF_IRQ,
+ .end = MPC52xx_SPI_SPIF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_USB] = {
+ .name = "ppc-soc-ohci",
+ .id = -1,
+ .num_resources = 2,
+ .dev.dma_mask = &mpc52xx_dma_mask,
+ .dev.coherent_dma_mask = 0xffffffffULL,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x1000,
+ .end = 0x10ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_USB_IRQ,
+ .end = MPC52xx_USB_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_BDLC] = {
+ .name = "mpc52xx-bdlc",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x1300,
+ .end = 0x130f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_BDLC_IRQ,
+ .end = MPC52xx_BDLC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC1] = {
+ .name = "mpc52xx-psc",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2000,
+ .end = 0x209f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC1_IRQ,
+ .end = MPC52xx_PSC1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC2] = {
+ .name = "mpc52xx-psc",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2200,
+ .end = 0x229f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC2_IRQ,
+ .end = MPC52xx_PSC2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC3] = {
+ .name = "mpc52xx-psc",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2400,
+ .end = 0x249f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC3_IRQ,
+ .end = MPC52xx_PSC3_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC4] = {
+ .name = "mpc52xx-psc",
+ .id = 3,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2600,
+ .end = 0x269f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC4_IRQ,
+ .end = MPC52xx_PSC4_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC5] = {
+ .name = "mpc52xx-psc",
+ .id = 4,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2800,
+ .end = 0x289f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC5_IRQ,
+ .end = MPC52xx_PSC5_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC6] = {
+ .name = "mpc52xx-psc",
+ .id = 5,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2c00,
+ .end = 0x2c9f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC6_IRQ,
+ .end = MPC52xx_PSC6_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_FEC] = {
+ .name = "mpc52xx-fec",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3000,
+ .end = 0x33ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_FEC_IRQ,
+ .end = MPC52xx_FEC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_ATA] = {
+ .name = "mpc52xx-ata",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3a00,
+ .end = 0x3aff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_ATA_IRQ,
+ .end = MPC52xx_ATA_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_I2C1] = {
+ .name = "fsl-i2c",
+ .id = 0,
+ .dev.platform_data = &mpc52xx_fsl_i2c_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3d00,
+ .end = 0x3d1f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_I2C1_IRQ,
+ .end = MPC52xx_I2C1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_I2C2] = {
+ .name = "fsl-i2c",
+ .id = 1,
+ .dev.platform_data = &mpc52xx_fsl_i2c_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3d40,
+ .end = 0x3d5f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_I2C2_IRQ,
+ .end = MPC52xx_I2C2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+};
+
+
+static int __init mach_mpc52xx_fixup(struct platform_device *pdev)
+{
+ ppc_sys_fixup_mem_resource(pdev, MPC52xx_MBAR);
+ return 0;
+}
+
+static int __init mach_mpc52xx_init(void)
+{
+ ppc_sys_device_fixup = mach_mpc52xx_fixup;
+ return 0;
+}
+
+postcore_initcall(mach_mpc52xx_init);
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
index 347be33954cd5..c723efd954a6a 100644
--- a/arch/ppc/syslib/mpc52xx_pci.c
+++ b/arch/ppc/syslib/mpc52xx_pci.c
@@ -183,7 +183,7 @@ mpc52xx_find_bridges(void)
pci_assign_all_busses = 1;
- pci_regs = ioremap(MPC52xx_PCI, sizeof(struct mpc52xx_pci));
+ pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE);
if (!pci_regs)
return;
diff --git a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c
index 1c5838f9d292a..4c4497e62517d 100644
--- a/arch/ppc/syslib/mpc52xx_pic.c
+++ b/arch/ppc/syslib/mpc52xx_pic.c
@@ -180,8 +180,8 @@ mpc52xx_init_irq(void)
u32 intr_ctrl;
/* Remap the necessary zones */
- intr = ioremap(MPC52xx_INTR, sizeof(struct mpc52xx_intr));
- sdma = ioremap(MPC52xx_SDMA, sizeof(struct mpc52xx_sdma));
+ intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+ sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
if ((intr==NULL) || (sdma==NULL))
panic("Can't ioremap PIC/SDMA register for init_irq !");
diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
index c0ecb24210c39..bb2374585a7b9 100644
--- a/arch/ppc/syslib/mpc52xx_setup.c
+++ b/arch/ppc/syslib/mpc52xx_setup.c
@@ -23,7 +23,6 @@
#include <asm/time.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
-#include <asm/ocp.h>
#include <asm/pgtable.h>
#include <asm/ppcboot.h>
@@ -39,18 +38,14 @@ static int core_mult[] = { /* CPU Frequency multiplier, taken */
void
mpc52xx_restart(char *cmd)
{
- struct mpc52xx_gpt __iomem *gpt0 =
- (struct mpc52xx_gpt __iomem *) MPC52xx_GPTx(0);
+ struct mpc52xx_gpt __iomem *gpt0 = MPC52xx_VA(MPC52xx_GPTx_OFFSET(0));
local_irq_disable();
/* Turn on the watchdog and wait for it to expire. It effectively
does a reset */
- if (gpt0 != NULL) {
- out_be32(&gpt0->count, 0x000000ff);
- out_be32(&gpt0->mode, 0x00009004);
- } else
- printk(KERN_ERR "mpc52xx_restart: Unable to ioremap GPT0 registers, -> looping ...");
+ out_be32(&gpt0->count, 0x000000ff);
+ out_be32(&gpt0->mode, 0x00009004);
while (1);
}
@@ -96,9 +91,7 @@ mpc52xx_map_io(void)
#ifdef CONFIG_SERIAL_TEXT_DEBUG
-#ifdef MPC52xx_PF_CONSOLE_PORT
-#define MPC52xx_CONSOLE MPC52xx_PSCx(MPC52xx_PF_CONSOLE_PORT)
-#else
+#ifndef MPC52xx_PF_CONSOLE_PORT
#error "mpc52xx PSC for console not selected"
#endif
@@ -114,8 +107,9 @@ void
mpc52xx_progress(char *s, unsigned short hex)
{
char c;
- struct mpc52xx_psc __iomem *psc =
- (struct mpc52xx_psc __iomem *)MPC52xx_CONSOLE;
+ struct mpc52xx_psc __iomem *psc;
+
+ psc = MPC52xx_VA(MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT));
while ((c = *s++) != 0) {
if (c == '\n')
@@ -144,7 +138,7 @@ mpc52xx_find_end_of_memory(void)
u32 sdram_config_0, sdram_config_1;
/* Temp BAT2 mapping active when this is called ! */
- mmap_ctl = (struct mpc52xx_mmap_ctl __iomem *) MPC52xx_MMAP_CTL;
+ mmap_ctl = MPC52xx_VA(MPC52xx_MMAP_CTL_OFFSET);
sdram_config_0 = in_be32(&mmap_ctl->sdram0);
sdram_config_1 = in_be32(&mmap_ctl->sdram1);
@@ -174,8 +168,8 @@ mpc52xx_calibrate_decr(void)
struct mpc52xx_rtc __iomem *rtc;
struct mpc52xx_cdm __iomem *cdm;
- rtc = ioremap(MPC52xx_RTC, sizeof(struct mpc52xx_rtc));
- cdm = ioremap(MPC52xx_CDM, sizeof(struct mpc52xx_cdm));
+ rtc = ioremap(MPC52xx_PA(MPC52xx_RTC_OFFSET), MPC52xx_RTC_SIZE);
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
if ((rtc==NULL) || (cdm==NULL))
panic("Can't ioremap RTC/CDM while computing bus freq");
@@ -222,11 +216,15 @@ mpc52xx_calibrate_decr(void)
tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
}
+int mpc52xx_match_psc_function(int psc_idx, const char *func)
+{
+ struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;
-void __init
-mpc52xx_add_board_devices(struct ocp_def board_ocp[]) {
- while (board_ocp->vendor != OCP_VENDOR_INVALID)
- if(ocp_add_one_device(board_ocp++))
- printk("mpc5200-ocp: Failed to add board device !\n");
-}
+ while ((cf->id != -1) && (cf->func != NULL)) {
+ if ((cf->id == psc_idx) && !strcmp(cf->func,func))
+ return 1;
+ cf++;
+ }
+ return 0;
+}
diff --git a/arch/ppc/syslib/mpc52xx_sys.c b/arch/ppc/syslib/mpc52xx_sys.c
new file mode 100644
index 0000000000000..9a0f90aa8aac8
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_sys.c
@@ -0,0 +1,38 @@
+/*
+ * arch/ppc/syslib/mpc52xx_sys.c
+ *
+ * Freescale MPC52xx system descriptions
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <asm/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+ {
+ .ppc_sys_name = "5200",
+ .mask = 0xffff0000,
+ .value = 0x80110000,
+ .num_devices = 15,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC52xx_MSCAN1, MPC52xx_MSCAN2, MPC52xx_SPI,
+ MPC52xx_USB, MPC52xx_BDLC, MPC52xx_PSC1, MPC52xx_PSC2,
+ MPC52xx_PSC3, MPC52xx_PSC4, MPC52xx_PSC5, MPC52xx_PSC6,
+ MPC52xx_FEC, MPC52xx_ATA, MPC52xx_I2C1, MPC52xx_I2C2,
+ },
+ },
+ { /* default match */
+ .ppc_sys_name = "",
+ .mask = 0x00000000,
+ .value = 0x00000000,
+ },
+};
diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c
index 389c509d85823..d806a92a9401b 100644
--- a/arch/ppc/syslib/mpc85xx_sys.c
+++ b/arch/ppc/syslib/mpc85xx_sys.c
@@ -80,7 +80,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "8555",
.mask = 0xFFFF0000,
.value = 0x80710000,
- .num_devices = 20,
+ .num_devices = 19,
.device_list = (enum ppc_sys_devices[])
{
MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -88,7 +88,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC85xx_PERFMON, MPC85xx_DUART,
MPC85xx_CPM_SPI, MPC85xx_CPM_I2C, MPC85xx_CPM_SCC1,
MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3,
- MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2, MPC85xx_CPM_FCC3,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
MPC85xx_CPM_USB,
},
@@ -97,7 +97,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "8555E",
.mask = 0xFFFF0000,
.value = 0x80790000,
- .num_devices = 21,
+ .num_devices = 20,
.device_list = (enum ppc_sys_devices[])
{
MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -105,7 +105,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
MPC85xx_CPM_SPI, MPC85xx_CPM_I2C, MPC85xx_CPM_SCC1,
MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3,
- MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2, MPC85xx_CPM_FCC3,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
MPC85xx_CPM_USB,
},
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index eeb9c2ec91182..15c4a1455caee 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -278,6 +278,23 @@ config LPARCFG
Provide system capacity information via human readable
<key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
+config SECCOMP
+ bool "Enable seccomp to safely compute untrusted bytecode"
+ depends on PROC_FS
+ default y
+ help
+ This kernel feature is useful for number crunching applications
+ that may need to compute untrusted bytecode during their
+ execution. By using pipes or other transports made available to
+ the process as file descriptors supporting the read/write
+ syscalls, it's possible to isolate those applications in
+ their own address space using seccomp. Once seccomp is
+ enabled via /proc/<pid>/seccomp, it cannot be disabled
+ and the task is only allowed to execute a few safe syscalls
+ defined by each seccomp mode.
+
+ If unsure, say Y. Only embedded should say N here.
+
endmenu
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index 3db6ef3fed53b..da20120f22617 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -285,7 +285,7 @@ static unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
return mem_blocks;
}
-static void __init iSeries_parse_cmdline(void)
+static void __init iSeries_get_cmdline(void)
{
char *p, *q;
@@ -305,6 +305,8 @@ static void __init iSeries_parse_cmdline(void)
static void __init iSeries_init_early(void)
{
+ extern unsigned long memory_limit;
+
DBG(" -> iSeries_init_early()\n");
ppcdbg_initialize();
@@ -352,6 +354,31 @@ static void __init iSeries_init_early(void)
*/
build_iSeries_Memory_Map();
+ iSeries_get_cmdline();
+
+ /* Save unparsed command line copy for /proc/cmdline */
+ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+
+ /* Parse early parameters, in particular mem=x */
+ parse_early_param();
+
+ if (memory_limit) {
+ if (memory_limit < systemcfg->physicalMemorySize)
+ systemcfg->physicalMemorySize = memory_limit;
+ else {
+ printk("Ignoring mem=%lu >= ram_top.\n", memory_limit);
+ memory_limit = 0;
+ }
+ }
+
+ /* Bolt kernel mappings for all of memory (or just a bit if we've got a limit) */
+ iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
+
+ lmb_init();
+ lmb_add(0, systemcfg->physicalMemorySize);
+ lmb_analyze();
+ lmb_reserve(0, __pa(klimit));
+
/* Initialize machine-dependency vectors */
#ifdef CONFIG_SMP
smp_init_iSeries();
@@ -377,9 +404,6 @@ static void __init iSeries_init_early(void)
initrd_start = initrd_end = 0;
#endif /* CONFIG_BLK_DEV_INITRD */
-
- iSeries_parse_cmdline();
-
DBG(" <- iSeries_init_early()\n");
}
@@ -540,14 +564,6 @@ static void __init build_iSeries_Memory_Map(void)
* nextPhysChunk
*/
systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk);
-
- /* Bolt kernel mappings for all of memory */
- iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
-
- lmb_init();
- lmb_add(0, systemcfg->physicalMemorySize);
- lmb_analyze(); /* ?? */
- lmb_reserve(0, __pa(klimit));
}
/*
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index 4f5c16d4cc6dd..103daaf735734 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -71,7 +71,11 @@ static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->msr |= MSR_SE;
- regs->nip = (unsigned long)&p->ainsn.insn;
+ /*single step inline if it a breakpoint instruction*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
+ regs->nip = (unsigned long)p->addr;
+ else
+ regs->nip = (unsigned long)&p->ainsn.insn;
}
static inline int kprobe_handler(struct pt_regs *regs)
@@ -86,6 +90,12 @@ static inline int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->msr &= ~MSR_SE;
+ regs->msr |= kprobe_saved_msr;
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -128,10 +138,9 @@ static inline int kprobe_handler(struct pt_regs *regs)
kprobe_status = KPROBE_HIT_ACTIVE;
current_kprobe = p;
kprobe_saved_msr = regs->msr;
- if (p->pre_handler(p, regs)) {
+ if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
return 1;
- }
ss_probe:
prepare_singlestep(p, regs);
diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c
index 56d7ba87fe608..d6c6bd03d2a42 100644
--- a/arch/ppc64/kernel/lmb.c
+++ b/arch/ppc64/kernel/lmb.c
@@ -344,3 +344,29 @@ lmb_abs_to_phys(unsigned long aa)
return pa;
}
+
+/*
+ * Truncate the lmb list to memory_limit if it's set
+ * You must call lmb_analyze() after this.
+ */
+void __init lmb_enforce_memory_limit(void)
+{
+ extern unsigned long memory_limit;
+ unsigned long i, limit;
+ struct lmb_region *mem = &(lmb.memory);
+
+ if (! memory_limit)
+ return;
+
+ limit = memory_limit;
+ for (i = 0; i < mem->cnt; i++) {
+ if (limit > mem->region[i].size) {
+ limit -= mem->region[i].size;
+ continue;
+ }
+
+ mem->region[i].size = limit;
+ mem->cnt = i + 1;
+ break;
+ }
+}
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index 3e3c40f248cb9..1a5f59b769b91 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -912,6 +912,8 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
const char *full_path, void *data)
{
u32 *prop;
+ u64 *prop64;
+ extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end;
if (strcmp(full_path, "/chosen") != 0)
return 0;
@@ -928,6 +930,18 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
iommu_force_on = 1;
+ prop64 = (u64*)get_flat_dt_prop(node, "linux,memory-limit", NULL);
+ if (prop64)
+ memory_limit = *prop64;
+
+ prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
+ if (prop64)
+ tce_alloc_start = *prop64;
+
+ prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
+ if (prop64)
+ tce_alloc_end = *prop64;
+
#ifdef CONFIG_PPC_RTAS
/* To help early debugging via the front panel, we retreive a minimal
* set of RTAS infos now if available
@@ -1067,6 +1081,7 @@ void __init early_init_devtree(void *params)
lmb_init();
scan_flat_dt(early_init_dt_scan_root, NULL);
scan_flat_dt(early_init_dt_scan_memory, NULL);
+ lmb_enforce_memory_limit();
lmb_analyze();
systemcfg->physicalMemorySize = lmb_phys_mem_size();
lmb_reserve(0, __pa(klimit));
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index d3ebe99915182..8dffa9ae2623d 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -177,6 +177,10 @@ static int __initdata of_platform;
static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
+static unsigned long __initdata prom_memory_limit;
+static unsigned long __initdata prom_tce_alloc_start;
+static unsigned long __initdata prom_tce_alloc_end;
+
static unsigned long __initdata alloc_top;
static unsigned long __initdata alloc_top_high;
static unsigned long __initdata alloc_bottom;
@@ -384,10 +388,70 @@ static int __init prom_setprop(phandle node, const char *pname,
(u32)(unsigned long) value, (u32) valuelen);
}
+/* We can't use the standard versions because of RELOC headaches. */
+#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
+ || ('a' <= (c) && (c) <= 'f') \
+ || ('A' <= (c) && (c) <= 'F'))
+
+#define isdigit(c) ('0' <= (c) && (c) <= '9')
+#define islower(c) ('a' <= (c) && (c) <= 'z')
+#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
+
+unsigned long prom_strtoul(const char *cp, const char **endp)
+{
+ unsigned long result = 0, base = 10, value;
+
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if (toupper(*cp) == 'X') {
+ cp++;
+ base = 16;
+ }
+ }
+
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
+ result = result * base + value;
+ cp++;
+ }
+
+ if (endp)
+ *endp = cp;
+
+ return result;
+}
+
+unsigned long prom_memparse(const char *ptr, const char **retptr)
+{
+ unsigned long ret = prom_strtoul(ptr, retptr);
+ int shift = 0;
+
+ /*
+ * We can't use a switch here because GCC *may* generate a
+ * jump table which won't work, because we're not running at
+ * the address we're linked at.
+ */
+ if ('G' == **retptr || 'g' == **retptr)
+ shift = 30;
+
+ if ('M' == **retptr || 'm' == **retptr)
+ shift = 20;
+
+ if ('K' == **retptr || 'k' == **retptr)
+ shift = 10;
+
+ if (shift) {
+ ret <<= shift;
+ (*retptr)++;
+ }
+
+ return ret;
+}
/*
* Early parsing of the command line passed to the kernel, used for
- * the options that affect the iommu
+ * "mem=x" and the options that affect the iommu
*/
static void __init early_cmdline_parse(void)
{
@@ -418,6 +482,14 @@ static void __init early_cmdline_parse(void)
else if (!strncmp(opt, RELOC("force"), 5))
RELOC(iommu_force_on) = 1;
}
+
+ opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
+ if (opt) {
+ opt += 4;
+ RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
+ /* Align to 16 MB == size of large page */
+ RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
+ }
}
/*
@@ -664,15 +736,7 @@ static void __init prom_init_mem(void)
}
}
- /* Setup our top/bottom alloc points, that is top of RMO or top of
- * segment 0 when running non-LPAR
- */
- if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
- RELOC(alloc_top) = RELOC(rmo_top);
- else
- RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top));
RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000);
- RELOC(alloc_top_high) = RELOC(ram_top);
/* Check if we have an initrd after the kernel, if we do move our bottom
* point to after it
@@ -682,7 +746,40 @@ static void __init prom_init_mem(void)
RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end));
}
+ /*
+ * If prom_memory_limit is set we reduce the upper limits *except* for
+ * alloc_top_high. This must be the real top of RAM so we can put
+ * TCE's up there.
+ */
+
+ RELOC(alloc_top_high) = RELOC(ram_top);
+
+ if (RELOC(prom_memory_limit)) {
+ if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
+ prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
+ RELOC(prom_memory_limit));
+ RELOC(prom_memory_limit) = 0;
+ } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
+ prom_printf("Ignoring mem=%x >= ram_top.\n",
+ RELOC(prom_memory_limit));
+ RELOC(prom_memory_limit) = 0;
+ } else {
+ RELOC(ram_top) = RELOC(prom_memory_limit);
+ RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
+ }
+ }
+
+ /*
+ * Setup our top alloc point, that is top of RMO or top of
+ * segment 0 when running non-LPAR.
+ */
+ if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
+ RELOC(alloc_top) = RELOC(rmo_top);
+ else
+ RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top));
+
prom_printf("memory layout at init:\n");
+ prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom));
prom_printf(" alloc_top : %x\n", RELOC(alloc_top));
prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
@@ -871,6 +968,16 @@ static void __init prom_initialize_tce_table(void)
reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
+ if (RELOC(prom_memory_limit)) {
+ /*
+ * We align the start to a 16MB boundary so we can map the TCE area
+ * using large pages if possible. The end should be the top of RAM
+ * so no need to align it.
+ */
+ RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, 0x1000000);
+ RELOC(prom_tce_alloc_end) = local_alloc_top;
+ }
+
/* Flag the first invalid entry */
prom_debug("ending prom_initialize_tce_table\n");
}
@@ -1684,9 +1791,21 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
*/
if (RELOC(ppc64_iommu_off))
prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0);
+
if (RELOC(iommu_force_on))
prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0);
+ if (RELOC(prom_memory_limit))
+ prom_setprop(_prom->chosen, "linux,memory-limit",
+ PTRRELOC(&prom_memory_limit), sizeof(RELOC(prom_memory_limit)));
+
+ if (RELOC(prom_tce_alloc_start)) {
+ prom_setprop(_prom->chosen, "linux,tce-alloc-start",
+ PTRRELOC(&prom_tce_alloc_start), sizeof(RELOC(prom_tce_alloc_start)));
+ prom_setprop(_prom->chosen, "linux,tce-alloc-end",
+ PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end)));
+ }
+
/*
* Now finally create the flattened device-tree
*/
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
index ac89fbdb65b44..354a287c67eb8 100644
--- a/arch/ppc64/kernel/ptrace.c
+++ b/arch/ppc64/kernel/ptrace.c
@@ -27,6 +27,7 @@
#include <linux/user.h>
#include <linux/security.h>
#include <linux/audit.h>
+#include <linux/seccomp.h>
#include <asm/uaccess.h>
#include <asm/page.h>
@@ -315,6 +316,8 @@ void do_syscall_trace_enter(struct pt_regs *regs)
void do_syscall_trace_leave(struct pt_regs *regs)
{
+ secure_computing(regs->gpr[0]);
+
if (unlikely(current->audit_context))
audit_syscall_exit(current, regs->result);
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index e0c547a9cfd31..21c57f539c293 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -636,12 +636,11 @@ void __init setup_system(void)
early_console_initialized = 1;
register_console(&udbg_console);
-#endif /* !CONFIG_PPC_ISERIES */
-
/* Save unparsed command line copy for /proc/cmdline */
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
parse_early_param();
+#endif /* !CONFIG_PPC_ISERIES */
#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
/*
@@ -800,20 +799,31 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
-#if 0 /* XXX not currently used */
+/*
+ * These three variables are used to save values passed to us by prom_init()
+ * via the device tree. The TCE variables are needed because with a memory_limit
+ * in force we may need to explicitly map the TCE are at the top of RAM.
+ */
unsigned long memory_limit;
+unsigned long tce_alloc_start;
+unsigned long tce_alloc_end;
+#ifdef CONFIG_PPC_ISERIES
+/*
+ * On iSeries we just parse the mem=X option from the command line.
+ * On pSeries it's a bit more complicated, see prom_init_mem()
+ */
static int __init early_parsemem(char *p)
{
if (!p)
return 0;
- memory_limit = memparse(p, &p);
+ memory_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
return 0;
}
early_param("mem", early_parsemem);
-#endif
+#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_MULTIPLATFORM
static int __init set_preferred_console(void)
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index 5fc27d0c5ed19..e48be12f518c4 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -149,6 +149,8 @@ void __init htab_initialize(void)
unsigned long pteg_count;
unsigned long mode_rw;
int i, use_largepages = 0;
+ unsigned long base = 0, size = 0;
+ extern unsigned long tce_alloc_start, tce_alloc_end;
DBG(" -> htab_initialize()\n");
@@ -204,8 +206,6 @@ void __init htab_initialize(void)
/* create bolted the linear mapping in the hash table */
for (i=0; i < lmb.memory.cnt; i++) {
- unsigned long base, size;
-
base = lmb.memory.region[i].physbase + KERNELBASE;
size = lmb.memory.region[i].size;
@@ -234,6 +234,25 @@ void __init htab_initialize(void)
#endif /* CONFIG_U3_DART */
create_pte_mapping(base, base + size, mode_rw, use_largepages);
}
+
+ /*
+ * If we have a memory_limit and we've allocated TCEs then we need to
+ * explicitly map the TCE area at the top of RAM. We also cope with the
+ * case that the TCEs start below memory_limit.
+ * tce_alloc_start/end are 16MB aligned so the mapping should work
+ * for either 4K or 16MB pages.
+ */
+ if (tce_alloc_start) {
+ tce_alloc_start += KERNELBASE;
+ tce_alloc_end += KERNELBASE;
+
+ if (base + size >= tce_alloc_start)
+ tce_alloc_start = base + size + 1;
+
+ create_pte_mapping(tce_alloc_start, tce_alloc_end,
+ mode_rw, use_largepages);
+ }
+
DBG(" <- htab_initialize()\n");
}
#undef KB
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index 5c603ba982310..ea862ec643d3a 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -285,6 +285,35 @@ static int cpu_numa_callback(struct notifier_block *nfb,
return ret;
}
+/*
+ * Check and possibly modify a memory region to enforce the memory limit.
+ *
+ * Returns the size the region should have to enforce the memory limit.
+ * This will either be the original value of size, a truncated value,
+ * or zero. If the returned value of size is 0 the region should be
+ * discarded as it lies wholy above the memory limit.
+ */
+static unsigned long __init numa_enforce_memory_limit(unsigned long start, unsigned long size)
+{
+ /*
+ * We use lmb_end_of_DRAM() in here instead of memory_limit because
+ * we've already adjusted it for the limit and it takes care of
+ * having memory holes below the limit.
+ */
+ extern unsigned long memory_limit;
+
+ if (! memory_limit)
+ return size;
+
+ if (start + size <= lmb_end_of_DRAM())
+ return size;
+
+ if (start >= lmb_end_of_DRAM())
+ return 0;
+
+ return lmb_end_of_DRAM() - start;
+}
+
static int __init parse_numa_properties(void)
{
struct device_node *cpu = NULL;
@@ -373,6 +402,13 @@ new_range:
if (max_domain < numa_domain)
max_domain = numa_domain;
+ if (! (size = numa_enforce_memory_limit(start, size))) {
+ if (--ranges)
+ goto new_range;
+ else
+ continue;
+ }
+
/*
* Initialize new node struct, or add to an existing one.
*/
@@ -405,8 +441,7 @@ new_range:
numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
numa_domain;
- ranges--;
- if (ranges)
+ if (--ranges)
goto new_range;
}
@@ -614,8 +649,11 @@ new_range:
if (numa_domain != nid)
continue;
- dbg("free_bootmem %lx %lx\n", mem_start, mem_size);
- free_bootmem_node(NODE_DATA(nid), mem_start, mem_size);
+ mem_size = numa_enforce_memory_limit(mem_start, mem_size);
+ if (mem_size) {
+ dbg("free_bootmem %lx %lx\n", mem_start, mem_size);
+ free_bootmem_node(NODE_DATA(nid), mem_start, mem_size);
+ }
if (--ranges) /* process all ranges in cell */
goto new_range;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index b1de24775c31e..80306bc8c799b 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -62,8 +62,8 @@ void bust_spinlocks(int yes)
oops_in_progress = 1;
} else {
int loglevel_save = console_loglevel;
- oops_in_progress = 0;
console_unblank();
+ oops_in_progress = 0;
/*
* OK, the message is on the console. Now we call printk()
* without oops_in_progress set so that printk will give klogd
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 7d97138f5d2e6..7066d7ba667a5 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -68,8 +68,14 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
regs->tstate |= TSTATE_PIL;
- regs->tpc = (unsigned long) &p->ainsn.insn[0];
- regs->tnpc = (unsigned long) &p->ainsn.insn[1];
+ /*single step inline, if it a breakpoint instruction*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION) {
+ regs->tpc = (unsigned long) p->addr;
+ regs->tnpc = current_kprobe_orig_tnpc;
+ } else {
+ regs->tpc = (unsigned long) &p->ainsn.insn[0];
+ regs->tnpc = (unsigned long) &p->ainsn.insn[1];
+ }
}
static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
@@ -97,6 +103,12 @@ static int kprobe_handler(struct pt_regs *regs)
*/
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
+ current_kprobe_orig_tstate_pil);
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -128,7 +140,7 @@ static int kprobe_handler(struct pt_regs *regs)
kprobe_status = KPROBE_HIT_ACTIVE;
current_kprobe = p;
- if (p->pre_handler(p, regs))
+ if (p->pre_handler && p->pre_handler(p, regs))
return 1;
ss_probe:
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index c27cab081ad28..b89989de364d1 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -16,7 +16,7 @@ config PT_PROXY
config GPROF
bool "Enable gprof support"
- depends on DEBUG_INFO && MODE_SKAS
+ depends on DEBUG_INFO && MODE_SKAS && !MODE_TT
help
This allows profiling of a User-Mode Linux kernel with the gprof
utility.
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index b760b5a2a3435..1f77deb3fd237 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -248,11 +248,8 @@ int write_chan(struct list_head *chans, const char *buf, int len,
n = chan->ops->write(chan->fd, buf, len, chan->data);
if (chan->primary) {
ret = n;
- if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))){
+ if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
reactivate_fd(chan->fd, write_irq);
- if (ret == -EAGAIN)
- ret = 0;
- }
}
}
return(ret);
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index d4286de17f070..6924f273ced9f 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -128,7 +128,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
ret = buffer_data(line, buf, len);
err = flush_buffer(line);
local_irq_restore(flags);
- if(err <= 0)
+ if(err <= 0 && (err != -EAGAIN || !ret))
ret = err;
}
else {
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index b514ea28d16c4..661d495e20448 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -9,15 +9,11 @@
#include "uml-config.h"
#include "user_constants.h"
-#ifdef UML_CONFIG_MODE_TT
-#include "sysdep/sc.h"
-#endif
-
-#ifdef UML_CONFIG_MODE_SKAS
-
#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+extern void update_debugregs(int seq);
+
/* syscall emulation path in ptrace */
#ifndef PTRACE_SYSEMU
@@ -28,9 +24,13 @@ void set_using_sysemu(int value);
int get_using_sysemu(void);
extern int sysemu_supported;
-#include "skas_ptregs.h"
+#ifdef UML_CONFIG_MODE_TT
+#include "sysdep/sc.h"
+#endif
-extern void update_debugregs(int seq);
+#ifdef UML_CONFIG_MODE_SKAS
+
+#include "skas_ptregs.h"
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index 36d9beec431b8..5db81ec9087d2 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -23,6 +23,9 @@ extern long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff);
+/* On i386 they choose a meaningless naming.*/
+#define __NR_kexec_load __NR_sys_kexec_load
+
#define ARCH_SYSCALLS \
[ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, \
[ __NR_break ] = (syscall_handler_t *) sys_ni_syscall, \
@@ -74,7 +77,7 @@ extern long sys_mmap2(unsigned long addr, unsigned long len,
[ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64, \
[ __NR_select ] = (syscall_handler_t *) old_select, \
[ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
+ [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
[ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \
[ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \
[ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \
@@ -97,19 +100,16 @@ extern long sys_mmap2(unsigned long addr, unsigned long len,
[ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
[ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
[ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
- [ 222 ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ 222 ] = (syscall_handler_t *) sys_ni_syscall, \
[ 223 ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \
[ 251 ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \
- [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \
- [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall,
-
+ [ 285 ] = (syscall_handler_t *) sys_ni_syscall,
+
/* 222 doesn't yet have a name in include/asm-i386/unistd.h */
-#define LAST_ARCH_SYSCALL __NR_vserver
+#define LAST_ARCH_SYSCALL 285
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 5eac9bed21ad3..915c82daffbd6 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -10,6 +10,9 @@
#include "uml-config.h"
#include "user_constants.h"
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
+
#ifdef UML_CONFIG_MODE_TT
#include "sysdep/sc.h"
#endif
@@ -17,9 +20,6 @@
#ifdef UML_CONFIG_MODE_SKAS
#include "skas_ptregs.h"
-#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
-
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index 65fd494420f99..b187a4157ff36 100644
--- a/arch/um/include/sysdep-x86_64/syscalls.h
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -71,12 +71,7 @@ extern syscall_handler_t sys_arch_prctl;
[ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \
[ __NR_semtimedop ] = (syscall_handler_t *) sys_semtimedop, \
- [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \
- [ 223 ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \
- [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall, \
[ 251 ] = (syscall_handler_t *) sys_ni_syscall,
#define LAST_ARCH_SYSCALL 251
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 82d19b451d5ea..668df13d8c9d6 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -108,12 +108,14 @@ static void tty_output(int master, int slave)
panic("check_sigio : write failed, errno = %d\n", errno);
while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
- if(got_sigio){
+ if (got_sigio) {
printk("Yes\n");
pty_output_sigio = 1;
+ } else if (n == -EAGAIN) {
+ printk("No, enabling workaround\n");
+ } else {
+ panic("check_sigio : read failed, err = %d\n", n);
}
- else if(n == -EAGAIN) printk("No, enabling workaround\n");
- else panic("check_sigio : read failed, err = %d\n", n);
}
static void tty_close(int master, int slave)
@@ -235,6 +237,8 @@ static int need_poll(int n)
return(0);
}
+/* Must be called with sigio_lock held, because it's needed by the marked
+ * critical section. */
static void update_thread(void)
{
unsigned long flags;
@@ -257,7 +261,7 @@ static void update_thread(void)
set_signals(flags);
return;
fail:
- sigio_lock();
+ /* Critical section start */
if(write_sigio_pid != -1)
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
@@ -265,7 +269,7 @@ static void update_thread(void)
os_close_file(sigio_private[1]);
os_close_file(write_sigio_fds[0]);
os_close_file(write_sigio_fds[1]);
- sigio_unlock();
+ /* Critical section end */
set_signals(flags);
}
@@ -418,19 +422,10 @@ int read_sigio_fd(int fd)
static void sigio_cleanup(void)
{
- if(write_sigio_pid != -1)
+ if (write_sigio_pid != -1) {
os_kill_process(write_sigio_pid, 1);
+ write_sigio_pid = -1;
+ }
}
__uml_exitcall(sigio_cleanup);
-
-/*
- * 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:
- */
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index c8e5fe49583ae..7575ec489b630 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -61,7 +61,8 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr)
void *arg;
int *res;
- va_copy(args, *(va_list *)arg_ptr);
+ /* Some old gccs recognize __va_copy, but not va_copy */
+ __va_copy(args, *(va_list *)arg_ptr);
addr = va_arg(args, unsigned long);
len = va_arg(args, int);
is_write = va_arg(args, int);
diff --git a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
index 202662a4e5251..7fc06c85b29d9 100644
--- a/arch/um/kernel/sys_call_table.c
+++ b/arch/um/kernel/sys_call_table.c
@@ -47,7 +47,6 @@ extern syscall_handler_t sys_vfork;
extern syscall_handler_t old_select;
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t sys_rt_sigsuspend;
-extern syscall_handler_t sys_vserver;
extern syscall_handler_t sys_mbind;
extern syscall_handler_t sys_get_mempolicy;
extern syscall_handler_t sys_set_mempolicy;
@@ -241,7 +240,8 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_epoll_create ] = (syscall_handler_t *) sys_epoll_create,
[ __NR_epoll_ctl ] = (syscall_handler_t *) sys_epoll_ctl,
[ __NR_epoll_wait ] = (syscall_handler_t *) sys_epoll_wait,
- [ __NR_set_tid_address ] = (syscall_handler_t *) sys_set_tid_address,
+ [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages,
+ [ __NR_set_tid_address ] = (syscall_handler_t *) sys_set_tid_address,
[ __NR_timer_create ] = (syscall_handler_t *) sys_timer_create,
[ __NR_timer_settime ] = (syscall_handler_t *) sys_timer_settime,
[ __NR_timer_gettime ] = (syscall_handler_t *) sys_timer_gettime,
@@ -251,12 +251,10 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_clock_gettime ] = (syscall_handler_t *) sys_clock_gettime,
[ __NR_clock_getres ] = (syscall_handler_t *) sys_clock_getres,
[ __NR_clock_nanosleep ] = (syscall_handler_t *) sys_clock_nanosleep,
- [ __NR_statfs64 ] = (syscall_handler_t *) sys_statfs64,
- [ __NR_fstatfs64 ] = (syscall_handler_t *) sys_fstatfs64,
[ __NR_tgkill ] = (syscall_handler_t *) sys_tgkill,
[ __NR_utimes ] = (syscall_handler_t *) sys_utimes,
- [ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64,
- [ __NR_vserver ] = (syscall_handler_t *) sys_vserver,
+ [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64,
+ [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_mbind ] = (syscall_handler_t *) sys_mbind,
[ __NR_get_mempolicy ] = (syscall_handler_t *) sys_get_mempolicy,
[ __NR_set_mempolicy ] = (syscall_handler_t *) sys_set_mempolicy,
@@ -266,14 +264,13 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_mq_timedreceive ] = (syscall_handler_t *) sys_mq_timedreceive,
[ __NR_mq_notify ] = (syscall_handler_t *) sys_mq_notify,
[ __NR_mq_getsetattr ] = (syscall_handler_t *) sys_mq_getsetattr,
- [ __NR_sys_kexec_load ] = (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_kexec_load ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_waitid ] = (syscall_handler_t *) sys_waitid,
- [ 285 ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_add_key ] = (syscall_handler_t *) sys_add_key,
[ __NR_request_key ] = (syscall_handler_t *) sys_request_key,
[ __NR_keyctl ] = (syscall_handler_t *) sys_keyctl,
ARCH_SYSCALLS
[ LAST_SYSCALL + 1 ... NR_syscalls ] =
- (syscall_handler_t *) sys_ni_syscall
+ (syscall_handler_t *) sys_ni_syscall
};
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index c75d1db0efc31..5c49d88eed3d0 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -47,7 +47,7 @@ char command_line[COMMAND_LINE_SIZE] = { 0 };
void add_arg(char *arg)
{
if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
- printf("add_arg: Too much command line!\n");
+ printf("add_arg: Too many command line arguments!\n");
exit(1);
}
if(strlen(command_line) > 0)
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index f0c459a4bfd58..68a9ab06ee7c2 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -65,7 +65,6 @@
#include <asm/types.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
-#include <asm/ipc.h>
#include <asm/atomic.h>
#include <asm/ldt.h>
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 131d24ef9a63d..4f2a852299b63 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -25,6 +25,8 @@
* interface to access function arguments.
* 2004-Oct Jim Keniston <kenistoj@us.ibm.com> and Prasanna S Panchamukhi
* <prasanna@in.ibm.com> adapted for x86_64
+ * 2005-Mar Roland McGrath <roland@redhat.com>
+ * Fixed to handle %rip-relative addressing mode correctly.
*/
#include <linux/config.h>
@@ -34,7 +36,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/preempt.h>
-#include <linux/vmalloc.h>
+#include <linux/moduleloader.h>
#include <asm/pgtable.h>
#include <asm/kdebug.h>
@@ -86,9 +88,132 @@ int arch_prepare_kprobe(struct kprobe *p)
return 0;
}
+/*
+ * Determine if the instruction uses the %rip-relative addressing mode.
+ * If it does, return the address of the 32-bit displacement word.
+ * If not, return null.
+ */
+static inline s32 *is_riprel(u8 *insn)
+{
+#define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf) \
+ (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \
+ (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \
+ (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \
+ (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \
+ << (row % 64))
+ static const u64 onebyte_has_modrm[256 / 64] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ W(0x00, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0)| /* 00 */
+ W(0x10, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0)| /* 10 */
+ W(0x20, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0)| /* 20 */
+ W(0x30, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0), /* 30 */
+ W(0x40, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 40 */
+ W(0x50, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 50 */
+ W(0x60, 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0)| /* 60 */
+ W(0x70, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 70 */
+ W(0x80, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 80 */
+ W(0x90, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 90 */
+ W(0xa0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* a0 */
+ W(0xb0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* b0 */
+ W(0xc0, 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0)| /* c0 */
+ W(0xd0, 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1)| /* d0 */
+ W(0xe0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* e0 */
+ W(0xf0, 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1) /* f0 */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ };
+ static const u64 twobyte_has_modrm[256 / 64] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ W(0x00, 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1)| /* 0f */
+ W(0x10, 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0)| /* 1f */
+ W(0x20, 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1)| /* 2f */
+ W(0x30, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 3f */
+ W(0x40, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 4f */
+ W(0x50, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 5f */
+ W(0x60, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 6f */
+ W(0x70, 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1), /* 7f */
+ W(0x80, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 8f */
+ W(0x90, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 9f */
+ W(0xa0, 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1)| /* af */
+ W(0xb0, 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1), /* bf */
+ W(0xc0, 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0)| /* cf */
+ W(0xd0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* df */
+ W(0xe0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* ef */
+ W(0xf0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0) /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ };
+#undef W
+ int need_modrm;
+
+ /* Skip legacy instruction prefixes. */
+ while (1) {
+ switch (*insn) {
+ case 0x66:
+ case 0x67:
+ case 0x2e:
+ case 0x3e:
+ case 0x26:
+ case 0x64:
+ case 0x65:
+ case 0x36:
+ case 0xf0:
+ case 0xf3:
+ case 0xf2:
+ ++insn;
+ continue;
+ }
+ break;
+ }
+
+ /* Skip REX instruction prefix. */
+ if ((*insn & 0xf0) == 0x40)
+ ++insn;
+
+ if (*insn == 0x0f) { /* Two-byte opcode. */
+ ++insn;
+ need_modrm = test_bit(*insn, twobyte_has_modrm);
+ } else { /* One-byte opcode. */
+ need_modrm = test_bit(*insn, onebyte_has_modrm);
+ }
+
+ if (need_modrm) {
+ u8 modrm = *++insn;
+ if ((modrm & 0xc7) == 0x05) { /* %rip+disp32 addressing mode */
+ /* Displacement follows ModRM byte. */
+ return (s32 *) ++insn;
+ }
+ }
+
+ /* No %rip-relative addressing mode here. */
+ return NULL;
+}
+
void arch_copy_kprobe(struct kprobe *p)
{
+ s32 *ripdisp;
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
+ ripdisp = is_riprel(p->ainsn.insn);
+ if (ripdisp) {
+ /*
+ * The copied instruction uses the %rip-relative
+ * addressing mode. Adjust the displacement for the
+ * difference between the original location of this
+ * instruction and the location of the copy that will
+ * actually be run. The tricky bit here is making sure
+ * that the sign extension happens correctly in this
+ * calculation, since we need a signed 32-bit result to
+ * be sign-extended to 64 bits when it's added to the
+ * %rip value and yield the same 64-bit result that the
+ * sign-extension of the original signed 32-bit
+ * displacement would have given.
+ */
+ s64 disp = (u8 *) p->addr + *ripdisp - (u8 *) p->ainsn.insn;
+ BUG_ON((s64) (s32) disp != disp); /* Sanity check. */
+ *ripdisp = disp;
+ }
}
void arch_remove_kprobe(struct kprobe *p)
@@ -108,8 +233,11 @@ static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
-
- regs->rip = (unsigned long)p->ainsn.insn;
+ /*single step inline if the instruction is an int3*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
+ regs->rip = (unsigned long)p->addr;
+ else
+ regs->rip = (unsigned long)p->ainsn.insn;
}
/*
@@ -131,6 +259,12 @@ int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->eflags &= ~TF_MASK;
+ regs->eflags |= kprobe_saved_rflags;
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -168,17 +302,16 @@ int kprobe_handler(struct pt_regs *regs)
if (is_IF_modifier(p->ainsn.insn))
kprobe_saved_rflags &= ~IF_MASK;
- if (p->pre_handler(p, regs)) {
+ if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
return 1;
- }
- ss_probe:
+ss_probe:
prepare_singlestep(p, regs);
kprobe_status = KPROBE_HIT_SS;
return 1;
- no_kprobe:
+no_kprobe:
preempt_enable_no_resched();
return ret;
}
@@ -439,8 +572,15 @@ static kprobe_opcode_t *get_insn_slot(void)
if (!kip) {
return NULL;
}
- kip->insns = (kprobe_opcode_t*) __vmalloc(PAGE_SIZE,
- GFP_KERNEL|__GFP_HIGHMEM, __pgprot(__PAGE_KERNEL_EXEC));
+
+ /*
+ * For the %rip-relative displacement fixups to be doable, we
+ * need our instruction copy to be within +/- 2GB of any data it
+ * might access via %rip. That is, within 2GB of where the
+ * kernel image and loaded module images reside. So we allocate
+ * a page in the module loading area.
+ */
+ kip->insns = module_alloc(PAGE_SIZE);
if (!kip->insns) {
kfree(kip);
return NULL;
@@ -481,7 +621,7 @@ static void free_insn_slot(kprobe_opcode_t *slot)
hlist_add_head(&kip->hlist,
&kprobe_insn_pages);
} else {
- vfree(kip->insns);
+ module_free(NULL, kip->insns);
kfree(kip);
}
}
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 33feab9c75691..171931ea7eaae 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -62,7 +62,7 @@ EXPORT_SYMBOL(boot_option_idle_override);
* Powermanagement idle function, if any..
*/
void (*pm_idle)(void);
-static cpumask_t cpu_idle_map;
+static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
void disable_hlt(void)
{
@@ -125,20 +125,31 @@ static void poll_idle (void)
}
}
-
void cpu_idle_wait(void)
{
- int cpu;
- cpumask_t map;
+ unsigned int cpu, this_cpu = get_cpu();
+ cpumask_t map;
+
+ set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+ put_cpu();
+
+ cpus_clear(map);
+ for_each_online_cpu(cpu) {
+ per_cpu(cpu_idle_state, cpu) = 1;
+ cpu_set(cpu, map);
+ }
- for_each_online_cpu(cpu)
- cpu_set(cpu, cpu_idle_map);
+ __get_cpu_var(cpu_idle_state) = 0;
- wmb();
- do {
- ssleep(1);
- cpus_and(map, cpu_idle_map, cpu_online_map);
- } while (!cpus_empty(map));
+ wmb();
+ do {
+ ssleep(1);
+ for_each_online_cpu(cpu) {
+ if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
+ cpu_clear(cpu, map);
+ }
+ cpus_and(map, map, cpu_online_map);
+ } while (!cpus_empty(map));
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
@@ -150,21 +161,21 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
*/
void cpu_idle (void)
{
- int cpu = smp_processor_id();
-
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
void (*idle)(void);
- if (cpu_isset(cpu, cpu_idle_map))
- cpu_clear(cpu, cpu_idle_map);
+ if (__get_cpu_var(cpu_idle_state))
+ __get_cpu_var(cpu_idle_state) = 0;
+
rmb();
idle = pm_idle;
if (!idle)
idle = default_idle;
idle();
}
+
schedule();
}
}
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index d0725cd1b9d68..e3cdbf9a88bd7 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -373,7 +373,10 @@ void smp_send_stop(void)
__smp_call_function(smp_really_stop_cpu, NULL, 0, 0);
if (!nolock)
spin_unlock(&call_lock);
- smp_stop_cpu();
+
+ local_irq_disable();
+ disable_local_APIC();
+ local_irq_enable();
}
/*
diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c
index 624bcf8e54731..477d8be57d64f 100644
--- a/arch/x86_64/kernel/sys_x86_64.c
+++ b/arch/x86_64/kernel/sys_x86_64.c
@@ -18,7 +18,6 @@
#include <linux/personality.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/ia32.h>
/*
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 8e1ace2d817e2..a0b5cf689e639 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -134,6 +134,8 @@ int device_power_down(pm_message_t state)
Done:
return error;
Error:
+ printk(KERN_ERR "Could not power down device %s: "
+ "error %d\n", kobject_name(&dev->kobj), error);
dpm_power_up();
goto Done;
}
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 08b2d48494694..02242e8ba9968 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -238,7 +238,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
q->make_request_fn = mfn;
q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
q->backing_dev_info.state = 0;
- q->backing_dev_info.memory_backed = 0;
+ q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
blk_queue_max_sectors(q, MAX_SECTORS);
blk_queue_hardsect_size(q, 512);
blk_queue_dma_alignment(q, 511);
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 6a126ee370d60..145c1fbffe013 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -325,7 +325,7 @@ static int rd_ioctl(struct inode *inode, struct file *file,
*/
static struct backing_dev_info rd_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK | BDI_CAP_MAP_COPY,
.unplug_io_fn = default_unplug_io_fn,
};
@@ -336,7 +336,7 @@ static struct backing_dev_info rd_backing_dev_info = {
*/
static struct backing_dev_info rd_file_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 0, /* Does contribute to dirty memory */
+ .capabilities = BDI_CAP_MAP_COPY, /* Does contribute to dirty memory */
.unplug_io_fn = default_unplug_io_fn,
};
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index acea9f08ea447..ce42889f98fbd 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -300,6 +300,7 @@ struct ub_dev {
/*
*/
+static void ub_cleanup(struct ub_dev *sc);
static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq);
static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
struct request *rq);
@@ -478,24 +479,55 @@ static int ub_id_get(void)
static void ub_id_put(int id)
{
+ unsigned long flags;
if (id < 0 || id >= UB_MAX_HOSTS) {
printk(KERN_ERR DRV_NAME ": bad host ID %d\n", id);
return;
}
+
+ spin_lock_irqsave(&ub_lock, flags);
if (ub_hostv[id] == 0) {
+ spin_unlock_irqrestore(&ub_lock, flags);
printk(KERN_ERR DRV_NAME ": freeing free host ID %d\n", id);
return;
}
ub_hostv[id] = 0;
+ spin_unlock_irqrestore(&ub_lock, flags);
+}
+
+/*
+ * Downcount for deallocation. This rides on two assumptions:
+ * - once something is poisoned, its refcount cannot grow
+ * - opens cannot happen at this time (del_gendisk was done)
+ * If the above is true, we can drop the lock, which we need for
+ * blk_cleanup_queue(): the silly thing may attempt to sleep.
+ * [Actually, it never needs to sleep for us, but it calls might_sleep()]
+ */
+static void ub_put(struct ub_dev *sc)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ub_lock, flags);
+ --sc->openc;
+ if (sc->openc == 0 && atomic_read(&sc->poison)) {
+ spin_unlock_irqrestore(&ub_lock, flags);
+ ub_cleanup(sc);
+ } else {
+ spin_unlock_irqrestore(&ub_lock, flags);
+ }
}
/*
* Final cleanup and deallocation.
- * This must be called with ub_lock taken.
*/
static void ub_cleanup(struct ub_dev *sc)
{
+ request_queue_t *q;
+
+ /* I don't think queue can be NULL. But... Stolen from sx8.c */
+ if ((q = sc->disk->queue) != NULL)
+ blk_cleanup_queue(q);
/*
* If we zero disk->private_data BEFORE put_disk, we have to check
@@ -1526,11 +1558,7 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
return 0;
err_open:
- spin_lock_irqsave(&ub_lock, flags);
- --sc->openc;
- if (sc->openc == 0 && atomic_read(&sc->poison))
- ub_cleanup(sc);
- spin_unlock_irqrestore(&ub_lock, flags);
+ ub_put(sc);
return rc;
}
@@ -1540,15 +1568,8 @@ static int ub_bd_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ub_dev *sc = disk->private_data;
- unsigned long flags;
- spin_lock_irqsave(&ub_lock, flags);
- --sc->openc;
- if (sc->openc == 0)
- sc->first_open = 0;
- if (sc->openc == 0 && atomic_read(&sc->poison))
- ub_cleanup(sc);
- spin_unlock_irqrestore(&ub_lock, flags);
+ ub_put(sc);
return 0;
}
@@ -2043,9 +2064,7 @@ err_diag:
usb_set_intfdata(intf, NULL);
// usb_put_intf(sc->intf);
usb_put_dev(sc->dev);
- spin_lock_irq(&ub_lock);
ub_id_put(sc->id);
- spin_unlock_irq(&ub_lock);
err_id:
kfree(sc);
err_core:
@@ -2056,10 +2075,18 @@ static void ub_disconnect(struct usb_interface *intf)
{
struct ub_dev *sc = usb_get_intfdata(intf);
struct gendisk *disk = sc->disk;
- request_queue_t *q = disk->queue;
unsigned long flags;
/*
+ * Prevent ub_bd_release from pulling the rug from under us.
+ * XXX This is starting to look like a kref.
+ * XXX Why not to take this ref at probe time?
+ */
+ spin_lock_irqsave(&ub_lock, flags);
+ sc->openc++;
+ spin_unlock_irqrestore(&ub_lock, flags);
+
+ /*
* Fence stall clearnings, operations triggered by unlinkings and so on.
* We do not attempt to unlink any URBs, because we do not trust the
* unlink paths in HC drivers. Also, we get -84 upon disconnect anyway.
@@ -2095,17 +2122,18 @@ static void ub_disconnect(struct usb_interface *intf)
spin_unlock_irqrestore(&sc->lock, flags);
/*
- * Unregister the upper layer, this waits for all commands to end.
+ * Unregister the upper layer.
*/
if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
- if (q)
- blk_cleanup_queue(q);
+ /*
+ * I wish I could do:
+ * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
+ * As it is, we rely on our internal poisoning and let
+ * the upper levels to spin furiously failing all the I/O.
+ */
/*
- * We really expect blk_cleanup_queue() to wait, so no amount
- * of paranoya is too much.
- *
* Taking a lock on a structure which is about to be freed
* is very nonsensual. Here it is largely a way to do a debug freeze,
* and a bracket which shows where the nonsensual code segment ends.
@@ -2139,13 +2167,10 @@ static void ub_disconnect(struct usb_interface *intf)
usb_put_dev(sc->dev);
sc->dev = NULL;
- spin_lock_irqsave(&ub_lock, flags);
- if (sc->openc == 0)
- ub_cleanup(sc);
- spin_unlock_irqrestore(&ub_lock, flags);
+ ub_put(sc);
}
-struct usb_driver ub_driver = {
+static struct usb_driver ub_driver = {
.owner = THIS_MODULE,
.name = "ub",
.probe = ub_probe,
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3dfcaffd37ccd..096a1202ea077 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -271,7 +271,7 @@ config SPECIALIX_RTSCTS
config SX
tristate "Specialix SX (and SI) card support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
help
This is a driver for the SX and SI multiport serial cards.
Please read the file <file:Documentation/sx.txt> for details.
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 03c8e9ae2d422..e1451dd9b6a7c 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -448,10 +448,10 @@ static void __devexit agp_via_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM
-static int agp_via_suspend(struct pci_dev *pdev, u32 state)
+static int agp_via_suspend(struct pci_dev *pdev, pm_message_t state)
{
pci_save_state (pdev);
- pci_set_power_state (pdev, 3);
+ pci_set_power_state (pdev, PCI_D3hot);
return 0;
}
@@ -460,7 +460,7 @@ static int agp_via_resume(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
- pci_set_power_state (pdev, 0);
+ pci_set_power_state (pdev, PCI_D0);
pci_restore_state(pdev);
if (bridge->driver == &via_agp3_driver)
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 4d159c610f7f3..947cb3cef8167 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -23,6 +23,7 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/ptrace.h>
#include <linux/device.h>
+#include <linux/backing-dev.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -282,30 +283,30 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
- ssize_t read, virtr, sz;
+ ssize_t low_count, read, sz;
char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
read = 0;
- virtr = 0;
if (p < (unsigned long) high_memory) {
- read = count;
+ low_count = count;
if (count > (unsigned long) high_memory - p)
- read = (unsigned long) high_memory - p;
+ low_count = (unsigned long) high_memory - p;
#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
/* we don't have page 0 mapped on sparc and m68k.. */
- if (p < PAGE_SIZE && read > 0) {
+ if (p < PAGE_SIZE && low_count > 0) {
size_t tmp = PAGE_SIZE - p;
- if (tmp > read) tmp = read;
+ if (tmp > low_count) tmp = low_count;
if (clear_user(buf, tmp))
return -EFAULT;
buf += tmp;
p += tmp;
- read -= tmp;
+ read += tmp;
+ low_count -= tmp;
count -= tmp;
}
#endif
- while (read > 0) {
+ while (low_count > 0) {
/*
* Handle first page in case it's not aligned
*/
@@ -314,7 +315,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
else
sz = PAGE_SIZE;
- sz = min_t(unsigned long, sz, count);
+ sz = min_t(unsigned long, sz, low_count);
/*
* On ia64 if a page has been mapped somewhere as
@@ -327,7 +328,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
return -EFAULT;
buf += sz;
p += sz;
- read -= sz;
+ read += sz;
+ low_count -= sz;
count -= sz;
}
}
@@ -350,13 +352,13 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
}
count -= len;
buf += len;
- virtr += len;
+ read += len;
p += len;
}
free_page((unsigned long)kbuf);
}
*ppos = p;
- return virtr + read;
+ return read;
}
@@ -758,6 +760,10 @@ static struct file_operations zero_fops = {
.mmap = mmap_zero,
};
+static struct backing_dev_info zero_bdi = {
+ .capabilities = BDI_CAP_MAP_COPY,
+};
+
static struct file_operations full_fops = {
.llseek = full_lseek,
.read = read_full,
@@ -804,6 +810,7 @@ static int memory_open(struct inode * inode, struct file * filp)
break;
#endif
case 5:
+ filp->f_mapping->backing_dev_info = &zero_bdi;
filp->f_op = &zero_fops;
break;
case 7:
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index 8f70185f192af..533085ec6f1bb 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -84,9 +84,7 @@ static struct IdentifyRta IdRta;
static struct KillNeighbour KillUnit;
int
-RIOFoadRta(HostP, MapP)
-struct Host * HostP;
-struct Map * MapP;
+RIOFoadRta(struct Host *HostP, struct Map *MapP)
{
struct CmdBlk *CmdBlkP;
@@ -117,9 +115,7 @@ struct Map * MapP;
}
int
-RIOZombieRta(HostP, MapP)
-struct Host * HostP;
-struct Map * MapP;
+RIOZombieRta(struct Host *HostP, struct Map *MapP)
{
struct CmdBlk *CmdBlkP;
@@ -150,10 +146,8 @@ struct Map * MapP;
}
int
-RIOCommandRta(p, RtaUnique, func)
-struct rio_info * p;
-uint RtaUnique;
-int (* func)( struct Host *HostP, struct Map *MapP );
+RIOCommandRta(struct rio_info *p, uint RtaUnique,
+ int (* func)(struct Host *HostP, struct Map *MapP))
{
uint Host;
@@ -195,9 +189,7 @@ int (* func)( struct Host *HostP, struct Map *MapP );
int
-RIOIdentifyRta(p, arg)
-struct rio_info * p;
-caddr_t arg;
+RIOIdentifyRta(struct rio_info *p, caddr_t arg)
{
uint Host;
@@ -263,9 +255,7 @@ caddr_t arg;
int
-RIOKillNeighbour(p, arg)
-struct rio_info * p;
-caddr_t arg;
+RIOKillNeighbour(struct rio_info *p, caddr_t arg)
{
uint Host;
uint ID;
@@ -329,10 +319,7 @@ caddr_t arg;
}
int
-RIOSuspendBootRta(HostP, ID, Link)
-struct Host *HostP;
-int ID;
-int Link;
+RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
{
struct CmdBlk *CmdBlkP;
@@ -363,8 +350,7 @@ int Link;
}
int
-RIOFoadWakeup(p)
-struct rio_info * p;
+RIOFoadWakeup(struct rio_info *p)
{
int port;
register struct Port *PortP;
@@ -398,11 +384,7 @@ struct rio_info * p;
** Incoming command on the COMMAND_RUP to be processed.
*/
static int
-RIOCommandRup(p, Rup, HostP, PacketP)
-struct rio_info * p;
-uint Rup;
-struct Host *HostP;
-PKT *PacketP;
+RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
{
struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
struct Port *PortP;
@@ -619,7 +601,7 @@ PKT *PacketP;
** Allocate an empty command block.
*/
struct CmdBlk *
-RIOGetCmdBlk()
+RIOGetCmdBlk(void)
{
struct CmdBlk *CmdBlkP;
@@ -634,8 +616,7 @@ RIOGetCmdBlk()
** Return a block to the head of the free list.
*/
void
-RIOFreeCmdBlk(CmdBlkP)
-struct CmdBlk *CmdBlkP;
+RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
{
sysfree((void *)CmdBlkP, sizeof(struct CmdBlk));
}
@@ -645,10 +626,7 @@ struct CmdBlk *CmdBlkP;
** a given rup.
*/
int
-RIOQueueCmdBlk(HostP, Rup, CmdBlkP)
-struct Host *HostP;
-uint Rup;
-struct CmdBlk *CmdBlkP;
+RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
{
struct CmdBlk **Base;
struct UnixRup *UnixRupP;
@@ -679,7 +657,6 @@ struct CmdBlk *CmdBlkP;
:TRUE)) {
rio_dprintk (RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n",
CmdBlkP->Packet.data[0]);
-
/*
** Whammy! blat that pack!
@@ -737,9 +714,7 @@ struct CmdBlk *CmdBlkP;
** must be called at splrio() or higher.
*/
void
-RIOPollHostCommands(p, HostP)
-struct rio_info * p;
-struct Host * HostP;
+RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
{
register struct CmdBlk *CmdBlkP;
register struct UnixRup *UnixRupP;
@@ -918,9 +893,7 @@ struct Host * HostP;
}
int
-RIOWFlushMark(iPortP, CmdBlkP)
-int iPortP;
-struct CmdBlk *CmdBlkP;
+RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP)
{
struct Port * PortP = (struct Port *)iPortP;
unsigned long flags;
@@ -936,9 +909,7 @@ struct CmdBlk *CmdBlkP;
}
int
-RIORFlushEnable(iPortP, CmdBlkP)
-int iPortP;
-struct CmdBlk *CmdBlkP;
+RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP)
{
struct Port * PortP = (struct Port *)iPortP;
PKT *PacketP;
@@ -965,9 +936,7 @@ struct CmdBlk *CmdBlkP;
}
int
-RIOUnUse(iPortP, CmdBlkP)
-int iPortP;
-struct CmdBlk *CmdBlkP;
+RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP)
{
struct Port * PortP = (struct Port *)iPortP;
unsigned long flags;
@@ -1009,9 +978,7 @@ struct CmdBlk *CmdBlkP;
}
void
-ShowPacket(Flags, PacketP)
-uint Flags;
-struct PKT *PacketP;
+ShowPacket(uint Flags, struct PKT *PacketP)
{
}
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 5a250be53fa78..3ad758a9a1dc1 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -4,7 +4,7 @@
* This driver will also support the older SI, and XIO cards.
*
*
- * (C) 1998 - 2000 R.E.Wolff@BitWizard.nl
+ * (C) 1998 - 2004 R.E.Wolff@BitWizard.nl
*
* Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
* version of this driver. Some fragments may have been copied. (none
@@ -354,13 +354,13 @@ static int si1_probe_addrs[]= { 0xd0000};
Some architectures may need more. */
static int sx_irqmask = -1;
-MODULE_PARM(sx_probe_addrs, "i");
-MODULE_PARM(si_probe_addrs, "i");
-MODULE_PARM(sx_poll, "i");
-MODULE_PARM(sx_slowpoll, "i");
-MODULE_PARM(sx_maxints, "i");
-MODULE_PARM(sx_debug, "i");
-MODULE_PARM(sx_irqmask, "i");
+module_param_array(sx_probe_addrs, int, NULL, 0);
+module_param_array(si_probe_addrs, int, NULL, 0);
+module_param(sx_poll, int, 0);
+module_param(sx_slowpoll, int, 0);
+module_param(sx_maxints, int, 0);
+module_param(sx_debug, int, 0);
+module_param(sx_irqmask, int, 0);
MODULE_LICENSE("GPL");
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = {
-#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\b",__FUNCTION__)
+#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__)
#define func_exit() sx_dprintk (SX_DEBUG_FLOW, "sx: exit %s\n", __FUNCTION__)
#define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
@@ -1158,7 +1158,6 @@ static inline void sx_check_modem_signals (struct sx_port *port)
if (hi_state & ST_BREAK) {
hi_state &= ~ST_BREAK;
sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n");
-
sx_write_channel_byte (port, hi_state, hi_state);
gs_got_break (&port->gs);
}
@@ -1206,7 +1205,7 @@ static irqreturn_t sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
struct sx_port *port;
int i;
- /* func_enter (); */
+ func_enter ();
sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq);
/* AAargh! The order in which to do these things is essential and
@@ -1297,7 +1296,7 @@ static irqreturn_t sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
clear_bit (SX_BOARD_INTR_LOCK, &board->locks);
sx_dprintk (SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, board->irq);
- /* func_exit (); */
+ func_exit ();
return IRQ_HANDLED;
}
@@ -1428,6 +1427,7 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
{
struct sx_port *port;
int retval, line;
+ unsigned long flags;
func_enter();
@@ -1449,9 +1449,12 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
+ spin_lock_irqsave(&port->gs.driver_lock, flags);
+
tty->driver_data = port;
port->gs.tty = tty;
port->gs.count++;
+ spin_unlock_irqrestore(&port->gs.driver_lock, flags);
sx_dprintk (SX_DEBUG_OPEN, "starting port\n");
@@ -1466,7 +1469,8 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
}
port->gs.flags |= GS_ACTIVE;
- sx_setsignals (port, 1,1);
+ if (port->gs.count <= 1)
+ sx_setsignals (port, 1,1);
#if 0
if (sx_debug & SX_DEBUG_OPEN)
@@ -1476,10 +1480,14 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
my_hd_io (port->board->base + port->ch_base, sizeof (*port));
#endif
- if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
- printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
- port->gs.count--;
- return -EIO;
+ if (port->gs.count <= 1) {
+ if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
+ printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
+ spin_lock_irqsave(&port->gs.driver_lock, flags);
+ port->gs.count--;
+ spin_unlock_irqrestore(&port->gs.driver_lock, flags);
+ return -EIO;
+ }
}
retval = gs_block_til_ready(port, filp);
@@ -1497,6 +1505,7 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
port->c_dcd = sx_get_CD (port);
sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
+
func_exit();
return 0;
@@ -1531,7 +1540,8 @@ static void sx_close (void *ptr)
if(port->gs.count) {
sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count);
- port->gs.count = 0;
+ //printk ("%s SETTING port count to zero: %p count: %d\n", __FUNCTION__, port, port->gs.count);
+ //port->gs.count = 0;
}
func_exit ();
@@ -1747,12 +1757,16 @@ static void sx_break (struct tty_struct * tty, int flag)
struct sx_port *port = tty->driver_data;
int rv;
+ func_enter ();
+
if (flag)
rv = sx_send_command (port, HS_START, -1, HS_IDLE_BREAK);
else
rv = sx_send_command (port, HS_STOP, -1, HS_IDLE_OPEN);
if (rv != 1) printk (KERN_ERR "sx: couldn't send break (%x).\n",
read_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat)));
+
+ func_exit ();
}
@@ -2101,7 +2115,7 @@ static int probe_sx (struct sx_board *board)
}
if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
- if (board->hw_base & 0x8000) {
+ if (((unsigned long)board->hw_base) & 0x8000) {
printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->hw_base);
printk (KERN_WARNING "sx: Read sx.txt for more info.\n");
}
@@ -2150,6 +2164,7 @@ static int probe_si (struct sx_board *board)
}
for (i=0;i<8;i++) {
if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
+ func_exit ();
return 0;
}
}
@@ -2164,11 +2179,13 @@ static int probe_si (struct sx_board *board)
/* This should be an SI1 board, which has this
location writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+ func_exit ();
return 0;
} else {
/* This should be an SI2 board, which has the bottom
3 bits non-writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+ func_exit ();
return 0;
}
@@ -2181,11 +2198,13 @@ static int probe_si (struct sx_board *board)
/* This should be an SI1 board, which has this
location writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+ func_exit();
return 0;
} else {
/* This should be an SI2 board, which has the bottom
3 bits non-writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+ func_exit ();
return 0;
}
@@ -2302,6 +2321,7 @@ static int sx_init_portstructs (int nboards, int nports)
#ifdef NEW_WRITE_LOCKING
port->gs.port_write_sem = MUTEX;
#endif
+ port->gs.driver_lock = SPIN_LOCK_UNLOCKED;
/*
* Initializing wait queue
*/
@@ -2473,7 +2493,7 @@ static int __init sx_init(void)
found++;
fix_sx_pci (pdev, board);
} else
- iounmap(board->base);
+ iounmap(board->base2);
}
#endif
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 8c385a3f7e64a..f59f7cbd525bc 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -31,9 +31,10 @@
#include <linux/suspend.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* for fsync_bdev() */
-
+#include <linux/swap.h>
#include <linux/spinlock.h>
#include <linux/vt_kern.h>
+#include <linux/workqueue.h>
#include <asm/ptrace.h>
@@ -209,6 +210,24 @@ static struct sysrq_key_op sysrq_term_op = {
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
+static void moom_callback(void *ignored)
+{
+ out_of_memory(GFP_KERNEL);
+}
+
+static DECLARE_WORK(moom_work, moom_callback, NULL);
+
+static void sysrq_handle_moom(int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
+{
+ schedule_work(&moom_work);
+}
+static struct sysrq_key_op sysrq_moom_op = {
+ .handler = sysrq_handle_moom,
+ .help_msg = "Full",
+ .action_msg = "Manual OOM execution",
+};
+
static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
@@ -257,7 +276,7 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
/* c */ NULL,
/* d */ NULL,
/* e */ &sysrq_term_op,
-/* f */ NULL,
+/* f */ &sysrq_moom_op,
/* g */ NULL,
/* h */ NULL,
/* i */ &sysrq_kill_op,
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 6229dd04ac314..e5ef1dfc54826 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2212,9 +2212,6 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
}
set_cursor(vc);
- if (!oops_in_progress)
- poke_blanked_console();
-
quit:
clear_bit(0, &printing);
}
@@ -2815,6 +2812,13 @@ void do_unblank_screen(int leaving_gfx)
{
struct vc_data *vc;
+ /* This should now always be called from a "sane" (read: can schedule)
+ * context for the sake of the low level drivers, except in the special
+ * case of oops_in_progress
+ */
+ if (!oops_in_progress)
+ might_sleep();
+
WARN_CONSOLE_UNLOCKED();
ignore_poke = 0;
@@ -2871,6 +2875,14 @@ void poke_blanked_console(void)
{
WARN_CONSOLE_UNLOCKED();
+ /* Add this so we quickly catch whoever might call us in a non
+ * safe context. Nowadays, unblank_screen() isn't to be called in
+ * atomic contexts and is allowed to schedule (with the special case
+ * of oops_in_progress, but that isn't of any concern for this
+ * function. --BenH.
+ */
+ might_sleep();
+
/* This isn't perfectly race free, but a race here would be mostly harmless,
* at worse, we'll do a spurrious blank and it's unlikely
*/
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 8bf4b0e218f1d..9636135ee0779 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1076,7 +1076,7 @@ static void ide_device_shutdown(struct device *dev)
}
printk("Shutdown: %s\n", drive->name);
- dev->bus->suspend(dev, PM_SUSPEND_STANDBY);
+ dev->bus->suspend(dev, PMSG_SUSPEND);
}
/*
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index bcc0b9c64a502..cea1e758eb469 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -2344,7 +2344,7 @@ pmac_suspend_devices(void)
}
/* Send suspend call to devices, hold the device core's dpm_sem */
- ret = device_suspend(PM_SUSPEND_MEM);
+ ret = device_suspend(PMSG_SUSPEND);
if (ret) {
broadcast_wake();
printk(KERN_ERR "Driver sleep failed\n");
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index 6147e580a1536..ae16112a06535 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -385,6 +385,30 @@ static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
};
}
+static int cx24110_diseqc_send_burst(struct dvb_frontend* fe,
+ fe_sec_mini_cmd_t burst)
+{
+ int rv, bit, i;
+ struct cx24110_state *state = fe->demodulator_priv;
+
+ if (burst == SEC_MINI_A)
+ bit = 0x00;
+ else if (burst == SEC_MINI_B)
+ bit = 0x08;
+ else
+ return -EINVAL;
+
+ rv = cx24110_readreg(state, 0x77);
+ cx24110_writereg(state, 0x77, rv|0x04);
+
+ rv = cx24110_readreg(state, 0x76);
+ cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40 | bit));
+ for (i = 500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40) ; )
+ ; /* wait for LNB ready */
+
+ return 0;
+}
+
static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *cmd)
{
@@ -394,6 +418,9 @@ static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
for (i = 0; i < cmd->msg_len; i++)
cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
+ rv = cx24110_readreg(state, 0x77);
+ cx24110_writereg(state, 0x77, rv|0x04);
+
rv = cx24110_readreg(state, 0x76);
cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
@@ -616,6 +643,7 @@ static struct dvb_frontend_ops cx24110_ops = {
.diseqc_send_master_cmd = cx24110_send_diseqc_msg,
.set_tone = cx24110_set_tone,
.set_voltage = cx24110_set_voltage,
+ .diseqc_send_burst = cx24110_diseqc_send_burst,
};
module_param(debug, int, 0644);
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 337ceeb50c5af..cdda423386c5c 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -440,7 +440,7 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
/* Unschedule all of the iso td's */
if (ucpia->sbuf[1].urb) {
- usb_unlink_urb(ucpia->sbuf[1].urb);
+ usb_kill_urb(ucpia->sbuf[1].urb);
usb_free_urb(ucpia->sbuf[1].urb);
ucpia->sbuf[1].urb = NULL;
}
@@ -451,7 +451,7 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
}
if (ucpia->sbuf[0].urb) {
- usb_unlink_urb(ucpia->sbuf[0].urb);
+ usb_kill_urb(ucpia->sbuf[0].urb);
usb_free_urb(ucpia->sbuf[0].urb);
ucpia->sbuf[0].urb = NULL;
}
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
index 1e1bec697a560..13b1e7b6fd6eb 100644
--- a/drivers/media/video/zr36050.c
+++ b/drivers/media/video/zr36050.c
@@ -419,7 +419,7 @@ zr36050_set_dri (struct zr36050 *ptr)
dri_data[2] = 0x00;
dri_data[3] = 0x04;
dri_data[4] = ptr->dri >> 8;
- dri_data[5] = ptr->dri * 0xff;
+ dri_data[5] = ptr->dri & 0xff;
return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data);
}
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 3e54f0a0815df..be673070bc34e 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -83,8 +83,8 @@
#define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.01.19"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.19"
+#define MPT_LINUX_VERSION_COMMON "3.01.20"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.20"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 8f0b2dbe0bbbd..c98d6257ec02f 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -96,23 +96,26 @@ MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
-#ifdef MODULE
-static int dv = MPTSCSIH_DOMAIN_VALIDATION;
-module_param(dv, int, 0);
-MODULE_PARM_DESC(dv, "DV Algorithm: enhanced = 1, basic = 0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
-
-static int width = MPTSCSIH_MAX_WIDTH;
-module_param(width, int, 0);
-MODULE_PARM_DESC(width, "Max Bus Width: wide = 1, narrow = 0 (default=MPTSCSIH_MAX_WIDTH=1)");
-
-static ushort factor = MPTSCSIH_MIN_SYNC;
-module_param(factor, ushort, 0);
-MODULE_PARM_DESC(factor, "Min Sync Factor: (default=MPTSCSIH_MIN_SYNC=0x08)");
-
-static int saf_te = MPTSCSIH_SAF_TE;
-module_param(saf_te, int, 0);
-MODULE_PARM_DESC(saf_te, "Force enabling SEP Processor: (default=MPTSCSIH_SAF_TE=0)");
-#endif
+/* Command line args */
+static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
+MODULE_PARM(mpt_dv, "i");
+MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
+
+static int mpt_width = MPTSCSIH_MAX_WIDTH;
+MODULE_PARM(mpt_width, "i");
+MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
+
+static int mpt_factor = MPTSCSIH_MIN_SYNC;
+MODULE_PARM(mpt_factor, "h");
+MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
+
+static int mpt_saf_te = MPTSCSIH_SAF_TE;
+MODULE_PARM(mpt_saf_te, "i");
+MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
+
+static int mpt_pq_filter = 0;
+MODULE_PARM(mpt_pq_filter, "i");
+MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -253,7 +256,6 @@ static int scandv_wait_done = 1;
/* Driver command line structure
*/
-static struct mptscsih_driver_setup driver_setup;
static struct scsi_host_template driver_template;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1224,29 +1226,23 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Update with the driver setup
* values.
*/
- if (ioc->spi_data.maxBusWidth >
- driver_setup.max_width) {
- ioc->spi_data.maxBusWidth =
- driver_setup.max_width;
- }
-
- if (ioc->spi_data.minSyncFactor <
- driver_setup.min_sync_factor) {
- ioc->spi_data.minSyncFactor =
- driver_setup.min_sync_factor;
- }
+ if (ioc->spi_data.maxBusWidth > mpt_width)
+ ioc->spi_data.maxBusWidth = mpt_width;
+ if (ioc->spi_data.minSyncFactor < mpt_factor)
+ ioc->spi_data.minSyncFactor = mpt_factor;
if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
ioc->spi_data.maxSyncOffset = 0;
}
- ioc->spi_data.Saf_Te = driver_setup.saf_te;
+ ioc->spi_data.Saf_Te = mpt_saf_te;
hd->negoNvram = 0;
#ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
#endif
ioc->spi_data.forceDv = 0;
+ ioc->spi_data.noQas = 0;
for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
ioc->spi_data.dvStatus[ii] =
MPT_SCSICFG_NEGOTIATE;
@@ -1256,12 +1252,12 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->spi_data.dvStatus[ii] |=
MPT_SCSICFG_DV_NOT_DONE;
- ddvprintk((MYIOC_s_INFO_FMT
+ dinitprintk((MYIOC_s_INFO_FMT
"dv %x width %x factor %x saf_te %x\n",
- ioc->name, driver_setup.dv,
- driver_setup.max_width,
- driver_setup.min_sync_factor,
- driver_setup.saf_te));
+ ioc->name, mpt_dv,
+ mpt_width,
+ mpt_factor,
+ mpt_saf_te));
}
mpt_scsi_hosts++;
@@ -1477,18 +1473,6 @@ mptscsih_init(void)
": Registered for IOC reset notifications\n"));
}
-#ifdef MODULE
- dinitprintk((KERN_INFO MYNAM
- ": Command Line Args: dv=%d max_width=%d "
- "factor=0x%x saf_te=%d\n",
- dv, width, factor, saf_te));
-
- driver_setup.dv = (dv) ? 1 : 0;
- driver_setup.max_width = (width) ? 1 : 0;
- driver_setup.min_sync_factor = factor;
- driver_setup.saf_te = (saf_te) ? 1 : 0;;
-#endif
-
if(mpt_device_driver_register(&mptscsih_driver,
MPTSCSIH_DRIVER) != 0 ) {
dprintk((KERN_INFO MYNAM
@@ -3165,6 +3149,18 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
hd->ioc->name, bus_id, target_id, lun, hd));
+ /*
+ * If the peripheral qualifier filter is enabled then if the target reports a 0x1
+ * (i.e. The targer is capable of supporting the specified peripheral device type
+ * on this logical unit; however, the physical device is not currently connected
+ * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
+ * capable of supporting a physical device on this logical unit). This is to work
+ * around a bug in th emid-layer in some distributions in which the mid-layer will
+ * continue to try to communicate to the LUN and evntually create a dummy LUN.
+ */
+ if (mpt_pq_filter && dlen && (data[0] & 0xE0))
+ data[0] |= 0x40;
+
/* Is LUN supported? If so, upper 2 bits will be 0
* in first byte of inquiry data.
*/
@@ -5161,7 +5157,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
}
ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
- if (driver_setup.dv == 0)
+ if (mpt_dv == 0)
goto target_done;
inq0 = (*pbuf1) & 0x1F;
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 893f3c761f286..5cb2fd45c38f1 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -91,12 +91,4 @@
#define MPTSCSIH_MIN_SYNC 0x08
#define MPTSCSIH_SAF_TE 0
-struct mptscsih_driver_setup
-{
- u8 dv;
- u8 max_width;
- u8 min_sync_factor;
- u8 saf_te;
-};
-
#endif
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index ea2927ee4085b..b5b4a7b119034 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -437,7 +437,7 @@ static void mmc_blk_remove(struct mmc_card *card)
}
#ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card, u32 state)
+static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
{
struct mmc_blk_data *md = mmc_get_drvdata(card);
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index 939a81fba028e..29a56e9cd5b3a 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -109,7 +109,7 @@ mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf,
return 0;
}
-static int mmc_bus_suspend(struct device *dev, u32 state)
+static int mmc_bus_suspend(struct device *dev, pm_message_t state)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = dev_to_mmc_card(dev);
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index caa563c3a1645..3fe8ba992c38b 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -907,6 +907,7 @@ static void b44_tx_timeout(struct net_device *dev)
static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct b44 *bp = netdev_priv(dev);
+ struct sk_buff *bounce_skb;
dma_addr_t mapping;
u32 len, entry, ctrl;
@@ -922,15 +923,31 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 1;
}
- entry = bp->tx_prod;
mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
if(mapping+len > B44_DMA_MASK) {
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
- pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE);
- memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len);
- mapping = pci_map_single(bp->pdev, bp->tx_bufs+entry*TX_PKT_BUF_SZ, len, PCI_DMA_TODEVICE);
+ pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
+
+ bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
+ GFP_ATOMIC|GFP_DMA);
+ if (!bounce_skb)
+ return NETDEV_TX_BUSY;
+
+ mapping = pci_map_single(bp->pdev, bounce_skb->data,
+ len, PCI_DMA_TODEVICE);
+ if(mapping+len > B44_DMA_MASK) {
+ pci_unmap_single(bp->pdev, mapping,
+ len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(bounce_skb);
+ return NETDEV_TX_BUSY;
+ }
+
+ memcpy(skb_put(bounce_skb, len), skb->data, skb->len);
+ dev_kfree_skb_any(skb);
+ skb = bounce_skb;
}
+ entry = bp->tx_prod;
bp->tx_buffers[entry].skb = skb;
pci_unmap_addr_set(&bp->tx_buffers[entry], mapping, mapping);
@@ -1077,11 +1094,6 @@ static void b44_free_consistent(struct b44 *bp)
bp->tx_ring, bp->tx_ring_dma);
bp->tx_ring = NULL;
}
- if (bp->tx_bufs) {
- pci_free_consistent(bp->pdev, B44_TX_RING_SIZE * TX_PKT_BUF_SZ,
- bp->tx_bufs, bp->tx_bufs_dma);
- bp->tx_bufs = NULL;
- }
}
/*
@@ -1104,12 +1116,6 @@ static int b44_alloc_consistent(struct b44 *bp)
goto out_err;
memset(bp->tx_buffers, 0, size);
- size = B44_TX_RING_SIZE * TX_PKT_BUF_SZ;
- bp->tx_bufs = pci_alloc_consistent(bp->pdev, size, &bp->tx_bufs_dma);
- if (!bp->tx_bufs)
- goto out_err;
- memset(bp->tx_bufs, 0, size);
-
size = DMA_TABLE_BYTES;
bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
if (!bp->rx_ring)
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 76a3290211e03..11c40a2e71c70 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -383,7 +383,6 @@ struct b44 {
struct ring_info *rx_buffers;
struct ring_info *tx_buffers;
- unsigned char *tx_bufs;
u32 dma_offset;
u32 flags;
@@ -415,7 +414,7 @@ struct b44 {
struct pci_dev *pdev;
struct net_device *dev;
- dma_addr_t rx_ring_dma, tx_ring_dma,tx_bufs_dma;
+ dma_addr_t rx_ring_dma, tx_ring_dma;
u32 rx_pending;
u32 tx_pending;
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 9abc7bff7c262..148930d4e9bda 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -203,6 +203,7 @@ struct e1000_adapter {
spinlock_t stats_lock;
atomic_t irq_sem;
struct work_struct tx_timeout_task;
+ struct work_struct watchdog_task;
uint8_t fc_autoneg;
struct timer_list blink_timer;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index e7687c9620732..82549a6fcfb39 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -65,7 +65,8 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-char e1000_driver_version[] = "5.7.6-k2"DRIVERNAPI;
+#define DRV_VERSION "5.7.6-k2"DRIVERNAPI
+char e1000_driver_version[] = DRV_VERSION;
char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
/* e1000_pci_tbl - PCI Device ID Table
@@ -142,6 +143,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter);
static void e1000_set_multi(struct net_device *netdev);
static void e1000_update_phy_info(unsigned long data);
static void e1000_watchdog(unsigned long data);
+static void e1000_watchdog_task(struct e1000_adapter *adapter);
static void e1000_82547_tx_fifo_stall(unsigned long data);
static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
@@ -210,6 +212,7 @@ static struct pci_driver e1000_driver = {
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
module_param(debug, int, 0);
@@ -574,6 +577,9 @@ e1000_probe(struct pci_dev *pdev,
adapter->watchdog_timer.function = &e1000_watchdog;
adapter->watchdog_timer.data = (unsigned long) adapter;
+ INIT_WORK(&adapter->watchdog_task,
+ (void (*)(void *))e1000_watchdog_task, adapter);
+
init_timer(&adapter->phy_info_timer);
adapter->phy_info_timer.function = &e1000_update_phy_info;
adapter->phy_info_timer.data = (unsigned long) adapter;
@@ -660,6 +666,8 @@ e1000_remove(struct pci_dev *pdev)
struct e1000_adapter *adapter = netdev->priv;
uint32_t manc;
+ flush_scheduled_work();
+
if(adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
@@ -1529,13 +1537,20 @@ e1000_82547_tx_fifo_stall(unsigned long data)
/**
* e1000_watchdog - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
+ * @data: pointer to adapter cast into an unsigned long
**/
-
static void
e1000_watchdog(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+
+ /* Do the rest outside of interrupt context */
+ schedule_work(&adapter->watchdog_task);
+}
+
+static void
+e1000_watchdog_task(struct e1000_adapter *adapter)
+{
struct net_device *netdev = adapter->netdev;
struct e1000_desc_ring *txdr = &adapter->tx_ring;
uint32_t link;
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index a4dde8181d253..be28c65de729e 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -638,6 +638,7 @@ cleanup_module(void)
#define vdma_free(baz)
#define sonic_chiptomem(bat) (bat)
#define PHYSADDR(quux) (quux)
+#define CPHYSADDR(quux) (quux)
#define sonic_request_irq request_irq
#define sonic_free_irq free_irq
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index fc7aaa9349d50..17947e6c87937 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1351,7 +1351,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
printk(KERN_INFO "%s: registered as %s\n", dev->name, lp->name);
cards_found++;
- a->write_bcr(ioaddr, 2, 0x1002); /* enable LED writes */
+ /* enable LED writes */
+ a->write_bcr(ioaddr, 2, a->read_bcr(ioaddr, 2) | 0x1000);
return 0;
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index aaa5f584c86f7..7092ca6b277e3 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -1,6 +1,6 @@
/************************************************************************
* regs.h: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
- * Copyright 2002 Raghavendra Koushik (raghavendra.koushik@s2io.com)
+ * Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
* the GNU General Public License (GPL), incorporated herein by reference.
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index e7983252b7efd..9c224eba057d5 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -1,6 +1,6 @@
/************************************************************************
* s2io.c: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
- * Copyright(c) 2002-2005 S2IO Technologies
+ * Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
* the GNU General Public License (GPL), incorporated herein by reference.
@@ -66,7 +66,7 @@
/* S2io Driver name & version. */
static char s2io_driver_name[] = "s2io";
-static char s2io_driver_version[] = "Version 1.7.5.1";
+static char s2io_driver_version[] = "Version 1.7.7.1";
/*
* Cards with following subsystem_id have a link state indication
@@ -245,6 +245,10 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,
PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_WIN,
+ PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
+ PCI_ANY_ID, PCI_ANY_ID},
{0,}
};
@@ -620,79 +624,15 @@ static int init_nic(struct s2io_nic *nic)
mac_info_t *mac_control;
struct config_param *config;
int mdio_cnt = 0, dtx_cnt = 0;
- unsigned long long print_var, mem_share;
+ unsigned long long mem_share;
mac_control = &nic->mac_control;
config = &nic->config;
- /*
- * Set proper endian settings and verify the same by
- * reading the PIF Feed-back register.
- */
-#ifdef __BIG_ENDIAN
- /*
- * The device by default set to a big endian format, so
- * a big endian driver need not set anything.
- */
- writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl);
- val64 = (SWAPPER_CTRL_PIF_R_FE |
- SWAPPER_CTRL_PIF_R_SE |
- SWAPPER_CTRL_PIF_W_FE |
- SWAPPER_CTRL_PIF_W_SE |
- SWAPPER_CTRL_TXP_FE |
- SWAPPER_CTRL_TXP_SE |
- SWAPPER_CTRL_TXD_R_FE |
- SWAPPER_CTRL_TXD_W_FE |
- SWAPPER_CTRL_TXF_R_FE |
- SWAPPER_CTRL_RXD_R_FE |
- SWAPPER_CTRL_RXD_W_FE |
- SWAPPER_CTRL_RXF_W_FE |
- SWAPPER_CTRL_XMSI_FE |
- SWAPPER_CTRL_XMSI_SE |
- SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
- writeq(val64, &bar0->swapper_ctrl);
-#else
- /*
- * Initially we enable all bits to make it accessible by
- * the driver, then we selectively enable only those bits
- * that we want to set.
- */
- writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl);
- val64 = (SWAPPER_CTRL_PIF_R_FE |
- SWAPPER_CTRL_PIF_R_SE |
- SWAPPER_CTRL_PIF_W_FE |
- SWAPPER_CTRL_PIF_W_SE |
- SWAPPER_CTRL_TXP_FE |
- SWAPPER_CTRL_TXP_SE |
- SWAPPER_CTRL_TXD_R_FE |
- SWAPPER_CTRL_TXD_R_SE |
- SWAPPER_CTRL_TXD_W_FE |
- SWAPPER_CTRL_TXD_W_SE |
- SWAPPER_CTRL_TXF_R_FE |
- SWAPPER_CTRL_RXD_R_FE |
- SWAPPER_CTRL_RXD_R_SE |
- SWAPPER_CTRL_RXD_W_FE |
- SWAPPER_CTRL_RXD_W_SE |
- SWAPPER_CTRL_RXF_W_FE |
- SWAPPER_CTRL_XMSI_FE |
- SWAPPER_CTRL_XMSI_SE |
- SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
- writeq(val64, &bar0->swapper_ctrl);
-#endif
-
- /*
- * Verifying if endian settings are accurate by
- * reading a feedback register.
- */
- val64 = readq(&bar0->pif_rd_swapper_fb);
- if (val64 != 0x0123456789ABCDEFULL) {
- /* Endian settings are incorrect, calls for another dekko. */
- print_var = (unsigned long long) val64;
- DBG_PRINT(INIT_DBG, "%s: Endian settings are wrong",
- dev->name);
- DBG_PRINT(ERR_DBG, ", feedback read %llx\n", print_var);
-
- return FAILURE;
+ /* Initialize swapper control register */
+ if (s2io_set_swapper(nic)) {
+ DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
+ return -1;
}
/* Remove XGXS from reset state */
@@ -920,11 +860,15 @@ static int init_nic(struct s2io_nic *nic)
* Initializing the Transmit and Receive Traffic Interrupt
* Scheme.
*/
- /* TTI Initialization */
- val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0xFFF) |
+ /* TTI Initialization. Default Tx timer gets us about
+ * 250 interrupts per sec. Continuous interrupts are enabled
+ * by default.
+ */
+ val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078) |
TTI_DATA1_MEM_TX_URNG_A(0xA) |
TTI_DATA1_MEM_TX_URNG_B(0x10) |
- TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN;
+ TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN |
+ TTI_DATA1_MEM_TX_TIMER_CI_EN;
writeq(val64, &bar0->tti_data1_mem);
val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
@@ -2508,23 +2452,74 @@ static int s2io_set_swapper(nic_t * sp)
{
struct net_device *dev = sp->dev;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- u64 val64;
+ u64 val64, valt, valr;
/*
* Set proper endian settings and verify the same by reading
* the PIF Feed-back register.
*/
+
+ val64 = readq(&bar0->pif_rd_swapper_fb);
+ if (val64 != 0x0123456789ABCDEFULL) {
+ int i = 0;
+ u64 value[] = { 0xC30000C3C30000C3ULL, /* FE=1, SE=1 */
+ 0x8100008181000081ULL, /* FE=1, SE=0 */
+ 0x4200004242000042ULL, /* FE=0, SE=1 */
+ 0}; /* FE=0, SE=0 */
+
+ while(i<4) {
+ writeq(value[i], &bar0->swapper_ctrl);
+ val64 = readq(&bar0->pif_rd_swapper_fb);
+ if (val64 == 0x0123456789ABCDEFULL)
+ break;
+ i++;
+ }
+ if (i == 4) {
+ DBG_PRINT(ERR_DBG, "%s: Endian settings are wrong, ",
+ dev->name);
+ DBG_PRINT(ERR_DBG, "feedback read %llx\n",
+ (unsigned long long) val64);
+ return FAILURE;
+ }
+ valr = value[i];
+ } else {
+ valr = readq(&bar0->swapper_ctrl);
+ }
+
+ valt = 0x0123456789ABCDEFULL;
+ writeq(valt, &bar0->xmsi_address);
+ val64 = readq(&bar0->xmsi_address);
+
+ if(val64 != valt) {
+ int i = 0;
+ u64 value[] = { 0x00C3C30000C3C300ULL, /* FE=1, SE=1 */
+ 0x0081810000818100ULL, /* FE=1, SE=0 */
+ 0x0042420000424200ULL, /* FE=0, SE=1 */
+ 0}; /* FE=0, SE=0 */
+
+ while(i<4) {
+ writeq((value[i] | valr), &bar0->swapper_ctrl);
+ writeq(valt, &bar0->xmsi_address);
+ val64 = readq(&bar0->xmsi_address);
+ if(val64 == valt)
+ break;
+ i++;
+ }
+ if(i == 4) {
+ DBG_PRINT(ERR_DBG, "Write failed, Xmsi_addr ");
+ DBG_PRINT(ERR_DBG, "reads:0x%llx\n",val64);
+ return FAILURE;
+ }
+ }
+ val64 = readq(&bar0->swapper_ctrl);
+ val64 &= 0xFFFF000000000000ULL;
+
#ifdef __BIG_ENDIAN
/*
* The device by default set to a big endian format, so a
* big endian driver need not set anything.
*/
- writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl);
- val64 = (SWAPPER_CTRL_PIF_R_FE |
- SWAPPER_CTRL_PIF_R_SE |
- SWAPPER_CTRL_PIF_W_FE |
- SWAPPER_CTRL_PIF_W_SE |
- SWAPPER_CTRL_TXP_FE |
+ val64 |= (SWAPPER_CTRL_TXP_FE |
SWAPPER_CTRL_TXP_SE |
SWAPPER_CTRL_TXD_R_FE |
SWAPPER_CTRL_TXD_W_FE |
@@ -2542,12 +2537,7 @@ static int s2io_set_swapper(nic_t * sp)
* driver, then we selectively enable only those bits that
* we want to set.
*/
- writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl);
- val64 = (SWAPPER_CTRL_PIF_R_FE |
- SWAPPER_CTRL_PIF_R_SE |
- SWAPPER_CTRL_PIF_W_FE |
- SWAPPER_CTRL_PIF_W_SE |
- SWAPPER_CTRL_TXP_FE |
+ val64 |= (SWAPPER_CTRL_TXP_FE |
SWAPPER_CTRL_TXP_SE |
SWAPPER_CTRL_TXD_R_FE |
SWAPPER_CTRL_TXD_R_SE |
@@ -2564,6 +2554,7 @@ static int s2io_set_swapper(nic_t * sp)
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
writeq(val64, &bar0->swapper_ctrl);
#endif
+ val64 = readq(&bar0->swapper_ctrl);
/*
* Verifying if endian settings are accurate by reading a
@@ -3920,45 +3911,45 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
nic_t *sp = dev->priv;
StatInfo_t *stat_info = sp->mac_control.stats_info;
- tmp_stats[i++] = stat_info->tmac_frms;
- tmp_stats[i++] = stat_info->tmac_data_octets;
- tmp_stats[i++] = stat_info->tmac_drop_frms;
- tmp_stats[i++] = stat_info->tmac_mcst_frms;
- tmp_stats[i++] = stat_info->tmac_bcst_frms;
- tmp_stats[i++] = stat_info->tmac_pause_ctrl_frms;
- tmp_stats[i++] = stat_info->tmac_any_err_frms;
- tmp_stats[i++] = stat_info->tmac_vld_ip_octets;
- tmp_stats[i++] = stat_info->tmac_vld_ip;
- tmp_stats[i++] = stat_info->tmac_drop_ip;
- tmp_stats[i++] = stat_info->tmac_icmp;
- tmp_stats[i++] = stat_info->tmac_rst_tcp;
- tmp_stats[i++] = stat_info->tmac_tcp;
- tmp_stats[i++] = stat_info->tmac_udp;
- tmp_stats[i++] = stat_info->rmac_vld_frms;
- tmp_stats[i++] = stat_info->rmac_data_octets;
- tmp_stats[i++] = stat_info->rmac_fcs_err_frms;
- tmp_stats[i++] = stat_info->rmac_drop_frms;
- tmp_stats[i++] = stat_info->rmac_vld_mcst_frms;
- tmp_stats[i++] = stat_info->rmac_vld_bcst_frms;
- tmp_stats[i++] = stat_info->rmac_in_rng_len_err_frms;
- tmp_stats[i++] = stat_info->rmac_long_frms;
- tmp_stats[i++] = stat_info->rmac_pause_ctrl_frms;
- tmp_stats[i++] = stat_info->rmac_discarded_frms;
- tmp_stats[i++] = stat_info->rmac_usized_frms;
- tmp_stats[i++] = stat_info->rmac_osized_frms;
- tmp_stats[i++] = stat_info->rmac_frag_frms;
- tmp_stats[i++] = stat_info->rmac_jabber_frms;
- tmp_stats[i++] = stat_info->rmac_ip;
- tmp_stats[i++] = stat_info->rmac_ip_octets;
- tmp_stats[i++] = stat_info->rmac_hdr_err_ip;
- tmp_stats[i++] = stat_info->rmac_drop_ip;
- tmp_stats[i++] = stat_info->rmac_icmp;
- tmp_stats[i++] = stat_info->rmac_tcp;
- tmp_stats[i++] = stat_info->rmac_udp;
- tmp_stats[i++] = stat_info->rmac_err_drp_udp;
- tmp_stats[i++] = stat_info->rmac_pause_cnt;
- tmp_stats[i++] = stat_info->rmac_accepted_ip;
- tmp_stats[i++] = stat_info->rmac_err_tcp;
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_data_octets);
+ tmp_stats[i++] = le64_to_cpu(stat_info->tmac_drop_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_mcst_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_bcst_frms);
+ tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_any_err_frms);
+ tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_vld_ip);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_drop_ip);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_icmp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_rst_tcp);
+ tmp_stats[i++] = le64_to_cpu(stat_info->tmac_tcp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_udp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_data_octets);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_fcs_err_frms);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_drop_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_mcst_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_bcst_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_discarded_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_usized_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_osized_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_frag_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_jabber_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ip);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_drop_ip);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_icmp);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_udp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_drp_udp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pause_cnt);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_accepted_ip);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp);
}
static int s2io_ethtool_get_regs_len(struct net_device *dev)
@@ -4547,7 +4538,7 @@ static void s2io_init_pci(nic_t * sp)
&(sp->pcix_cmd));
}
-MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@s2io.com>");
+MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
MODULE_LICENSE("GPL");
module_param(tx_fifo_num, int, 0);
module_param_array(tx_fifo_len, int, NULL, 0);
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index f5c2ae0bc3713..1711c8c3dc99f 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -1,6 +1,6 @@
/************************************************************************
* s2io.h: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
- * Copyright 2002 Raghavendra Koushik (raghavendra.koushik@s2io.com)
+ * Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
* the GNU General Public License (GPL), incorporated herein by reference.
@@ -73,121 +73,6 @@ static int debug_level = ERR_DBG; /* Default level. */
/* The statistics block of Xena */
typedef struct stat_block {
-#ifdef __BIG_ENDIAN
-/* Tx MAC statistics counters. */
- u32 tmac_frms;
- u32 tmac_data_octets;
- u64 tmac_drop_frms;
- u32 tmac_mcst_frms;
- u32 tmac_bcst_frms;
- u64 tmac_pause_ctrl_frms;
- u32 tmac_ttl_octets;
- u32 tmac_ucst_frms;
- u32 tmac_nucst_frms;
- u32 tmac_any_err_frms;
- u64 tmac_ttl_less_fb_octets;
- u64 tmac_vld_ip_octets;
- u32 tmac_vld_ip;
- u32 tmac_drop_ip;
- u32 tmac_icmp;
- u32 tmac_rst_tcp;
- u64 tmac_tcp;
- u32 tmac_udp;
- u32 reserved_0;
-
-/* Rx MAC Statistics counters. */
- u32 rmac_vld_frms;
- u32 rmac_data_octets;
- u64 rmac_fcs_err_frms;
- u64 rmac_drop_frms;
- u32 rmac_vld_mcst_frms;
- u32 rmac_vld_bcst_frms;
- u32 rmac_in_rng_len_err_frms;
- u32 rmac_out_rng_len_err_frms;
- u64 rmac_long_frms;
- u64 rmac_pause_ctrl_frms;
- u64 rmac_unsup_ctrl_frms;
- u32 rmac_ttl_octets;
- u32 rmac_accepted_ucst_frms;
- u32 rmac_accepted_nucst_frms;
- u32 rmac_discarded_frms;
- u32 rmac_drop_events;
- u32 reserved_1;
- u64 rmac_ttl_less_fb_octets;
- u64 rmac_ttl_frms;
- u64 reserved_2;
- u32 reserved_3;
- u32 rmac_usized_frms;
- u32 rmac_osized_frms;
- u32 rmac_frag_frms;
- u32 rmac_jabber_frms;
- u32 reserved_4;
- u64 rmac_ttl_64_frms;
- u64 rmac_ttl_65_127_frms;
- u64 reserved_5;
- u64 rmac_ttl_128_255_frms;
- u64 rmac_ttl_256_511_frms;
- u64 reserved_6;
- u64 rmac_ttl_512_1023_frms;
- u64 rmac_ttl_1024_1518_frms;
- u32 reserved_7;
- u32 rmac_ip;
- u64 rmac_ip_octets;
- u32 rmac_hdr_err_ip;
- u32 rmac_drop_ip;
- u32 rmac_icmp;
- u32 reserved_8;
- u64 rmac_tcp;
- u32 rmac_udp;
- u32 rmac_err_drp_udp;
- u64 rmac_xgmii_err_sym;
- u64 rmac_frms_q0;
- u64 rmac_frms_q1;
- u64 rmac_frms_q2;
- u64 rmac_frms_q3;
- u64 rmac_frms_q4;
- u64 rmac_frms_q5;
- u64 rmac_frms_q6;
- u64 rmac_frms_q7;
- u16 rmac_full_q0;
- u16 rmac_full_q1;
- u16 rmac_full_q2;
- u16 rmac_full_q3;
- u16 rmac_full_q4;
- u16 rmac_full_q5;
- u16 rmac_full_q6;
- u16 rmac_full_q7;
- u32 rmac_pause_cnt;
- u32 reserved_9;
- u64 rmac_xgmii_data_err_cnt;
- u64 rmac_xgmii_ctrl_err_cnt;
- u32 rmac_accepted_ip;
- u32 rmac_err_tcp;
-
-/* PCI/PCI-X Read transaction statistics. */
- u32 rd_req_cnt;
- u32 new_rd_req_cnt;
- u32 new_rd_req_rtry_cnt;
- u32 rd_rtry_cnt;
- u32 wr_rtry_rd_ack_cnt;
-
-/* PCI/PCI-X write transaction statistics. */
- u32 wr_req_cnt;
- u32 new_wr_req_cnt;
- u32 new_wr_req_rtry_cnt;
- u32 wr_rtry_cnt;
- u32 wr_disc_cnt;
- u32 rd_rtry_wr_ack_cnt;
-
-/* DMA Transaction statistics. */
- u32 txp_wr_cnt;
- u32 txd_rd_cnt;
- u32 txd_wr_cnt;
- u32 rxd_rd_cnt;
- u32 rxd_wr_cnt;
- u32 txf_rd_cnt;
- u32 rxf_wr_cnt;
-#else
/* Tx MAC statistics counters. */
u32 tmac_data_octets;
u32 tmac_frms;
@@ -301,7 +186,6 @@ typedef struct stat_block {
u32 rxd_rd_cnt;
u32 rxf_wr_cnt;
u32 txf_rd_cnt;
-#endif
} StatInfo_t;
/* Structures representing different init time configuration
@@ -869,6 +753,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
static int verify_xena_quiescence(u64 val64, int flag);
static struct ethtool_ops netdev_ethtool_ops;
static void s2io_set_link(unsigned long data);
+static int s2io_set_swapper(nic_t * sp);
static void s2io_card_down(nic_t * nic);
static int s2io_card_up(nic_t * nic);
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 2951b9084bfd2..c5774e7855d03 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2976,10 +2976,12 @@ static void __devexit parport_pc_pci_remove(struct pci_dev *dev)
pci_set_drvdata(dev, NULL);
- for (i = data->num - 1; i >= 0; i--)
- parport_pc_unregister_port(data->ports[i]);
+ if (data) {
+ for (i = data->num - 1; i >= 0; i--)
+ parport_pc_unregister_port(data->ports[i]);
- kfree(data);
+ kfree(data);
+ }
}
static struct pci_driver parport_pc_pci_driver = {
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 5ce156382652e..fb2b64b1f827c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -312,22 +312,24 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
/**
* pci_choose_state - Choose the power state of a PCI device
* @dev: PCI device to be suspended
- * @state: target sleep state for the whole system
+ * @state: target sleep state for the whole system. This is the value
+ * that is passed to suspend() function.
*
* Returns PCI power state suitable for given device and given system
* message.
*/
-pci_power_t pci_choose_state(struct pci_dev *dev, u32 state)
+pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
{
if (!pci_find_capability(dev, PCI_CAP_ID_PM))
return PCI_D0;
switch (state) {
- case 0: return PCI_D0;
- case 2: return PCI_D2;
+ case 0: return PCI_D0;
case 3: return PCI_D3hot;
- default: BUG();
+ default:
+ printk("They asked me for state %d\n", state);
+ BUG();
}
return PCI_D0;
}
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 5e095967a0965..03fc885db1c57 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -140,7 +140,7 @@ static u8 pcmcia_used_irq[NR_IRQS];
static int socket_resume(struct pcmcia_socket *skt);
static int socket_suspend(struct pcmcia_socket *skt);
-int pcmcia_socket_dev_suspend(struct device *dev, u32 state)
+int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state)
{
struct pcmcia_socket *socket;
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 0a20f69fbc095..f3fdc748659d0 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -42,7 +42,7 @@ static struct pci_device_id i82092aa_pci_ids[] = {
};
MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids);
-static int i82092aa_socket_suspend (struct pci_dev *dev, u32 state)
+static int i82092aa_socket_suspend (struct pci_dev *dev, pm_message_t state)
{
return pcmcia_socket_dev_suspend(&dev->dev, state);
}
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 7bda91537e3c6..90a335a5d9faf 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1333,7 +1333,7 @@ static struct pccard_operations pcic_operations = {
/*====================================================================*/
-static int i82365_suspend(struct device *dev, u32 state, u32 level)
+static int i82365_suspend(struct device *dev, pm_message_t state, u32 level)
{
int ret = 0;
if (level == SUSPEND_SAVE_STATE)
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 9a16e243f183d..3f4364341d8d0 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -827,7 +827,7 @@ static void __devexit pd6729_pci_remove(struct pci_dev *dev)
kfree(socket);
}
-static int pd6729_socket_suspend(struct pci_dev *dev, u32 state)
+static int pd6729_socket_suspend(struct pci_dev *dev, pm_message_t state)
{
return pcmcia_socket_dev_suspend(&dev->dev, state);
}
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 6d1b9817f5bd3..aacbbb5f055d8 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -373,7 +373,7 @@ static int __init get_tcic_id(void)
/*====================================================================*/
-static int tcic_drv_suspend(struct device *dev, u32 state, u32 level)
+static int tcic_drv_suspend(struct device *dev, pm_message_t state, u32 level)
{
int ret = 0;
if (level == SUSPEND_SAVE_STATE)
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 557a29e73d0d3..6404d97a12ebc 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1017,7 +1017,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
}
-static int yenta_dev_suspend (struct pci_dev *dev, u32 state)
+static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state)
{
struct yenta_socket *socket = pci_get_drvdata(dev);
int ret;
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 199698597ba8e..a2b18f5a4f930 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -3,7 +3,7 @@
Written By: Adam Radford <linuxraid@amcc.com>
- Copyright (C) 2004 Applied Micro Circuits Corporation.
+ Copyright (C) 2004-2005 Applied Micro Circuits Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -51,6 +51,14 @@
-------
2.26.02.000 - Driver cleanup for kernel submission.
2.26.02.001 - Replace schedule_timeout() calls with msleep().
+ 2.26.02.002 - Add support for PAE mode.
+ Add lun support.
+ Fix twa_remove() to free irq handler/unregister_chrdev()
+ before shutting down card.
+ Change to new 'change_queue_depth' api.
+ Fix 'handled=1' ISR usage, remove bogus IRQ check.
+ Remove un-needed eh_abort handler.
+ Add support for embedded firmware error strings.
*/
#include <linux/module.h>
@@ -73,7 +81,7 @@
#include "3w-9xxx.h"
/* Globals */
-static const char *twa_driver_version="2.26.02.001";
+#define TW_DRIVER_VERSION "2.26.02.002"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@@ -83,6 +91,7 @@ extern struct timezone sys_tz;
MODULE_AUTHOR ("AMCC");
MODULE_DESCRIPTION ("3ware 9000 Storage Controller Linux Driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(TW_DRIVER_VERSION);
/* Function prototypes */
static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header);
@@ -108,9 +117,9 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds);
static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds);
static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal);
-static int twa_reset_device_extension(TW_Device_Extension *tw_dev);
+static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset);
static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
-static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Apache *sglistarg);
+static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
@@ -126,7 +135,7 @@ static ssize_t twa_show_stats(struct class_device *class_dev, char *buf)
ssize_t len;
spin_lock_irqsave(tw_dev->host->host_lock, flags);
- len = snprintf(buf, PAGE_SIZE, "Driver version: %s\n"
+ len = snprintf(buf, PAGE_SIZE, "3w-9xxx Driver version: %s\n"
"Current commands posted: %4d\n"
"Max commands posted: %4d\n"
"Current pending commands: %4d\n"
@@ -136,9 +145,8 @@ static ssize_t twa_show_stats(struct class_device *class_dev, char *buf)
"Last sector count: %4d\n"
"Max sector count: %4d\n"
"SCSI Host Resets: %4d\n"
- "SCSI Aborts/Timeouts: %4d\n"
"AEN's: %4d\n",
- twa_driver_version,
+ TW_DRIVER_VERSION,
tw_dev->posted_request_count,
tw_dev->max_posted_request_count,
tw_dev->pending_request_count,
@@ -148,40 +156,19 @@ static ssize_t twa_show_stats(struct class_device *class_dev, char *buf)
tw_dev->sector_count,
tw_dev->max_sector_count,
tw_dev->num_resets,
- tw_dev->num_aborts,
tw_dev->aen_count);
spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
return len;
} /* End twa_show_stats() */
/* This function will set a devices queue depth */
-static ssize_t twa_store_queue_depth(struct device *dev, const char *buf, size_t count)
+static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth)
{
- int queue_depth;
- struct scsi_device *sdev = to_scsi_device(dev);
-
- queue_depth = simple_strtoul(buf, NULL, 0);
if (queue_depth > TW_Q_LENGTH-2)
- return -EINVAL;
+ queue_depth = TW_Q_LENGTH-2;
scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
-
- return count;
-} /* End twa_store_queue_depth() */
-
-/* Create sysfs 'queue_depth' entry */
-static struct device_attribute twa_queue_depth_attr = {
- .attr = {
- .name = "queue_depth",
- .mode = S_IRUSR | S_IWUSR,
- },
- .store = twa_store_queue_depth
-};
-
-/* Device attributes initializer */
-static struct device_attribute *twa_dev_attrs[] = {
- &twa_queue_depth_attr,
- NULL,
-};
+ return queue_depth;
+} /* End twa_change_queue_depth() */
/* Create sysfs 'stats' entry */
static struct class_device_attribute twa_host_stats_attr = {
@@ -265,7 +252,7 @@ static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset)
{
int request_id = 0;
char cdb[TW_MAX_CDB_LEN];
- TW_SG_Apache sglist[1];
+ TW_SG_Entry sglist[1];
int finished = 0, count = 0;
TW_Command_Full *full_command_packet;
TW_Command_Apache_Header *header;
@@ -286,7 +273,7 @@ static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset)
cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */
/* Initialize sglist */
- memset(&sglist, 0, sizeof(TW_SG_Apache));
+ memset(&sglist, 0, sizeof(TW_SG_Entry));
sglist[0].length = TW_SECTOR_SIZE;
sglist[0].address = tw_dev->generic_buffer_phys[request_id];
@@ -359,6 +346,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
TW_Event *event;
unsigned short aen;
char host[16];
+ char *error_str;
tw_dev->aen_count++;
@@ -385,6 +373,9 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
event->sequence_id = tw_dev->error_sequence_id;
tw_dev->error_sequence_id++;
+ /* Check for embedded error string */
+ error_str = &(header->err_specific_desc[strlen(header->err_specific_desc)+1]);
+
header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
event->parameter_len = strlen(header->err_specific_desc);
memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len);
@@ -393,7 +384,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
host,
twa_aen_severity_lookup(TW_SEV_OUT(header->status_block.severity__reserved)),
TW_MESSAGE_SOURCE_CONTROLLER_EVENT, aen,
- twa_string_lookup(twa_aen_table, aen),
+ error_str[0] == '\0' ? twa_string_lookup(twa_aen_table, aen) : error_str,
header->err_specific_desc);
else
tw_dev->aen_count--;
@@ -407,7 +398,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
{
char cdb[TW_MAX_CDB_LEN];
- TW_SG_Apache sglist[1];
+ TW_SG_Entry sglist[1];
TW_Command_Full *full_command_packet;
int retval = 1;
@@ -420,7 +411,7 @@ static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */
/* Initialize sglist */
- memset(&sglist, 0, sizeof(TW_SG_Apache));
+ memset(&sglist, 0, sizeof(TW_SG_Entry));
sglist[0].length = TW_SECTOR_SIZE;
sglist[0].address = tw_dev->generic_buffer_phys[request_id];
@@ -558,18 +549,18 @@ static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed)
u32 init_connect_result = 0;
if (twa_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS,
- TW_EXTENDED_INIT_CONNECT, TW_CURRENT_FW_SRL,
- TW_9000_ARCH_ID, TW_CURRENT_FW_BRANCH,
- TW_CURRENT_FW_BUILD, &fw_on_ctlr_srl,
+ TW_EXTENDED_INIT_CONNECT, TW_CURRENT_DRIVER_SRL,
+ TW_9000_ARCH_ID, TW_CURRENT_DRIVER_BRANCH,
+ TW_CURRENT_DRIVER_BUILD, &fw_on_ctlr_srl,
&fw_on_ctlr_arch_id, &fw_on_ctlr_branch,
&fw_on_ctlr_build, &init_connect_result)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x7, "Initconnection failed while checking SRL");
goto out;
}
- tw_dev->working_srl = TW_CURRENT_FW_SRL;
- tw_dev->working_branch = TW_CURRENT_FW_BRANCH;
- tw_dev->working_build = TW_CURRENT_FW_BUILD;
+ tw_dev->working_srl = fw_on_ctlr_srl;
+ tw_dev->working_branch = fw_on_ctlr_branch;
+ tw_dev->working_build = fw_on_ctlr_build;
/* Try base mode compatibility */
if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) {
@@ -584,7 +575,7 @@ static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed)
goto out;
}
if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) {
- if (TW_CURRENT_FW_SRL > fw_on_ctlr_srl) {
+ if (TW_CURRENT_DRIVER_SRL > fw_on_ctlr_srl) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x32, "Firmware and driver incompatibility: please upgrade firmware");
} else {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x33, "Firmware and driver incompatibility: please upgrade driver");
@@ -641,7 +632,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
data_buffer_length_adjusted = (driver_command.buffer_length + 511) & ~511;
/* Now allocate ioctl buf memory */
- cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, &dma_handle);
+ cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, &dma_handle, GFP_KERNEL);
if (!cpu_addr) {
retval = TW_IOCTL_ERROR_OS_ENOMEM;
goto out2;
@@ -679,26 +670,28 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
/* Now wait for command to complete */
- timeout = wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
+ timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
+
+ /* See if we reset while waiting for the ioctl to complete */
+ if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
+ clear_bit(TW_IN_RESET, &tw_dev->flags);
+ retval = TW_IOCTL_ERROR_OS_ERESTARTSYS;
+ goto out3;
+ }
- /* Check if we timed out, got a signal, or didn't get
- an interrupt */
- if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) {
+ /* We timed out, and didn't get an interrupt */
+ if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
/* Now we need to reset the board */
- if (timeout == TW_IOCTL_ERROR_OS_ERESTARTSYS) {
- retval = timeout;
- } else {
- printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n",
- tw_dev->host->host_no, TW_DRIVER, 0xc,
- cmd);
- retval = TW_IOCTL_ERROR_OS_EIO;
- }
+ printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n",
+ tw_dev->host->host_no, TW_DRIVER, 0xc,
+ cmd);
+ retval = TW_IOCTL_ERROR_OS_EIO;
spin_lock_irqsave(tw_dev->host->host_lock, flags);
tw_dev->state[request_id] = TW_S_COMPLETED;
twa_free_request_id(tw_dev, request_id);
tw_dev->posted_request_count--;
- twa_reset_device_extension(tw_dev);
spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+ twa_reset_device_extension(tw_dev, 1);
goto out3;
}
@@ -716,10 +709,16 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
tw_ioctl->driver_command.status = 0;
/* Copy compatiblity struct into ioctl data buffer */
tw_compat_info = (TW_Compatibility_Info *)tw_ioctl->data_buffer;
- strncpy(tw_compat_info->driver_version, twa_driver_version, strlen(twa_driver_version));
+ strncpy(tw_compat_info->driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION));
tw_compat_info->working_srl = tw_dev->working_srl;
tw_compat_info->working_branch = tw_dev->working_branch;
tw_compat_info->working_build = tw_dev->working_build;
+ tw_compat_info->driver_srl_high = TW_CURRENT_DRIVER_SRL;
+ tw_compat_info->driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
+ tw_compat_info->driver_build_high = TW_CURRENT_DRIVER_BUILD;
+ tw_compat_info->driver_srl_low = TW_BASE_FW_SRL;
+ tw_compat_info->driver_branch_low = TW_BASE_FW_BRANCH;
+ tw_compat_info->driver_build_low = TW_BASE_FW_BUILD;
break;
case TW_IOCTL_GET_LAST_EVENT:
if (tw_dev->event_queue_wrapped) {
@@ -849,7 +848,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
retval = 0;
out3:
/* Now free ioctl buf memory */
- pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
+ dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
out2:
up(&tw_dev->ioctl_sem);
out:
@@ -936,8 +935,13 @@ static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_
TW_Command_Full *full_command_packet;
unsigned short error;
int retval = 1;
+ char *error_str;
full_command_packet = tw_dev->command_packet_virt[request_id];
+
+ /* Check for embedded error string */
+ error_str = &(full_command_packet->header.err_specific_desc[strlen(full_command_packet->header.err_specific_desc) + 1]);
+
/* Don't print error for Logical unit not supported during rollcall */
error = full_command_packet->header.status_block.error;
if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) {
@@ -946,15 +950,17 @@ static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_
tw_dev->host->host_no,
TW_MESSAGE_SOURCE_CONTROLLER_ERROR,
full_command_packet->header.status_block.error,
+ error_str[0] == '\0' ?
twa_string_lookup(twa_error_table,
- full_command_packet->header.status_block.error),
+ full_command_packet->header.status_block.error) : error_str,
full_command_packet->header.err_specific_desc);
else
printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s:%s.\n",
TW_MESSAGE_SOURCE_CONTROLLER_ERROR,
full_command_packet->header.status_block.error,
+ error_str[0] == '\0' ?
twa_string_lookup(twa_error_table,
- full_command_packet->header.status_block.error),
+ full_command_packet->header.status_block.error) : error_str,
full_command_packet->header.err_specific_desc);
}
@@ -1075,10 +1081,9 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits,
tw_initconnect->request_id = request_id;
tw_initconnect->message_credits = message_credits;
tw_initconnect->features = set_features;
-#if BITS_PER_LONG > 32
- /* Turn on 64-bit sgl support */
- tw_initconnect->features |= 1;
-#endif
+
+ /* Turn on 64-bit sgl support if we need to */
+ tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0;
if (set_features & TW_EXTENDED_INIT_CONNECT) {
tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
@@ -1173,139 +1178,142 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance, struct pt_regs *re
/* Get the per adapter lock */
spin_lock(tw_dev->host->host_lock);
- /* See if the interrupt matches this instance */
- if (tw_dev->tw_pci_dev->irq == (unsigned int)irq) {
+ /* Read the registers */
+ status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
- handled = 1;
+ /* Check if this is our interrupt, otherwise bail */
+ if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
+ goto twa_interrupt_bail;
- /* Read the registers */
- status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+ handled = 1;
- /* Check if this is our interrupt, otherwise bail */
- if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
+ /* Check controller for errors */
+ if (twa_check_bits(status_reg_value)) {
+ if (twa_decode_bits(tw_dev, status_reg_value)) {
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
goto twa_interrupt_bail;
+ }
+ }
+
+ /* Handle host interrupt */
+ if (status_reg_value & TW_STATUS_HOST_INTERRUPT)
+ TW_CLEAR_HOST_INTERRUPT(tw_dev);
+
+ /* Handle attention interrupt */
+ if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
+ TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
+ if (!(test_and_set_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags))) {
+ twa_get_request_id(tw_dev, &request_id);
+
+ error = twa_aen_read_queue(tw_dev, request_id);
+ if (error) {
+ tw_dev->state[request_id] = TW_S_COMPLETED;
+ twa_free_request_id(tw_dev, request_id);
+ clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags);
+ }
+ }
+ }
- /* Check controller for errors */
- if (twa_check_bits(status_reg_value)) {
- if (twa_decode_bits(tw_dev, status_reg_value)) {
+ /* Handle command interrupt */
+ if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
+ TW_MASK_COMMAND_INTERRUPT(tw_dev);
+ /* Drain as many pending commands as we can */
+ while (tw_dev->pending_request_count > 0) {
+ request_id = tw_dev->pending_queue[tw_dev->pending_head];
+ if (tw_dev->state[request_id] != TW_S_PENDING) {
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x19, "Found request id that wasn't pending");
TW_CLEAR_ALL_INTERRUPTS(tw_dev);
goto twa_interrupt_bail;
}
+ if (twa_post_command_packet(tw_dev, request_id, 1)==0) {
+ tw_dev->pending_head = (tw_dev->pending_head + 1) % TW_Q_LENGTH;
+ tw_dev->pending_request_count--;
+ } else {
+ /* If we get here, we will continue re-posting on the next command interrupt */
+ break;
+ }
}
+ }
- /* Handle host interrupt */
- if (status_reg_value & TW_STATUS_HOST_INTERRUPT)
- TW_CLEAR_HOST_INTERRUPT(tw_dev);
-
- /* Handle attention interrupt */
- if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
- TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
- if (!(test_and_set_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags))) {
- twa_get_request_id(tw_dev, &request_id);
-
- error = twa_aen_read_queue(tw_dev, request_id);
- if (error) {
- tw_dev->state[request_id] = TW_S_COMPLETED;
- twa_free_request_id(tw_dev, request_id);
- clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags);
+ /* Handle response interrupt */
+ if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
+
+ /* Drain the response queue from the board */
+ while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+ /* Complete the response */
+ response_que.value = readl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
+ request_id = TW_RESID_OUT(response_que.response_id);
+ full_command_packet = tw_dev->command_packet_virt[request_id];
+ error = 0;
+ command_packet = &full_command_packet->command.oldcommand;
+ /* Check for command packet errors */
+ if (full_command_packet->command.newcommand.status != 0) {
+ if (tw_dev->srb[request_id] != 0) {
+ error = twa_fill_sense(tw_dev, request_id, 1, 1);
+ } else {
+ /* Skip ioctl error prints */
+ if (request_id != tw_dev->chrdev_request_id) {
+ error = twa_fill_sense(tw_dev, request_id, 0, 1);
+ }
}
}
- }
- /* Handle command interrupt */
- if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
- TW_MASK_COMMAND_INTERRUPT(tw_dev);
- /* Drain as many pending commands as we can */
- while (tw_dev->pending_request_count > 0) {
- request_id = tw_dev->pending_queue[tw_dev->pending_head];
- if (tw_dev->state[request_id] != TW_S_PENDING) {
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x19, "Found request id that wasn't pending");
+ /* Check for correct state */
+ if (tw_dev->state[request_id] != TW_S_POSTED) {
+ if (tw_dev->srb[request_id] != 0) {
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Received a request id that wasn't posted");
TW_CLEAR_ALL_INTERRUPTS(tw_dev);
goto twa_interrupt_bail;
}
- if (twa_post_command_packet(tw_dev, request_id, 1)==0) {
- tw_dev->pending_head = (tw_dev->pending_head + 1) % TW_Q_LENGTH;
- tw_dev->pending_request_count--;
- } else {
- /* If we get here, we will continue re-posting on the next command interrupt */
- break;
- }
}
- }
- /* Handle response interrupt */
- if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
-
- /* Drain the response queue from the board */
- while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
- /* Complete the response */
- response_que.value = readl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
- request_id = TW_RESID_OUT(response_que.response_id);
- full_command_packet = tw_dev->command_packet_virt[request_id];
- error = 0;
- command_packet = &full_command_packet->command.oldcommand;
- /* Check for command packet errors */
- if (full_command_packet->command.newcommand.status != 0) {
- if (tw_dev->srb[request_id] != 0) {
- error = twa_fill_sense(tw_dev, request_id, 1, 1);
- } else {
- /* Skip ioctl error prints */
- if (request_id != tw_dev->chrdev_request_id) {
- error = twa_fill_sense(tw_dev, request_id, 0, 1);
- }
- }
+ /* Check for internal command completion */
+ if (tw_dev->srb[request_id] == 0) {
+ if (request_id != tw_dev->chrdev_request_id) {
+ if (twa_aen_complete(tw_dev, request_id))
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Error completing AEN during attention interrupt");
+ } else {
+ tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+ wake_up(&tw_dev->ioctl_wqueue);
}
-
- /* Check for correct state */
- if (tw_dev->state[request_id] != TW_S_POSTED) {
- if (tw_dev->srb[request_id] != 0) {
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Received a request id that wasn't posted");
- TW_CLEAR_ALL_INTERRUPTS(tw_dev);
- goto twa_interrupt_bail;
- }
+ } else {
+ twa_scsiop_execute_scsi_complete(tw_dev, request_id);
+ /* If no error command was a success */
+ if (error == 0) {
+ tw_dev->srb[request_id]->result = (DID_OK << 16);
}
- /* Check for internal command completion */
- if (tw_dev->srb[request_id] == 0) {
- if (request_id != tw_dev->chrdev_request_id) {
- if (twa_aen_complete(tw_dev, request_id))
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Error completing AEN during attention interrupt");
- } else {
- tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
- wake_up(&tw_dev->ioctl_wqueue);
- }
- } else {
- twa_scsiop_execute_scsi_complete(tw_dev, request_id);
- /* If no error command was a success */
- if (error == 0) {
- tw_dev->srb[request_id]->result = (DID_OK << 16);
- }
-
- /* If error, command failed */
- if (error == 1) {
- /* Ask for a host reset */
- tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
- }
+ /* If error, command failed */
+ if (error == 1) {
+ /* Ask for a host reset */
+ tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+ }
- /* Now complete the io */
- tw_dev->state[request_id] = TW_S_COMPLETED;
- twa_free_request_id(tw_dev, request_id);
- tw_dev->posted_request_count--;
- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
- twa_unmap_scsi_data(tw_dev, request_id);
+ /* Report residual bytes for single sgl */
+ if ((tw_dev->srb[request_id]->use_sg <= 1) && (full_command_packet->command.newcommand.status == 0)) {
+ if (full_command_packet->command.newcommand.sg_list[0].length < tw_dev->srb[request_id]->request_bufflen)
+ tw_dev->srb[request_id]->resid = tw_dev->srb[request_id]->request_bufflen - full_command_packet->command.newcommand.sg_list[0].length;
}
- /* Check for valid status after each drain */
- status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
- if (twa_check_bits(status_reg_value)) {
- if (twa_decode_bits(tw_dev, status_reg_value)) {
- TW_CLEAR_ALL_INTERRUPTS(tw_dev);
- goto twa_interrupt_bail;
- }
+ /* Now complete the io */
+ tw_dev->state[request_id] = TW_S_COMPLETED;
+ twa_free_request_id(tw_dev, request_id);
+ tw_dev->posted_request_count--;
+ tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+ twa_unmap_scsi_data(tw_dev, request_id);
+ }
+
+ /* Check for valid status after each drain */
+ status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+ if (twa_check_bits(status_reg_value)) {
+ if (twa_decode_bits(tw_dev, status_reg_value)) {
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
+ goto twa_interrupt_bail;
}
}
}
}
+
twa_interrupt_bail:
spin_unlock(tw_dev->host->host_lock);
return IRQ_RETVAL(handled);
@@ -1320,9 +1328,12 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) {
newcommand = &full_command_packet->command.newcommand;
- newcommand->request_id = request_id;
+ newcommand->request_id__lunl =
+ TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id);
newcommand->sg_list[0].address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
newcommand->sg_list[0].length = length;
+ newcommand->sgl_entries__lunh =
+ TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1);
} else {
oldcommand = &full_command_packet->command.oldcommand;
oldcommand->request_id = request_id;
@@ -1332,6 +1343,9 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
sgl->length = length;
+
+ if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
+ oldcommand->size += 1;
}
}
} /* End twa_load_sgl() */
@@ -1486,7 +1500,7 @@ out:
static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal)
{
u32 status_reg_value;
- unsigned long command_que_value;
+ dma_addr_t command_que_value;
int retval = 1;
command_que_value = tw_dev->command_packet_phys[request_id];
@@ -1517,11 +1531,13 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id,
goto out;
} else {
/* We successfully posted the command packet */
-#if BITS_PER_LONG > 32
- writeq(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
-#else
- writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
-#endif
+ if (sizeof(dma_addr_t) > 4) {
+ command_que_value += TW_COMMAND_OFFSET;
+ writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
+ writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4);
+ } else {
+ writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
+ }
tw_dev->state[request_id] = TW_S_POSTED;
tw_dev->posted_request_count++;
if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) {
@@ -1534,10 +1550,16 @@ out:
} /* End twa_post_command_packet() */
/* This function will reset a device extension */
-static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
+static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset)
{
int i = 0;
int retval = 1;
+ unsigned long flags = 0;
+
+ set_bit(TW_IN_RESET, &tw_dev->flags);
+ TW_DISABLE_INTERRUPTS(tw_dev);
+ TW_MASK_COMMAND_INTERRUPT(tw_dev);
+ spin_lock_irqsave(tw_dev->host->host_lock, flags);
/* Abort all requests that are in progress */
for (i = 0; i < TW_Q_LENGTH; i++) {
@@ -1564,16 +1586,21 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
tw_dev->pending_head = TW_Q_START;
tw_dev->pending_tail = TW_Q_START;
tw_dev->reset_print = 0;
- tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
- tw_dev->flags = 0;
- TW_DISABLE_INTERRUPTS(tw_dev);
+ spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
if (twa_reset_sequence(tw_dev, 1))
goto out;
- TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+ TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+ /* Wake up any ioctl that was pending before the reset */
+ if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || (ioctl_reset)) {
+ clear_bit(TW_IN_RESET, &tw_dev->flags);
+ } else {
+ tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+ wake_up(&tw_dev->ioctl_wqueue);
+ }
retval = 0;
out:
return retval;
@@ -1589,7 +1616,7 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset)
TW_SOFT_RESET(tw_dev);
/* Make sure controller is in a good state */
- if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 30)) {
+ if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 60)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1f, "Microcontroller not ready during reset sequence");
do_soft_reset = 1;
tries++;
@@ -1660,38 +1687,6 @@ static int twa_scsi_biosparam(struct scsi_device *sdev, struct block_device *bde
return 0;
} /* End twa_scsi_biosparam() */
-/* This is the new scsi eh abort function */
-static int twa_scsi_eh_abort(struct scsi_cmnd *SCpnt)
-{
- int i;
- TW_Device_Extension *tw_dev = NULL;
- int retval = FAILED;
-
- tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
-
- spin_unlock_irq(tw_dev->host->host_lock);
-
- tw_dev->num_aborts++;
-
- /* If we find any IO's in process, we have to reset the card */
- for (i = 0; i < TW_Q_LENGTH; i++) {
- if ((tw_dev->state[i] != TW_S_FINISHED) && (tw_dev->state[i] != TW_S_INITIAL)) {
- printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Unit #%d: Command (0x%x) timed out, resetting card.\n",
- tw_dev->host->host_no, TW_DRIVER, 0x2c,
- SCpnt->device->id, SCpnt->cmnd[0]);
- if (twa_reset_device_extension(tw_dev)) {
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2a, "Controller reset failed during scsi abort");
- goto out;
- }
- break;
- }
- }
- retval = SUCCESS;
-out:
- spin_lock_irq(tw_dev->host->host_lock);
- return retval;
-} /* End twa_scsi_eh_abort() */
-
/* This is the new scsi eh reset function */
static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
{
@@ -1704,14 +1699,14 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
tw_dev->num_resets++;
- printk(KERN_WARNING "3w-9xxx: scsi%d: SCSI host reset started.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, TW_DRIVER, 0x2c, SCpnt->device->id, SCpnt->cmnd[0]);
/* Now reset the card and some of the device extension data */
- if (twa_reset_device_extension(tw_dev)) {
+ if (twa_reset_device_extension(tw_dev, 0)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset");
goto out;
}
- printk(KERN_WARNING "3w-9xxx: scsi%d: SCSI host reset succeeded.\n", tw_dev->host->host_no);
+
retval = SUCCESS;
out:
spin_lock_irq(tw_dev->host->host_lock);
@@ -1724,6 +1719,14 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
int request_id, retval;
TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+ /* Check if this FW supports luns */
+ if ((SCpnt->device->lun != 0) && (tw_dev->working_srl < TW_FW_SRL_LUNS_SUPPORTED)) {
+ SCpnt->result = (DID_BAD_TARGET << 16);
+ done(SCpnt);
+ retval = 0;
+ goto out;
+ }
+
/* Save done function into scsi_cmnd struct */
SCpnt->scsi_done = done;
@@ -1748,12 +1751,12 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
done(SCpnt);
retval = 0;
}
-
+out:
return retval;
} /* End twa_scsi_queue() */
/* This function hands scsi cdb's to the firmware */
-static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Apache *sglistarg)
+static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg)
{
TW_Command_Full *full_command_packet;
TW_Command_Apache *command_packet;
@@ -1787,12 +1790,16 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
else
memcpy(command_packet->cdb, cdb, TW_MAX_CDB_LEN);
- if (srb)
+ if (srb) {
command_packet->unit = srb->device->id;
- else
+ command_packet->request_id__lunl =
+ TW_REQ_LUN_IN(srb->device->lun, request_id);
+ } else {
+ command_packet->request_id__lunl =
+ TW_REQ_LUN_IN(0, request_id);
command_packet->unit = 0;
+ }
- command_packet->request_id = request_id;
command_packet->sgl_offset = 16;
if (!sglistarg) {
@@ -1809,7 +1816,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
command_packet->sg_list[0].address = buffaddr;
command_packet->sg_list[0].length = tw_dev->srb[request_id]->request_bufflen;
}
- command_packet->sgl_entries = 1;
+ command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), 1);
if (command_packet->sg_list[0].address & TW_ALIGNMENT_9000_SGL) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
@@ -1818,19 +1825,24 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
}
if (tw_dev->srb[request_id]->use_sg > 0) {
- sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
- if (sg_count == 0)
- goto out;
-
- for (i = 0; i < sg_count; i++) {
- command_packet->sg_list[i].address = sg_dma_address(&sglist[i]);
- command_packet->sg_list[i].length = sg_dma_len(&sglist[i]);
- if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
+ if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
+ command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
+ command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
+ } else {
+ sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
+ if (sg_count == 0)
goto out;
+
+ for (i = 0; i < sg_count; i++) {
+ command_packet->sg_list[i].address = sg_dma_address(&sglist[i]);
+ command_packet->sg_list[i].length = sg_dma_len(&sglist[i]);
+ if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
+ goto out;
+ }
}
}
- command_packet->sgl_entries = tw_dev->srb[request_id]->use_sg;
+ command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg);
}
} else {
/* Internal cdb post */
@@ -1842,7 +1854,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
goto out;
}
}
- command_packet->sgl_entries = use_sg;
+ command_packet->sgl_entries__lunh = TW_REQ_LUN_IN(0, use_sg);
}
if (srb) {
@@ -1903,7 +1915,7 @@ static void __twa_shutdown(TW_Device_Extension *tw_dev)
}
/* Clear all interrupts just before exit */
- TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
} /* End __twa_shutdown() */
/* Wrapper for __twa_shutdown */
@@ -1946,9 +1958,9 @@ static struct scsi_host_template driver_template = {
.module = THIS_MODULE,
.name = "3ware 9000 Storage Controller",
.queuecommand = twa_scsi_queue,
- .eh_abort_handler = twa_scsi_eh_abort,
.eh_host_reset_handler = twa_scsi_eh_reset,
.bios_param = twa_scsi_biosparam,
+ .change_queue_depth = twa_change_queue_depth,
.can_queue = TW_Q_LENGTH-2,
.this_id = -1,
.sg_tablesize = TW_APACHE_MAX_SGL_LENGTH,
@@ -1956,7 +1968,6 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = TW_MAX_CMDS_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = twa_host_attrs,
- .sdev_attrs = twa_dev_attrs,
.emulated = 1
};
@@ -1976,7 +1987,7 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
pci_set_master(pdev);
- retval = pci_set_dma_mask(pdev, TW_DMA_MASK);
+ retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK);
if (retval) {
TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask");
goto out_disable_device;
@@ -2028,8 +2039,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
host->max_id = TW_MAX_UNITS;
host->max_cmd_len = TW_MAX_CDB_LEN;
- /* Luns and channels aren't supported by adapter */
- host->max_lun = 0;
+ /* Channels aren't supported by adapter */
+ host->max_lun = TW_MAX_LUNS(tw_dev->working_srl);
host->max_channel = 0;
/* Register the card with the kernel SCSI layer */
@@ -2095,23 +2106,24 @@ static void twa_remove(struct pci_dev *pdev)
scsi_remove_host(tw_dev->host);
- __twa_shutdown(tw_dev);
+ /* Unregister character device */
+ if (twa_major >= 0) {
+ unregister_chrdev(twa_major, "twa");
+ twa_major = -1;
+ }
/* Free up the IRQ */
free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+ /* Shutdown the card */
+ __twa_shutdown(tw_dev);
+
/* Free up the mem region */
pci_release_regions(pdev);
/* Free up device extension resources */
twa_free_device_extension(tw_dev);
- /* Unregister character device */
- if (twa_major >= 0) {
- unregister_chrdev(twa_major, "twa");
- twa_major = -1;
- }
-
scsi_host_put(tw_dev->host);
pci_disable_device(pdev);
twa_device_extension_count--;
@@ -2139,7 +2151,7 @@ static struct pci_driver twa_driver = {
/* This function is called on driver initialization */
static int __init twa_init(void)
{
- printk(KERN_WARNING "3ware 9000 Storage Controller device driver for Linux v%s.\n", twa_driver_version);
+ printk(KERN_WARNING "3ware 9000 Storage Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION);
return pci_module_init(&twa_driver);
} /* End twa_init() */
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index 29f70d531744c..8c8ecbed3b587 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -3,7 +3,7 @@
Written By: Adam Radford <linuxraid@amcc.com>
- Copyright (C) 2004 Applied Micro Circuits Corporation.
+ Copyright (C) 2004-2005 Applied Micro Circuits Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -293,7 +293,6 @@ static twa_message_type twa_error_table[] = {
#define TW_RESPONSE_ID_MASK 0x00000FF0
/* PCI related defines */
-#define TW_DEVICE_NAME "3w-9xxx"
#define TW_NUMDEVICES 1
#define TW_PCI_CLEAR_PARITY_ERRORS 0xc100
#define TW_PCI_CLEAR_PCI_ABORT 0x2000
@@ -325,9 +324,9 @@ static twa_message_type twa_error_table[] = {
/* Compatibility defines */
#define TW_9000_ARCH_ID 0x5
-#define TW_CURRENT_FW_SRL 24
-#define TW_CURRENT_FW_BUILD 5
-#define TW_CURRENT_FW_BRANCH 1
+#define TW_CURRENT_DRIVER_SRL 28
+#define TW_CURRENT_DRIVER_BUILD 9
+#define TW_CURRENT_DRIVER_BRANCH 4
/* Phase defines */
#define TW_PHASE_INITIAL 0
@@ -346,19 +345,10 @@ static twa_message_type twa_error_table[] = {
#define TW_BUNDLED_FW_SAFE_TO_FLASH 0x4
#define TW_CTLR_FW_RECOMMENDS_FLASH 0x8
#define TW_CTLR_FW_COMPATIBLE 0x2
-#define TW_BASE_FW_SRL 0x17
+#define TW_BASE_FW_SRL 24
#define TW_BASE_FW_BRANCH 0
#define TW_BASE_FW_BUILD 1
-#if BITS_PER_LONG > 32
-#define TW_APACHE_MAX_SGL_LENGTH 72
-#define TW_ESCALADE_MAX_SGL_LENGTH 41
-#define TW_APACHE_CMD_PKT_SIZE 5
-#else
-#define TW_APACHE_MAX_SGL_LENGTH 109
-#define TW_ESCALADE_MAX_SGL_LENGTH 62
-#define TW_APACHE_CMD_PKT_SIZE 4
-#endif
-#define TW_ATA_PASS_SGL_MAX 60
+#define TW_FW_SRL_LUNS_SUPPORTED 28
#define TW_Q_LENGTH 256
#define TW_Q_START 0
#define TW_MAX_SLOT 32
@@ -366,7 +356,7 @@ static twa_message_type twa_error_table[] = {
#define TW_MAX_CMDS_PER_LUN 254
#define TW_MAX_RESPONSE_DRAIN 256
#define TW_MAX_AEN_DRAIN 40
-#define TW_IN_IOCTL 2
+#define TW_IN_RESET 2
#define TW_IN_CHRDEV_IOCTL 3
#define TW_IN_ATTENTION_LOOP 4
#define TW_MAX_SECTORS 256
@@ -424,13 +414,6 @@ static twa_message_type twa_error_table[] = {
#define TW_DRIVER TW_MESSAGE_SOURCE_LINUX_DRIVER
#define TW_MESSAGE_SOURCE_LINUX_OS 9
#define TW_OS TW_MESSAGE_SOURCE_LINUX_OS
-#if BITS_PER_LONG > 32
-#define TW_COMMAND_SIZE 5
-#define TW_DMA_MASK DMA_64BIT_MASK
-#else
-#define TW_COMMAND_SIZE 4
-#define TW_DMA_MASK DMA_32BIT_MASK
-#endif
#ifndef PCI_DEVICE_ID_3WARE_9000
#define PCI_DEVICE_ID_3WARE_9000 0x1002
#endif
@@ -451,14 +434,14 @@ static twa_message_type twa_error_table[] = {
/* reserved_1: 4, response_id: 8, reserved_2: 20 */
#define TW_RESID_OUT(x) ((x >> 4) & 0xff)
+/* request_id: 12, lun: 4 */
+#define TW_REQ_LUN_IN(lun, request_id) (((lun << 12) & 0xf000) | (request_id & 0xfff))
+#define TW_LUN_OUT(lun) ((lun >> 12) & 0xf)
+
/* Macros */
#define TW_CONTROL_REG_ADDR(x) (x->base_addr)
#define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4)
-#if BITS_PER_LONG > 32
-#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x20)
-#else
-#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x8)
-#endif
+#define TW_COMMAND_QUEUE_REG_ADDR(x) (sizeof(dma_addr_t) > 4 ? ((unsigned char __iomem *)x->base_addr + 0x20) : ((unsigned char __iomem *)x->base_addr + 0x8))
#define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC)
#define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
#define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
@@ -480,12 +463,17 @@ printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s.\n",h->host_no,
else \
printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s.\n",a,b,c); \
}
+#define TW_MAX_LUNS(srl) (srl < TW_FW_SRL_LUNS_SUPPORTED ? 1 : 16)
+#define TW_COMMAND_SIZE (sizeof(dma_addr_t) > 4 ? 5 : 4)
+#define TW_APACHE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 72 : 109)
+#define TW_ESCALADE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 41 : 62)
+#define TW_PADDING_LENGTH (sizeof(dma_addr_t) > 4 ? 8 : 0)
#pragma pack(1)
/* Scatter Gather List Entry */
typedef struct TAG_TW_SG_Entry {
- unsigned long address;
+ dma_addr_t address;
u32 length;
} TW_SG_Entry;
@@ -506,42 +494,27 @@ typedef struct TW_Command {
struct {
u32 lba;
TW_SG_Entry sgl[TW_ESCALADE_MAX_SGL_LENGTH];
-#if BITS_PER_LONG > 32
- u32 padding[2]; /* pad to 512 bytes */
-#else
- u32 padding;
-#endif
+ dma_addr_t padding;
} io;
struct {
TW_SG_Entry sgl[TW_ESCALADE_MAX_SGL_LENGTH];
-#if BITS_PER_LONG > 32
- u32 padding[3];
-#else
- u32 padding[2];
-#endif
+ u32 padding;
+ dma_addr_t padding2;
} param;
} byte8_offset;
} TW_Command;
-/* Scatter gather element for 9000+ controllers */
-typedef struct TAG_TW_SG_Apache {
- unsigned long address;
- u32 length;
-} TW_SG_Apache;
-
/* Command Packet for 9000+ controllers */
typedef struct TAG_TW_Command_Apache {
unsigned char opcode__reserved;
unsigned char unit;
- unsigned short request_id;
+ unsigned short request_id__lunl;
unsigned char status;
unsigned char sgl_offset;
- unsigned short sgl_entries;
+ unsigned short sgl_entries__lunh;
unsigned char cdb[16];
- TW_SG_Apache sg_list[TW_APACHE_MAX_SGL_LENGTH];
-#if BITS_PER_LONG > 32
- unsigned char padding[8];
-#endif
+ TW_SG_Entry sg_list[TW_APACHE_MAX_SGL_LENGTH];
+ unsigned char padding[TW_PADDING_LENGTH];
} TW_Command_Apache;
/* New command packet header */
@@ -652,14 +625,20 @@ typedef struct TAG_TW_Compatibility_Info
unsigned short working_srl;
unsigned short working_branch;
unsigned short working_build;
+ unsigned short driver_srl_high;
+ unsigned short driver_branch_high;
+ unsigned short driver_build_high;
+ unsigned short driver_srl_low;
+ unsigned short driver_branch_low;
+ unsigned short driver_build_low;
} TW_Compatibility_Info;
typedef struct TAG_TW_Device_Extension {
u32 __iomem *base_addr;
unsigned long *generic_buffer_virt[TW_Q_LENGTH];
- unsigned long generic_buffer_phys[TW_Q_LENGTH];
+ dma_addr_t generic_buffer_phys[TW_Q_LENGTH];
TW_Command_Full *command_packet_virt[TW_Q_LENGTH];
- unsigned long command_packet_phys[TW_Q_LENGTH];
+ dma_addr_t command_packet_phys[TW_Q_LENGTH];
struct pci_dev *tw_pci_dev;
struct scsi_cmnd *srb[TW_Q_LENGTH];
unsigned char free_queue[TW_Q_LENGTH];
@@ -675,7 +654,6 @@ typedef struct TAG_TW_Device_Extension {
unsigned int max_pending_request_count;
unsigned int max_sgl_entries;
unsigned int sgl_entries;
- unsigned int num_aborts;
unsigned int num_resets;
unsigned int sector_count;
unsigned int max_sector_count;
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 9073638c836aa..48f9ece1cbd09 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -6,7 +6,7 @@
Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Brad Strand <linux@3ware.com>
- Copyright (C) 1999-2004 3ware Inc.
+ Copyright (C) 1999-2005 3ware Inc.
Kernel compatiblity By: Andre Hedrick <andre@suse.com>
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
@@ -185,6 +185,12 @@
Fix data_buffer_length usage in tw_chrdev_ioctl().
Update contact information.
1.26.02.000 - Convert driver to pci_driver format.
+ 1.26.02.001 - Increase max ioctl buffer size to 512 sectors.
+ Make tw_scsi_queue() return 0 for 'Unknown scsi opcode'.
+ Fix tw_remove() to free irq handler/unregister_chrdev()
+ before shutting down card.
+ Change to new 'change_queue_depth' api.
+ Fix 'handled=1' ISR usage, remove bogus IRQ check.
*/
#include <linux/module.h>
@@ -207,7 +213,7 @@
#include "3w-xxxx.h"
/* Globals */
-#define TW_DRIVER_VERSION "1.26.02.000"
+#define TW_DRIVER_VERSION "1.26.02.001"
static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
static int tw_device_extension_count = 0;
static int twe_major = -1;
@@ -509,33 +515,13 @@ static ssize_t tw_show_stats(struct class_device *class_dev, char *buf)
} /* End tw_show_stats() */
/* This function will set a devices queue depth */
-static ssize_t tw_store_queue_depth(struct device *dev, const char *buf, size_t count)
+static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth)
{
- int queue_depth;
- struct scsi_device *sdev = to_scsi_device(dev);
-
- queue_depth = simple_strtoul(buf, NULL, 0);
if (queue_depth > TW_Q_LENGTH-2)
- return -EINVAL;
+ queue_depth = TW_Q_LENGTH-2;
scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
-
- return count;
-} /* End tw_store_queue_depth() */
-
-/* Create sysfs 'queue_depth' entry */
-static struct device_attribute tw_queue_depth_attr = {
- .attr = {
- .name = "queue_depth",
- .mode = S_IRUSR | S_IWUSR,
- },
- .store = tw_store_queue_depth
-};
-
-/* Device attributes initializer */
-static struct device_attribute *tw_dev_attrs[] = {
- &tw_queue_depth_attr,
- NULL,
-};
+ return queue_depth;
+} /* End tw_change_queue_depth() */
/* Create sysfs 'stats' entry */
static struct class_device_attribute tw_host_stats_attr = {
@@ -910,7 +896,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
goto out;
/* Check size */
- if (data_buffer_length > TW_MAX_SECTORS * 512) {
+ if (data_buffer_length > TW_MAX_IOCTL_SECTORS * 512) {
retval = -EINVAL;
goto out;
}
@@ -995,7 +981,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
/* Now wait for the command to complete */
- timeout = wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
+ timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
/* See if we reset while waiting for the ioctl to complete */
if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
@@ -1004,16 +990,11 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
goto out2;
}
- /* Check if we timed out, got a signal, or didn't get
- an interrupt */
- if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) {
+ /* We timed out, and didn't get an interrupt */
+ if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
/* Now we need to reset the board */
- if (timeout == -ERESTARTSYS) {
- retval = timeout;
- } else {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
- retval = -EIO;
- }
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
+ retval = -EIO;
spin_lock_irqsave(tw_dev->host->host_lock, flags);
tw_dev->state[request_id] = TW_S_COMPLETED;
tw_state_request_finish(tw_dev, request_id);
@@ -2060,7 +2041,7 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
tw_state_request_finish(tw_dev, request_id);
SCpnt->result = (DID_BAD_TARGET << 16);
done(SCpnt);
- goto out;
+ retval = 0;
}
if (retval) {
tw_dev->state[request_id] = TW_S_COMPLETED;
@@ -2069,7 +2050,6 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
done(SCpnt);
retval = 0;
}
-out:
return retval;
} /* End tw_scsi_queue() */
@@ -2088,183 +2068,180 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance,
/* Get the host lock for io completions */
spin_lock(tw_dev->host->host_lock);
- /* See if the interrupt matches this instance */
- if (tw_dev->tw_pci_dev->irq == (unsigned int)irq) {
+ /* Read the registers */
+ status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
- handled = 1;
+ /* Check if this is our interrupt, otherwise bail */
+ if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
+ goto tw_interrupt_bail;
- /* Read the registers */
- status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
+ handled = 1;
- /* Check if this is our interrupt, otherwise bail */
- if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
+ /* Check controller for errors */
+ if (tw_check_bits(status_reg_value)) {
+ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+ if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
goto tw_interrupt_bail;
-
- /* Check controller for errors */
- if (tw_check_bits(status_reg_value)) {
- dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
- if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
- TW_CLEAR_ALL_INTERRUPTS(tw_dev);
- goto tw_interrupt_bail;
- }
}
+ }
- /* Handle host interrupt */
- if (status_reg_value & TW_STATUS_HOST_INTERRUPT) {
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
- TW_CLEAR_HOST_INTERRUPT(tw_dev);
- }
+ /* Handle host interrupt */
+ if (status_reg_value & TW_STATUS_HOST_INTERRUPT) {
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
+ TW_CLEAR_HOST_INTERRUPT(tw_dev);
+ }
- /* Handle attention interrupt */
- if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
- TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
- tw_state_request_start(tw_dev, &request_id);
- error = tw_aen_read_queue(tw_dev, request_id);
- if (error) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- }
+ /* Handle attention interrupt */
+ if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
+ TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
+ tw_state_request_start(tw_dev, &request_id);
+ error = tw_aen_read_queue(tw_dev, request_id);
+ if (error) {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
+ tw_dev->state[request_id] = TW_S_COMPLETED;
+ tw_state_request_finish(tw_dev, request_id);
}
+ }
- /* Handle command interrupt */
- if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
- /* Drain as many pending commands as we can */
- while (tw_dev->pending_request_count > 0) {
- request_id = tw_dev->pending_queue[tw_dev->pending_head];
- if (tw_dev->state[request_id] != TW_S_PENDING) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
- break;
- }
- if (tw_post_command_packet(tw_dev, request_id)==0) {
- if (tw_dev->pending_head == TW_Q_LENGTH-1) {
- tw_dev->pending_head = TW_Q_START;
- } else {
- tw_dev->pending_head = tw_dev->pending_head + 1;
- }
- tw_dev->pending_request_count--;
+ /* Handle command interrupt */
+ if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
+ /* Drain as many pending commands as we can */
+ while (tw_dev->pending_request_count > 0) {
+ request_id = tw_dev->pending_queue[tw_dev->pending_head];
+ if (tw_dev->state[request_id] != TW_S_PENDING) {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
+ break;
+ }
+ if (tw_post_command_packet(tw_dev, request_id)==0) {
+ if (tw_dev->pending_head == TW_Q_LENGTH-1) {
+ tw_dev->pending_head = TW_Q_START;
} else {
- /* If we get here, we will continue re-posting on the next command interrupt */
- break;
+ tw_dev->pending_head = tw_dev->pending_head + 1;
}
+ tw_dev->pending_request_count--;
+ } else {
+ /* If we get here, we will continue re-posting on the next command interrupt */
+ break;
}
- /* If there are no more pending requests, we mask command interrupt */
- if (tw_dev->pending_request_count == 0)
- TW_MASK_COMMAND_INTERRUPT(tw_dev);
}
-
- /* Handle response interrupt */
- if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
- /* Drain the response queue from the board */
- while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
- /* Read response queue register */
- response_que.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
- request_id = TW_RESID_OUT(response_que.response_id);
- command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
- error = 0;
-
- /* Check for bad response */
- if (command_packet->status != 0) {
- /* If internal command, don't error, don't fill sense */
- if (tw_dev->srb[request_id] == NULL) {
- tw_decode_sense(tw_dev, request_id, 0);
- } else {
- error = tw_decode_sense(tw_dev, request_id, 1);
- }
+ /* If there are no more pending requests, we mask command interrupt */
+ if (tw_dev->pending_request_count == 0)
+ TW_MASK_COMMAND_INTERRUPT(tw_dev);
+ }
+
+ /* Handle response interrupt */
+ if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
+ /* Drain the response queue from the board */
+ while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+ /* Read response queue register */
+ response_que.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
+ request_id = TW_RESID_OUT(response_que.response_id);
+ command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+ error = 0;
+
+ /* Check for bad response */
+ if (command_packet->status != 0) {
+ /* If internal command, don't error, don't fill sense */
+ if (tw_dev->srb[request_id] == NULL) {
+ tw_decode_sense(tw_dev, request_id, 0);
+ } else {
+ error = tw_decode_sense(tw_dev, request_id, 1);
}
+ }
- /* Check for correct state */
- if (tw_dev->state[request_id] != TW_S_POSTED) {
- if (tw_dev->srb[request_id] != NULL) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id that wasn't posted.\n", tw_dev->host->host_no);
- error = 1;
- }
+ /* Check for correct state */
+ if (tw_dev->state[request_id] != TW_S_POSTED) {
+ if (tw_dev->srb[request_id] != NULL) {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id that wasn't posted.\n", tw_dev->host->host_no);
+ error = 1;
}
+ }
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
- /* Check for internal command completion */
- if (tw_dev->srb[request_id] == NULL) {
- dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
- /* Check for chrdev ioctl completion */
- if (request_id != tw_dev->chrdev_request_id) {
- retval = tw_aen_complete(tw_dev, request_id);
- if (retval) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
- }
- } else {
- tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
- wake_up(&tw_dev->ioctl_wqueue);
+ /* Check for internal command completion */
+ if (tw_dev->srb[request_id] == NULL) {
+ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
+ /* Check for chrdev ioctl completion */
+ if (request_id != tw_dev->chrdev_request_id) {
+ retval = tw_aen_complete(tw_dev, request_id);
+ if (retval) {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
}
} else {
+ tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+ wake_up(&tw_dev->ioctl_wqueue);
+ }
+ } else {
switch (tw_dev->srb[request_id]->cmnd[0]) {
- case READ_10:
- case READ_6:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
- break;
- case WRITE_10:
- case WRITE_6:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
- break;
- case TEST_UNIT_READY:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n");
- error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id);
- break;
- case INQUIRY:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
- error = tw_scsiop_inquiry_complete(tw_dev, request_id);
- break;
- case READ_CAPACITY:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
- error = tw_scsiop_read_capacity_complete(tw_dev, request_id);
- break;
- case MODE_SENSE:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught MODE_SENSE\n");
- error = tw_scsiop_mode_sense_complete(tw_dev, request_id);
- break;
- case SYNCHRONIZE_CACHE:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught SYNCHRONIZE_CACHE\n");
- break;
- default:
- printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n");
- error = 1;
- }
-
- /* If no error command was a success */
- if (error == 0) {
- tw_dev->srb[request_id]->result = (DID_OK << 16);
- }
+ case READ_10:
+ case READ_6:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
+ break;
+ case WRITE_10:
+ case WRITE_6:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
+ break;
+ case TEST_UNIT_READY:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n");
+ error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id);
+ break;
+ case INQUIRY:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
+ error = tw_scsiop_inquiry_complete(tw_dev, request_id);
+ break;
+ case READ_CAPACITY:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
+ error = tw_scsiop_read_capacity_complete(tw_dev, request_id);
+ break;
+ case MODE_SENSE:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught MODE_SENSE\n");
+ error = tw_scsiop_mode_sense_complete(tw_dev, request_id);
+ break;
+ case SYNCHRONIZE_CACHE:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught SYNCHRONIZE_CACHE\n");
+ break;
+ default:
+ printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n");
+ error = 1;
+ }
- /* If error, command failed */
- if (error == 1) {
- /* Ask for a host reset */
- tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
- }
+ /* If no error command was a success */
+ if (error == 0) {
+ tw_dev->srb[request_id]->result = (DID_OK << 16);
+ }
- /* Now complete the io */
- if ((error != TW_ISR_DONT_COMPLETE)) {
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- tw_dev->posted_request_count--;
- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+ /* If error, command failed */
+ if (error == 1) {
+ /* Ask for a host reset */
+ tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+ }
- tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
- }
+ /* Now complete the io */
+ if ((error != TW_ISR_DONT_COMPLETE)) {
+ tw_dev->state[request_id] = TW_S_COMPLETED;
+ tw_state_request_finish(tw_dev, request_id);
+ tw_dev->posted_request_count--;
+ tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+
+ tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
}
+ }
- /* Check for valid status after each drain */
- status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
- if (tw_check_bits(status_reg_value)) {
- dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
- if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
- TW_CLEAR_ALL_INTERRUPTS(tw_dev);
- goto tw_interrupt_bail;
- }
+ /* Check for valid status after each drain */
+ status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
+ if (tw_check_bits(status_reg_value)) {
+ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+ if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
+ goto tw_interrupt_bail;
}
}
}
}
+
tw_interrupt_bail:
spin_unlock(tw_dev->host->host_lock);
return IRQ_RETVAL(handled);
@@ -2304,6 +2281,7 @@ static struct scsi_host_template driver_template = {
.queuecommand = tw_scsi_queue,
.eh_host_reset_handler = tw_scsi_eh_reset,
.bios_param = tw_scsi_biosparam,
+ .change_queue_depth = tw_change_queue_depth,
.can_queue = TW_Q_LENGTH-2,
.this_id = -1,
.sg_tablesize = TW_MAX_SGL_LENGTH,
@@ -2311,7 +2289,6 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = TW_MAX_CMDS_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = tw_host_attrs,
- .sdev_attrs = tw_dev_attrs,
.emulated = 1
};
@@ -2438,23 +2415,24 @@ static void tw_remove(struct pci_dev *pdev)
scsi_remove_host(tw_dev->host);
- __tw_shutdown(tw_dev);
+ /* Unregister character device */
+ if (twe_major >= 0) {
+ unregister_chrdev(twe_major, "twe");
+ twe_major = -1;
+ }
/* Free up the IRQ */
free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+ /* Shutdown the card */
+ __tw_shutdown(tw_dev);
+
/* Free up the mem region */
pci_release_regions(pdev);
/* Free up device extension resources */
tw_free_device_extension(tw_dev);
- /* Unregister character device */
- if (twe_major >= 0) {
- unregister_chrdev(twe_major, "twe");
- twe_major = -1;
- }
-
scsi_host_put(tw_dev->host);
pci_disable_device(pdev);
tw_device_extension_count--;
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index b2fa60dccfa71..98bad773f2408 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -6,7 +6,7 @@
Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Brad Strand <linux@3ware.com>
- Copyright (C) 1999-2004 3ware Inc.
+ Copyright (C) 1999-2005 3ware Inc.
Kernel compatiblity By: Andre Hedrick <andre@suse.com>
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
@@ -227,6 +227,7 @@ static unsigned char tw_sense_table[][4] =
#define TW_IN_RESET 2
#define TW_IN_CHRDEV_IOCTL 3
#define TW_MAX_SECTORS 256
+#define TW_MAX_IOCTL_SECTORS 512
#define TW_AEN_WAIT_TIME 1000
#define TW_IOCTL_WAIT_TIME (1 * HZ) /* 1 second */
#define TW_ISR_DONT_COMPLETE 2
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index bfc41bea58385..a591fcb8aab13 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -167,7 +167,6 @@ MODULE_LICENSE("GPL");
#include "53c700_d.h"
-STATIC irqreturn_t NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs);
STATIC int NCR_700_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *));
STATIC int NCR_700_abort(struct scsi_cmnd * SCpnt);
STATIC int NCR_700_bus_reset(struct scsi_cmnd * SCpnt);
@@ -297,8 +296,7 @@ NCR_700_get_SXFER(struct scsi_device *SDp)
struct Scsi_Host *
NCR_700_detect(struct scsi_host_template *tpnt,
- struct NCR_700_Host_Parameters *hostdata, struct device *dev,
- unsigned long irq, u8 scsi_id)
+ struct NCR_700_Host_Parameters *hostdata, struct device *dev)
{
dma_addr_t pScript, pSlots;
__u8 *memory;
@@ -394,8 +392,6 @@ NCR_700_detect(struct scsi_host_template *tpnt,
host->unique_id = hostdata->base;
host->base = hostdata->base;
hostdata->eh_complete = NULL;
- host->irq = irq;
- host->this_id = scsi_id;
host->hostdata[0] = (unsigned long)hostdata;
/* kick the chip */
NCR_700_writeb(0xff, host, CTEST9_REG);
@@ -416,28 +412,16 @@ NCR_700_detect(struct scsi_host_template *tpnt,
/* reset the chip */
NCR_700_chip_reset(host);
- if (request_irq(irq, NCR_700_intr, SA_SHIRQ, dev->bus_id, host)) {
- dev_printk(KERN_ERR, dev, "53c700: irq %lu request failed\n ",
- irq);
- goto out_put_host;
- }
-
if (scsi_add_host(host, dev)) {
dev_printk(KERN_ERR, dev, "53c700: scsi_add_host failed\n");
- goto out_release_irq;
+ scsi_host_put(host);
+ return NULL;
}
spi_signalling(host) = hostdata->differential ? SPI_SIGNAL_HVD :
SPI_SIGNAL_SE;
return host;
-
- out_release_irq:
- free_irq(irq, host);
- out_put_host:
- scsi_host_put(host);
-
- return NULL;
}
int
@@ -1489,7 +1473,7 @@ NCR_700_start_command(struct scsi_cmnd *SCp)
return 1;
}
-STATIC irqreturn_t
+irqreturn_t
NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct Scsi_Host *host = (struct Scsi_Host *)dev_id;
@@ -2164,6 +2148,7 @@ STATIC struct device_attribute *NCR_700_dev_attrs[] = {
EXPORT_SYMBOL(NCR_700_detect);
EXPORT_SYMBOL(NCR_700_release);
+EXPORT_SYMBOL(NCR_700_intr);
static struct spi_function_template NCR_700_transport_functions = {
.set_period = NCR_700_set_period,
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index f25c7bce227ec..df4aa30ae0aa1 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -60,9 +60,9 @@ struct NCR_700_Host_Parameters;
/* These are the externally used routines */
struct Scsi_Host *NCR_700_detect(struct scsi_host_template *,
- struct NCR_700_Host_Parameters *, struct device *,
- unsigned long, u8);
+ struct NCR_700_Host_Parameters *, struct device *);
int NCR_700_release(struct Scsi_Host *host);
+irqreturn_t NCR_700_intr(int, void *, struct pt_regs *);
enum NCR_700_Host_State {
diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
index 61e9dc7aec145..507751941f1e6 100644
--- a/drivers/scsi/NCR_D700.c
+++ b/drivers/scsi/NCR_D700.c
@@ -97,6 +97,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mca.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
@@ -168,11 +169,13 @@ static struct scsi_host_template NCR_D700_driver_template = {
struct NCR_D700_private {
struct device *dev;
struct Scsi_Host *hosts[2];
+ char name[30];
+ char pad;
};
static int
-NCR_D700_probe_one(struct NCR_D700_private *p, int siop,
- int irq, int slot, u32 region, int differential)
+NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq,
+ int slot, u32 region, int differential)
{
struct NCR_700_Host_Parameters *hostdata;
struct Scsi_Host *host;
@@ -201,18 +204,18 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop,
NCR_700_set_io_mapped(hostdata);
/* and register the siop */
- host = NCR_700_detect(&NCR_D700_driver_template, hostdata,
- p->dev, irq,
- /* FIXME: read this from SUS */
- id_array[slot * 2 + siop]);
+ host = NCR_700_detect(&NCR_D700_driver_template, hostdata, p->dev);
if (!host) {
ret = -ENOMEM;
goto detect_failed;
}
+ p->hosts[siop] = host;
+ /* FIXME: read this from SUS */
+ host->this_id = id_array[slot * 2 + siop];
+ host->irq = irq;
scsi_scan_host(host);
- p->hosts[siop] = host;
return 0;
detect_failed:
@@ -223,6 +226,20 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop,
return ret;
}
+static int
+NCR_D700_intr(int irq, void *data, struct pt_regs *regs)
+{
+ struct NCR_D700_private *p = (struct NCR_D700_private *)data;
+ int i, found = 0;
+
+ for (i = 0; i < 2; i++)
+ if (p->hosts[i] &&
+ NCR_700_intr(irq, p->hosts[i], regs) == IRQ_HANDLED)
+ found++;
+
+ return found ? IRQ_HANDLED : IRQ_NONE;
+}
+
/* Detect a D700 card. Note, because of the setup --- the chips are
* essentially connectecd to the MCA bus independently, it is easier
* to set them up as two separate host adapters, rather than one
@@ -301,13 +318,19 @@ NCR_D700_probe(struct device *dev)
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;
+ memset(p, '\0', sizeof(*p));
p->dev = dev;
-
+ snprintf(p->name, sizeof(p->name), "D700(%s)", dev->bus_id);
+ if (request_irq(irq, NCR_D700_intr, SA_SHIRQ, p->name, p)) {
+ printk(KERN_ERR "D700: request_irq failed\n");
+ kfree(p);
+ return -EBUSY;
+ }
/* plumb in both 700 chips */
for (i = 0; i < 2; i++) {
int err;
- if ((err = NCR_D700_probe_one(p, i, irq, slot,
+ if ((err = NCR_D700_probe_one(p, i, slot, irq,
offset_addr + (0x80 * i),
differential)) != 0)
printk("D700: SIOP%d: probe failed, error = %d\n",
diff --git a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c
index 6237de419ba9c..9d18ec90510f6 100644
--- a/drivers/scsi/NCR_Q720.c
+++ b/drivers/scsi/NCR_Q720.c
@@ -225,7 +225,7 @@ NCR_Q720_probe(struct device *dev)
/* The first 1k of the memory buffer is a memory map of the registers
*/
- mem_base = (__u32)dma_mark_declared_memory_occupied(dev, base_addr,
+ mem_base = dma_mark_declared_memory_occupied(dev, base_addr,
1024);
if (IS_ERR(mem_base)) {
printk("NCR_Q720 failed to reserve memory mapped region\n");
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index aaf3d1983d64b..f3fc35386060c 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -195,10 +195,12 @@ int aac_get_config_status(struct aac_dev *dev)
= (struct aac_get_config_status_resp *) fib_data(fibptr);
dprintk((KERN_WARNING
"aac_get_config_status: response=%d status=%d action=%d\n",
- reply->response, reply->status, reply->data.action));
- if ((reply->response != ST_OK)
- || (reply->status != CT_OK)
- || (reply->data.action > CFACT_PAUSE)) {
+ le32_to_cpu(reply->response),
+ le32_to_cpu(reply->status),
+ le32_to_cpu(reply->data.action)));
+ if ((le32_to_cpu(reply->response) != ST_OK) ||
+ (le32_to_cpu(reply->status) != CT_OK) ||
+ (le32_to_cpu(reply->data.action) > CFACT_PAUSE)) {
printk(KERN_WARNING "aac_get_config_status: Will not issue the Commit Configuration\n");
status = -EINVAL;
}
@@ -265,7 +267,7 @@ int aac_get_containers(struct aac_dev *dev)
NULL, NULL);
if (status >= 0) {
dresp = (struct aac_get_container_count_resp *)fib_data(fibptr);
- maximum_num_containers = dresp->ContainerSwitchEntries;
+ maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
fib_complete(fibptr);
}
@@ -624,25 +626,28 @@ int aac_get_adapter_info(struct aac_dev* dev)
memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info));
- tmp = dev->adapter_info.kernelrev;
- printk(KERN_INFO"%s%d: kernel %d.%d.%d build %d\n",
+ tmp = le32_to_cpu(dev->adapter_info.kernelrev);
+ printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d]\n",
+ dev->name,
+ dev->id,
+ tmp>>24,
+ (tmp>>16)&0xff,
+ tmp&0xff,
+ le32_to_cpu(dev->adapter_info.kernelbuild));
+ tmp = le32_to_cpu(dev->adapter_info.monitorrev);
+ printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n",
dev->name, dev->id,
- tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
- dev->adapter_info.kernelbuild);
- tmp = dev->adapter_info.monitorrev;
- printk(KERN_INFO"%s%d: monitor %d.%d.%d build %d\n",
+ tmp>>24,(tmp>>16)&0xff,tmp&0xff,
+ le32_to_cpu(dev->adapter_info.monitorbuild));
+ tmp = le32_to_cpu(dev->adapter_info.biosrev);
+ printk(KERN_INFO "%s%d: bios %d.%d-%d[%d]\n",
dev->name, dev->id,
- tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
- dev->adapter_info.monitorbuild);
- tmp = dev->adapter_info.biosrev;
- printk(KERN_INFO"%s%d: bios %d.%d.%d build %d\n",
+ tmp>>24,(tmp>>16)&0xff,tmp&0xff,
+ le32_to_cpu(dev->adapter_info.biosbuild));
+ if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
+ printk(KERN_INFO "%s%d: serial %x\n",
dev->name, dev->id,
- tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
- dev->adapter_info.biosbuild);
- printk(KERN_INFO"%s%d: serial %x%x\n",
- dev->name, dev->id,
- dev->adapter_info.serial[0],
- dev->adapter_info.serial[1]);
+ le32_to_cpu(dev->adapter_info.serial[0]));
dev->nondasd_support = 0;
dev->raid_scsi_mode = 0;
@@ -742,7 +747,8 @@ static void read_callback(void *context, struct fib * fibptr)
if (le32_to_cpu(readreply->status) == ST_OK)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
else {
- printk(KERN_WARNING "read_callback: read failed, status = %d\n", readreply->status);
+ printk(KERN_WARNING "read_callback: read failed, status = %d\n",
+ le32_to_cpu(readreply->status));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR,
@@ -853,13 +859,15 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
readcmd->cid = cpu_to_le16(cid);
readcmd->sector_count = cpu_to_le16(count);
readcmd->block = cpu_to_le32(lba);
- readcmd->pad = cpu_to_le16(0);
- readcmd->flags = cpu_to_le16(0);
+ readcmd->pad = 0;
+ readcmd->flags = 0;
aac_build_sg64(scsicmd, &readcmd->sg);
- if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
- BUG();
- fibsize = sizeof(struct aac_read64) + ((readcmd->sg.count - 1) * sizeof (struct sgentry64));
+ fibsize = sizeof(struct aac_read64) +
+ ((le32_to_cpu(readcmd->sg.count) - 1) *
+ sizeof (struct sgentry64));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
*/
@@ -882,9 +890,11 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
BUG();
aac_build_sg(scsicmd, &readcmd->sg);
- if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
- BUG();
- fibsize = sizeof(struct aac_read) + ((readcmd->sg.count - 1) * sizeof (struct sgentry));
+ fibsize = sizeof(struct aac_read) +
+ ((le32_to_cpu(readcmd->sg.count) - 1) *
+ sizeof (struct sgentry));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
*/
@@ -903,10 +913,7 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS)
- {
- dprintk("read queued.\n");
return 0;
- }
printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status);
/*
@@ -943,7 +950,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
}
- dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
+ dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n",
+ smp_processor_id(), (unsigned long long)lba, jiffies));
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
@@ -961,13 +969,15 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
writecmd->cid = cpu_to_le16(cid);
writecmd->sector_count = cpu_to_le16(count);
writecmd->block = cpu_to_le32(lba);
- writecmd->pad = cpu_to_le16(0);
- writecmd->flags = cpu_to_le16(0);
+ writecmd->pad = 0;
+ writecmd->flags = 0;
aac_build_sg64(scsicmd, &writecmd->sg);
- if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
- BUG();
- fibsize = sizeof(struct aac_write64) + ((writecmd->sg.count - 1) * sizeof (struct sgentry64));
+ fibsize = sizeof(struct aac_write64) +
+ ((le32_to_cpu(writecmd->sg.count) - 1) *
+ sizeof (struct sgentry64));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
*/
@@ -993,9 +1003,11 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
}
aac_build_sg(scsicmd, &writecmd->sg);
- if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
- BUG();
- fibsize = sizeof(struct aac_write) + ((writecmd->sg.count - 1) * sizeof (struct sgentry));
+ fibsize = sizeof(struct aac_write) +
+ ((le32_to_cpu(writecmd->sg.count) - 1) *
+ sizeof (struct sgentry));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
*/
@@ -1051,7 +1063,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
u32 cid = ID_LUN_TO_CONTAINER(sdev->id, sdev->lun);
printk(KERN_WARNING
"synchronize_callback: synchronize failed, status = %d\n",
- synchronizereply->status);
+ le32_to_cpu(synchronizereply->status));
cmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *)&dev->fsa_dev[cid].sense_data,
@@ -1538,7 +1550,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
* Calculate resid for sg
*/
- scsicmd->resid = scsicmd->request_bufflen - srbreply->data_xfer_length;
+ scsicmd->resid = scsicmd->request_bufflen -
+ le32_to_cpu(srbreply->data_xfer_length);
if(scsicmd->use_sg)
pci_unmap_sg(dev->pdev,
@@ -1556,8 +1569,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
if (le32_to_cpu(srbreply->status) != ST_OK){
int len;
printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status));
- len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?
- sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;
+ len = (le32_to_cpu(srbreply->sense_data_size) >
+ sizeof(scsicmd->sense_buffer)) ?
+ sizeof(scsicmd->sense_buffer) :
+ le32_to_cpu(srbreply->sense_data_size);
scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
}
@@ -1693,7 +1708,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
default:
#ifdef AAC_DETAILED_STATUS_INFO
printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",
- le32_to_cpu(srbreply->srb_status & 0x3F),
+ le32_to_cpu(srbreply->srb_status) & 0x3F,
aac_get_status_string(
le32_to_cpu(srbreply->srb_status) & 0x3F),
scsicmd->cmnd[0],
@@ -1705,8 +1720,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){ // Check Condition
int len;
scsicmd->result |= SAM_STAT_CHECK_CONDITION;
- len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?
- sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;
+ len = (le32_to_cpu(srbreply->sense_data_size) >
+ sizeof(scsicmd->sense_buffer)) ?
+ sizeof(scsicmd->sense_buffer) :
+ le32_to_cpu(srbreply->sense_data_size);
#ifdef AAC_DETAILED_STATUS_INFO
dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
le32_to_cpu(srbreply->status), len));
@@ -1786,7 +1803,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
timeout = 1;
}
srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds
- srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
+ srbcmd->retry_limit = 0; /* Obsolete parameter */
srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len);
if( dev->dac_support == 1 ) {
@@ -1798,13 +1815,19 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Build Scatter/Gather list
*/
- fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64));
+ fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
+ ((le32_to_cpu(srbcmd->sg.count) & 0xff) *
+ sizeof (struct sgentry64));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ScsiPortCommand64, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
- (fib_callback) aac_srb_callback, (void *) scsicmd);
+ status = fib_send(ScsiPortCommand64, cmd_fibcontext,
+ fibsize, FsaNormal, 0, 1,
+ (fib_callback) aac_srb_callback,
+ (void *) scsicmd);
} else {
aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg);
srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
@@ -1814,7 +1837,11 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Build Scatter/Gather list
*/
- fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
+ fibsize = sizeof (struct aac_srb) +
+ (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
+ sizeof (struct sgentry));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
@@ -1843,9 +1870,9 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
// Get rid of old data
- psg->count = cpu_to_le32(0);
- psg->sg[0].addr = cpu_to_le32(0);
- psg->sg[0].count = cpu_to_le32(0);
+ psg->count = 0;
+ psg->sg[0].addr = 0;
+ psg->sg[0].count = 0;
if (scsicmd->use_sg) {
struct scatterlist *sg;
int i;
@@ -1899,10 +1926,10 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
// Get rid of old data
- psg->count = cpu_to_le32(0);
- psg->sg[0].addr[0] = cpu_to_le32(0);
- psg->sg[0].addr[1] = cpu_to_le32(0);
- psg->sg[0].count = cpu_to_le32(0);
+ psg->count = 0;
+ psg->sg[0].addr[0] = 0;
+ psg->sg[0].addr[1] = 0;
+ psg->sg[0].count = 0;
if (scsicmd->use_sg) {
struct scatterlist *sg;
int i;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 7309129568b68..700d90331c1cd 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -507,40 +507,32 @@ struct aac_queue_block
*/
struct sa_drawbridge_CSR {
- // Offset | Name
- u32 reserved[10]; // 00h-27h | Reserved
- u8 LUT_Offset; // 28h | Looup Table Offset
- u8 reserved1[3]; // 29h-2bh | Reserved
- u32 LUT_Data; // 2ch | Looup Table Data
- u32 reserved2[26]; // 30h-97h | Reserved
- u16 PRICLEARIRQ; // 98h | Primary Clear Irq
- u16 SECCLEARIRQ; // 9ah | Secondary Clear Irq
- u16 PRISETIRQ; // 9ch | Primary Set Irq
- u16 SECSETIRQ; // 9eh | Secondary Set Irq
- u16 PRICLEARIRQMASK; // a0h | Primary Clear Irq Mask
- u16 SECCLEARIRQMASK; // a2h | Secondary Clear Irq Mask
- u16 PRISETIRQMASK; // a4h | Primary Set Irq Mask
- u16 SECSETIRQMASK; // a6h | Secondary Set Irq Mask
- u32 MAILBOX0; // a8h | Scratchpad 0
- u32 MAILBOX1; // ach | Scratchpad 1
- u32 MAILBOX2; // b0h | Scratchpad 2
- u32 MAILBOX3; // b4h | Scratchpad 3
- u32 MAILBOX4; // b8h | Scratchpad 4
- u32 MAILBOX5; // bch | Scratchpad 5
- u32 MAILBOX6; // c0h | Scratchpad 6
- u32 MAILBOX7; // c4h | Scratchpad 7
-
- u32 ROM_Setup_Data; // c8h | Rom Setup and Data
- u32 ROM_Control_Addr; // cch | Rom Control and Address
-
- u32 reserved3[12]; // d0h-ffh | reserved
- u32 LUT[64]; // 100h-1ffh| Lookup Table Entries
-
- //
- // TO DO
- // need to add DMA, I2O, UART, etc registers form 80h to 364h
- //
-
+ /* Offset | Name */
+ __le32 reserved[10]; /* 00h-27h | Reserved */
+ u8 LUT_Offset; /* 28h | Lookup Table Offset */
+ u8 reserved1[3]; /* 29h-2bh | Reserved */
+ __le32 LUT_Data; /* 2ch | Looup Table Data */
+ __le32 reserved2[26]; /* 30h-97h | Reserved */
+ __le16 PRICLEARIRQ; /* 98h | Primary Clear Irq */
+ __le16 SECCLEARIRQ; /* 9ah | Secondary Clear Irq */
+ __le16 PRISETIRQ; /* 9ch | Primary Set Irq */
+ __le16 SECSETIRQ; /* 9eh | Secondary Set Irq */
+ __le16 PRICLEARIRQMASK;/* a0h | Primary Clear Irq Mask */
+ __le16 SECCLEARIRQMASK;/* a2h | Secondary Clear Irq Mask */
+ __le16 PRISETIRQMASK; /* a4h | Primary Set Irq Mask */
+ __le16 SECSETIRQMASK; /* a6h | Secondary Set Irq Mask */
+ __le32 MAILBOX0; /* a8h | Scratchpad 0 */
+ __le32 MAILBOX1; /* ach | Scratchpad 1 */
+ __le32 MAILBOX2; /* b0h | Scratchpad 2 */
+ __le32 MAILBOX3; /* b4h | Scratchpad 3 */
+ __le32 MAILBOX4; /* b8h | Scratchpad 4 */
+ __le32 MAILBOX5; /* bch | Scratchpad 5 */
+ __le32 MAILBOX6; /* c0h | Scratchpad 6 */
+ __le32 MAILBOX7; /* c4h | Scratchpad 7 */
+ __le32 ROM_Setup_Data; /* c8h | Rom Setup and Data */
+ __le32 ROM_Control_Addr;/* cch | Rom Control and Address */
+ __le32 reserved3[12]; /* d0h-ffh | reserved */
+ __le32 LUT[64]; /* 100h-1ffh | Lookup Table Entries */
};
#define Mailbox0 SaDbCSR.MAILBOX0
@@ -556,13 +548,13 @@ struct sa_drawbridge_CSR {
#define DoorbellClrReg_p SaDbCSR.PRICLEARIRQ
-#define DOORBELL_0 cpu_to_le16(0x0001)
-#define DOORBELL_1 cpu_to_le16(0x0002)
-#define DOORBELL_2 cpu_to_le16(0x0004)
-#define DOORBELL_3 cpu_to_le16(0x0008)
-#define DOORBELL_4 cpu_to_le16(0x0010)
-#define DOORBELL_5 cpu_to_le16(0x0020)
-#define DOORBELL_6 cpu_to_le16(0x0040)
+#define DOORBELL_0 0x0001
+#define DOORBELL_1 0x0002
+#define DOORBELL_2 0x0004
+#define DOORBELL_3 0x0008
+#define DOORBELL_4 0x0010
+#define DOORBELL_5 0x0020
+#define DOORBELL_6 0x0040
#define PrintfReady DOORBELL_5
@@ -585,25 +577,29 @@ struct sa_registers {
*/
struct rx_mu_registers {
- // Local | PCI* | Name
- // | |
- u32 ARSR; // 1300h | 00h | APIC Register Select Register
- u32 reserved0; // 1304h | 04h | Reserved
- u32 AWR; // 1308h | 08h | APIC Window Register
- u32 reserved1; // 130Ch | 0Ch | Reserved
- u32 IMRx[2]; // 1310h | 10h | Inbound Message Registers
- u32 OMRx[2]; // 1318h | 18h | Outbound Message Registers
- u32 IDR; // 1320h | 20h | Inbound Doorbell Register
- u32 IISR; // 1324h | 24h | Inbound Interrupt Status Register
- u32 IIMR; // 1328h | 28h | Inbound Interrupt Mask Register
- u32 ODR; // 132Ch | 2Ch | Outbound Doorbell Register
- u32 OISR; // 1330h | 30h | Outbound Interrupt Status Register
- u32 OIMR; // 1334h | 34h | Outbound Interrupt Mask Register
- // * Must access through ATU Inbound Translation Window
+ /* Local | PCI*| Name */
+ __le32 ARSR; /* 1300h | 00h | APIC Register Select Register */
+ __le32 reserved0; /* 1304h | 04h | Reserved */
+ __le32 AWR; /* 1308h | 08h | APIC Window Register */
+ __le32 reserved1; /* 130Ch | 0Ch | Reserved */
+ __le32 IMRx[2]; /* 1310h | 10h | Inbound Message Registers */
+ __le32 OMRx[2]; /* 1318h | 18h | Outbound Message Registers */
+ __le32 IDR; /* 1320h | 20h | Inbound Doorbell Register */
+ __le32 IISR; /* 1324h | 24h | Inbound Interrupt
+ Status Register */
+ __le32 IIMR; /* 1328h | 28h | Inbound Interrupt
+ Mask Register */
+ __le32 ODR; /* 132Ch | 2Ch | Outbound Doorbell Register */
+ __le32 OISR; /* 1330h | 30h | Outbound Interrupt
+ Status Register */
+ __le32 OIMR; /* 1334h | 34h | Outbound Interrupt
+ Mask Register */
+ /* * Must access through ATU Inbound
+ Translation Window */
};
struct rx_inbound {
- u32 Mailbox[8];
+ __le32 Mailbox[8];
};
#define InboundMailbox0 IndexRegs.Mailbox[0]
@@ -613,28 +609,27 @@ struct rx_inbound {
#define InboundMailbox4 IndexRegs.Mailbox[4]
#define InboundMailbox5 IndexRegs.Mailbox[5]
#define InboundMailbox6 IndexRegs.Mailbox[6]
-#define InboundMailbox7 IndexRegs.Mailbox[7]
-
-#define INBOUNDDOORBELL_0 cpu_to_le32(0x00000001)
-#define INBOUNDDOORBELL_1 cpu_to_le32(0x00000002)
-#define INBOUNDDOORBELL_2 cpu_to_le32(0x00000004)
-#define INBOUNDDOORBELL_3 cpu_to_le32(0x00000008)
-#define INBOUNDDOORBELL_4 cpu_to_le32(0x00000010)
-#define INBOUNDDOORBELL_5 cpu_to_le32(0x00000020)
-#define INBOUNDDOORBELL_6 cpu_to_le32(0x00000040)
-
-#define OUTBOUNDDOORBELL_0 cpu_to_le32(0x00000001)
-#define OUTBOUNDDOORBELL_1 cpu_to_le32(0x00000002)
-#define OUTBOUNDDOORBELL_2 cpu_to_le32(0x00000004)
-#define OUTBOUNDDOORBELL_3 cpu_to_le32(0x00000008)
-#define OUTBOUNDDOORBELL_4 cpu_to_le32(0x00000010)
+
+#define INBOUNDDOORBELL_0 0x00000001
+#define INBOUNDDOORBELL_1 0x00000002
+#define INBOUNDDOORBELL_2 0x00000004
+#define INBOUNDDOORBELL_3 0x00000008
+#define INBOUNDDOORBELL_4 0x00000010
+#define INBOUNDDOORBELL_5 0x00000020
+#define INBOUNDDOORBELL_6 0x00000040
+
+#define OUTBOUNDDOORBELL_0 0x00000001
+#define OUTBOUNDDOORBELL_1 0x00000002
+#define OUTBOUNDDOORBELL_2 0x00000004
+#define OUTBOUNDDOORBELL_3 0x00000008
+#define OUTBOUNDDOORBELL_4 0x00000010
#define InboundDoorbellReg MUnit.IDR
#define OutboundDoorbellReg MUnit.ODR
struct rx_registers {
- struct rx_mu_registers MUnit; // 1300h - 1334h
- u32 reserved1[6]; // 1338h - 134ch
+ struct rx_mu_registers MUnit; /* 1300h - 1334h */
+ __le32 reserved1[6]; /* 1338h - 134ch */
struct rx_inbound IndexRegs;
};
@@ -652,7 +647,7 @@ struct rx_registers {
struct rkt_registers {
struct rkt_mu_registers MUnit; /* 1300h - 1334h */
- u32 reserved1[1010]; /* 1338h - 22fch */
+ __le32 reserved1[1010]; /* 1338h - 22fch */
struct rkt_inbound IndexRegs; /* 2300h - */
};
@@ -824,6 +819,9 @@ struct aac_adapter_info
#define AAC_OPT_NONDASD cpu_to_le32(1<<12)
#define AAC_OPT_SCSI_MANAGED cpu_to_le32(1<<13)
#define AAC_OPT_RAID_SCSI_MODE cpu_to_le32(1<<14)
+#define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<16)
+#define AAC_OPT_NEW_COMM cpu_to_le32(1<<17)
+#define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18)
struct aac_dev
{
@@ -1482,15 +1480,19 @@ extern struct aac_common aac_config;
* Monitor/Kernel API
*/
-#define BREAKPOINT_REQUEST cpu_to_le32(0x00000004)
-#define INIT_STRUCT_BASE_ADDRESS cpu_to_le32(0x00000005)
-#define READ_PERMANENT_PARAMETERS cpu_to_le32(0x0000000a)
-#define WRITE_PERMANENT_PARAMETERS cpu_to_le32(0x0000000b)
-#define HOST_CRASHING cpu_to_le32(0x0000000d)
-#define SEND_SYNCHRONOUS_FIB cpu_to_le32(0x0000000c)
-#define COMMAND_POST_RESULTS cpu_to_le32(0x00000014)
-#define GET_ADAPTER_PROPERTIES cpu_to_le32(0x00000019)
-#define RE_INIT_ADAPTER cpu_to_le32(0x000000ee)
+#define BREAKPOINT_REQUEST 0x00000004
+#define INIT_STRUCT_BASE_ADDRESS 0x00000005
+#define READ_PERMANENT_PARAMETERS 0x0000000a
+#define WRITE_PERMANENT_PARAMETERS 0x0000000b
+#define HOST_CRASHING 0x0000000d
+#define SEND_SYNCHRONOUS_FIB 0x0000000c
+#define COMMAND_POST_RESULTS 0x00000014
+#define GET_ADAPTER_PROPERTIES 0x00000019
+#define GET_DRIVER_BUFFER_PROPERTIES 0x00000023
+#define RCV_TEMP_READINGS 0x00000025
+#define GET_COMM_PREFERRED_SETTINGS 0x00000026
+#define IOP_RESET 0x00001000
+#define RE_INIT_ADAPTER 0x000000ee
/*
* Adapter Status Register
@@ -1513,22 +1515,22 @@ extern struct aac_common aac_config;
* Phases are bit oriented. It is NOT valid to have multiple bits set
*/
-#define SELF_TEST_FAILED (cpu_to_le32(0x00000004))
-#define MONITOR_PANIC (cpu_to_le32(0x00000020))
-#define KERNEL_UP_AND_RUNNING (cpu_to_le32(0x00000080))
-#define KERNEL_PANIC (cpu_to_le32(0x00000100))
+#define SELF_TEST_FAILED 0x00000004
+#define MONITOR_PANIC 0x00000020
+#define KERNEL_UP_AND_RUNNING 0x00000080
+#define KERNEL_PANIC 0x00000100
/*
* Doorbell bit defines
*/
-#define DoorBellSyncCmdAvailable cpu_to_le32(1<<0) // Host -> Adapter
-#define DoorBellPrintfDone cpu_to_le32(1<<5) // Host -> Adapter
-#define DoorBellAdapterNormCmdReady cpu_to_le32(1<<1) // Adapter -> Host
-#define DoorBellAdapterNormRespReady cpu_to_le32(1<<2) // Adapter -> Host
-#define DoorBellAdapterNormCmdNotFull cpu_to_le32(1<<3) // Adapter -> Host
-#define DoorBellAdapterNormRespNotFull cpu_to_le32(1<<4) // Adapter -> Host
-#define DoorBellPrintfReady cpu_to_le32(1<<5) // Adapter -> Host
+#define DoorBellSyncCmdAvailable (1<<0) /* Host -> Adapter */
+#define DoorBellPrintfDone (1<<5) /* Host -> Adapter */
+#define DoorBellAdapterNormCmdReady (1<<1) /* Adapter -> Host */
+#define DoorBellAdapterNormRespReady (1<<2) /* Adapter -> Host */
+#define DoorBellAdapterNormCmdNotFull (1<<3) /* Adapter -> Host */
+#define DoorBellAdapterNormRespNotFull (1<<4) /* Adapter -> Host */
+#define DoorBellPrintfReady (1<<5) /* Adapter -> Host */
/*
* For FIB communication, we need all of the following things
@@ -1599,7 +1601,6 @@ void fib_dealloc(struct fib * context);
void aac_printf(struct aac_dev *dev, u32 val);
int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
-int aac_consumer_avail(struct aac_dev * dev, struct aac_queue * q);
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
int fib_complete(struct fib * context);
#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data)
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 7f3a22200af4d..30dd1f7120f4b 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -74,12 +74,14 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* will not overrun the buffer when we copy the memory. Return
* an error if we would.
*/
- if(le32_to_cpu(kfib->header.Size) > sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) {
+ if (le16_to_cpu(kfib->header.Size) >
+ sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) {
fib_free(fibptr);
return -EINVAL;
}
- if (copy_from_user((void *) kfib, arg, le32_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr))) {
+ if (copy_from_user(kfib, arg, le16_to_cpu(kfib->header.Size) +
+ sizeof(struct aac_fibhdr))) {
fib_free(fibptr);
return -EFAULT;
}
@@ -93,7 +95,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
kfib->header.XferState = 0;
} else {
int retval = fib_send(kfib->header.Command, fibptr,
- le32_to_cpu(kfib->header.Size) , FsaNormal,
+ le16_to_cpu(kfib->header.Size) , FsaNormal,
1, 1, NULL, NULL);
if (retval) {
fib_free(fibptr);
@@ -538,7 +540,9 @@ int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
struct sgmap* psg = &srbcmd->sg;
byte_count = 0;
- actual_fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
+ actual_fibsize = sizeof (struct aac_srb) +
+ (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
+ sizeof (struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue
printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
rcode = -EINVAL;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index d3ca7a37e489d..6832a55ca907b 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -83,7 +83,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
*/
dev->aif_base_va = (struct hw_fib *)base;
- init->AdapterFibsVirtualAddress = cpu_to_le32(0);
+ init->AdapterFibsVirtualAddress = 0;
init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys);
init->AdapterFibsSize = cpu_to_le32(fibsize);
init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib));
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index a379bc9a1276b..3f36dbaa2bb32 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -102,7 +102,7 @@ int fib_setup(struct aac_dev * dev)
fibptr->next = fibptr+1; /* Forward chain the fibs */
init_MUTEX_LOCKED(&fibptr->event_wait);
spin_lock_init(&fibptr->event_lock);
- hw_fib_va->header.XferState = cpu_to_le32(0xffffffff);
+ hw_fib_va->header.XferState = 0xffffffff;
hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
fibptr->hw_fib_pa = hw_fib_pa;
hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + sizeof(struct hw_fib));
@@ -148,7 +148,7 @@ struct fib * fib_alloc(struct aac_dev *dev)
* Null out fields that depend on being zero at the start of
* each I/O
*/
- fibptr->hw_fib->header.XferState = cpu_to_le32(0);
+ fibptr->hw_fib->header.XferState = 0;
fibptr->callback = NULL;
fibptr->callback_data = NULL;
@@ -175,7 +175,8 @@ void fib_free(struct fib * fibptr)
} else {
if (fibptr->hw_fib->header.XferState != 0) {
printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
- (void*)fibptr, fibptr->hw_fib->header.XferState);
+ (void*)fibptr,
+ le32_to_cpu(fibptr->hw_fib->header.XferState));
}
fibptr->next = fibptr->dev->free_fib;
fibptr->dev->free_fib = fibptr;
@@ -215,7 +216,7 @@ void fib_dealloc(struct fib * fibptr)
struct hw_fib *hw_fib = fibptr->hw_fib;
if(hw_fib->header.StructType != FIB_MAGIC)
BUG();
- hw_fib->header.XferState = cpu_to_le32(0);
+ hw_fib->header.XferState = 0;
}
/*
@@ -344,7 +345,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
* in the queue entry.
*/
if (map)
- entry->addr = fibptr->hw_fib_pa;
+ entry->addr = cpu_to_le32(fibptr->hw_fib_pa);
return 0;
}
@@ -418,13 +419,13 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_queue * q;
unsigned long flags = 0;
- if (!(le32_to_cpu(hw_fib->header.XferState) & HostOwned))
+ if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned)))
return -EBUSY;
/*
* There are 5 cases with the wait and reponse requested flags.
* The only invalid cases are if the caller requests to wait and
* does not request a response and if the caller does not want a
- * response and the Fibis not allocated from pool. If a response
+ * response and the Fib is not allocated from pool. If a response
* is not requesed the Fib will just be deallocaed by the DPC
* routine when the response comes back from the adapter. No
* further processing will be done besides deleting the Fib. We
@@ -566,12 +567,6 @@ int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entr
return(status);
}
-int aac_consumer_avail(struct aac_dev *dev, struct aac_queue * q)
-{
- return (le32_to_cpu(*q->headers.producer) != le32_to_cpu(*q->headers.consumer));
-}
-
-
/**
* aac_consumer_free - free consumer entry
* @dev: Adapter
@@ -632,7 +627,7 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_dev * dev = fibptr->dev;
unsigned long nointr = 0;
- if (le32_to_cpu(hw_fib->header.XferState) == 0)
+ if (hw_fib->header.XferState == 0)
return 0;
/*
* If we plan to do anything check the structure type first.
@@ -704,7 +699,7 @@ int fib_complete(struct fib * fibptr)
* Check for a fib which has already been completed
*/
- if (hw_fib->header.XferState == cpu_to_le32(0))
+ if (hw_fib->header.XferState == 0)
return 0;
/*
* If we plan to do anything check the structure type first.
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index df8ccb93fd4e9..1b8ed47cfe30b 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -63,7 +63,7 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
{
bellbits = rkt_readl(dev, OutboundDoorbellReg);
if (bellbits & DoorBellPrintfReady) {
- aac_printf(dev, le32_to_cpu(rkt_readl (dev, IndexRegs.Mailbox[5])));
+ aac_printf(dev, rkt_readl(dev, IndexRegs.Mailbox[5]));
rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady);
rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
}
@@ -94,7 +94,7 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
* @p1: first parameter
* @ret: adapter status
*
- * This routine will send a synchronous comamnd to the adapter and wait
+ * This routine will send a synchronous command to the adapter and wait
* for its completion.
*/
@@ -105,11 +105,11 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
/*
* Write the command into Mailbox 0
*/
- rkt_writel(dev, InboundMailbox0, cpu_to_le32(command));
+ rkt_writel(dev, InboundMailbox0, command);
/*
* Write the parameters into Mailboxes 1 - 4
*/
- rkt_writel(dev, InboundMailbox1, cpu_to_le32(p1));
+ rkt_writel(dev, InboundMailbox1, p1);
rkt_writel(dev, InboundMailbox2, 0);
rkt_writel(dev, InboundMailbox3, 0);
rkt_writel(dev, InboundMailbox4, 0);
@@ -168,7 +168,7 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
* Pull the synch status from Mailbox 0.
*/
if (status)
- *status = le32_to_cpu(rkt_readl(dev, IndexRegs.Mailbox[0]));
+ *status = rkt_readl(dev, IndexRegs.Mailbox[0]);
/*
* Clear the synch command doorbell.
*/
@@ -275,7 +275,7 @@ static void aac_rkt_start_adapter(struct aac_dev *dev)
*/
static int aac_rkt_check_health(struct aac_dev *dev)
{
- u32 status = le32_to_cpu(rkt_readl(dev, MUnit.OMRx[0]));
+ u32 status = rkt_readl(dev, MUnit.OMRx[0]);
/*
* Check to see if the board failed any self tests.
@@ -307,9 +307,9 @@ static int aac_rkt_check_health(struct aac_dev *dev)
return ret;
}
memset(buffer, 0, 512);
- post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
+ post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
post->Post_Address = cpu_to_le32(baddr);
- rkt_writel(dev, MUnit.IMRx[0], cpu_to_le32(paddr));
+ rkt_writel(dev, MUnit.IMRx[0], paddr);
rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
@@ -388,8 +388,9 @@ int aac_rkt_init(struct aac_dev *dev)
{
if(time_after(jiffies, start+180*HZ))
{
- status = rkt_readl(dev, IndexRegs.Mailbox[7]) >> 16;
- printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n", dev->name, instance, status);
+ status = rkt_readl(dev, MUnit.OMRx[0]);
+ printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
+ dev->name, instance, status);
goto error_iounmap;
}
set_current_state(TASK_UNINTERRUPTIBLE);
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index df12f5301b6a1..630b99e1fe83c 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -94,7 +94,7 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
* @p1: first parameter
* @ret: adapter status
*
- * This routine will send a synchronous comamnd to the adapter and wait
+ * This routine will send a synchronous command to the adapter and wait
* for its completion.
*/
@@ -105,11 +105,11 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
/*
* Write the command into Mailbox 0
*/
- rx_writel(dev, InboundMailbox0, cpu_to_le32(command));
+ rx_writel(dev, InboundMailbox0, command);
/*
* Write the parameters into Mailboxes 1 - 4
*/
- rx_writel(dev, InboundMailbox1, cpu_to_le32(p1));
+ rx_writel(dev, InboundMailbox1, p1);
rx_writel(dev, InboundMailbox2, 0);
rx_writel(dev, InboundMailbox3, 0);
rx_writel(dev, InboundMailbox4, 0);
@@ -167,7 +167,8 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
/*
* Pull the synch status from Mailbox 0.
*/
- *status = le32_to_cpu(rx_readl(dev, IndexRegs.Mailbox[0]));
+ if (status)
+ *status = rx_readl(dev, IndexRegs.Mailbox[0]);
/*
* Clear the synch command doorbell.
*/
@@ -274,7 +275,7 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
*/
static int aac_rx_check_health(struct aac_dev *dev)
{
- u32 status = le32_to_cpu(rx_readl(dev, MUnit.OMRx[0]));
+ u32 status = rx_readl(dev, MUnit.OMRx[0]);
/*
* Check to see if the board failed any self tests.
@@ -308,7 +309,7 @@ static int aac_rx_check_health(struct aac_dev *dev)
memset(buffer, 0, 512);
post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
post->Post_Address = cpu_to_le32(baddr);
- rx_writel(dev, MUnit.IMRx[0], cpu_to_le32(paddr));
+ rx_writel(dev, MUnit.IMRx[0], paddr);
rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
@@ -388,8 +389,9 @@ int aac_rx_init(struct aac_dev *dev)
{
if(time_after(jiffies, start+180*HZ))
{
- status = rx_readl(dev, IndexRegs.Mailbox[7]) >> 16;
- printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n", dev->name, instance, status);
+ status = rx_readl(dev, IndexRegs.Mailbox[7]);
+ printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
+ dev->name, instance, status);
goto error_iounmap;
}
set_current_state(TASK_UNINTERRUPTIBLE);
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 13e88188485a3..bd6c30723fbaa 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -62,7 +62,7 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
if (intstat & mask) {
if (intstat & PrintfReady) {
- aac_printf(dev, le32_to_cpu(sa_readl(dev, Mailbox5)));
+ aac_printf(dev, sa_readl(dev, Mailbox5));
sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */
sa_writew(dev, DoorbellReg_s, PrintfDone);
} else if (intstat & DOORBELL_1) { // dev -> Host Normal Command Ready
@@ -128,7 +128,7 @@ void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
* @p1: first parameter
* @ret: adapter status
*
- * This routine will send a synchronous comamnd to the adapter and wait
+ * This routine will send a synchronous command to the adapter and wait
* for its completion.
*/
@@ -139,11 +139,11 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
/*
* Write the Command into Mailbox 0
*/
- sa_writel(dev, Mailbox0, cpu_to_le32(command));
+ sa_writel(dev, Mailbox0, command);
/*
* Write the parameters into Mailboxes 1 - 4
*/
- sa_writel(dev, Mailbox1, cpu_to_le32(p1));
+ sa_writel(dev, Mailbox1, p1);
sa_writel(dev, Mailbox2, 0);
sa_writel(dev, Mailbox3, 0);
sa_writel(dev, Mailbox4, 0);
@@ -186,7 +186,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
/*
* Pull the synch status from Mailbox 0.
*/
- *ret = le32_to_cpu(sa_readl(dev, Mailbox0));
+ if (ret)
+ *ret = sa_readl(dev, Mailbox0);
return 0;
}
@@ -218,9 +219,8 @@ static void aac_sa_start_adapter(struct aac_dev *dev)
* Fill in the remaining pieces of the init.
*/
init = dev->init;
- init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ);
+ init->HostElapsedSeconds = cpu_to_le32(get_seconds());
- dprintk(("INIT\n"));
/*
* Tell the adapter we are back and up and running so it will scan its command
* queues and enable our interrupts
@@ -230,10 +230,8 @@ static void aac_sa_start_adapter(struct aac_dev *dev)
* First clear out all interrupts. Then enable the one's that
* we can handle.
*/
- dprintk(("MASK\n"));
sa_writew(dev, SaDbCSR.PRISETIRQMASK, cpu_to_le16(0xffff));
sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
- dprintk(("SYNCCMD\n"));
/* We can only use a 32 bit address here */
sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &ret);
}
@@ -286,14 +284,12 @@ int aac_sa_init(struct aac_dev *dev)
int instance;
const char *name;
- dprintk(("PREINST\n"));
instance = dev->id;
name = dev->name;
/*
* Map in the registers from the adapter.
*/
- dprintk(("PREMAP\n"));
if((dev->regs.sa = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
{
@@ -320,15 +316,15 @@ int aac_sa_init(struct aac_dev *dev)
*/
while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
if (time_after(jiffies, start+180*HZ)) {
- status = sa_readl(dev, Mailbox7) >> 16;
- printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status));
+ status = sa_readl(dev, Mailbox7);
+ printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %lx.\n",
+ name, instance, status);
goto error_iounmap;
}
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
- dprintk(("ATIRQ\n"));
if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) {
printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance);
goto error_iounmap;
@@ -343,12 +339,10 @@ int aac_sa_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
dev->a_ops.adapter_check_health = aac_sa_check_health;
- dprintk(("FUNCDONE\n"));
if(aac_init_adapter(dev) == NULL)
goto error_irq;
- dprintk(("NEWADAPTDONE\n"));
/*
* Start any kernel threads needed
*/
@@ -362,9 +356,7 @@ int aac_sa_init(struct aac_dev *dev)
* Tell the adapter that all is configure, and it can start
* accepting requests
*/
- dprintk(("STARTING\n"));
aac_sa_start_adapter(dev);
- dprintk(("STARTED\n"));
return 0;
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 99079147b3ff1..45b75ddacaaba 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -39,9 +39,9 @@
#include "atp870u.h"
static struct scsi_host_template atp870u_template;
-void send_s870(struct atp_unit *dev,unsigned char c);
-void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
-void tscam_885(void);
+static void send_s870(struct atp_unit *dev,unsigned char c);
+static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
+static void tscam_885(void);
static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -364,7 +364,7 @@ stop_dma:
}
outb(j, tmport);
while ((inb(tmport) & 0x01) != j) {
- outb(j,tmport);
+ outb(j,tmport);
}
if (dev->id[c][target_id].last_len == 0) {
tmport = workport + 0x18;
@@ -491,7 +491,7 @@ go_42:
/*
* Clear it off the queue
*/
- dev->id[c][target_id].curr_req = 0;
+ dev->id[c][target_id].curr_req = NULL;
dev->working[c]--;
spin_unlock_irqrestore(dev->host->host_lock, flags);
/*
@@ -614,7 +614,8 @@ handled:
*
* Queue a command to the ATP queue. Called with the host lock held.
*/
-int atp870u_queuecommand(struct scsi_cmnd * req_p, void (*done) (struct scsi_cmnd *))
+static int atp870u_queuecommand(struct scsi_cmnd * req_p,
+ void (*done) (struct scsi_cmnd *))
{
unsigned char c;
unsigned int tmport,m;
@@ -711,7 +712,7 @@ int atp870u_queuecommand(struct scsi_cmnd * req_p, void (*done) (struct scsi_cmn
*
* Caller holds the host lock.
*/
-void send_s870(struct atp_unit *dev,unsigned char c)
+static void send_s870(struct atp_unit *dev,unsigned char c)
{
unsigned int tmport;
struct scsi_cmnd *workreq;
@@ -821,9 +822,9 @@ oktosend:
}
outb(j, tmport);
while ((inb(tmport) & 0x01) != j) {
- outb(j,tmport);
+ outb(j,tmport);
#ifdef ED_DBGP
- printk("send_s870 while loop 1\n");
+ printk("send_s870 while loop 1\n");
#endif
}
/*
@@ -946,18 +947,18 @@ oktosend:
#ifdef ED_DBGP
printk("1. bttl %x, l %x\n",bttl, l);
#endif
- while (l > 0x10000) {
- (((u16 *) (prd))[i + 3]) = 0x0000;
- (((u16 *) (prd))[i + 2]) = 0x0000;
- (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
- l -= 0x10000;
- bttl += 0x10000;
- i += 0x04;
- }
+ while (l > 0x10000) {
+ (((u16 *) (prd))[i + 3]) = 0x0000;
+ (((u16 *) (prd))[i + 2]) = 0x0000;
(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
- (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
- (((u16 *) (prd))[i + 3]) = 0;
- i += 0x04;
+ l -= 0x10000;
+ bttl += 0x10000;
+ i += 0x04;
+ }
+ (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
+ (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
+ (((u16 *) (prd))[i + 3]) = 0;
+ i += 0x04;
}
(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
#ifdef ED_DBGP
@@ -1174,7 +1175,8 @@ wait_rdyok:
outb(0x09, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
k = inb(tmport);
if (k != 0x16) {
@@ -1245,7 +1247,8 @@ TCM_SYNC:
tmport += 0x03;
outb(0x09, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0);
+ while ((inb(tmport) & 0x80) == 0)
+ cpu_relax();
tmport -= 0x08;
inb(tmport);
return;
@@ -1341,7 +1344,7 @@ G2Q_QUIN: /* k=binID#, */
}
-void is870(struct atp_unit *dev, unsigned int wkport)
+static void is870(struct atp_unit *dev, unsigned int wkport)
{
unsigned int tmport;
unsigned char i, j, k, rmb, n;
@@ -1401,12 +1404,16 @@ void is870(struct atp_unit *dev, unsigned int wkport)
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
dev->active_id[0] |= m;
tmport = wkport + 0x10;
@@ -1418,7 +1425,8 @@ phase_cmd:
tmport = wkport + 0x18;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -1444,16 +1452,21 @@ sel_ok:
tmport += 0x03;
outb(inqd[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
tmport = wkport + 0x1b;
- if (dev->chip_ver == 4) {
+ if (dev->chip_ver == 4)
outb(0x00, tmport);
- }
+
tmport = wkport + 0x18;
outb(0x08, tmport);
tmport += 0x07;
@@ -1483,7 +1496,10 @@ rd_inq_data:
tmport += 0x03;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
if (inb(tmport) != 0x16) {
goto sel_ok;
@@ -1523,12 +1539,16 @@ inq_ok:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
try_wide:
j = 0;
tmport = wkport + 0x14;
@@ -1545,7 +1565,10 @@ try_wide:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto widep_in;
@@ -1618,7 +1641,10 @@ widep_cmd:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -1672,12 +1698,16 @@ set_sync:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
try_sync:
j = 0;
tmport = wkport + 0x14;
@@ -1702,7 +1732,10 @@ try_sync:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto phase_ins;
@@ -1760,7 +1793,10 @@ phase_ins1:
goto phase_ins1;
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport);
if (j == 0x85) {
goto tar_dcons;
@@ -1785,7 +1821,10 @@ tar_dcons:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -1885,12 +1924,16 @@ static void is880(struct atp_unit *dev, unsigned int wkport)
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
dev->active_id[0] |= m;
tmport = wkport + 0x50;
@@ -1902,7 +1945,10 @@ phase_cmd:
tmport = wkport + 0x58;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -1928,12 +1974,17 @@ sel_ok:
tmport += 0x03;
outb(inqd[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
tmport = wkport + 0x5b;
outb(0x00, tmport);
tmport = wkport + 0x58;
@@ -1965,11 +2016,13 @@ rd_inq_data:
tmport += 0x03;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if (inb(tmport) != 0x16) {
+ if (inb(tmport) != 0x16)
goto sel_ok;
- }
+
inq_ok:
mbuf[36] = 0;
printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
@@ -2010,12 +2063,17 @@ inq_ok:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
try_u3:
j = 0;
tmport = wkport + 0x54;
@@ -2032,7 +2090,10 @@ try_u3:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto u3p_in;
@@ -2105,7 +2166,10 @@ u3p_cmd:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -2151,12 +2215,16 @@ chg_wide:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
try_wide:
j = 0;
tmport = wkport + 0x54;
@@ -2173,7 +2241,9 @@ try_wide:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto widep_in;
@@ -2246,7 +2316,10 @@ widep_cmd:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -2313,12 +2386,16 @@ set_sync:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
- while (inb(tmport) != 0x8e);
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
try_sync:
j = 0;
tmport = wkport + 0x54;
@@ -2347,7 +2424,10 @@ try_sync:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto phase_ins;
@@ -2405,7 +2485,10 @@ phase_ins1:
goto phase_ins1;
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport);
if (j == 0x85) {
goto tar_dcons;
@@ -2430,7 +2513,10 @@ tar_dcons:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -2544,7 +2630,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_enable_device(pdev))
return -EIO;
- if (!pci_set_dma_mask(pdev, 0xFFFFFFUL)) {
+ if (!pci_set_dma_mask(pdev, 0xFFFFFFFFUL)) {
printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
} else {
printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
@@ -2822,7 +2908,10 @@ flash_ok_885:
tmport += 0x18;
outb(0, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0);
+
+ while ((inb(tmport) & 0x80) == 0)
+ cpu_relax();
+
tmport -= 0x08;
inb(tmport);
tmport = base_io + 0x81;
@@ -2840,7 +2929,10 @@ flash_ok_885:
tmport += 0x18;
outb(0, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0);
+
+ while ((inb(tmport) & 0x80) == 0)
+ cpu_relax();
+
tmport -= 0x08;
inb(tmport);
tmport = base_io + 0xc1;
@@ -3005,7 +3097,7 @@ unregister:
it is available to be used again. Until this gets worked out, we will
leave it commented out. */
-int atp870u_abort(struct scsi_cmnd * SCpnt)
+static int atp870u_abort(struct scsi_cmnd * SCpnt)
{
unsigned char j, k, c;
struct scsi_cmnd *workrequ;
@@ -3044,7 +3136,7 @@ int atp870u_abort(struct scsi_cmnd * SCpnt)
return SUCCESS;
}
-const char *atp870u_info(struct Scsi_Host *notused)
+static const char *atp870u_info(struct Scsi_Host *notused)
{
static char buffer[128];
@@ -3053,13 +3145,9 @@ const char *atp870u_info(struct Scsi_Host *notused)
return buffer;
}
-int atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
-{
- return -ENOSYS; /* Currently this is a no-op */
-}
-
#define BLS buffer + len + size
-int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, char **start, off_t offset, int length, int inout)
+int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
+ char **start, off_t offset, int length, int inout)
{
static u8 buff[512];
int size = 0;
@@ -3068,10 +3156,9 @@ int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, char **start, off_
off_t pos = 0;
if (inout)
- return -ENOSYS;
- if (offset == 0) {
+ return -EINVAL;
+ if (offset == 0)
memset(buff, 0, sizeof(buff));
- }
size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
len += size;
pos = begin + len;
@@ -3188,7 +3275,7 @@ static void __exit atp870u_exit(void)
pci_unregister_driver(&atp870u_driver);
}
-void tscam_885(void)
+static void tscam_885(void)
{
unsigned char i;
@@ -3200,7 +3287,7 @@ void tscam_885(void)
-void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
+static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
{
unsigned int tmport;
unsigned char i, j, k, rmb, n, lvdmode;
@@ -3255,12 +3342,14 @@ void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
- while (inb(tmport) != 0x8e);
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
dev->active_id[c] |= m;
tmport = wkport + 0x10;
@@ -3272,7 +3361,8 @@ phase_cmd:
tmport = wkport + 0x18;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -3298,12 +3388,14 @@ sel_ok:
tmport += 0x03;
outb(inqd[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
- while (inb(tmport) != 0x8e);
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
tmport = wkport + 0x1b;
outb(0x00, tmport);
tmport = wkport + 0x18;
@@ -3335,7 +3427,8 @@ rd_inq_data:
tmport += 0x03;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
if (inb(tmport) != 0x16) {
goto sel_ok;
@@ -3379,12 +3472,14 @@ inq_ok:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
- while (inb(tmport) != 0x8e);
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
try_u3:
j = 0;
tmport = wkport + 0x14;
@@ -3399,9 +3494,11 @@ try_u3:
outb(u3[j++], tmport);
tmport += 0x06;
}
+ cpu_relax();
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto u3p_in;
@@ -3423,6 +3520,7 @@ u3p_out:
outb(0, tmport);
tmport += 0x06;
}
+ cpu_relax();
}
tmport -= 0x08;
j = inb(tmport) & 0x0f;
@@ -3493,14 +3591,14 @@ u3p_cmd:
goto chg_wide;
}
if (mbuf[3] == 0x09) {
- m = 1;
- m = m << i;
- dev->wide_id[c] |= m;
- dev->id[c][i].devsp = 0xce;
+ m = 1;
+ m = m << i;
+ dev->wide_id[c] |= m;
+ dev->id[c][i].devsp = 0xce;
#ifdef ED_DBGP
- printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
+ printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
#endif
- continue;
+ continue;
}
chg_wide:
tmport = wkport + 0x1b;
@@ -3523,12 +3621,14 @@ chg_wide:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
- while (inb(tmport) != 0x8e);
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
try_wide:
j = 0;
tmport = wkport + 0x14;
@@ -3543,9 +3643,11 @@ try_wide:
outb(wide[j++], tmport);
tmport += 0x06;
}
+ cpu_relax();
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto widep_in;
@@ -3567,6 +3669,7 @@ widep_out:
outb(0, tmport);
tmport += 0x06;
}
+ cpu_relax();
}
tmport -= 0x08;
j = inb(tmport) & 0x0f;
@@ -3618,7 +3721,8 @@ widep_cmd:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -3686,12 +3790,14 @@ set_sync:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
- while (inb(tmport) != 0x8e);
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
try_sync:
j = 0;
tmport = wkport + 0x14;
@@ -3720,7 +3826,8 @@ try_sync:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto phase_ins;
@@ -3742,6 +3849,7 @@ phase_outs:
outb(0x00, tmport);
tmport += 0x06;
}
+ cpu_relax();
}
tmport -= 0x08;
j = inb(tmport);
@@ -3803,7 +3911,8 @@ tar_dcons:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index b594def19aba3..ba347576d99b0 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -443,3 +443,20 @@ int scsi_queue_work(struct Scsi_Host *shost, struct work_struct *work)
}
EXPORT_SYMBOL_GPL(scsi_queue_work);
+/**
+ * scsi_flush_work - Flush a Scsi_Host's workqueue.
+ * @shost: Pointer to Scsi_Host.
+ **/
+void scsi_flush_work(struct Scsi_Host *shost)
+{
+ if (!shost->work_q) {
+ printk(KERN_ERR
+ "ERROR: Scsi host '%s' attempted to flush scsi-work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+ return;
+ }
+
+ flush_workqueue(shost->work_q);
+}
+EXPORT_SYMBOL_GPL(scsi_flush_work);
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 25729f3f81648..29f250c80b98f 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -111,8 +111,8 @@ lasi700_probe(struct parisc_device *dev)
memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
hostdata->dev = &dev->dev;
- dma_set_mask(&dev->dev, 0xffffffffUL);
- hostdata->base = base;
+ dma_set_mask(&dev->dev, DMA_32BIT_MASK);
+ hostdata->base = ioremap(base, 0x100);
hostdata->differential = 0;
if (dev->id.sversion == LASI_700_SVERSION) {
@@ -127,17 +127,25 @@ lasi700_probe(struct parisc_device *dev)
NCR_700_set_mem_mapped(hostdata);
- host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev,
- dev->irq, 7);
+ host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev);
if (!host)
goto out_kfree;
+ host->this_id = 7;
+ host->irq = dev->irq;
+ if(request_irq(dev->irq, NCR_700_intr, SA_SHIRQ, "lasi700", host)) {
+ printk(KERN_ERR "lasi700: request_irq failed!\n");
+ goto out_put_host;
+ }
dev_set_drvdata(&dev->dev, host);
scsi_scan_host(host);
return 0;
+ out_put_host:
+ scsi_host_put(host);
out_kfree:
+ iounmap(hostdata->base);
kfree(hostdata);
return -ENODEV;
}
@@ -152,6 +160,7 @@ lasi700_driver_remove(struct parisc_device *dev)
scsi_remove_host(host);
NCR_700_release(host);
free_irq(host->irq, host);
+ iounmap(hostdata->base);
kfree(hostdata);
return 0;
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 9b91b2efe4d2b..7ae13236788ec 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -86,7 +86,7 @@
*/
/* Name and version of the driver */
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3f"
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3g"
#define SCSI_NCR_DEBUG_FLAGS (0)
@@ -1219,7 +1219,7 @@ static struct lcb * ncr_alloc_lcb (struct ncb *np, u_char tn, u_char ln);
static struct lcb * ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev);
static void ncr_getclock (struct ncb *np, int mult);
static void ncr_selectclock (struct ncb *np, u_char scntl3);
-static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln);
+static struct ccb *ncr_get_ccb (struct ncb *np, struct scsi_cmnd *cmd);
static void ncr_chip_reset (struct ncb *np, int delay);
static void ncr_init (struct ncb *np, int reset, char * msg, u_long code);
static int ncr_int_sbmc (struct ncb *np);
@@ -1238,8 +1238,6 @@ static void ncr_getsync (struct ncb *np, u_char sfac, u_char *fakp, u_char *scnt
static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char sxfer);
static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev);
static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack);
-static int ncr_show_msg (u_char * msg);
-static void ncr_print_msg (struct ccb *cp, char *label, u_char *msg);
static int ncr_snooptest (struct ncb *np);
static void ncr_timeout (struct ncb *np);
static void ncr_wakeup (struct ncb *np, u_long code);
@@ -2746,7 +2744,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
for (i=0; i<MAX_START; i++) {
*p++ =SCR_CALL;
*p++ =PADDR (idle);
- };
+ }
BUG_ON((u_long)p != (u_long)&scrh->tryloop + sizeof (scrh->tryloop));
@@ -2771,7 +2769,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
*p++ =PADDR (dispatch);
*p++ =SCR_MOVE_TBL ^ SCR_DATA_IN;
*p++ =offsetof (struct dsb, data[i]);
- };
+ }
BUG_ON((u_long)p != (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in));
@@ -2781,7 +2779,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
*p++ =PADDR (dispatch);
*p++ =SCR_MOVE_TBL ^ SCR_DATA_IN;
*p++ =offsetof (struct dsb, data[i]);
- };
+ }
BUG_ON((u_long)p != (u_long)&scr->data_in + sizeof (scr->data_in));
@@ -2791,7 +2789,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
*p++ =PADDR (dispatch);
*p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT;
*p++ =offsetof (struct dsb, data[i]);
- };
+ }
BUG_ON((u_long)p != (u_long)&scrh->hdata_out + sizeof (scrh->hdata_out));
@@ -2801,7 +2799,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
*p++ =PADDR (dispatch);
*p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT;
*p++ =offsetof (struct dsb, data[i]);
- };
+ }
BUG_ON((u_long) p != (u_long)&scr->data_out + sizeof (scr->data_out));
}
@@ -2842,7 +2840,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len)
printk (KERN_ERR "%s: ERROR0 IN SCRIPT at %d.\n",
ncr_name(np), (int) (src-start-1));
mdelay(1000);
- };
+ }
if (DEBUG_FLAGS & DEBUG_SCRIPT)
printk (KERN_DEBUG "%p: <%x>\n",
@@ -2911,7 +2909,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len)
default:
relocs = 0;
break;
- };
+ }
if (relocs) {
while (relocs--) {
@@ -2958,7 +2956,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len)
} else
*dst++ = cpu_to_scr(*src++);
- };
+ }
}
/*
@@ -2969,25 +2967,25 @@ struct host_data {
struct ncb *ncb;
};
-/*
-** Print something which allows to retrieve the controller type, unit,
-** target, lun concerned by a kernel message.
-*/
+#define PRINT_ADDR(cmd, arg...) dev_info(&cmd->device->sdev_gendev , ## arg)
-static void PRINT_TARGET(struct ncb *np, int target)
+static void ncr_print_msg(struct ccb *cp, char *label, u_char *msg)
{
- printk(KERN_INFO "%s-<%d,*>: ", ncr_name(np), target);
-}
+ int i;
+ PRINT_ADDR(cp->cmd, "%s: ", label);
-static void PRINT_LUN(struct ncb *np, int target, int lun)
-{
- printk(KERN_INFO "%s-<%d,%d>: ", ncr_name(np), target, lun);
-}
+ printk ("%x",*msg);
+ if (*msg == M_EXTENDED) {
+ for (i = 1; i < 8; i++) {
+ if (i - 1 > msg[1])
+ break;
+ printk ("-%x",msg[i]);
+ }
+ } else if ((*msg & 0xf0) == 0x20) {
+ printk ("-%x",msg[1]);
+ }
-static void PRINT_ADDR(struct scsi_cmnd *cmd)
-{
- struct host_data *host_data = (struct host_data *) cmd->device->host->hostdata;
- PRINT_LUN(host_data->ncb, cmd->device->id, cmd->device->lun);
+ printk(".\n");
}
/*==========================================================
@@ -3280,6 +3278,7 @@ static void __init ncr_prepare_setting(struct ncb *np)
tp->usrsync = driver_setup.default_sync;
tp->usrwide = driver_setup.max_wide;
tp->usrtags = MAX_TAGS;
+ tp->period = 0xffff;
if (!driver_setup.disconnection)
np->target[i].usrflag = UF_NODISC;
}
@@ -3369,34 +3368,23 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
int nego = 0;
struct scsi_target *starget = tp->starget;
- if (likely(starget)) {
-
- /*
- ** negotiate wide transfers ?
- */
-
- if (!tp->widedone) {
- if (spi_support_wide(starget)) {
- nego = NS_WIDE;
- } else
- tp->widedone=1;
-
- };
-
- /*
- ** negotiate synchronous transfers?
- */
+ /* negotiate wide transfers ? */
+ if (!tp->widedone) {
+ if (spi_support_wide(starget)) {
+ nego = NS_WIDE;
+ } else
+ tp->widedone=1;
+ }
- if (!nego && !tp->period) {
- if (spi_support_sync(starget)) {
- nego = NS_SYNC;
- } else {
- tp->period =0xffff;
- PRINT_TARGET(np, cp->target);
- printk ("target did not report SYNC.\n");
- };
- };
- };
+ /* negotiate synchronous transfers? */
+ if (!nego && !tp->period) {
+ if (spi_support_sync(starget)) {
+ nego = NS_SYNC;
+ } else {
+ tp->period =0xffff;
+ dev_info(&starget->dev, "target did not report SYNC.\n");
+ }
+ }
switch (nego) {
case NS_SYNC:
@@ -3412,7 +3400,7 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
msgptr[msglen++] = M_X_WIDE_REQ;
msgptr[msglen++] = tp->usrwide;
break;
- };
+ }
cp->nego_status = nego;
@@ -3421,8 +3409,8 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
if (DEBUG_FLAGS & DEBUG_NEGO) {
ncr_print_msg(cp, nego == NS_WIDE ?
"wide msgout":"sync_msgout", msgptr);
- };
- };
+ }
+ }
return msglen;
}
@@ -3440,9 +3428,9 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
*/
static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
{
-/* struct scsi_device *device = cmd->device; */
- struct tcb *tp = &np->target[cmd->device->id];
- struct lcb *lp = tp->lp[cmd->device->lun];
+ struct scsi_device *sdev = cmd->device;
+ struct tcb *tp = &np->target[sdev->id];
+ struct lcb *lp = tp->lp[sdev->lun];
struct ccb *cp;
int segments;
@@ -3457,9 +3445,9 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
**
**---------------------------------------------
*/
- if ((cmd->device->id == np->myaddr ) ||
- (cmd->device->id >= MAX_TARGET) ||
- (cmd->device->lun >= MAX_LUN )) {
+ if ((sdev->id == np->myaddr ) ||
+ (sdev->id >= MAX_TARGET) ||
+ (sdev->lun >= MAX_LUN )) {
return(DID_BAD_TARGET);
}
@@ -3479,8 +3467,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
}
if (DEBUG_FLAGS & DEBUG_TINY) {
- PRINT_ADDR(cmd);
- printk ("CMD=%x ", cmd->cmnd[0]);
+ PRINT_ADDR(cmd, "CMD=%x ", cmd->cmnd[0]);
}
/*---------------------------------------------------
@@ -3499,7 +3486,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
np->settle_time = tlimit;
}
- if (np->settle_time || !(cp=ncr_get_ccb (np, cmd->device->id, cmd->device->lun))) {
+ if (np->settle_time || !(cp=ncr_get_ccb (np, cmd))) {
insert_into_waiting_list(np, cmd);
return(DID_OK);
}
@@ -3512,7 +3499,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
**----------------------------------------------------
*/
- idmsg = M_IDENTIFY | cmd->device->lun;
+ idmsg = M_IDENTIFY | sdev->lun;
if (cp ->tag != NO_TAG ||
(cp != np->ccb && np->disc && !(tp->usrflag & UF_NODISC)))
@@ -3533,8 +3520,8 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
if (lp->tags_smap) {
order = M_ORDERED_TAG;
if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){
- PRINT_ADDR(cmd);
- printk("ordered tag forced.\n");
+ PRINT_ADDR(cmd,
+ "ordered tag forced.\n");
}
}
lp->tags_stime = ktime_get(3*HZ);
@@ -3682,7 +3669,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
/*
** select
*/
- cp->phys.select.sel_id = cmd->device->id;
+ cp->phys.select.sel_id = sdev->id;
cp->phys.select.sel_scntl3 = tp->wval;
cp->phys.select.sel_sxfer = tp->sval;
/*
@@ -3719,9 +3706,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
**----------------------------------------------------
*/
- /*
- ** activate this job.
- */
+ /* activate this job. */
cp->magic = CCB_MAGIC;
/*
@@ -3734,11 +3719,9 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
else
ncr_put_start_queue(np, cp);
- /*
- ** Command is successfully queued.
- */
+ /* Command is successfully queued. */
- return(DID_OK);
+ return DID_OK;
}
@@ -4203,8 +4186,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
*/
if (cp->parity_status > 1) {
- PRINT_ADDR(cmd);
- printk ("%d parity error(s).\n",cp->parity_status);
+ PRINT_ADDR(cmd, "%d parity error(s).\n",cp->parity_status);
}
/*
@@ -4212,16 +4194,16 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
*/
if (cp->xerr_status != XE_OK) {
- PRINT_ADDR(cmd);
switch (cp->xerr_status) {
case XE_EXTRA_DATA:
- printk ("extraneous data discarded.\n");
+ PRINT_ADDR(cmd, "extraneous data discarded.\n");
break;
case XE_BAD_PHASE:
- printk ("invalid scsi phase (4/5).\n");
+ PRINT_ADDR(cmd, "invalid scsi phase (4/5).\n");
break;
default:
- printk ("extended error %d.\n", cp->xerr_status);
+ PRINT_ADDR(cmd, "extended error %d.\n",
+ cp->xerr_status);
break;
}
if (cp->host_status==HS_COMPLETE)
@@ -4233,9 +4215,9 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
*/
if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) {
if (cp->host_status!=HS_COMPLETE || cp->scsi_status!=S_GOOD) {
- PRINT_ADDR(cmd);
- printk ("ERROR: cmd=%x host_status=%x scsi_status=%x\n",
- cmd->cmnd[0], cp->host_status, cp->scsi_status);
+ PRINT_ADDR(cmd, "ERROR: cmd=%x host_status=%x "
+ "scsi_status=%x\n", cmd->cmnd[0],
+ cp->host_status, cp->scsi_status);
}
}
@@ -4296,8 +4278,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) {
u_char * p = (u_char*) & cmd->sense_buffer;
int i;
- PRINT_ADDR(cmd);
- printk ("sense data:");
+ PRINT_ADDR(cmd, "sense data:");
for (i=0; i<14; i++) printk (" %x", *p++);
printk (".\n");
}
@@ -4344,8 +4325,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
/*
** Other protocol messes
*/
- PRINT_ADDR(cmd);
- printk ("COMMAND FAILED (%x %x) @%p.\n",
+ PRINT_ADDR(cmd, "COMMAND FAILED (%x %x) @%p.\n",
cp->host_status, cp->scsi_status, cp);
cmd->result = ScsiResult(DID_ERROR, cp->scsi_status);
@@ -4358,8 +4338,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
if (tp->usrflag & UF_TRACE) {
u_char * p;
int i;
- PRINT_ADDR(cmd);
- printk (" CMD:");
+ PRINT_ADDR(cmd, " CMD:");
p = (u_char*) &cmd->cmnd[0];
for (i=0; i<cmd->cmd_len; i++) printk (" %x", *p++);
@@ -4667,12 +4646,11 @@ void ncr_init (struct ncb *np, int reset, char * msg, u_long code)
}
else
tp->usrsync = 255;
- };
+ }
if (tp->usrwide > np->maxwide)
tp->usrwide = np->maxwide;
- ncr_negotiate (np, tp);
}
/*
@@ -4849,7 +4827,7 @@ static void ncr_set_sync_wide_status (struct ncb *np, u_char target)
#endif
cp->phys.select.sel_scntl3 = tp->wval;
cp->phys.select.sel_sxfer = tp->sval;
- };
+ }
}
/*==========================================================
@@ -4885,40 +4863,19 @@ static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char s
else
tp->period = 0xffff;
- /*
- ** Stop there if sync parameters are unchanged
- */
- if (tp->sval == sxfer && tp->wval == scntl3) return;
+ /* Stop there if sync parameters are unchanged */
+ if (tp->sval == sxfer && tp->wval == scntl3)
+ return;
tp->sval = sxfer;
tp->wval = scntl3;
- /*
- ** Bells and whistles ;-)
- */
- PRINT_TARGET(np, target);
if (sxfer & 0x01f) {
- unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0);
- unsigned mb10 = (f10 + tp->period/2) / tp->period;
- char *scsi;
-
- /*
- ** Disable extended Sreq/Sack filtering
- */
- if (tp->period <= 2000) OUTOFFB (nc_stest2, EXT);
-
- /*
- ** Bells and whistles ;-)
- */
- if (tp->period < 500) scsi = "FAST-40";
- else if (tp->period < 1000) scsi = "FAST-20";
- else if (tp->period < 2000) scsi = "FAST-10";
- else scsi = "FAST-5";
-
- printk ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi,
- tp->widedone > 1 ? "WIDE " : "",
- mb10 / 10, mb10 % 10, tp->period / 10, sxfer & 0x1f);
- } else
- printk ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : "");
+ /* Disable extended Sreq/Sack filtering */
+ if (tp->period <= 2000)
+ OUTOFFB(nc_stest2, EXT);
+ }
+
+ spi_display_xfer_agreement(tp->starget);
/*
** set actual value and sync_status
@@ -4964,11 +4921,8 @@ static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack
** Bells and whistles ;-)
*/
if (bootverbose >= 2) {
- PRINT_TARGET(np, target);
- if (scntl3 & EWS)
- printk ("WIDE SCSI (16 bit) enabled.\n");
- else
- printk ("WIDE SCSI disabled.\n");
+ dev_info(&cmd->device->sdev_target->dev, "WIDE SCSI %sabled.\n",
+ (scntl3 & EWS) ? "en" : "dis");
}
/*
@@ -5023,7 +4977,7 @@ static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev)
reqtags = lp->numtags;
} else {
reqtags = 1;
- };
+ }
/*
** Update max number of tags
@@ -5063,12 +5017,13 @@ static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev)
** Announce change to user.
*/
if (bootverbose) {
- PRINT_LUN(np, tn, ln);
if (lp->usetags) {
- printk("tagged command queue depth set to %d\n", reqtags);
- }
- else {
- printk("tagged command queueing disabled\n");
+ dev_info(&sdev->sdev_gendev,
+ "tagged command queue depth set to %d\n",
+ reqtags);
+ } else {
+ dev_info(&sdev->sdev_gendev,
+ "tagged command queueing disabled\n");
}
}
}
@@ -5274,7 +5229,7 @@ void ncr_exception (struct ncb *np)
istat = INB (nc_istat);
if (DEBUG_FLAGS & DEBUG_TINY) printk ("F ");
ncr_wakeup_done (np);
- };
+ }
if (!(istat & (SIP|DIP)))
return;
@@ -5335,7 +5290,7 @@ void ncr_exception (struct ncb *np)
}
OUTONB_STD ();
return;
- };
+ }
/*========================================================
** Now, interrupts that need some fixing up.
@@ -5355,7 +5310,7 @@ void ncr_exception (struct ncb *np)
if (sist & RST) {
ncr_init (np, 1, bootverbose ? "scsi reset" : NULL, HS_RESET);
return;
- };
+ }
if ((sist & STO) &&
!(dstat & (MDPE|BF|ABRT))) {
@@ -5366,7 +5321,7 @@ void ncr_exception (struct ncb *np)
ncr_int_sto (np);
return;
- };
+ }
/*=========================================================
** Now, interrupts we are not able to recover cleanly.
@@ -5387,7 +5342,7 @@ void ncr_exception (struct ncb *np)
((char*)&np->regdump)[i] = INB_OFF(i);
np->regdump.nc_dstat = dstat;
np->regdump.nc_sist = sist;
- };
+ }
ncr_log_hard_error(np, sist, dstat);
@@ -5399,20 +5354,20 @@ void ncr_exception (struct ncb *np)
(dstat & (MDPE|BF|ABRT|IID))) {
ncr_start_reset(np);
return;
- };
+ }
if (sist & HTH) {
printk ("%s: handshake timeout\n", ncr_name(np));
ncr_start_reset(np);
return;
- };
+ }
if (sist & UDC) {
printk ("%s: unexpected disconnect\n", ncr_name(np));
OUTB (HS_PRT, HS_UNEXPECTED);
OUTL_DSP (NCB_SCRIPT_PHYS (np, cleanup));
return;
- };
+ }
/*=========================================================
** We just miss the cause of the interrupt. :(
@@ -5456,7 +5411,7 @@ void ncr_int_sto (struct ncb *np)
if (cp) {
cp-> host_status = HS_SEL_TIMEOUT;
ncr_complete (np, cp);
- };
+ }
/*
** repair start queue and jump to start point.
@@ -5647,7 +5602,7 @@ static void ncr_int_ma (struct ncb *np)
ss2 = INB (nc_sstat2);
if (ss2 & OLF1) rest++;
if (ss2 & ORF1) rest++;
- };
+ }
if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE))
printk ("P%x%x RL=%d D=%d SS0=%x ", cmd&7, sbcl&7,
@@ -5716,7 +5671,7 @@ static void ncr_int_ma (struct ncb *np)
cp, np->header.cp,
(unsigned)dsp,
(unsigned)nxtdsp, vdsp, cmd);
- };
+ }
/*
** cp=0 means that the DSA does not point to a valid control
@@ -5744,7 +5699,7 @@ static void ncr_int_ma (struct ncb *np)
} else {
tblp = (u32 *) 0;
olen = scr_to_cpu(vdsp[0]) & 0xffffff;
- };
+ }
if (DEBUG_FLAGS & DEBUG_PHASE) {
printk ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n",
@@ -5752,16 +5707,15 @@ static void ncr_int_ma (struct ncb *np)
tblp,
(unsigned) olen,
(unsigned) oadr);
- };
+ }
/*
** check cmd against assumed interrupted script command.
*/
if (cmd != (scr_to_cpu(vdsp[0]) >> 24)) {
- PRINT_ADDR(cp->cmd);
- printk ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n",
- (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0]) >> 24);
+ PRINT_ADDR(cp->cmd, "internal error: cmd=%02x != %02x=(vdsp[0] "
+ ">> 24)\n", cmd, scr_to_cpu(vdsp[0]) >> 24);
goto reset_all;
}
@@ -5783,12 +5737,11 @@ static void ncr_int_ma (struct ncb *np)
*/
if (cmd & 0x06) {
- PRINT_ADDR(cp->cmd);
- printk ("phase change %x-%x %d@%08x resid=%d.\n",
+ PRINT_ADDR(cp->cmd, "phase change %x-%x %d@%08x resid=%d.\n",
cmd&7, sbcl&7, (unsigned)olen,
(unsigned)oadr, (unsigned)rest);
goto unexpected_phase;
- };
+ }
/*
** choose the correct patch area.
@@ -5812,8 +5765,7 @@ static void ncr_int_ma (struct ncb *np)
newcmd[3] = cpu_to_scr(nxtdsp);
if (DEBUG_FLAGS & DEBUG_PHASE) {
- PRINT_ADDR(cp->cmd);
- printk ("newcmd[%d] %x %x %x %x.\n",
+ PRINT_ADDR(cp->cmd, "newcmd[%d] %x %x %x %x.\n",
(int) (newcmd - cp->patch),
(unsigned)scr_to_cpu(newcmd[0]),
(unsigned)scr_to_cpu(newcmd[1]),
@@ -5939,9 +5891,8 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp)
if (!lp)
goto out;
if (bootverbose >= 1) {
- PRINT_ADDR(cmd);
- printk ("QUEUE FULL! %d busy, %d disconnected CCBs\n",
- busy_cnt, disc_cnt);
+ PRINT_ADDR(cmd, "QUEUE FULL! %d busy, %d disconnected "
+ "CCBs\n", busy_cnt, disc_cnt);
}
if (disc_cnt < lp->numtags) {
lp->numtags = disc_cnt > 2 ? disc_cnt : 2;
@@ -5978,7 +5929,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp)
**
** identify message
*/
- cp->scsi_smsg2[0] = M_IDENTIFY | cmd->device->lun;
+ cp->scsi_smsg2[0] = IDENTIFY(0, cmd->device->lun);
cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2));
cp->phys.smsg.size = cpu_to_scr(1);
@@ -6048,34 +5999,6 @@ out:
**==========================================================
*/
-static int ncr_show_msg (u_char * msg)
-{
- u_char i;
- printk ("%x",*msg);
- if (*msg==M_EXTENDED) {
- for (i=1;i<8;i++) {
- if (i-1>msg[1]) break;
- printk ("-%x",msg[i]);
- };
- return (i+1);
- } else if ((*msg & 0xf0) == 0x20) {
- printk ("-%x",msg[1]);
- return (2);
- };
- return (1);
-}
-
-static void ncr_print_msg ( struct ccb *cp, char *label, u_char *msg)
-{
- if (cp)
- PRINT_ADDR(cp->cmd);
- if (label)
- printk("%s: ", label);
-
- (void) ncr_show_msg (msg);
- printk(".\n");
-}
-
void ncr_int_sir (struct ncb *np)
{
u_char scntl3;
@@ -6230,10 +6153,9 @@ void ncr_int_sir (struct ncb *np)
*/
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("negotiation failed sir=%x status=%x.\n",
- num, cp->nego_status);
- };
+ PRINT_ADDR(cp->cmd, "negotiation failed sir=%x "
+ "status=%x.\n", num, cp->nego_status);
+ }
/*
** any error in negotiation:
@@ -6242,37 +6164,26 @@ void ncr_int_sir (struct ncb *np)
switch (cp->nego_status) {
case NS_SYNC:
- ncr_setsync (np, cp, 0, 0xe0);
spi_period(starget) = 0;
spi_offset(starget) = 0;
+ ncr_setsync (np, cp, 0, 0xe0);
break;
case NS_WIDE:
- ncr_setwide (np, cp, 0, 0);
spi_width(starget) = 0;
+ ncr_setwide (np, cp, 0, 0);
break;
- };
+ }
np->msgin [0] = M_NOOP;
np->msgout[0] = M_NOOP;
cp->nego_status = 0;
break;
case SIR_NEGO_SYNC:
- /*
- ** Synchronous request message received.
- */
-
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("sync msgin: ");
- (void) ncr_show_msg (np->msgin);
- printk (".\n");
- };
-
- /*
- ** get requested values.
- */
+ ncr_print_msg(cp, "sync msgin", np->msgin);
+ }
chg = 0;
per = np->msgin[3];
@@ -6284,8 +6195,8 @@ void ncr_int_sir (struct ncb *np)
** it CAN transfer synch.
*/
- if (ofs && tp->starget)
- spi_support_sync(tp->starget) = 1;
+ if (ofs && starget)
+ spi_support_sync(starget) = 1;
/*
** check values against driver limits.
@@ -6318,9 +6229,8 @@ void ncr_int_sir (struct ncb *np)
}
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n",
- per, scntl3, ofs, fak, chg);
+ PRINT_ADDR(cp->cmd, "sync: per=%d scntl3=0x%x ofs=%d "
+ "fak=%d chg=%d.\n", per, scntl3, ofs, fak, chg);
}
if (INB (HS_PRT) == HS_NEGOTIATE) {
@@ -6328,43 +6238,37 @@ void ncr_int_sir (struct ncb *np)
switch (cp->nego_status) {
case NS_SYNC:
- /*
- ** This was an answer message
- */
+ /* This was an answer message */
if (chg) {
- /*
- ** Answer wasn't acceptable.
- */
- ncr_setsync (np, cp, 0, 0xe0);
+ /* Answer wasn't acceptable. */
spi_period(starget) = 0;
spi_offset(starget) = 0;
- OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad));
+ ncr_setsync(np, cp, 0, 0xe0);
+ OUTL_DSP(NCB_SCRIPT_PHYS (np, msg_bad));
} else {
- /*
- ** Answer is ok.
- */
- ncr_setsync (np, cp, scntl3, (fak<<5)|ofs);
+ /* Answer is ok. */
spi_period(starget) = per;
spi_offset(starget) = ofs;
- OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack));
- };
+ ncr_setsync(np, cp, scntl3, (fak<<5)|ofs);
+ OUTL_DSP(NCB_SCRIPT_PHYS (np, clrack));
+ }
return;
case NS_WIDE:
- ncr_setwide (np, cp, 0, 0);
spi_width(starget) = 0;
+ ncr_setwide(np, cp, 0, 0);
break;
- };
- };
+ }
+ }
/*
** It was a request. Set value and
** prepare an answer message
*/
- ncr_setsync (np, cp, scntl3, (fak<<5)|ofs);
spi_period(starget) = per;
spi_offset(starget) = ofs;
+ ncr_setsync(np, cp, scntl3, (fak<<5)|ofs);
np->msgout[0] = M_EXTENDED;
np->msgout[1] = 3;
@@ -6375,10 +6279,7 @@ void ncr_int_sir (struct ncb *np)
cp->nego_status = NS_SYNC;
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("sync msgout: ");
- (void) ncr_show_msg (np->msgout);
- printk (".\n");
+ ncr_print_msg(cp, "sync msgout", np->msgout);
}
if (!ofs) {
@@ -6394,11 +6295,8 @@ void ncr_int_sir (struct ncb *np)
** Wide request message received.
*/
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("wide msgin: ");
- (void) ncr_show_msg (np->msgin);
- printk (".\n");
- };
+ ncr_print_msg(cp, "wide msgin", np->msgin);
+ }
/*
** get requested values.
@@ -6412,8 +6310,8 @@ void ncr_int_sir (struct ncb *np)
** it CAN transfer wide.
*/
- if (wide && tp->starget)
- spi_support_wide(tp->starget) = 1;
+ if (wide && starget)
+ spi_support_wide(starget) = 1;
/*
** check values against driver limits.
@@ -6423,8 +6321,8 @@ void ncr_int_sir (struct ncb *np)
{chg = 1; wide = tp->usrwide;}
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("wide: wide=%d chg=%d.\n", wide, chg);
+ PRINT_ADDR(cp->cmd, "wide: wide=%d chg=%d.\n", wide,
+ chg);
}
if (INB (HS_PRT) == HS_NEGOTIATE) {
@@ -6436,37 +6334,33 @@ void ncr_int_sir (struct ncb *np)
** This was an answer message
*/
if (chg) {
- /*
- ** Answer wasn't acceptable.
- */
- ncr_setwide (np, cp, 0, 1);
+ /* Answer wasn't acceptable. */
spi_width(starget) = 0;
+ ncr_setwide(np, cp, 0, 1);
OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad));
} else {
- /*
- ** Answer is ok.
- */
- ncr_setwide (np, cp, wide, 1);
+ /* Answer is ok. */
spi_width(starget) = wide;
+ ncr_setwide(np, cp, wide, 1);
OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack));
- };
+ }
return;
case NS_SYNC:
- ncr_setsync (np, cp, 0, 0xe0);
spi_period(starget) = 0;
spi_offset(starget) = 0;
+ ncr_setsync(np, cp, 0, 0xe0);
break;
- };
- };
+ }
+ }
/*
** It was a request, set value and
** prepare an answer message
*/
- ncr_setwide (np, cp, wide, 1);
spi_width(starget) = wide;
+ ncr_setwide(np, cp, wide, 1);
np->msgout[0] = M_EXTENDED;
np->msgout[1] = 2;
@@ -6478,10 +6372,7 @@ void ncr_int_sir (struct ncb *np)
cp->nego_status = NS_WIDE;
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("wide msgout: ");
- (void) ncr_show_msg (np->msgin);
- printk (".\n");
+ ncr_print_msg(cp, "wide msgout", np->msgin);
}
break;
@@ -6500,8 +6391,7 @@ void ncr_int_sir (struct ncb *np)
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd);
- printk ("M_REJECT received (%x:%x).\n",
+ PRINT_ADDR(cp->cmd, "M_REJECT received (%x:%x).\n",
(unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]);
break;
@@ -6513,10 +6403,7 @@ void ncr_int_sir (struct ncb *np)
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd);
- printk ("M_REJECT sent for ");
- (void) ncr_show_msg (np->msgin);
- printk (".\n");
+ ncr_print_msg(cp, "M_REJECT sent for", np->msgin);
break;
/*--------------------------------------------------------------------
@@ -6535,8 +6422,8 @@ void ncr_int_sir (struct ncb *np)
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd);
- printk ("M_IGN_RESIDUE received, but not yet implemented.\n");
+ PRINT_ADDR(cp->cmd, "M_IGN_RESIDUE received, but not yet "
+ "implemented.\n");
break;
#if 0
case SIR_MISSING_SAVE:
@@ -6548,15 +6435,14 @@ void ncr_int_sir (struct ncb *np)
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd);
- printk ("M_DISCONNECT received, but datapointer not saved: "
- "data=%x save=%x goal=%x.\n",
+ PRINT_ADDR(cp->cmd, "M_DISCONNECT received, but datapointer "
+ "not saved: data=%x save=%x goal=%x.\n",
(unsigned) INL (nc_temp),
(unsigned) scr_to_cpu(np->header.savep),
(unsigned) scr_to_cpu(np->header.goalp));
break;
#endif
- };
+ }
out:
OUTONB_STD ();
@@ -6571,8 +6457,10 @@ out:
**==========================================================
*/
-static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln)
+static struct ccb *ncr_get_ccb(struct ncb *np, struct scsi_cmnd *cmd)
{
+ u_char tn = cmd->device->id;
+ u_char ln = cmd->device->lun;
struct tcb *tp = &np->target[tn];
struct lcb *lp = tp->lp[ln];
u_char tag = NO_TAG;
@@ -6602,8 +6490,8 @@ static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln)
if (qp) {
cp = list_entry(qp, struct ccb, link_ccbq);
if (cp->magic) {
- PRINT_LUN(np, tn, ln);
- printk ("ccb free list corrupted (@%p)\n", cp);
+ PRINT_ADDR(cmd, "ccb free list corrupted "
+ "(@%p)\n", cp);
cp = NULL;
} else {
list_add_tail(qp, &lp->wait_ccbq);
@@ -6637,7 +6525,7 @@ static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln)
if (flags & SCSI_NOSLEEP) break;
if (tsleep ((caddr_t)cp, PRIBIO|PCATCH, "ncr", 0))
break;
- };
+ }
#endif
if (cp->magic)
@@ -6665,8 +6553,7 @@ static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln)
cp->lun = ln;
if (DEBUG_FLAGS & DEBUG_TAGS) {
- PRINT_LUN(np, tn, ln);
- printk ("ccb @%p using tag %d.\n", cp, tag);
+ PRINT_ADDR(cmd, "ccb @%p using tag %d.\n", cp, tag);
}
return cp;
@@ -6687,8 +6574,7 @@ static void ncr_free_ccb (struct ncb *np, struct ccb *cp)
struct lcb *lp = tp->lp[cp->lun];
if (DEBUG_FLAGS & DEBUG_TAGS) {
- PRINT_LUN(np, cp->target, cp->lun);
- printk ("ccb @%p freeing tag %d.\n", cp, cp->tag);
+ PRINT_ADDR(cp->cmd, "ccb @%p freeing tag %d.\n", cp, cp->tag);
}
/*
@@ -7014,21 +6900,12 @@ static struct lcb *ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev)
unsigned char tn = sdev->id, ln = sdev->lun;
struct tcb *tp = &np->target[tn];
struct lcb *lp = tp->lp[ln];
- struct scsi_target *starget = tp->starget;
- /*
- ** If no lcb, try to allocate it.
- */
+ /* If no lcb, try to allocate it. */
if (!lp && !(lp = ncr_alloc_lcb(np, tn, ln)))
goto fail;
/*
- ** Prepare negotiation
- */
- if (spi_support_wide(starget) || spi_support_sync(starget))
- ncr_negotiate(np, tp);
-
- /*
** If unit supports tagged commands, allocate the
** CCB JUMP table if not yet.
*/
@@ -7170,7 +7047,7 @@ static int __init ncr_regtest (struct ncb* np)
printk ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n",
(unsigned) data);
return (0x10);
- };
+ }
return (0);
}
@@ -7223,7 +7100,7 @@ static int __init ncr_snooptest (struct ncb* np)
if (i>=NCR_SNOOP_TIMEOUT) {
printk ("CACHE TEST FAILED: timeout.\n");
return (0x20);
- };
+ }
/*
** Check termination position.
*/
@@ -7233,7 +7110,7 @@ static int __init ncr_snooptest (struct ncb* np)
(u_long) NCB_SCRIPTH_PHYS (np, snooptest), (u_long) pc,
(u_long) NCB_SCRIPTH_PHYS (np, snoopend) +8);
return (0x40);
- };
+ }
/*
** Show results.
*/
@@ -7241,17 +7118,17 @@ static int __init ncr_snooptest (struct ncb* np)
printk ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n",
(int) host_wr, (int) ncr_rd);
err |= 1;
- };
+ }
if (host_rd != ncr_wr) {
printk ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n",
(int) ncr_wr, (int) host_rd);
err |= 2;
- };
+ }
if (ncr_bk != ncr_wr) {
printk ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n",
(int) ncr_wr, (int) ncr_bk);
err |= 4;
- };
+ }
return (err);
}
@@ -7424,6 +7301,16 @@ static void __init ncr_getclock (struct ncb *np, int mult)
/*===================== LINUX ENTRY POINTS SECTION ==========================*/
+static int ncr53c8xx_slave_alloc(struct scsi_device *device)
+{
+ struct Scsi_Host *host = device->host;
+ struct ncb *np = ((struct host_data *) host->hostdata)->ncb;
+ struct tcb *tp = &np->target[device->id];
+ tp->starget = device->sdev_target;
+
+ return 0;
+}
+
static int ncr53c8xx_slave_configure(struct scsi_device *device)
{
struct Scsi_Host *host = device->host;
@@ -7432,8 +7319,6 @@ static int ncr53c8xx_slave_configure(struct scsi_device *device)
struct lcb *lp = tp->lp[device->lun];
int numtags, depth_to_use;
- tp->starget = device->sdev_target;
-
ncr_setup_lcb(np, device);
/*
@@ -7778,6 +7663,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt,
tpnt->queuecommand = ncr53c8xx_queue_command;
tpnt->slave_configure = ncr53c8xx_slave_configure;
+ tpnt->slave_alloc = ncr53c8xx_slave_alloc;
tpnt->eh_bus_reset_handler = ncr53c8xx_bus_reset;
tpnt->can_queue = SCSI_NCR_CAN_QUEUE;
tpnt->this_id = 7;
@@ -7925,7 +7811,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt,
if (ncr_snooptest(np)) {
printk(KERN_ERR "CACHE INCORRECTLY CONFIGURED.\n");
goto attach_error;
- };
+ }
/* Install the interrupt handler. */
np->irq = device->slot.irq;
@@ -8057,6 +7943,25 @@ static void ncr53c8xx_set_width(struct scsi_target *starget, int width)
ncr_negotiate(np, tp);
}
+static void ncr53c8xx_get_signalling(struct Scsi_Host *shost)
+{
+ struct ncb *np = ((struct host_data *)shost->hostdata)->ncb;
+ enum spi_signal_type type;
+
+ switch (np->scsi_mode) {
+ case SMODE_SE:
+ type = SPI_SIGNAL_SE;
+ break;
+ case SMODE_HVD:
+ type = SPI_SIGNAL_HVD;
+ break;
+ default:
+ type = SPI_SIGNAL_UNKNOWN;
+ break;
+ }
+ spi_signalling(shost) = type;
+}
+
static struct spi_function_template ncr53c8xx_transport_functions = {
.set_period = ncr53c8xx_set_period,
.show_period = 1,
@@ -8064,6 +7969,7 @@ static struct spi_function_template ncr53c8xx_transport_functions = {
.show_offset = 1,
.set_width = ncr53c8xx_set_width,
.show_width = 1,
+ .get_signalling = ncr53c8xx_get_signalling,
};
int __init ncr53c8xx_init(void)
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 68ce3c84930b2..c585c7bef247c 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -24,7 +24,7 @@
*/
static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
-const char * osst_version = "0.99.3";
+static const char * osst_version = "0.99.3";
/* The "failure to reconnect" firmware bug */
#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
@@ -170,7 +170,7 @@ static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
static int osst_probe(struct device *);
static int osst_remove(struct device *);
-struct scsi_driver osst_template = {
+static struct scsi_driver osst_template = {
.owner = THIS_MODULE,
.gendrv = {
.name = "osst",
@@ -4770,9 +4770,6 @@ static int os_scsi_tape_close(struct inode * inode, struct file * filp)
{
int result = 0;
struct osst_tape * STp = filp->private_data;
- struct scsi_request * SRpnt = NULL;
-
- if (SRpnt) scsi_release_request(SRpnt);
if (STp->door_locked == ST_LOCKED_AUTO)
do_door_lock(STp, 0);
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index ee9ff417aea05..9bc597bd13bad 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -31,7 +31,6 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/scsi_request.h>
-#include <scsi/scsi_devinfo.h>
#include "scsi_priv.h"
#include "scsi_logging.h"
@@ -352,10 +351,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
return NEEDS_RETRY;
case HARDWARE_ERROR:
- if (scsi_get_device_flags(scmd->device,
- scmd->device->vendor,
- scmd->device->model)
- & BLIST_RETRY_HWERROR)
+ if (scmd->device->retry_hwerror)
return NEEDS_RETRY;
else
return SUCCESS;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index c47bc3f483b63..7cbc4127fb5a6 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -252,6 +252,16 @@ static void scsi_wait_done(struct scsi_cmnd *cmd)
complete(req->waiting);
}
+/* This is the end routine we get to if a command was never attached
+ * to the request. Simply complete the request without changing
+ * rq_status; this will cause a DRIVER_ERROR. */
+static void scsi_wait_req_end_io(struct request *req)
+{
+ BUG_ON(!req->waiting);
+
+ complete(req->waiting);
+}
+
void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer,
unsigned bufflen, int timeout, int retries)
{
@@ -259,6 +269,7 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer,
sreq->sr_request->waiting = &wait;
sreq->sr_request->rq_status = RQ_SCSI_BUSY;
+ sreq->sr_request->end_io = scsi_wait_req_end_io;
scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done,
timeout, retries);
wait_for_completion(&wait);
@@ -1233,6 +1244,22 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
}
/*
+ * Kill requests for a dead device
+ */
+static void scsi_kill_requests(request_queue_t *q)
+{
+ struct request *req;
+
+ while ((req = elv_next_request(q)) != NULL) {
+ blkdev_dequeue_request(req);
+ req->flags |= REQ_QUIET;
+ while (end_that_request_first(req, 0, req->nr_sectors))
+ ;
+ end_that_request_last(req);
+ }
+}
+
+/*
* Function: scsi_request_fn()
*
* Purpose: Main strategy routine for SCSI.
@@ -1246,10 +1273,16 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
static void scsi_request_fn(struct request_queue *q)
{
struct scsi_device *sdev = q->queuedata;
- struct Scsi_Host *shost = sdev->host;
+ struct Scsi_Host *shost;
struct scsi_cmnd *cmd;
struct request *req;
+ if (!sdev) {
+ printk("scsi: killing requests for dead queue\n");
+ scsi_kill_requests(q);
+ return;
+ }
+
if(!get_device(&sdev->sdev_gendev))
/* We must be tearing the block queue down already */
return;
@@ -1258,6 +1291,7 @@ static void scsi_request_fn(struct request_queue *q)
* To start with, we keep looping until the queue is empty, or until
* the host is no longer able to accept any more requests.
*/
+ shost = sdev->host;
while (!blk_queue_plugged(q)) {
int rtn;
/*
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index b6165617a0de9..a8a37a338c02f 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -725,6 +725,9 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
if (*bflags & BLIST_NOT_LOCKABLE)
sdev->lockable = 0;
+ if (*bflags & BLIST_RETRY_HWERROR)
+ sdev->retry_hwerror = 1;
+
transport_configure_device(&sdev->sdev_gendev);
if (sdev->host->hostt->slave_configure)
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 61afa000b244c..134d3a3e4222a 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -168,8 +168,10 @@ void scsi_device_dev_release(struct device *dev)
list_del(&sdev->starved_entry);
spin_unlock_irqrestore(sdev->host->host_lock, flags);
- if (sdev->request_queue)
+ if (sdev->request_queue) {
+ sdev->request_queue->queuedata = NULL;
scsi_free_queue(sdev->request_queue);
+ }
scsi_target_reap(scsi_target(sdev));
@@ -561,15 +563,7 @@ static int attr_add(struct device *dev, struct device_attribute *attr)
**/
int scsi_sysfs_add_sdev(struct scsi_device *sdev)
{
- struct Scsi_Host *shost = sdev->host;
- struct scsi_target *starget = scsi_target(sdev);
int error, i;
- unsigned long flags;
-
- spin_lock_irqsave(shost->host_lock, flags);
- list_add_tail(&sdev->same_target_siblings, &starget->devices);
- list_add_tail(&sdev->siblings, &shost->__devices);
- spin_unlock_irqrestore(shost->host_lock, flags);
if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
return error;
@@ -786,6 +780,10 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
void scsi_sysfs_device_initialize(struct scsi_device *sdev)
{
+ unsigned long flags;
+ struct Scsi_Host *shost = sdev->host;
+ struct scsi_target *starget = sdev->sdev_target;
+
device_initialize(&sdev->sdev_gendev);
sdev->sdev_gendev.bus = &scsi_bus_type;
sdev->sdev_gendev.release = scsi_device_dev_release;
@@ -801,6 +799,10 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
sdev->channel, sdev->id, sdev->lun);
sdev->scsi_level = SCSI_2;
transport_setup_device(&sdev->sdev_gendev);
+ spin_lock_irqsave(shost->host_lock, flags);
+ list_add_tail(&sdev->same_target_siblings, &starget->devices);
+ list_add_tail(&sdev->siblings, &shost->__devices);
+ spin_unlock_irqrestore(shost->host_lock, flags);
}
int scsi_is_sdev_device(const struct device *dev)
@@ -811,4 +813,4 @@ EXPORT_SYMBOL(scsi_is_sdev_device);
/* A blank transport template that is used in drivers that don't
* yet implement Transport Attributes */
-struct scsi_transport_template blank_transport_template = { { { {0, }, }, }, };
+struct scsi_transport_template blank_transport_template = { { { {NULL, }, }, }, };
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 47a066dd0df27..35d1c1e8e345d 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -1375,12 +1375,14 @@ EXPORT_SYMBOL(fc_remote_port_add);
static void
fc_rport_tgt_remove(struct fc_rport *rport)
{
+ struct Scsi_Host *shost = rport_to_shost(rport);
+
scsi_target_unblock(&rport->dev);
/* Stop anything on the workq */
- if (cancel_delayed_work(&rport->dev_loss_work) ||
- cancel_delayed_work(&rport->scan_work))
+ if (!cancel_delayed_work(&rport->dev_loss_work))
flush_scheduled_work();
+ scsi_flush_work(shost);
scsi_remove_target(&rport->dev);
}
@@ -1625,7 +1627,7 @@ fc_remote_port_unblock(struct fc_rport *rport)
* failure as the state machine state change will validate the
* transaction.
*/
- if (cancel_delayed_work(work))
+ if (!cancel_delayed_work(work))
flush_scheduled_work();
if (rport->port_state == FC_PORTSTATE_OFFLINE)
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index ed800ae7ea4eb..303d7656f7102 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -293,9 +293,12 @@ static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf)
picosec = tp->period * 4000;
}
- if (picosec == -1)
- return sprintf(buf, "reserved");
- len = sprint_frac(buf, picosec, 1000);
+ if (picosec == -1) {
+ len = sprintf(buf, "reserved");
+ } else {
+ len = sprint_frac(buf, picosec, 1000);
+ }
+
buf[len++] = '\n';
buf[len] = '\0';
return len;
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index add2e635f7bcd..63bf2aecbc57c 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -127,16 +127,24 @@ sim710_probe_common(struct device *dev, unsigned long base_addr,
NCR_700_set_io_mapped(hostdata);
/* and register the chip */
- if((host = NCR_700_detect(&sim710_driver_template, hostdata, dev, irq,
- scsi_id)) == NULL) {
+ if((host = NCR_700_detect(&sim710_driver_template, hostdata, dev))
+ == NULL) {
printk(KERN_ERR "sim710: No host detected; card configuration problem?\n");
goto out_release;
}
+ host->this_id = scsi_id;
+ host->irq = irq;
+ if (request_irq(irq, NCR_700_intr, SA_SHIRQ, "sim710", host)) {
+ printk(KERN_ERR "sim710: request_irq failed\n");
+ goto out_put_host;
+ }
scsi_scan_host(host);
return 0;
+ out_put_host:
+ scsi_host_put(host);
out_release:
release_region(host->base, 64);
out_free:
diff --git a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h
index c1d1e959f30cf..4c4ae7d4713fd 100644
--- a/drivers/scsi/sym53c8xx_defs.h
+++ b/drivers/scsi/sym53c8xx_defs.h
@@ -314,9 +314,9 @@
#define writew_b2l __raw_writew
#define writel_b2l __raw_writel
#define readw_raw __raw_readw
-#define readl_raw(a) __raw_readl((unsigned long)(a))
+#define readl_raw __raw_readl
#define writew_raw __raw_writew
-#define writel_raw(v,a) __raw_writel(v,(unsigned long)(a))
+#define writel_raw __raw_writel
#else /* Other big-endian */
#define readw_l2b readw
#define readl_l2b readl
@@ -1281,34 +1281,34 @@ struct scr_tblsel {
** Messages
*/
-#define M_COMPLETE (0x00)
-#define M_EXTENDED (0x01)
-#define M_SAVE_DP (0x02)
-#define M_RESTORE_DP (0x03)
-#define M_DISCONNECT (0x04)
-#define M_ID_ERROR (0x05)
-#define M_ABORT (0x06)
-#define M_REJECT (0x07)
-#define M_NOOP (0x08)
-#define M_PARITY (0x09)
-#define M_LCOMPLETE (0x0a)
-#define M_FCOMPLETE (0x0b)
-#define M_RESET (0x0c)
-#define M_ABORT_TAG (0x0d)
-#define M_CLEAR_QUEUE (0x0e)
-#define M_INIT_REC (0x0f)
-#define M_REL_REC (0x10)
+#define M_COMPLETE COMMAND_COMPLETE
+#define M_EXTENDED EXTENDED_MESSAGE
+#define M_SAVE_DP SAVE_POINTERS
+#define M_RESTORE_DP RESTORE_POINTERS
+#define M_DISCONNECT DISCONNECT
+#define M_ID_ERROR INITIATOR_ERROR
+#define M_ABORT ABORT_TASK_SET
+#define M_REJECT MESSAGE_REJECT
+#define M_NOOP NOP
+#define M_PARITY MSG_PARITY_ERROR
+#define M_LCOMPLETE LINKED_CMD_COMPLETE
+#define M_FCOMPLETE LINKED_FLG_CMD_COMPLETE
+#define M_RESET TARGET_RESET
+#define M_ABORT_TAG ABORT_TASK
+#define M_CLEAR_QUEUE CLEAR_TASK_SET
+#define M_INIT_REC INITIATE_RECOVERY
+#define M_REL_REC RELEASE_RECOVERY
#define M_TERMINATE (0x11)
-#define M_SIMPLE_TAG (0x20)
-#define M_HEAD_TAG (0x21)
-#define M_ORDERED_TAG (0x22)
-#define M_IGN_RESIDUE (0x23)
+#define M_SIMPLE_TAG SIMPLE_QUEUE_TAG
+#define M_HEAD_TAG HEAD_OF_QUEUE_TAG
+#define M_ORDERED_TAG ORDERED_QUEUE_TAG
+#define M_IGN_RESIDUE IGNORE_WIDE_RESIDUE
#define M_IDENTIFY (0x80)
-#define M_X_MODIFY_DP (0x00)
-#define M_X_SYNC_REQ (0x01)
-#define M_X_WIDE_REQ (0x03)
-#define M_X_PPR_REQ (0x04)
+#define M_X_MODIFY_DP EXTENDED_MODIFY_DATA_POINTER
+#define M_X_SYNC_REQ EXTENDED_SDTR
+#define M_X_WIDE_REQ EXTENDED_WDTR
+#define M_X_PPR_REQ EXTENDED_PPR
/*
** Status
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index 31ba6a9168c77..5a51051e31f0e 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -88,31 +88,30 @@ zalon_probe(struct parisc_device *dev)
struct gsc_irq gsc_irq;
u32 zalon_vers;
int error = -ENODEV;
- unsigned long zalon = dev->hpa;
- unsigned long io_port = zalon + GSC_SCSI_ZALON_OFFSET;
+ void __iomem *zalon = ioremap(dev->hpa, 4096);
+ void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET;
static int unit = 0;
struct Scsi_Host *host;
struct ncr_device device;
__raw_writel(CMD_RESET, zalon + IO_MODULE_IO_COMMAND);
while (!(__raw_readl(zalon + IO_MODULE_IO_STATUS) & IOSTATUS_RY))
- ;
+ cpu_relax();
__raw_writel(IOIIDATA_MINT5EN | IOIIDATA_PACKEN | IOIIDATA_PREFETCHEN,
zalon + IO_MODULE_II_CDATA);
/* XXX: Save the Zalon version for bug workarounds? */
- zalon_vers = __raw_readl(dev->hpa + IO_MODULE_II_CDATA) & 0x07000000;
- zalon_vers >>= 24;
+ zalon_vers = (__raw_readl(zalon + IO_MODULE_II_CDATA) >> 24) & 0x07;
/* Setup the interrupts first.
** Later on request_irq() will register the handler.
*/
dev->irq = gsc_alloc_irq(&gsc_irq);
- printk("%s: Zalon vers field is 0x%x, IRQ %d\n", __FUNCTION__,
+ printk(KERN_INFO "%s: Zalon version %d, IRQ %d\n", __FUNCTION__,
zalon_vers, dev->irq);
- __raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, dev->hpa + IO_MODULE_EIM);
+ __raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, zalon + IO_MODULE_EIM);
if (zalon_vers == 0)
printk(KERN_WARNING "%s: Zalon 1.1 or earlier\n", __FUNCTION__);
@@ -120,16 +119,16 @@ zalon_probe(struct parisc_device *dev)
memset(&device, 0, sizeof(struct ncr_device));
/* The following three are needed before any other access. */
- writeb(0x20, io_port + 0x38); /* DCNTL_REG, EA */
- writeb(0x04, io_port + 0x1b); /* CTEST0_REG, EHP */
- writeb(0x80, io_port + 0x22); /* CTEST4_REG, MUX */
+ __raw_writeb(0x20, io_port + 0x38); /* DCNTL_REG, EA */
+ __raw_writeb(0x04, io_port + 0x1b); /* CTEST0_REG, EHP */
+ __raw_writeb(0x80, io_port + 0x22); /* CTEST4_REG, MUX */
/* Initialise ncr_device structure with items required by ncr_attach. */
device.chip = zalon720_chip;
device.host_id = 7;
device.dev = &dev->dev;
- device.slot.base = (u_long)io_port;
- device.slot.base_c = (u_long)io_port;
+ device.slot.base = dev->hpa + GSC_SCSI_ZALON_OFFSET;
+ device.slot.base_v = io_port;
device.slot.irq = dev->irq;
device.differential = 2;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 2eae67f9a621f..49071f2394527 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2333,7 +2333,7 @@ static int __devexit serial8250_remove(struct device *dev)
return 0;
}
-static int serial8250_suspend(struct device *dev, u32 state, u32 level)
+static int serial8250_suspend(struct device *dev, pm_message_t state, u32 level)
{
int i;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index fbfe5d35de330..cdf110fd63518 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -615,7 +615,7 @@ config SERIAL_68360
config SERIAL_PMACZILOG
tristate "PowerMac z85c30 ESCC support"
- depends on PPC_OF
+ depends on PPC_OF && PPC_PMAC
select SERIAL_CORE
help
This driver supports the Zilog z85C30 serial ports found on
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index fc2a8f03218e9..d273134f9e6cc 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -22,6 +22,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
+ * [29-Mar-2005] Mike Lee
+ * Added hardware handshake
*/
#include <linux/config.h>
@@ -428,6 +430,11 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
else
ucr2 = UCR2_SRST | UCR2_IRTS;
+ if (termios->c_cflag & CRTSCTS) {
+ ucr2 &= ~UCR2_IRTS;
+ ucr2 |= UCR2_CTSC;
+ }
+
if (termios->c_cflag & CSTOPB)
ucr2 |= UCR2_STPB;
if (termios->c_cflag & PARENB) {
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 47945745291d2..2a5cf174ca30d 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -18,7 +18,7 @@
* Some of the code has been inspired/copied from the 2.4 code written
* by Dale Farnsworth <dfarnsworth@mvista.com>.
*
- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 MontaVista, Software, Inc.
*
* This file is licensed under the terms of the GNU General Public License
@@ -26,33 +26,26 @@
* kind, whether express or implied.
*/
-/* OCP Usage :
+/* Platform device Usage :
*
- * This drivers uses the OCP model. To load the serial driver for one of the
- * PSCs, just add this to the core_ocp table :
+ * Since PSCs can have multiple function, the correct driver for each one
+ * is selected by calling mpc52xx_match_psc_function(...). The function
+ * handled by this driver is "uart".
*
- * {
- * .vendor = OCP_VENDOR_FREESCALE,
- * .function = OCP_FUNC_PSC_UART,
- * .index = 0,
- * .paddr = MPC52xx_PSC1,
- * .irq = MPC52xx_PSC1_IRQ,
- * .pm = OCP_CPM_NA,
- * },
- *
- * This is for PSC1, replace the paddr and irq according to the PSC you want to
- * use. The driver all necessary registers to place the PSC in uart mode without
+ * The driver init all necessary registers to place the PSC in uart mode without
* DCD. However, the pin multiplexing aren't changed and should be set either
* by the bootloader or in the platform init code.
- * The index field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2,
+ *
+ * The idx field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2,
* and so on). So the PSC1 is mapped to /dev/ttyS0, PSC2 to /dev/ttyS1 and so
* on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly for
* the console code : without this 1:1 mapping, at early boot time, when we are
* parsing the kernel args console=ttyS?, we wouldn't know wich PSC it will be
- * mapped to because OCP stuff is not yet initialized.
+ * mapped to.
*/
#include <linux/config.h>
+#include <linux/device.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/serial.h>
@@ -61,7 +54,6 @@
#include <asm/delay.h>
#include <asm/io.h>
-#include <asm/ocp.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
@@ -191,6 +183,13 @@ static int
mpc52xx_uart_startup(struct uart_port *port)
{
struct mpc52xx_psc __iomem *psc = PSC(port);
+ int ret;
+
+ /* Request IRQ */
+ ret = request_irq(port->irq, mpc52xx_uart_int,
+ SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
+ if (ret)
+ return ret;
/* Reset/activate the port, clear and enable interrupts */
out_8(&psc->command,MPC52xx_PSC_RST_RX);
@@ -225,6 +224,9 @@ mpc52xx_uart_shutdown(struct uart_port *port)
port->read_status_mask = 0;
out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask);
+
+ /* Release interrupt */
+ free_irq(port->irq, port);
}
static void
@@ -326,15 +328,21 @@ mpc52xx_uart_release_port(struct uart_port *port)
iounmap(port->membase);
port->membase = NULL;
}
+
+ release_mem_region(port->mapbase, MPC52xx_PSC_SIZE);
}
static int
mpc52xx_uart_request_port(struct uart_port *port)
{
if (port->flags & UPF_IOREMAP) /* Need to remap ? */
- port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));
-
- return port->membase != NULL ? 0 : -EBUSY;
+ port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
+
+ if (!port->membase)
+ return -EINVAL;
+
+ return request_mem_region(port->mapbase, MPC52xx_PSC_SIZE,
+ "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
}
static void
@@ -354,7 +362,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
if ( (ser->irq != port->irq) ||
(ser->io_type != SERIAL_IO_MEM) ||
(ser->baud_base != port->uartclk) ||
- // FIXME Should check addresses/irq as well ?
+ (ser->iomem_base != (void*)port->mapbase) ||
(ser->hub6 != 0 ) )
return -EINVAL;
@@ -630,7 +638,7 @@ mpc52xx_console_setup(struct console *co, char *options)
{
struct uart_port *port = &mpc52xx_uart_ports[co->index];
- int baud = 9600;
+ int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
int bits = 8;
int parity = 'n';
int flow = 'n';
@@ -643,14 +651,12 @@ mpc52xx_console_setup(struct console *co, char *options)
spin_lock_init(&port->lock);
port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
port->ops = &mpc52xx_uart_ops;
- port->mapbase = MPC52xx_PSCx(co->index);
+ port->mapbase = MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1));
- /* We ioremap ourself */
- port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));
- if (port->membase == NULL) {
- release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
- return -EBUSY;
- }
+ /* We ioremap ourself */
+ port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
+ if (port->membase == NULL)
+ return -EINVAL;
/* Setup the port parameters accoding to options */
if (options)
@@ -707,26 +713,32 @@ static struct uart_driver mpc52xx_uart_driver = {
/* ======================================================================== */
-/* OCP Driver */
+/* Platform Driver */
/* ======================================================================== */
static int __devinit
-mpc52xx_uart_probe(struct ocp_device *ocp)
+mpc52xx_uart_probe(struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *res = pdev->resource;
+
struct uart_port *port = NULL;
- int idx, ret;
+ int i, idx, ret;
- /* Get the corresponding port struct */
- idx = ocp->def->index;
+ /* Check validity & presence */
+ idx = pdev->id;
if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)
return -EINVAL;
-
- port = &mpc52xx_uart_ports[idx];
+
+ if (!mpc52xx_match_psc_function(idx,"uart"))
+ return -ENODEV;
/* Init the port structure */
+ port = &mpc52xx_uart_ports[idx];
+
+ memset(port, 0x00, sizeof(struct uart_port));
+
spin_lock_init(&port->lock);
- port->mapbase = ocp->def->paddr;
- port->irq = ocp->def->irq;
port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
port->fifosize = 255; /* Should be 512 ! But it can't be */
/* stored in a unsigned char */
@@ -735,95 +747,65 @@ mpc52xx_uart_probe(struct ocp_device *ocp)
( uart_console(port) ? 0 : UPF_IOREMAP );
port->line = idx;
port->ops = &mpc52xx_uart_ops;
- port->read_status_mask = 0;
-
- /* Requests the mem & irqs */
- /* Unlike other serial drivers, we reserve the resources here, so we
- * can detect early if multiple drivers uses the same PSC. Special
- * care must be taken with the console PSC
- */
- ret = request_irq(
- port->irq, mpc52xx_uart_int,
- SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
- if (ret)
- goto error;
- ret = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
- "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
- if (ret)
- goto free_irq;
+ /* Search for IRQ and mapbase */
+ for (i=0 ; i<pdev->num_resources ; i++, res++) {
+ if (res->flags & IORESOURCE_MEM)
+ port->mapbase = res->start;
+ else if (res->flags & IORESOURCE_IRQ)
+ port->irq = res->start;
+ }
+ if (!port->irq || !port->mapbase)
+ return -EINVAL;
/* Add the port to the uart sub-system */
ret = uart_add_one_port(&mpc52xx_uart_driver, port);
- if (ret)
- goto release_mem;
-
- ocp_set_drvdata(ocp, (void*)port);
-
- return 0;
-
-
-free_irq:
- free_irq(port->irq, mpc52xx_uart_int);
-
-release_mem:
- release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
-
-error:
- if (uart_console(port))
- printk( "mpc52xx_uart.c: Error during resource alloction for "
- "the console port !!! Check that the console PSC is "
- "not used by another OCP driver !!!\n" );
+ if (!ret)
+ dev_set_drvdata(dev, (void*)port);
return ret;
}
-static void
-mpc52xx_uart_remove(struct ocp_device *ocp)
+static int
+mpc52xx_uart_remove(struct device *dev)
{
- struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- ocp_set_drvdata(ocp, NULL);
+ dev_set_drvdata(dev, NULL);
- if (port) {
+ if (port)
uart_remove_one_port(&mpc52xx_uart_driver, port);
- release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
- free_irq(port->irq, mpc52xx_uart_int);
- }
+
+ return 0;
}
#ifdef CONFIG_PM
static int
-mpc52xx_uart_suspend(struct ocp_device *ocp, u32 state)
+mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level)
{
- struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- uart_suspend_port(&mpc52xx_uart_driver, port);
+ if (sport && level == SUSPEND_DISABLE)
+ uart_suspend_port(&mpc52xx_uart_driver, port);
return 0;
}
static int
-mpc52xx_uart_resume(struct ocp_device *ocp)
+mpc52xx_uart_resume(struct device *dev, u32 level)
{
- struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- uart_resume_port(&mpc52xx_uart_driver, port);
+ if (port && level == RESUME_ENABLE)
+ uart_resume_port(&mpc52xx_uart_driver, port);
return 0;
}
#endif
-static struct ocp_device_id mpc52xx_uart_ids[] __devinitdata = {
- { .vendor = OCP_VENDOR_FREESCALE, .function = OCP_FUNC_PSC_UART },
- { .vendor = OCP_VENDOR_INVALID /* Terminating entry */ }
-};
-
-MODULE_DEVICE_TABLE(ocp, mpc52xx_uart_ids);
-
-static struct ocp_driver mpc52xx_uart_ocp_driver = {
- .name = "mpc52xx_psc_uart",
- .id_table = mpc52xx_uart_ids,
+static struct device_driver mpc52xx_uart_platform_driver = {
+ .name = "mpc52xx-psc",
+ .bus = &platform_bus_type,
.probe = mpc52xx_uart_probe,
.remove = mpc52xx_uart_remove,
#ifdef CONFIG_PM
@@ -845,10 +827,11 @@ mpc52xx_uart_init(void)
printk(KERN_INFO "Serial: MPC52xx PSC driver\n");
ret = uart_register_driver(&mpc52xx_uart_driver);
- if (ret)
- return ret;
-
- ret = ocp_register_driver(&mpc52xx_uart_ocp_driver);
+ if (ret == 0) {
+ ret = driver_register(&mpc52xx_uart_platform_driver);
+ if (ret)
+ uart_unregister_driver(&mpc52xx_uart_driver);
+ }
return ret;
}
@@ -856,7 +839,7 @@ mpc52xx_uart_init(void)
static void __exit
mpc52xx_uart_exit(void)
{
- ocp_unregister_driver(&mpc52xx_uart_ocp_driver);
+ driver_unregister(&mpc52xx_uart_platform_driver);
uart_unregister_driver(&mpc52xx_uart_driver);
}
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index f250c8a7dd756..a61d4433a989f 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -50,8 +50,8 @@ obj-$(CONFIG_USB_KAWETH) += net/
obj-$(CONFIG_USB_PEGASUS) += net/
obj-$(CONFIG_USB_RTL8150) += net/
obj-$(CONFIG_USB_USBNET) += net/
+obj-$(CONFIG_USB_ZD1201) += net/
-obj-$(CONFIG_USB_HPUSBSCSI) += image/
obj-$(CONFIG_USB_MDC800) += image/
obj-$(CONFIG_USB_MICROTEK) += image/
diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
index b5f85504cf559..5f8af35e76330 100644
--- a/drivers/usb/class/usb-midi.c
+++ b/drivers/usb/class/usb-midi.c
@@ -992,7 +992,7 @@ static struct midi_in_endpoint *alloc_midi_in_endpoint( struct usb_device *d, in
endPoint &= 0x0f; /* Silently force endPoint to lie in range 0 to 15. */
pipe = usb_rcvbulkpipe( d, endPoint );
- bufSize = usb_maxpacket( d, pipe, usb_pipein(pipe) );
+ bufSize = usb_maxpacket( d, pipe, 0 );
/* usb_pipein() = ! usb_pipeout() = true for an in Endpoint */
ep = (struct midi_in_endpoint *)kmalloc(sizeof(struct midi_in_endpoint), GFP_KERNEL);
@@ -1063,7 +1063,7 @@ static struct midi_out_endpoint *alloc_midi_out_endpoint( struct usb_device *d,
endPoint &= 0x0f;
pipe = usb_sndbulkpipe( d, endPoint );
- bufSize = usb_maxpacket( d, pipe, usb_pipeout(pipe) );
+ bufSize = usb_maxpacket( d, pipe, 1 );
ep = (struct midi_out_endpoint *)kmalloc(sizeof(struct midi_out_endpoint), GFP_KERNEL);
if ( !ep ) {
@@ -1451,8 +1451,6 @@ static struct usb_midi_device *parse_descriptor( struct usb_device *d, unsigned
} else {
if ( oep < 15 ) {
pins = oep+1;
- if ( pins > 16 )
- pins = 16;
u->out[oep].endpoint = p1[2];
u->out[oep].cableId = ( 1 << pins ) - 1;
if ( u->out[oep].cableId )
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 1e2a42ad34a40..b7827df21f486 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -76,7 +76,6 @@ int hcd_buffer_create (struct usb_hcd *hcd)
}
return 0;
}
-EXPORT_SYMBOL (hcd_buffer_create);
/**
@@ -98,7 +97,6 @@ void hcd_buffer_destroy (struct usb_hcd *hcd)
}
}
}
-EXPORT_SYMBOL (hcd_buffer_destroy);
/* sometimes alloc/free could use kmalloc with SLAB_DMA, for
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 837bad1324490..0b092bdf98f39 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -221,7 +221,7 @@ skip_to_next_interface_descriptor:
return buffer - buffer0 + i;
}
-int usb_parse_configuration(struct device *ddev, int cfgidx,
+static int usb_parse_configuration(struct device *ddev, int cfgidx,
struct usb_host_config *config, unsigned char *buffer, int size)
{
unsigned char *buffer0 = buffer;
@@ -420,8 +420,8 @@ void usb_destroy_configuration(struct usb_device *dev)
for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
struct usb_host_config *cf = &dev->config[c];
- if (cf->string)
- kfree(cf->string);
+ kfree(cf->string);
+ cf->string = NULL;
for (i = 0; i < cf->desc.bNumInterfaces; i++) {
if (cf->intf_cache[i])
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index c9b0fc8d1a6e5..8b61bcd742cac 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -460,7 +460,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
return 0;
if (level > MAX_TOPO_LEVEL)
- return total_written;
+ return 0;
/* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */
if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1)))
return -ENOMEM;
@@ -527,10 +527,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
length = *nbytes;
if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) {
free_pages((unsigned long)pages_start, 1);
-
- if (total_written == 0)
- return -EFAULT;
- return total_written;
+ return -EFAULT;
}
*nbytes -= length;
*file_offset += length;
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index efc6f47fbceff..b9a3dae070363 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -226,8 +226,8 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
/* entry if root hub wasn't yet suspended ... from sysfs,
* without autosuspend, or if USB_SUSPEND isn't configured.
*/
- case USB_STATE_RUNNING:
- hcd->state = USB_STATE_QUIESCING;
+ case HC_STATE_RUNNING:
+ hcd->state = HC_STATE_QUIESCING;
retval = hcd->driver->suspend (hcd, state);
if (retval) {
dev_dbg (hcd->self.controller,
@@ -235,7 +235,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
retval);
break;
}
- hcd->state = HCD_STATE_SUSPENDED;
+ hcd->state = HC_STATE_SUSPENDED;
/* FALLTHROUGH */
/* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the
@@ -245,7 +245,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
* FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will
* have been called, otherwise root hub timers still run ...
*/
- case HCD_STATE_SUSPENDED:
+ case HC_STATE_SUSPENDED:
if (state <= dev->current_state)
break;
@@ -311,7 +311,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
int has_pci_pm;
hcd = pci_get_drvdata(dev);
- if (hcd->state != HCD_STATE_SUSPENDED) {
+ if (hcd->state != HC_STATE_SUSPENDED) {
dev_dbg (hcd->self.controller,
"can't resume, not suspended!\n");
return 0;
@@ -323,7 +323,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
pci_state(dev->current_state),
has_pci_pm ? "" : " (legacy)");
- hcd->state = USB_STATE_RESUMING;
+ hcd->state = HC_STATE_RESUMING;
if (has_pci_pm)
pci_set_power_state (dev, 0);
@@ -343,7 +343,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
#endif
retval = hcd->driver->resume (hcd);
- if (!HCD_IS_RUNNING (hcd->state)) {
+ if (!HC_IS_RUNNING (hcd->state)) {
dev_dbg (hcd->self.controller,
"resume fail, retval %d\n", retval);
usb_hc_died (hcd);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 824a0e496ab02..266e9e06a9f50 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -101,6 +101,9 @@ static struct usb_busmap busmap;
DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */
EXPORT_SYMBOL_GPL (usb_bus_list_lock);
+/* used for controlling access to virtual root hubs */
+static DEFINE_SPINLOCK(hcd_root_hub_lock);
+
/* used when updating hcd data */
static DEFINE_SPINLOCK(hcd_data_lock);
@@ -455,7 +458,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
default:
/* non-generic request */
- if (HCD_IS_SUSPENDED (hcd->state))
+ if (HC_IS_SUSPENDED (hcd->state))
status = -EAGAIN;
else {
switch (typeReq) {
@@ -701,7 +704,7 @@ void usb_host_cleanup(void)
* This code is used to initialize a usb_bus structure, memory for which is
* separately managed.
*/
-void usb_bus_init (struct usb_bus *bus)
+static void usb_bus_init (struct usb_bus *bus)
{
memset (&bus->devmap, 0, sizeof(struct usb_devmap));
@@ -719,7 +722,6 @@ void usb_bus_init (struct usb_bus *bus)
class_device_initialize(&bus->class_dev);
bus->class_dev.class = &usb_host_class;
}
-EXPORT_SYMBOL (usb_bus_init);
/**
* usb_alloc_bus - creates a new USB host controller structure
@@ -745,7 +747,6 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op)
bus->op = op;
return bus;
}
-EXPORT_SYMBOL (usb_alloc_bus);
/*-------------------------------------------------------------------------*/
@@ -757,7 +758,7 @@ EXPORT_SYMBOL (usb_alloc_bus);
* Assigns a bus number, and links the controller into usbcore data
* structures so that it can be seen by scanning the bus list.
*/
-int usb_register_bus(struct usb_bus *bus)
+static int usb_register_bus(struct usb_bus *bus)
{
int busnum;
int retval;
@@ -792,7 +793,6 @@ int usb_register_bus(struct usb_bus *bus)
dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
return 0;
}
-EXPORT_SYMBOL (usb_register_bus);
/**
* usb_deregister_bus - deregisters the USB host controller
@@ -802,7 +802,7 @@ EXPORT_SYMBOL (usb_register_bus);
* Recycles the bus number, and unlinks the controller from usbcore data
* structures so that it won't be seen by scanning the bus list.
*/
-void usb_deregister_bus (struct usb_bus *bus)
+static void usb_deregister_bus (struct usb_bus *bus)
{
dev_info (bus->controller, "USB bus %d deregistered\n", bus->busnum);
@@ -822,12 +822,11 @@ void usb_deregister_bus (struct usb_bus *bus)
class_device_del(&bus->class_dev);
}
-EXPORT_SYMBOL (usb_deregister_bus);
/**
- * usb_register_root_hub - called by HCD to register its root hub
+ * usb_hcd_register_root_hub - called by HCD to register its root hub
* @usb_dev: the usb root hub device to be registered.
- * @parent_dev: the parent device of this root hub.
+ * @hcd: host controller for this root hub
*
* The USB host controller calls this function to register the root hub
* properly with the USB subsystem. It sets up the device properly in
@@ -835,11 +834,20 @@ EXPORT_SYMBOL (usb_deregister_bus);
* then calls usb_new_device() to register the usb device. It also
* assigns the root hub's USB address (always 1).
*/
-int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
+int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd)
{
+ struct device *parent_dev = hcd->self.controller;
const int devnum = 1;
int retval;
+ /* hcd->driver->start() reported can_wakeup, probably with
+ * assistance from board's boot firmware.
+ * NOTE: normal devices won't enable wakeup by default.
+ */
+ if (hcd->can_wakeup)
+ dev_dbg (parent_dev, "supports USB remote wakeup\n");
+ hcd->remote_wakeup = hcd->can_wakeup;
+
usb_dev->devnum = devnum;
usb_dev->bus->devnum_next = devnum + 1;
memset (&usb_dev->bus->devmap.devicemap, 0,
@@ -869,9 +877,20 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
usb_dev->dev.bus_id, retval);
}
up (&usb_bus_list_lock);
+
+ if (retval == 0) {
+ spin_lock_irq (&hcd_root_hub_lock);
+ hcd->rh_registered = 1;
+ spin_unlock_irq (&hcd_root_hub_lock);
+
+ /* Did the HC die before the root hub was registered? */
+ if (hcd->state == HC_STATE_HALT)
+ usb_hc_died (hcd); /* This time clean up */
+ }
+
return retval;
}
-EXPORT_SYMBOL (usb_register_root_hub);
+EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub);
/*-------------------------------------------------------------------------*/
@@ -1112,8 +1131,8 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
else if (unlikely (urb->reject))
status = -EPERM;
else switch (hcd->state) {
- case USB_STATE_RUNNING:
- case USB_STATE_RESUMING:
+ case HC_STATE_RUNNING:
+ case HC_STATE_RESUMING:
usb_get_dev (urb->dev);
list_add_tail (&urb->urb_list, &ep->urb_list);
status = 0;
@@ -1187,7 +1206,7 @@ done:
static int hcd_get_frame_number (struct usb_device *udev)
{
struct usb_hcd *hcd = (struct usb_hcd *)udev->bus->hcpriv;
- if (!HCD_IS_RUNNING (hcd->state))
+ if (!HC_IS_RUNNING (hcd->state))
return -ESHUTDOWN;
return hcd->driver->get_frame_number (hcd);
}
@@ -1269,7 +1288,7 @@ static int hcd_unlink_urb (struct urb *urb, int status)
* halted ~= no unlink handshake is needed
* suspended, resuming == should never happen
*/
- WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
+ WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);
/* insist the urb is still queued */
list_for_each(tmp, &ep->urb_list) {
@@ -1336,7 +1355,7 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
hcd = udev->bus->hcpriv;
- WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
+ WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);
local_irq_disable ();
@@ -1423,7 +1442,31 @@ static int hcd_hub_resume (struct usb_bus *bus)
return 0;
}
+/**
+ * usb_hcd_resume_root_hub - called by HCD to resume its root hub
+ * @hcd: host controller for this root hub
+ *
+ * The USB host controller calls this function when its root hub is
+ * suspended (with the remote wakeup feature enabled) and a remote
+ * wakeup request is received. It queues a request for khubd to
+ * resume the root hub.
+ */
+void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave (&hcd_root_hub_lock, flags);
+ if (hcd->rh_registered)
+ usb_resume_root_hub (hcd->self.root_hub);
+ spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+}
+
+#else
+void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+{
+}
#endif
+EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
/*-------------------------------------------------------------------------*/
@@ -1547,17 +1590,16 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
struct usb_hcd *hcd = __hcd;
int start = hcd->state;
- if (start == USB_STATE_HALT)
+ if (start == HC_STATE_HALT)
return IRQ_NONE;
if (hcd->driver->irq (hcd, r) == IRQ_NONE)
return IRQ_NONE;
hcd->saw_irq = 1;
- if (hcd->state != start && hcd->state == USB_STATE_HALT)
+ if (hcd->state != start && hcd->state == HC_STATE_HALT)
usb_hc_died (hcd);
return IRQ_HANDLED;
}
-EXPORT_SYMBOL (usb_hcd_irq);
/*-------------------------------------------------------------------------*/
@@ -1571,12 +1613,21 @@ EXPORT_SYMBOL (usb_hcd_irq);
*/
void usb_hc_died (struct usb_hcd *hcd)
{
+ unsigned long flags;
+
dev_err (hcd->self.controller, "HC died; cleaning up\n");
- /* make khubd clean up old urbs and devices */
- usb_set_device_state(hcd->self.root_hub, USB_STATE_NOTATTACHED);
- mod_timer(&hcd->rh_timer, jiffies);
+ spin_lock_irqsave (&hcd_root_hub_lock, flags);
+ if (hcd->rh_registered) {
+
+ /* make khubd clean up old urbs and devices */
+ usb_set_device_state (hcd->self.root_hub,
+ USB_STATE_NOTATTACHED);
+ usb_kick_khubd (hcd->self.root_hub);
+ }
+ spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
}
+EXPORT_SYMBOL_GPL (usb_hc_died);
/*-------------------------------------------------------------------------*/
@@ -1688,13 +1739,15 @@ int usb_add_hcd(struct usb_hcd *hcd,
hcd->irq = irqnum;
dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp,
(hcd->driver->flags & HCD_MEMORY) ?
- "io mem" : "io base", hcd->rsrc_start);
+ "io mem" : "io base",
+ (unsigned long long)hcd->rsrc_start);
} else {
hcd->irq = -1;
if (hcd->rsrc_start)
dev_info(hcd->self.controller, "%s 0x%08llx\n",
(hcd->driver->flags & HCD_MEMORY) ?
- "io mem" : "io base", hcd->rsrc_start);
+ "io mem" : "io base",
+ (unsigned long long)hcd->rsrc_start);
}
if ((retval = hcd->driver->start(hcd)) < 0) {
@@ -1727,14 +1780,17 @@ void usb_remove_hcd(struct usb_hcd *hcd)
{
dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
- if (HCD_IS_RUNNING (hcd->state))
- hcd->state = USB_STATE_QUIESCING;
+ if (HC_IS_RUNNING (hcd->state))
+ hcd->state = HC_STATE_QUIESCING;
dev_dbg(hcd->self.controller, "roothub graceful disconnect\n");
+ spin_lock_irq (&hcd_root_hub_lock);
+ hcd->rh_registered = 0;
+ spin_unlock_irq (&hcd_root_hub_lock);
usb_disconnect(&hcd->self.root_hub);
hcd->driver->stop(hcd);
- hcd->state = USB_STATE_HALT;
+ hcd->state = HC_STATE_HALT;
if (hcd->irq >= 0)
free_irq(hcd->irq, hcd);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 44fac434e19e4..6c625b35fa0c9 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -74,6 +74,8 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
unsigned saw_irq : 1;
unsigned can_wakeup:1; /* hw supports wakeup? */
unsigned remote_wakeup:1;/* sw should use wakeup? */
+ unsigned rh_registered:1;/* is root hub registered? */
+
int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */
u64 rsrc_start; /* memory/io resource start */
@@ -87,14 +89,14 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
# define __SUSPEND 0x04
# define __TRANSIENT 0x80
-# define USB_STATE_HALT 0
-# define USB_STATE_RUNNING (__ACTIVE)
-# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
-# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT)
-# define HCD_STATE_SUSPENDED (__SUSPEND)
+# define HC_STATE_HALT 0
+# define HC_STATE_RUNNING (__ACTIVE)
+# define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
+# define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT)
+# define HC_STATE_SUSPENDED (__SUSPEND)
-#define HCD_IS_RUNNING(state) ((state) & __ACTIVE)
-#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
+#define HC_IS_RUNNING(state) ((state) & __ACTIVE)
+#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
/* more shared queuing code would be good; it should support
* smarter scheduling, handle transaction translators, etc;
@@ -208,7 +210,6 @@ struct hc_driver {
};
extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
-extern void usb_bus_init (struct usb_bus *bus);
extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
struct device *dev, char *bus_name);
@@ -340,25 +341,10 @@ extern long usb_calc_bus_time (int speed, int is_input,
extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
-extern int usb_register_bus (struct usb_bus *);
-extern void usb_deregister_bus (struct usb_bus *);
-
-extern int usb_register_root_hub (struct usb_device *usb_dev,
- struct device *parent_dev);
-
-static inline int hcd_register_root (struct usb_device *usb_dev,
- struct usb_hcd *hcd)
-{
- /* hcd->driver->start() reported can_wakeup, probably with
- * assistance from board's boot firmware.
- * NOTE: normal devices won't enable wakeup by default.
- */
- if (hcd->can_wakeup)
- dev_dbg (hcd->self.controller, "supports USB remote wakeup\n");
- hcd->remote_wakeup = hcd->can_wakeup;
+extern int usb_hcd_register_root_hub (struct usb_device *usb_dev,
+ struct usb_hcd *hcd);
- return usb_register_root_hub (usb_dev, hcd->self.controller);
-}
+extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
extern void usb_set_device_state(struct usb_device *udev,
enum usb_device_state new_state);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 90a45935da7e8..fa0dc4f6de473 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -289,6 +289,11 @@ static void kick_khubd(struct usb_hub *hub)
spin_unlock_irqrestore(&hub_event_lock, flags);
}
+void usb_kick_khubd(struct usb_device *hdev)
+{
+ kick_khubd(hdev_to_hub(hdev));
+}
+
/* completion function, fires on port status changes and various faults */
static void hub_irq(struct urb *urb, struct pt_regs *regs)
@@ -1383,8 +1388,13 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
dev_err(hub->intfdev,
"cannot reset port %d (err = %d)\n",
port1, status);
- else
+ else {
status = hub_port_wait_reset(hub, port1, udev, delay);
+ if (status)
+ dev_dbg(hub->intfdev,
+ "port_wait_reset: err = %d\n",
+ status);
+ }
/* return on disconnect or reset */
switch (status) {
@@ -1533,7 +1543,8 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
* Linux (2.6) currently has NO mechanisms to initiate that: no khubd
* timer, no SRP, no requests through sysfs.
*/
-int __usb_suspend_device (struct usb_device *udev, int port1, pm_message_t state)
+static int __usb_suspend_device (struct usb_device *udev, int port1,
+ pm_message_t state)
{
int status;
@@ -1614,9 +1625,11 @@ int __usb_suspend_device (struct usb_device *udev, int port1, pm_message_t state
struct usb_bus *bus = udev->bus;
if (bus && bus->op->hub_suspend) {
status = bus->op->hub_suspend (bus);
- if (status == 0)
+ if (status == 0) {
+ dev_dbg(&udev->dev, "usb suspend\n");
usb_set_device_state(udev,
USB_STATE_SUSPENDED);
+ }
} else
status = -EOPNOTSUPP;
} else
@@ -1646,7 +1659,7 @@ int __usb_suspend_device (struct usb_device *udev, int port1, pm_message_t state
*
* Returns 0 on success, else negative errno.
*/
-int usb_suspend_device(struct usb_device *udev, u32 state)
+int usb_suspend_device(struct usb_device *udev, pm_message_t state)
{
int port1, status;
@@ -1834,9 +1847,11 @@ int usb_resume_device(struct usb_device *udev)
} else
status = -EOPNOTSUPP;
if (status == 0) {
+ dev_dbg(&udev->dev, "usb resume\n");
/* TRSMRCY = 10 msec */
msleep(10);
usb_set_device_state (udev, USB_STATE_CONFIGURED);
+ udev->dev.power.power_state = PMSG_ON;
status = hub_resume (udev
->actconfig->interface[0]);
}
@@ -1955,13 +1970,22 @@ static int hub_resume(struct usb_interface *intf)
}
intf->dev.power.power_state = PMSG_ON;
+ hub->resume_root_hub = 0;
hub_activate(hub);
return 0;
}
+void usb_resume_root_hub(struct usb_device *hdev)
+{
+ struct usb_hub *hub = hdev_to_hub(hdev);
+
+ hub->resume_root_hub = 1;
+ kick_khubd(hub);
+}
+
#else /* !CONFIG_USB_SUSPEND */
-int usb_suspend_device(struct usb_device *udev, u32 state)
+int usb_suspend_device(struct usb_device *udev, pm_message_t state)
{
return 0;
}
@@ -2615,15 +2639,30 @@ static void hub_events(void)
(u16) hub->event_bits[0]);
usb_get_intf(intf);
+ i = hub->resume_root_hub;
spin_unlock_irq(&hub_event_lock);
+ /* Is this is a root hub wanting to be resumed? */
+ if (i)
+ usb_resume_device(hdev);
+
/* Lock the device, then check to see if we were
* disconnected while waiting for the lock to succeed. */
if (locktree(hdev) < 0) {
usb_put_intf(intf);
continue;
}
- if (hub != usb_get_intfdata(intf) || hub->quiescing)
+ if (hub != usb_get_intfdata(intf))
+ goto loop;
+
+ /* If the hub has died, clean up after it */
+ if (hdev->state == USB_STATE_NOTATTACHED) {
+ hub_pre_reset(hub);
+ goto loop;
+ }
+
+ /* If this is an inactive or suspended hub, do nothing */
+ if (hub->quiescing)
goto loop;
if (hub->error) {
@@ -2643,6 +2682,8 @@ static void hub_events(void)
/* deal with port status changes */
for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
+ if (test_bit(i, hub->busy_bits))
+ continue;
connect_change = test_bit(i, hub->change_bits);
if (!test_and_clear_bit(i, hub->event_bits) &&
!connect_change && !hub->activating)
@@ -2948,6 +2989,7 @@ int usb_reset_device(struct usb_device *udev)
hub_pre_reset(hub);
}
+ set_bit(port1, parent_hub->busy_bits);
for (i = 0; i < SET_CONFIG_TRIES; ++i) {
/* ep0 maxpacket size may change; let the HCD know about it.
@@ -2957,6 +2999,7 @@ int usb_reset_device(struct usb_device *udev)
if (ret >= 0)
break;
}
+ clear_bit(port1, parent_hub->busy_bits);
if (ret < 0)
goto re_enumerate;
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 265ab9d7c7446..d114b847d56f8 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -205,6 +205,7 @@ struct usb_hub {
unsigned long event_bits[1]; /* status change bitmask */
unsigned long change_bits[1]; /* ports with logical connect
status change */
+ unsigned long busy_bits[1]; /* ports being reset */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#endif
@@ -216,6 +217,7 @@ struct usb_hub {
unsigned quiescing:1;
unsigned activating:1;
+ unsigned resume_root_hub:1;
unsigned has_indicators:1;
enum hub_led_mode indicator[USB_MAXCHILDREN];
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index b4624501cd582..40bdb38e7bcba 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -90,8 +90,10 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
/*-------------------------------------------------------------------*/
// returns status (negative) or length (positive)
-int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
- struct usb_ctrlrequest *cmd, void *data, int len, int timeout)
+static int usb_internal_control_msg(struct usb_device *usb_dev,
+ unsigned int pipe,
+ struct usb_ctrlrequest *cmd,
+ void *data, int len, int timeout)
{
struct urb *urb;
int retv;
@@ -1041,8 +1043,8 @@ usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
*
* Enables all the endpoints for the interface's current altsetting.
*/
-void usb_enable_interface(struct usb_device *dev,
- struct usb_interface *intf)
+static void usb_enable_interface(struct usb_device *dev,
+ struct usb_interface *intf)
{
struct usb_host_interface *alt = intf->cur_altsetting;
int i;
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 9fd8b495427f1..f0534ee064901 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -60,7 +60,7 @@ extern void usb_host_cleanup(void);
const char *usbcore_name = "usbcore";
-int nousb; /* Disable USB when built into kernel image */
+static int nousb; /* Disable USB when built into kernel image */
/* Not honored on modular build */
static DECLARE_RWSEM(usb_all_devices_rwsem);
@@ -86,7 +86,7 @@ static struct device_driver usb_generic_driver = {
static int usb_generic_driver_data;
/* called from driver core with usb_bus_type.subsys writelock */
-int usb_probe_interface(struct device *dev)
+static int usb_probe_interface(struct device *dev)
{
struct usb_interface * intf = to_usb_interface(dev);
struct usb_driver * driver = to_usb_driver(dev->driver);
@@ -114,7 +114,7 @@ int usb_probe_interface(struct device *dev)
}
/* called from driver core with usb_bus_type.subsys writelock */
-int usb_unbind_interface(struct device *dev)
+static int usb_unbind_interface(struct device *dev)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_driver *driver = to_usb_driver(intf->dev.driver);
@@ -615,6 +615,33 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
alt->desc.bInterfaceSubClass,
alt->desc.bInterfaceProtocol))
return -ENOMEM;
+
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=usb:v%04Xp%04Xdl%04Xdh%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice),
+ usb_dev->descriptor.bDeviceClass,
+ usb_dev->descriptor.bDeviceSubClass,
+ usb_dev->descriptor.bDeviceProtocol,
+ alt->desc.bInterfaceClass,
+ alt->desc.bInterfaceSubClass,
+ alt->desc.bInterfaceProtocol))
+ return -ENOMEM;
+ } else {
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=usb:v%04Xp%04Xdl%04Xdh%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice),
+ usb_dev->descriptor.bDeviceClass,
+ usb_dev->descriptor.bDeviceSubClass,
+ usb_dev->descriptor.bDeviceProtocol))
+ return -ENOMEM;
}
envp[i] = NULL;
@@ -1148,6 +1175,7 @@ void usb_buffer_free (
*
* Reverse the effect of this call with usb_buffer_unmap().
*/
+#if 0
struct urb *usb_buffer_map (struct urb *urb)
{
struct usb_bus *bus;
@@ -1177,6 +1205,7 @@ struct urb *usb_buffer_map (struct urb *urb)
| URB_NO_SETUP_DMA_MAP);
return urb;
}
+#endif /* 0 */
/* XXX DISABLED, no users currently. If you wish to re-enable this
* XXX please determine whether the sync is to transfer ownership of
@@ -1221,6 +1250,7 @@ void usb_buffer_dmasync (struct urb *urb)
*
* Reverses the effect of usb_buffer_map().
*/
+#if 0
void usb_buffer_unmap (struct urb *urb)
{
struct usb_bus *bus;
@@ -1247,6 +1277,7 @@ void usb_buffer_unmap (struct urb *urb)
urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP
| URB_NO_SETUP_DMA_MAP);
}
+#endif /* 0 */
/**
* usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
@@ -1527,11 +1558,11 @@ EXPORT_SYMBOL(usb_get_current_frame_number);
EXPORT_SYMBOL (usb_buffer_alloc);
EXPORT_SYMBOL (usb_buffer_free);
-EXPORT_SYMBOL (usb_buffer_map);
#if 0
+EXPORT_SYMBOL (usb_buffer_map);
EXPORT_SYMBOL (usb_buffer_dmasync);
-#endif
EXPORT_SYMBOL (usb_buffer_unmap);
+#endif
EXPORT_SYMBOL (usb_buffer_map_sg);
#if 0
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 5b95a53babdd4..4c33eee520011 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -4,8 +4,6 @@ extern void usb_create_sysfs_dev_files (struct usb_device *dev);
extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
extern void usb_create_sysfs_intf_files (struct usb_interface *intf);
extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
-extern int usb_probe_interface (struct device *dev);
-extern int usb_unbind_interface (struct device *dev);
extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
extern void usb_disable_interface (struct usb_device *dev,
@@ -13,9 +11,6 @@ extern void usb_disable_interface (struct usb_device *dev,
extern void usb_release_interface_cache(struct kref *ref);
extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
-extern void usb_enable_interface (struct usb_device *dev,
- struct usb_interface *intf);
-
extern int usb_get_device_descriptor(struct usb_device *dev,
unsigned int size);
extern int usb_set_configuration(struct usb_device *dev, int configuration);
@@ -23,6 +18,9 @@ extern int usb_set_configuration(struct usb_device *dev, int configuration);
extern void usb_lock_all_devices(void);
extern void usb_unlock_all_devices(void);
+extern void usb_kick_khubd(struct usb_device *dev);
+extern void usb_resume_root_hub(struct usb_device *dev);
+
/* for labeling diagnostics */
extern const char *usbcore_name;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 8b2c34ea98eec..3b24f9f2c2341 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -135,21 +135,6 @@ config USB_GOKU
depends on USB_GADGET_GOKU
default USB_GADGET
-# this could be built elsewhere (doesn't yet exist)
-config USB_GADGET_SA1100
- boolean "SA 1100"
- depends on ARCH_SA1100
- help
- Intel's SA-1100 is an ARM-4 processor with an integrated
- full speed USB 1.1 device controller.
-
- It has two fixed-function endpoints, as well as endpoint
- zero (for control transfers).
-
-config USB_SA1100
- tristate
- depends on USB_GADGET_SA1100
- default USB_GADGET
config USB_GADGET_LH7A40X
boolean "LH7A40X"
@@ -163,34 +148,6 @@ config USB_LH7A40X
default USB_GADGET
-config USB_GADGET_DUMMY_HCD
- boolean "Dummy HCD (DEVELOPMENT)"
- depends on USB && EXPERIMENTAL
- select USB_GADGET_DUALSPEED
- help
- This host controller driver emulates USB, looping all data transfer
- requests back to a USB "gadget driver" in the same host. The host
- side is the master; the gadget side is the slave. Gadget drivers
- can be high, full, or low speed; and they have access to endpoints
- like those from NET2280, PXA2xx, or SA1100 hardware.
-
- This may help in some stages of creating a driver to embed in a
- Linux device, since it lets you debug several parts of the gadget
- driver without its hardware or drivers being involved.
-
- Since such a gadget side driver needs to interoperate with a host
- side Linux-USB device driver, this may help to debug both sides
- of a USB protocol stack.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "dummy_hcd" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_DUMMY_HCD
- tristate
- depends on USB_GADGET_DUMMY_HCD
- default USB_GADGET
-
config USB_GADGET_OMAP
boolean "OMAP USB Device Controller"
depends on ARCH_OMAP
@@ -222,6 +179,38 @@ config USB_OTG
Select this only if your OMAP board has a Mini-AB connector.
+
+config USB_GADGET_DUMMY_HCD
+ boolean "Dummy HCD (DEVELOPMENT)"
+ depends on USB && EXPERIMENTAL
+ select USB_GADGET_DUALSPEED
+ help
+ This host controller driver emulates USB, looping all data transfer
+ requests back to a USB "gadget driver" in the same host. The host
+ side is the master; the gadget side is the slave. Gadget drivers
+ can be high, full, or low speed; and they have access to endpoints
+ like those from NET2280, PXA2xx, or SA1100 hardware.
+
+ This may help in some stages of creating a driver to embed in a
+ Linux device, since it lets you debug several parts of the gadget
+ driver without its hardware or drivers being involved.
+
+ Since such a gadget side driver needs to interoperate with a host
+ side Linux-USB device driver, this may help to debug both sides
+ of a USB protocol stack.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "dummy_hcd" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_DUMMY_HCD
+ tristate
+ depends on USB_GADGET_DUMMY_HCD
+ default USB_GADGET
+
+# NOTE: Please keep dummy_hcd LAST so that "real hardware" appears
+# first and will be selected by default.
+
endchoice
config USB_GADGET_DUALSPEED
@@ -355,8 +344,6 @@ config USB_GADGETFS
config USB_FILE_STORAGE
tristate "File-backed Storage Gadget"
- # we don't support the SA1100 because of its limitations
- depends on USB_GADGET_SA1100 = n
help
The File-backed Storage Gadget acts as a USB Mass Storage
disk drive. As its storage repository it can use a regular
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index 531909242b247..83b4866df9af0 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -25,6 +25,7 @@
#include <linux/device.h>
#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
/**
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 50832010b4ef6..8ef8a9cd9ac4f 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -1647,11 +1647,11 @@ static int dummy_start (struct usb_hcd *hcd)
return -ENOMEM;
/* root hub enters addressed state... */
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
root->speed = USB_SPEED_HIGH;
/* ...then configured, so khubd sees us. */
- if ((retval = hcd_register_root (root, hcd)) != 0) {
+ if ((retval = usb_hcd_register_root_hub (root, hcd)) != 0) {
goto err1;
}
@@ -1669,7 +1669,7 @@ static int dummy_start (struct usb_hcd *hcd)
usb_disconnect (&hcd->self.root_hub);
err1:
usb_put_dev (root);
- hcd->state = USB_STATE_QUIESCING;
+ hcd->state = HC_STATE_QUIESCING;
return retval;
}
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index cb70fcd143297..cff9fb0b73cc0 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1,7 +1,7 @@
/*
* ether.c -- Ethernet gadget driver, with CDC and non-CDC options
*
- * Copyright (C) 2003-2004 David Brownell
+ * Copyright (C) 2003-2005 David Brownell
* Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
*
* This program is free software; you can redistribute it and/or modify
@@ -98,12 +98,18 @@ static const char driver_desc [] = DRIVER_DESC;
#define rndis_exit() do{}while(0)
#endif
+/* CDC and RNDIS support the same host-chosen outgoing packet filters. */
+#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
+ |USB_CDC_PACKET_TYPE_DIRECTED)
+
+
/*-------------------------------------------------------------------------*/
struct eth_dev {
spinlock_t lock;
struct usb_gadget *gadget;
struct usb_request *req; /* for control responses */
+ struct usb_request *stat_req; /* for cdc & rndis status */
u8 config;
struct usb_ep *in_ep, *out_ep, *status_ep;
@@ -243,6 +249,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_CDC
#endif
+#ifdef CONFIG_USB_GADGET_AT91
+#define DEV_CONFIG_CDC
+#endif
+
/* For CDC-incapable hardware, choose the simple cdc subset.
* Anything that talks bulk (without notable bugs) can do this.
@@ -266,8 +276,39 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
/*-------------------------------------------------------------------------*/
+/* "main" config is either CDC, or its simple subset */
+static inline int is_cdc(struct eth_dev *dev)
+{
+#if !defined(DEV_CONFIG_SUBSET)
+ return 1; /* only cdc possible */
+#elif !defined (DEV_CONFIG_CDC)
+ return 0; /* only subset possible */
+#else
+ return dev->cdc; /* depends on what hardware we found */
+#endif
+}
+
+/* "secondary" RNDIS config may sometimes be activated */
+static inline int rndis_active(struct eth_dev *dev)
+{
+#ifdef CONFIG_USB_ETH_RNDIS
+ return dev->rndis;
+#else
+ return 0;
+#endif
+}
+
+#define subset_active(dev) (!is_cdc(dev) && !rndis_active(dev))
+#define cdc_active(dev) ( is_cdc(dev) && !rndis_active(dev))
+
+
+
#define DEFAULT_QLEN 2 /* double buffering by default */
+/* peak bulk transfer bits-per-second */
+#define HS_BPS (13 * 512 * 8 * 1000 * 8)
+#define FS_BPS (19 * 64 * 1 * 1000 * 8)
+
#ifdef CONFIG_USB_GADGET_DUALSPEED
static unsigned qmult = 5;
@@ -281,12 +322,12 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR);
/* also defer IRQs on highspeed TX */
#define TX_DELAY qmult
-#define BITRATE(g) ((g->speed == USB_SPEED_HIGH) ? 4800000 : 120000)
+#define BITRATE(g) (((g)->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS)
#else /* full speed (low speed doesn't do bulk) */
#define qlen(gadget) DEFAULT_QLEN
-#define BITRATE(g) (12000)
+#define BITRATE(g) FS_BPS
#endif
@@ -519,9 +560,8 @@ static const struct usb_cdc_ether_desc ether_desc = {
#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
/* include the status endpoint if we can, even where it's optional.
- * use small wMaxPacketSize, since many "interrupt" endpoints have
- * very small fifos and it's no big deal if CDC_NOTIFY_SPEED_CHANGE
- * takes two packets. also default to a big transfer interval, to
+ * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
+ * packet, to simplify cancelation; and a big transfer interval, to
* waste less bandwidth.
*
* some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
@@ -534,7 +574,7 @@ static const struct usb_cdc_ether_desc ether_desc = {
*/
#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT 8 /* 8 byte header + data */
+#define STATUS_BYTECOUNT 16 /* 8 byte header + data */
static struct usb_endpoint_descriptor
fs_status_desc = {
@@ -916,14 +956,12 @@ static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
if (strcmp (ep->name, EP_IN_NAME) == 0) {
d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);
ep->driver_data = dev;
- dev->in_ep = ep;
dev->in = d;
/* one endpoint just reads OUT packets */
} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc);
ep->driver_data = dev;
- dev->out_ep = ep;
dev->out = d;
/* optional status/notification endpoint */
@@ -937,7 +975,6 @@ static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
return result;
ep->driver_data = dev;
- dev->status_ep = ep;
dev->status = d;
}
return 0;
@@ -964,7 +1001,6 @@ static inline int ether_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
return result;
ep->driver_data = dev;
- dev->in_ep = ep;
dev->in = d;
/* one endpoint just reads OUT packets */
@@ -975,7 +1011,6 @@ static inline int ether_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
return result;
ep->driver_data = dev;
- dev->out_ep = ep;
dev->out = d;
}
@@ -1006,7 +1041,6 @@ set_ether_config (struct eth_dev *dev, int gfp_flags)
result = usb_ep_enable (ep, d);
if (result == 0) {
ep->driver_data = dev;
- dev->status_ep = ep;
dev->status = d;
continue;
}
@@ -1034,22 +1068,19 @@ set_ether_config (struct eth_dev *dev, int gfp_flags)
/* on error, disable any endpoints */
if (result < 0) {
#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
- if (dev->status_ep)
+ if (dev->status)
(void) usb_ep_disable (dev->status_ep);
#endif
- dev->status_ep = NULL;
dev->status = NULL;
#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
if (dev->rndis || !dev->cdc) {
- if (dev->in_ep)
+ if (dev->in)
(void) usb_ep_disable (dev->in_ep);
- if (dev->out_ep)
+ if (dev->out)
(void) usb_ep_disable (dev->out_ep);
}
#endif
- dev->in_ep = NULL;
dev->in = NULL;
- dev->out_ep = NULL;
dev->out = NULL;
} else
@@ -1089,7 +1120,7 @@ static void eth_reset_config (struct eth_dev *dev)
/* disable endpoints, forcing (synchronous) completion of
* pending i/o. then free the requests.
*/
- if (dev->in_ep) {
+ if (dev->in) {
usb_ep_disable (dev->in_ep);
while (likely (!list_empty (&dev->tx_reqs))) {
req = container_of (dev->tx_reqs.next,
@@ -1097,9 +1128,8 @@ static void eth_reset_config (struct eth_dev *dev)
list_del (&req->list);
usb_ep_free_request (dev->in_ep, req);
}
- dev->in_ep = NULL;
}
- if (dev->out_ep) {
+ if (dev->out) {
usb_ep_disable (dev->out_ep);
while (likely (!list_empty (&dev->rx_reqs))) {
req = container_of (dev->rx_reqs.next,
@@ -1107,12 +1137,10 @@ static void eth_reset_config (struct eth_dev *dev)
list_del (&req->list);
usb_ep_free_request (dev->out_ep, req);
}
- dev->out_ep = NULL;
}
- if (dev->status_ep) {
+ if (dev->status) {
usb_ep_disable (dev->status_ep);
- dev->status_ep = NULL;
}
dev->config = 0;
}
@@ -1213,28 +1241,22 @@ static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
event->wLength = __constant_cpu_to_le16 (8);
/* SPEED_CHANGE data is up/down speeds in bits/sec */
- data [0] = data [1] = cpu_to_le32(
- (dev->gadget->speed == USB_SPEED_HIGH)
- ? (13 * 512 * 8 * 1000 * 8)
- : (19 * 64 * 1 * 1000 * 8));
+ data [0] = data [1] = cpu_to_le32 (BITRATE (dev->gadget));
- req->length = 16;
+ req->length = STATUS_BYTECOUNT;
value = usb_ep_queue (ep, req, GFP_ATOMIC);
DEBUG (dev, "send SPEED_CHANGE --> %d\n", value);
if (value == 0)
return;
- } else
+ } else if (value != -ECONNRESET)
DEBUG (dev, "event %02x --> %d\n",
event->bNotificationType, value);
-
- /* free when done */
- usb_ep_free_buffer (ep, req->buf, req->dma, 16);
- usb_ep_free_request (ep, req);
+ event->bmRequestType = 0xff;
}
static void issue_start_status (struct eth_dev *dev)
{
- struct usb_request *req;
+ struct usb_request *req = dev->stat_req;
struct usb_cdc_notification *event;
int value;
@@ -1250,21 +1272,6 @@ static void issue_start_status (struct eth_dev *dev)
usb_ep_disable (dev->status_ep);
usb_ep_enable (dev->status_ep, dev->status);
- /* FIXME make these allocations static like dev->req */
- req = usb_ep_alloc_request (dev->status_ep, GFP_ATOMIC);
- if (req == 0) {
- DEBUG (dev, "status ENOMEM\n");
- return;
- }
- req->buf = usb_ep_alloc_buffer (dev->status_ep, 16,
- &dev->req->dma, GFP_ATOMIC);
- if (req->buf == 0) {
- DEBUG (dev, "status buf ENOMEM\n");
-free_req:
- usb_ep_free_request (dev->status_ep, req);
- return;
- }
-
/* 3.8.1 says to issue first NETWORK_CONNECTION, then
* a SPEED_CHANGE. could be useful in some configs.
*/
@@ -1275,15 +1282,11 @@ free_req:
event->wIndex = __constant_cpu_to_le16 (1);
event->wLength = 0;
- req->length = 8;
+ req->length = sizeof *event;
req->complete = eth_status_complete;
value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC);
- if (value < 0) {
+ if (value < 0)
DEBUG (dev, "status buf queue --> %d\n", value);
- usb_ep_free_buffer (dev->status_ep,
- req->buf, dev->req->dma, 16);
- goto free_req;
- }
}
#endif
@@ -1431,7 +1434,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case 0: /* control/master intf */
if (wValue != 0)
break;
- if (dev->status_ep) {
+ if (dev->status) {
usb_ep_disable (dev->status_ep);
usb_ep_enable (dev->status_ep, dev->status);
}
@@ -1450,8 +1453,9 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (wValue == 1) {
usb_ep_enable (dev->in_ep, dev->in);
usb_ep_enable (dev->out_ep, dev->out);
+ dev->cdc_filter = DEFAULT_FILTER;
netif_carrier_on (dev->net);
- if (dev->status_ep)
+ if (dev->status)
issue_start_status (dev);
if (netif_running (dev->net)) {
spin_unlock (&dev->lock);
@@ -1502,14 +1506,18 @@ done_set_intf:
|| wLength != 0
|| wIndex > 1)
break;
- DEBUG (dev, "NOP packet filter %04x\n", wValue);
- /* NOTE: table 62 has 5 filter bits to reduce traffic,
- * and we "must" support multicast and promiscuous.
- * this NOP implements a bad filter (always promisc)
- */
+ DEBUG (dev, "packet filter %02x\n", wValue);
dev->cdc_filter = wValue;
value = 0;
break;
+
+ /* and potentially:
+ * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
+ * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
+ * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
+ * case USB_CDC_GET_ETHERNET_STATISTIC:
+ */
+
#endif /* DEV_CONFIG_CDC */
#ifdef CONFIG_USB_ETH_RNDIS
@@ -1904,6 +1912,14 @@ static void tx_complete (struct usb_ep *ep, struct usb_request *req)
netif_wake_queue (dev->net);
}
+static inline int eth_is_promisc (struct eth_dev *dev)
+{
+ /* no filters for the CDC subset; always promisc */
+ if (subset_active (dev))
+ return 1;
+ return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
+}
+
static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
{
struct eth_dev *dev = netdev_priv(net);
@@ -1912,10 +1928,27 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
struct usb_request *req = NULL;
unsigned long flags;
- /* FIXME check dev->cdc_filter to decide whether to send this,
- * instead of acting as if USB_CDC_PACKET_TYPE_PROMISCUOUS were
- * always set. RNDIS has the same kind of outgoing filter.
- */
+ /* apply outgoing CDC or RNDIS filters */
+ if (!eth_is_promisc (dev)) {
+ u8 *dest = skb->data;
+
+ if (dest [0] & 0x01) {
+ u16 type;
+
+ /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
+ * SET_ETHERNET_MULTICAST_FILTERS requests
+ */
+ if (memcmp (dest, net->broadcast, ETH_ALEN) == 0)
+ type = USB_CDC_PACKET_TYPE_BROADCAST;
+ else
+ type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
+ if (!(dev->cdc_filter & type)) {
+ dev_kfree_skb_any (skb);
+ return 0;
+ }
+ }
+ /* ignores USB_CDC_PACKET_TYPE_DIRECTED */
+ }
spin_lock_irqsave (&dev->lock, flags);
req = container_of (dev->tx_reqs.next, struct usb_request, list);
@@ -2137,6 +2170,30 @@ static int eth_stop (struct net_device *net)
/*-------------------------------------------------------------------------*/
+static struct usb_request *eth_req_alloc (struct usb_ep *ep, unsigned size)
+{
+ struct usb_request *req;
+
+ req = usb_ep_alloc_request (ep, GFP_KERNEL);
+ if (!req)
+ return NULL;
+
+ req->buf = kmalloc (size, GFP_KERNEL);
+ if (!req->buf) {
+ usb_ep_free_request (ep, req);
+ req = NULL;
+ }
+ return req;
+}
+
+static void
+eth_req_free (struct usb_ep *ep, struct usb_request *req)
+{
+ kfree (req->buf);
+ usb_ep_free_request (ep, req);
+}
+
+
static void
eth_unbind (struct usb_gadget *gadget)
{
@@ -2150,12 +2207,13 @@ eth_unbind (struct usb_gadget *gadget)
/* we've already been disconnected ... no i/o is active */
if (dev->req) {
- usb_ep_free_buffer (gadget->ep0,
- dev->req->buf, dev->req->dma,
- USB_BUFSIZ);
- usb_ep_free_request (gadget->ep0, dev->req);
+ eth_req_free (gadget->ep0, dev->req);
dev->req = NULL;
}
+ if (dev->stat_req) {
+ eth_req_free (dev->status_ep, dev->stat_req);
+ dev->stat_req = NULL;
+ }
unregister_netdev (dev->net);
free_netdev(dev->net);
@@ -2201,7 +2259,7 @@ eth_bind (struct usb_gadget *gadget)
struct eth_dev *dev;
struct net_device *net;
u8 cdc = 1, zlp = 1, rndis = 1;
- struct usb_ep *ep;
+ struct usb_ep *in_ep, *out_ep, *status_ep = NULL;
int status = -ENOMEM;
/* these flags are only ever cleared; compiler take note */
@@ -2251,6 +2309,8 @@ eth_bind (struct usb_gadget *gadget)
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
} else if (gadget_is_s3c2410(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
+ } else if (gadget_is_at91(gadget)) {
+ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
} else {
/* can't assume CDC works. don't want to default to
* anything less functional on CDC-capable hardware,
@@ -2308,32 +2368,32 @@ eth_bind (struct usb_gadget *gadget)
/* all we really need is bulk IN/OUT */
usb_ep_autoconfig_reset (gadget);
- ep = usb_ep_autoconfig (gadget, &fs_source_desc);
- if (!ep) {
+ in_ep = usb_ep_autoconfig (gadget, &fs_source_desc);
+ if (!in_ep) {
autoconf_fail:
dev_err (&gadget->dev,
"can't autoconfigure on %s\n",
gadget->name);
return -ENODEV;
}
- EP_IN_NAME = ep->name;
- ep->driver_data = ep; /* claim */
+ EP_IN_NAME = in_ep->name;
+ in_ep->driver_data = in_ep; /* claim */
- ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
- if (!ep)
+ out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
+ if (!out_ep)
goto autoconf_fail;
- EP_OUT_NAME = ep->name;
- ep->driver_data = ep; /* claim */
+ EP_OUT_NAME = out_ep->name;
+ out_ep->driver_data = out_ep; /* claim */
#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
/* CDC Ethernet control interface doesn't require a status endpoint.
* Since some hosts expect one, try to allocate one anyway.
*/
if (cdc || rndis) {
- ep = usb_ep_autoconfig (gadget, &fs_status_desc);
- if (ep) {
- EP_STATUS_NAME = ep->name;
- ep->driver_data = ep; /* claim */
+ status_ep = usb_ep_autoconfig (gadget, &fs_status_desc);
+ if (status_ep) {
+ EP_STATUS_NAME = status_ep->name;
+ status_ep->driver_data = status_ep; /* claim */
} else if (rndis) {
dev_err (&gadget->dev,
"can't run RNDIS on %s\n",
@@ -2409,6 +2469,10 @@ autoconf_fail:
dev->cdc = cdc;
dev->zlp = zlp;
+ dev->in_ep = in_ep;
+ dev->out_ep = out_ep;
+ dev->status_ep = status_ep;
+
/* Module params for these addresses should come from ID proms.
* The host side address is used with CDC and RNDIS, and commonly
* ends up in a persistent config database.
@@ -2442,16 +2506,20 @@ autoconf_fail:
// set_multicast_list
SET_ETHTOOL_OPS(net, &ops);
- /* preallocate control response and buffer */
- dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
+ /* preallocate control message data and buffer */
+ dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ);
if (!dev->req)
goto fail;
dev->req->complete = eth_setup_complete;
- dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
- &dev->req->dma, GFP_KERNEL);
- if (!dev->req->buf) {
- usb_ep_free_request (gadget->ep0, dev->req);
- goto fail;
+
+ /* ... and maybe likewise for status transfer */
+ if (dev->status_ep) {
+ dev->stat_req = eth_req_alloc (dev->status_ep,
+ STATUS_BYTECOUNT);
+ if (!dev->stat_req) {
+ eth_req_free (gadget->ep0, dev->req);
+ goto fail;
+ }
}
/* finish hookup to lower layer ... */
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index ae82b80748aee..4857f0e4ef449 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1,7 +1,7 @@
/*
* file_storage.c -- File-backed USB Storage Gadget, for USB development
*
- * Copyright (C) 2003, 2004 Alan Stern
+ * Copyright (C) 2003-2005 Alan Stern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -832,6 +832,8 @@ static void inline put_be32(u8 *buf, u32 val)
#define STRING_MANUFACTURER 1
#define STRING_PRODUCT 2
#define STRING_SERIAL 3
+#define STRING_CONFIG 4
+#define STRING_INTERFACE 5
/* There is only one configuration. */
#define CONFIG_VALUE 1
@@ -863,6 +865,7 @@ config_desc = {
/* wTotalLength computed by usb_gadget_config_buf() */
.bNumInterfaces = 1,
.bConfigurationValue = CONFIG_VALUE,
+ .iConfiguration = STRING_CONFIG,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = 1, // self-powered
};
@@ -886,6 +889,7 @@ intf_desc = {
.bInterfaceClass = USB_CLASS_MASS_STORAGE,
.bInterfaceSubClass = USB_SC_SCSI, // Adjusted during fsg_bind()
.bInterfaceProtocol = USB_PR_BULK, // Adjusted during fsg_bind()
+ .iInterface = STRING_INTERFACE,
};
/* Three full-speed endpoint descriptors: bulk-in, bulk-out,
@@ -1009,7 +1013,7 @@ static const struct usb_descriptor_header *hs_function[] = {
/* The CBI specification limits the serial string to 12 uppercase hexadecimal
* characters. */
-static char manufacturer[50];
+static char manufacturer[64];
static char serial[13];
/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
@@ -1017,6 +1021,8 @@ static struct usb_string strings[] = {
{STRING_MANUFACTURER, manufacturer},
{STRING_PRODUCT, longname},
{STRING_SERIAL, serial},
+ {STRING_CONFIG, "Self-powered"},
+ {STRING_INTERFACE, "Mass Storage"},
{}
};
@@ -1270,6 +1276,8 @@ static int class_setup_req(struct fsg_dev *fsg,
{
struct usb_request *req = fsg->ep0req;
int value = -EOPNOTSUPP;
+ u16 w_index = ctrl->wIndex;
+ u16 w_length = ctrl->wLength;
if (!fsg->config)
return value;
@@ -1282,7 +1290,7 @@ static int class_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_OUT |
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break;
- if (ctrl->wIndex != 0) {
+ if (w_index != 0) {
value = -EDOM;
break;
}
@@ -1298,13 +1306,13 @@ static int class_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_IN |
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break;
- if (ctrl->wIndex != 0) {
+ if (w_index != 0) {
value = -EDOM;
break;
}
VDBG(fsg, "get max LUN\n");
*(u8 *) req->buf = fsg->nluns - 1;
- value = min(ctrl->wLength, (u16) 1);
+ value = min(w_length, (u16) 1);
break;
}
}
@@ -1317,15 +1325,15 @@ static int class_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_OUT |
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break;
- if (ctrl->wIndex != 0) {
+ if (w_index != 0) {
value = -EDOM;
break;
}
- if (ctrl->wLength > MAX_COMMAND_SIZE) {
+ if (w_length > MAX_COMMAND_SIZE) {
value = -EOVERFLOW;
break;
}
- value = ctrl->wLength;
+ value = w_length;
fsg->ep0req->context = received_cbi_adsc;
break;
}
@@ -1336,7 +1344,7 @@ static int class_setup_req(struct fsg_dev *fsg,
"unknown class-specific control req "
"%02x.%02x v%04x i%04x l%u\n",
ctrl->bRequestType, ctrl->bRequest,
- ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+ ctrl->wValue, w_index, w_length);
return value;
}
@@ -1350,6 +1358,9 @@ static int standard_setup_req(struct fsg_dev *fsg,
{
struct usb_request *req = fsg->ep0req;
int value = -EOPNOTSUPP;
+ u16 w_index = ctrl->wIndex;
+ u16 w_value = ctrl->wValue;
+ u16 w_length = ctrl->wLength;
/* Usually this just stores reply data in the pre-allocated ep0 buffer,
* but config change events will also reconfigure hardware. */
@@ -1359,11 +1370,11 @@ static int standard_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
USB_RECIP_DEVICE))
break;
- switch (ctrl->wValue >> 8) {
+ switch (w_value >> 8) {
case USB_DT_DEVICE:
VDBG(fsg, "get device descriptor\n");
- value = min(ctrl->wLength, (u16) sizeof device_desc);
+ value = min(w_length, (u16) sizeof device_desc);
memcpy(req->buf, &device_desc, value);
break;
#ifdef CONFIG_USB_GADGET_DUALSPEED
@@ -1371,7 +1382,7 @@ static int standard_setup_req(struct fsg_dev *fsg,
VDBG(fsg, "get device qualifier\n");
if (!fsg->gadget->is_dualspeed)
break;
- value = min(ctrl->wLength, (u16) sizeof dev_qualifier);
+ value = min(w_length, (u16) sizeof dev_qualifier);
memcpy(req->buf, &dev_qualifier, value);
break;
@@ -1388,10 +1399,10 @@ static int standard_setup_req(struct fsg_dev *fsg,
#endif
value = populate_config_buf(fsg->gadget,
req->buf,
- ctrl->wValue >> 8,
- ctrl->wValue & 0xff);
+ w_value >> 8,
+ w_value & 0xff);
if (value >= 0)
- value = min(ctrl->wLength, (u16) value);
+ value = min(w_length, (u16) value);
break;
case USB_DT_STRING:
@@ -1399,9 +1410,9 @@ static int standard_setup_req(struct fsg_dev *fsg,
/* wIndex == language code */
value = usb_gadget_get_string(&stringtab,
- ctrl->wValue & 0xff, req->buf);
+ w_value & 0xff, req->buf);
if (value >= 0)
- value = min(ctrl->wLength, (u16) value);
+ value = min(w_length, (u16) value);
break;
}
break;
@@ -1412,8 +1423,8 @@ static int standard_setup_req(struct fsg_dev *fsg,
USB_RECIP_DEVICE))
break;
VDBG(fsg, "set configuration\n");
- if (ctrl->wValue == CONFIG_VALUE || ctrl->wValue == 0) {
- fsg->new_config = ctrl->wValue;
+ if (w_value == CONFIG_VALUE || w_value == 0) {
+ fsg->new_config = w_value;
/* Raise an exception to wipe out previous transaction
* state (queued bufs, etc) and set the new config. */
@@ -1427,14 +1438,14 @@ static int standard_setup_req(struct fsg_dev *fsg,
break;
VDBG(fsg, "get configuration\n");
*(u8 *) req->buf = fsg->config;
- value = min(ctrl->wLength, (u16) 1);
+ value = min(w_length, (u16) 1);
break;
case USB_REQ_SET_INTERFACE:
if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
USB_RECIP_INTERFACE))
break;
- if (fsg->config && ctrl->wIndex == 0) {
+ if (fsg->config && w_index == 0) {
/* Raise an exception to wipe out previous transaction
* state (queued bufs, etc) and install the new
@@ -1449,20 +1460,20 @@ static int standard_setup_req(struct fsg_dev *fsg,
break;
if (!fsg->config)
break;
- if (ctrl->wIndex != 0) {
+ if (w_index != 0) {
value = -EDOM;
break;
}
VDBG(fsg, "get interface\n");
*(u8 *) req->buf = 0;
- value = min(ctrl->wLength, (u16) 1);
+ value = min(w_length, (u16) 1);
break;
default:
VDBG(fsg,
"unknown control req %02x.%02x v%04x i%04x l%u\n",
ctrl->bRequestType, ctrl->bRequest,
- ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+ w_value, w_index, w_length);
}
return value;
@@ -3740,6 +3751,10 @@ static int __init check_parameters(struct fsg_dev *fsg)
mod_data.release = 0x0310;
else if (gadget_is_pxa27x(fsg->gadget))
mod_data.release = 0x0311;
+ else if (gadget_is_s3c2410(gadget))
+ mod_data.release = 0x0312;
+ else if (gadget_is_at91(fsg->gadget))
+ mod_data.release = 0x0313;
else {
WARN(fsg, "controller '%s' not recognized\n",
fsg->gadget->name);
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index 40c8d27491403..ea2eb52c766d6 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -80,7 +80,12 @@
#define gadget_is_s3c2410(g) 0
#endif
-// CONFIG_USB_GADGET_AT91RM9200
+#ifdef CONFIG_USB_GADGET_AT91
+#define gadget_is_at91(g) !strcmp("at91_udc", (g)->name)
+#else
+#define gadget_is_at91(g) 0
+#endif
+
// CONFIG_USB_GADGET_SX2
// CONFIG_USB_GADGET_AU1X00
// ...
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 790b4b0b2eb54..2cff67ccce452 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1318,6 +1318,8 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
struct usb_request *req = dev->req;
int value = -EOPNOTSUPP;
struct usb_gadgetfs_event *event;
+ u16 w_value = ctrl->wValue;
+ u16 w_length = ctrl->wLength;
spin_lock (&dev->lock);
dev->setup_abort = 0;
@@ -1378,17 +1380,17 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_REQ_GET_DESCRIPTOR:
if (ctrl->bRequestType != USB_DIR_IN)
goto unrecognized;
- switch (ctrl->wValue >> 8) {
+ switch (w_value >> 8) {
case USB_DT_DEVICE:
- value = min (ctrl->wLength, (u16) sizeof *dev->dev);
+ value = min (w_length, (u16) sizeof *dev->dev);
req->buf = dev->dev;
break;
#ifdef HIGHSPEED
case USB_DT_DEVICE_QUALIFIER:
if (!dev->hs_config)
break;
- value = min (ctrl->wLength, (u16)
+ value = min (w_length, (u16)
sizeof (struct usb_qualifier_descriptor));
make_qualifier (dev);
break;
@@ -1397,10 +1399,10 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
#endif
case USB_DT_CONFIG:
value = config_buf (dev,
- ctrl->wValue >> 8,
- ctrl->wValue & 0xff);
+ w_value >> 8,
+ w_value & 0xff);
if (value >= 0)
- value = min (ctrl->wLength, (u16) value);
+ value = min (w_length, (u16) value);
break;
case USB_DT_STRING:
goto unrecognized;
@@ -1414,7 +1416,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_REQ_SET_CONFIGURATION:
if (ctrl->bRequestType != 0)
break;
- if (0 == (u8) ctrl->wValue) {
+ if (0 == (u8) w_value) {
value = 0;
dev->current_config = 0;
usb_gadget_vbus_draw(gadget, 8 /* mA */ );
@@ -1432,7 +1434,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
power = dev->config->bMaxPower;
}
- if (config == (u8) ctrl->wValue) {
+ if (config == (u8) w_value) {
value = 0;
dev->current_config = config;
usb_gadget_vbus_draw(gadget, 2 * power);
@@ -1463,7 +1465,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (ctrl->bRequestType != 0x80)
break;
*(u8 *)req->buf = dev->current_config;
- value = min (ctrl->wLength, (u16) 1);
+ value = min (w_length, (u16) 1);
break;
#endif
@@ -1472,7 +1474,7 @@ unrecognized:
VDEBUG (dev, "%s req%02x.%02x v%04x i%04x l%d\n",
dev->usermode_setup ? "delegate" : "fail",
ctrl->bRequestType, ctrl->bRequest,
- ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+ w_value, le16_to_cpu(ctrl->wIndex), w_length);
/* if there's an ep0 reader, don't stall */
if (dev->usermode_setup) {
@@ -1485,9 +1487,9 @@ delegate:
value = 0;
/* read DATA stage for OUT right away */
- if (unlikely (!dev->setup_in && ctrl->wLength)) {
+ if (unlikely (!dev->setup_in && w_length)) {
value = setup_req (gadget->ep0, dev->req,
- ctrl->wLength);
+ w_length);
if (value < 0)
break;
value = usb_ep_queue (gadget->ep0, dev->req,
@@ -1513,8 +1515,7 @@ delegate:
/* proceed with data transfer and status phases? */
if (value >= 0 && dev->state != STATE_SETUP) {
req->length = value;
- req->zero = value < ctrl->wLength
- && (value % gadget->ep0->maxpacket) == 0;
+ req->zero = value < w_length;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
DBG (dev, "ep_queue --> %d\n", value);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 50e48b17bc4a5..e5457f2026ccd 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1270,7 +1270,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
}
spin_unlock_irqrestore (&ep->dev->lock, flags);
- return req ? 0 : -EOPNOTSUPP;
+ return 0;
}
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 2da469c5c80aa..6390c5726d81c 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -310,7 +310,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
/* flush fifo (mostly for IN buffers) */
pxa2xx_ep_fifo_flush (_ep);
- ep->desc = 0;
+ ep->desc = NULL;
ep->stopped = 1;
DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
@@ -334,7 +334,7 @@ pxa2xx_ep_alloc_request (struct usb_ep *_ep, int gfp_flags)
req = kmalloc (sizeof *req, gfp_flags);
if (!req)
- return 0;
+ return NULL;
memset (req, 0, sizeof *req);
INIT_LIST_HEAD (&req->queue);
@@ -369,7 +369,11 @@ pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM));
if (retval)
+#ifdef USE_DMA
*dma = virt_to_bus (retval);
+#else
+ *dma = (dma_addr_t)~0;
+#endif
return retval;
}
@@ -411,7 +415,6 @@ static void done(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int status)
static inline void ep0_idle (struct pxa2xx_udc *dev)
{
dev->ep0state = EP0_IDLE;
- LED_EP0_OFF;
}
static int
@@ -930,7 +933,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
case EP0_IN_DATA_PHASE:
dev->stats.write.ops++;
if (write_ep0_fifo(ep, req))
- req = 0;
+ req = NULL;
break;
case EP0_OUT_DATA_PHASE:
@@ -940,7 +943,8 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
DBG(DBG_VERBOSE, "ep0 config ack%s\n",
dev->has_cfr ? "" : " raced");
if (dev->has_cfr)
- UDCCFR = UDCCFR_AREN|UDCCFR_ACM;
+ UDCCFR = UDCCFR_AREN|UDCCFR_ACM
+ |UDCCFR_MB1;
done(ep, req, 0);
dev->ep0state = EP0_END_XFER;
local_irq_restore (flags);
@@ -952,7 +956,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
&& read_ep0_fifo(ep, req))) {
ep0_idle(dev);
done(ep, req, 0);
- req = 0;
+ req = NULL;
}
break;
@@ -970,10 +974,10 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
&& (*ep->reg_udccs & UDCCS_BI_TFS) != 0
&& write_fifo(ep, req)) {
- req = 0;
+ req = NULL;
} else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0
&& read_fifo(ep, req)) {
- req = 0;
+ req = NULL;
}
if (likely (req && ep->desc) && ep->dma < 0)
@@ -1094,7 +1098,6 @@ static int pxa2xx_ep_set_halt(struct usb_ep *_ep, int value)
start_watchdog(ep->dev);
ep->dev->req_pending = 0;
ep->dev->ep0state = EP0_STALL;
- LED_EP0_OFF;
/* and bulk/intr endpoints like dropping stalls too */
} else {
@@ -1194,13 +1197,71 @@ static int pxa2xx_udc_wakeup(struct usb_gadget *_gadget)
return 0;
}
+static void stop_activity(struct pxa2xx_udc *, struct usb_gadget_driver *);
+static void udc_enable (struct pxa2xx_udc *);
+static void udc_disable(struct pxa2xx_udc *);
+
+/* We disable the UDC -- and its 48 MHz clock -- whenever it's not
+ * in active use.
+ */
+static int pullup(struct pxa2xx_udc *udc, int is_active)
+{
+ is_active = is_active && udc->vbus && udc->pullup;
+ DMSG("%s\n", is_active ? "active" : "inactive");
+ if (is_active)
+ udc_enable(udc);
+ else {
+ if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+ DMSG("disconnect %s\n", udc->driver
+ ? udc->driver->driver.name
+ : "(no driver)");
+ stop_activity(udc, udc->driver);
+ }
+ udc_disable(udc);
+ }
+ return 0;
+}
+
+/* VBUS reporting logically comes from a transceiver */
+static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
+{
+ struct pxa2xx_udc *udc;
+
+ udc = container_of(_gadget, struct pxa2xx_udc, gadget);
+ udc->vbus = is_active = (is_active != 0);
+ DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
+ pullup(udc, is_active);
+ return 0;
+}
+
+/* drivers may have software control over D+ pullup */
+static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active)
+{
+ struct pxa2xx_udc *udc;
+
+ udc = container_of(_gadget, struct pxa2xx_udc, gadget);
+
+ /* not all boards support pullup control */
+ if (!udc->mach->udc_command)
+ return -EOPNOTSUPP;
+
+ is_active = (is_active != 0);
+ udc->pullup = is_active;
+ pullup(udc, is_active);
+ return 0;
+}
+
static const struct usb_gadget_ops pxa2xx_udc_ops = {
- .get_frame = pxa2xx_udc_get_frame,
- .wakeup = pxa2xx_udc_wakeup,
- // current versions must always be self-powered
+ .get_frame = pxa2xx_udc_get_frame,
+ .wakeup = pxa2xx_udc_wakeup,
+ .vbus_session = pxa2xx_udc_vbus_session,
+ .pullup = pxa2xx_udc_pullup,
+
+ // .vbus_draw ... boards may consume current from VBUS, up to
+ // 100-500mA based on config. the 500uA suspend ceiling means
+ // that exclusively vbus-powered PXA designs violate USB specs.
};
-
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
@@ -1427,7 +1488,7 @@ static void udc_reinit(struct pxa2xx_udc *dev)
if (i != 0)
list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
- ep->desc = 0;
+ ep->desc = NULL;
ep->stopped = 0;
INIT_LIST_HEAD (&ep->queue);
ep->pio_irqs = ep->dma_irqs = 0;
@@ -1446,6 +1507,7 @@ static void udc_enable (struct pxa2xx_udc *dev)
#ifdef CONFIG_ARCH_PXA
/* Enable clock for USB device */
pxa_set_cken(CKEN11_USB, 1);
+ udelay(5);
#endif
/* try to clear these bits before we enable the udc */
@@ -1469,7 +1531,7 @@ static void udc_enable (struct pxa2xx_udc *dev)
/* pxa255 (a0+) can avoid a set_config race that could
* prevent gadget drivers from configuring correctly
*/
- UDCCFR = UDCCFR_ACM;
+ UDCCFR = UDCCFR_ACM | UDCCFR_MB1;
} else {
/* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1)
* which could result in missing packets and interrupts.
@@ -1498,18 +1560,13 @@ static void udc_enable (struct pxa2xx_udc *dev)
}
#endif
- /* caller must be able to sleep in order to cope
- * with startup transients.
- */
- msleep(100);
-
/* enable suspend/resume and reset irqs */
udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
/* enable ep0 irqs */
UICR0 &= ~UICR0_IM0;
- /* if hardware supports it, connect to usb and wait for host */
+ /* if hardware supports it, pullup D+ and wait for reset */
let_usb_appear();
}
@@ -1540,6 +1597,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
/* first hook up the driver ... */
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
+ dev->pullup = 1;
device_add (&dev->gadget.dev);
retval = driver->bind(&dev->gadget);
@@ -1548,18 +1606,17 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
driver->driver.name, retval);
device_del (&dev->gadget.dev);
- dev->driver = 0;
- dev->gadget.dev.driver = 0;
+ dev->driver = NULL;
+ dev->gadget.dev.driver = NULL;
return retval;
}
device_create_file(dev->dev, &dev_attr_function);
/* ... then enable host detection and ep0; and we're ready
* for set_configuration as well as eventual disconnect.
- * NOTE: this shouldn't power up until later.
*/
DMSG("registered gadget driver '%s'\n", driver->driver.name);
- udc_enable(dev);
+ pullup(dev, 1);
dump_state(dev);
return 0;
}
@@ -1572,7 +1629,7 @@ stop_activity(struct pxa2xx_udc *dev, struct usb_gadget_driver *driver)
/* don't disconnect drivers more than once */
if (dev->gadget.speed == USB_SPEED_UNKNOWN)
- driver = 0;
+ driver = NULL;
dev->gadget.speed = USB_SPEED_UNKNOWN;
/* prevent new request submissions, kill any outstanding requests */
@@ -1603,12 +1660,12 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return -EINVAL;
local_irq_disable();
- udc_disable(dev);
+ pullup(dev, 0);
stop_activity(dev, driver);
local_irq_enable();
driver->unbind(&dev->gadget);
- dev->driver = 0;
+ dev->driver = NULL;
device_del (&dev->gadget.dev);
device_remove_file(dev->dev, &dev_attr_function);
@@ -1624,61 +1681,41 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver);
#ifdef CONFIG_ARCH_LUBBOCK
-/* Lubbock can report connect or disconnect irqs. Likely more hardware
- * could support it as a timer callback.
- *
- * FIXME for better power management, keep the hardware powered down
- * until a host is powering the link. means scheduling work later
- * in some task that can udc_enable().
+/* Lubbock has separate connect and disconnect irqs. More typical designs
+ * use one GPIO as the VBUS IRQ, and another to control the D+ pullup.
*/
-#define enable_disconnect_irq() \
- if (machine_is_lubbock()) { enable_irq(LUBBOCK_USB_DISC_IRQ); }
-#define disable_disconnect_irq() \
- if (machine_is_lubbock()) { disable_irq(LUBBOCK_USB_DISC_IRQ); }
-
static irqreturn_t
-usb_connection_irq(int irq, void *_dev, struct pt_regs *r)
+lubbock_vbus_irq(int irq, void *_dev, struct pt_regs *r)
{
struct pxa2xx_udc *dev = _dev;
+ int vbus;
dev->stats.irqs++;
HEX_DISPLAY(dev->stats.irqs);
-
- if (!is_usb_connected()) {
- LED_CONNECTED_OFF;
- disable_disconnect_irq();
- /* report disconnect just once */
- if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
- DMSG("disconnect %s\n",
- dev->driver ? dev->driver->driver.name : 0);
- stop_activity(dev, dev->driver);
-
- // udc_disable (dev);
- // no more udc irqs
- // maybe "ACTION=disconnect /sbin/hotplug gadget".
- }
- } else if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
+ switch (irq) {
+ case LUBBOCK_USB_IRQ:
LED_CONNECTED_ON;
-
- DMSG("?? connect irq ??\n");
-
- // if there's no driver bound, ignore; else
- // udc_enable (dev);
- // UDC irqs drive the rest.
- // maybe "ACTION=connect /sbin/hotplug gadget".
+ vbus = 1;
+ disable_irq(LUBBOCK_USB_IRQ);
+ enable_irq(LUBBOCK_USB_DISC_IRQ);
+ break;
+ case LUBBOCK_USB_DISC_IRQ:
+ LED_CONNECTED_OFF;
+ vbus = 0;
+ disable_irq(LUBBOCK_USB_DISC_IRQ);
+ enable_irq(LUBBOCK_USB_IRQ);
+ break;
+ default:
+ return IRQ_NONE;
}
+
+ pxa2xx_udc_vbus_session(&dev->gadget, vbus);
return IRQ_HANDLED;
}
#endif
-#ifndef enable_disconnect_irq
-#warning USB disconnect() is not yet reported.
-#define enable_disconnect_irq() do {} while (0)
-#define disable_disconnect_irq() do {} while (0)
-#endif
-
/*-------------------------------------------------------------------------*/
@@ -1720,7 +1757,7 @@ static void handle_ep0 (struct pxa2xx_udc *dev)
} u;
if (list_empty(&ep->queue))
- req = 0;
+ req = NULL;
else
req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
@@ -1764,14 +1801,11 @@ bad_setup:
goto bad_setup;
got_setup:
- le16_to_cpus (&u.r.wValue);
- le16_to_cpus (&u.r.wIndex);
- le16_to_cpus (&u.r.wLength);
-
- LED_EP0_ON;
DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n",
u.r.bRequestType, u.r.bRequest,
- u.r.wValue, u.r.wIndex, u.r.wLength);
+ le16_to_cpu(u.r.wValue),
+ le16_to_cpu(u.r.wIndex),
+ le16_to_cpu(u.r.wLength));
/* cope with automagic for some standard requests. */
dev->req_std = (u.r.bRequestType & USB_TYPE_MASK)
@@ -1803,7 +1837,8 @@ config_change:
* - ep reset doesn't include halt(?).
*/
DMSG("broken set_interface (%d/%d)\n",
- u.r.wIndex, u.r.wValue);
+ le16_to_cpu(u.r.wIndex),
+ le16_to_cpu(u.r.wValue));
goto config_change;
}
break;
@@ -1847,7 +1882,6 @@ stall:
ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall");
start_watchdog(dev);
dev->ep0state = EP0_STALL;
- LED_EP0_OFF;
/* deferred i/o == no response yet */
} else if (dev->req_pending) {
@@ -1948,7 +1982,7 @@ static void handle_ep(struct pxa2xx_ep *ep)
req = list_entry(ep->queue.next,
struct pxa2xx_request, queue);
else
- req = 0;
+ req = NULL;
// TODO check FST handling
@@ -2050,8 +2084,6 @@ pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r)
if ((UDCCR & UDCCR_UDA) == 0) {
DBG(DBG_VERBOSE, "USB reset start\n");
- if (dev->gadget.speed != USB_SPEED_UNKNOWN)
- disable_disconnect_irq();
/* reset driver and endpoints,
* in case that's not yet done
@@ -2059,12 +2091,11 @@ pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r)
stop_activity (dev, dev->driver);
} else {
- INFO("USB reset\n");
+ DBG(DBG_VERBOSE, "USB reset end\n");
dev->gadget.speed = USB_SPEED_FULL;
LED_CONNECTED_ON;
memset(&dev->stats, 0, sizeof dev->stats);
/* driver and endpoints are still reset */
- enable_disconnect_irq();
}
} else {
@@ -2478,6 +2509,8 @@ static int __init pxa2xx_udc_probe(struct device *_dev)
udc_disable(dev);
udc_reinit(dev);
+ dev->vbus = is_usb_connected();
+
/* irq setup after old hardware state is cleaned up */
retval = request_irq(IRQ_USB, pxa2xx_udc_irq,
SA_INTERRUPT, driver_name, dev);
@@ -2490,18 +2523,32 @@ static int __init pxa2xx_udc_probe(struct device *_dev)
#ifdef CONFIG_ARCH_LUBBOCK
if (machine_is_lubbock()) {
- disable_irq(LUBBOCK_USB_DISC_IRQ);
retval = request_irq(LUBBOCK_USB_DISC_IRQ,
- usb_connection_irq,
- SA_INTERRUPT /* OOPSING | SA_SAMPLE_RANDOM */,
+ lubbock_vbus_irq,
+ SA_INTERRUPT | SA_SAMPLE_RANDOM,
driver_name, dev);
if (retval != 0) {
- enable_irq(LUBBOCK_USB_DISC_IRQ);
printk(KERN_ERR "%s: can't get irq %i, err %d\n",
driver_name, LUBBOCK_USB_DISC_IRQ, retval);
+lubbock_fail0:
+ free_irq(IRQ_USB, dev);
return -EBUSY;
}
- dev->got_disc = 1;
+ retval = request_irq(LUBBOCK_USB_IRQ,
+ lubbock_vbus_irq,
+ SA_INTERRUPT | SA_SAMPLE_RANDOM,
+ driver_name, dev);
+ if (retval != 0) {
+ printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+ driver_name, LUBBOCK_USB_IRQ, retval);
+ free_irq(LUBBOCK_USB_DISC_IRQ, dev);
+ goto lubbock_fail0;
+ }
+#ifdef DEBUG
+ /* with U-Boot (but not BLOB), hex is off by default */
+ HEX_DISPLAY(dev->stats.irqs);
+ LUB_DISC_BLNK_LED &= 0xff;
+#endif
}
#endif
create_proc_files();
@@ -2510,7 +2557,7 @@ static int __init pxa2xx_udc_probe(struct device *_dev)
}
static int __exit pxa2xx_udc_remove(struct device *_dev)
{
- struct pxa2xx_udc *dev = _dev->driver_data;
+ struct pxa2xx_udc *dev = dev_get_drvdata(_dev);
udc_disable(dev);
remove_proc_files();
@@ -2520,15 +2567,57 @@ static int __exit pxa2xx_udc_remove(struct device *_dev)
free_irq(IRQ_USB, dev);
dev->got_irq = 0;
}
- if (machine_is_lubbock() && dev->got_disc) {
+ if (machine_is_lubbock()) {
free_irq(LUBBOCK_USB_DISC_IRQ, dev);
- dev->got_disc = 0;
+ free_irq(LUBBOCK_USB_IRQ, dev);
+ }
+ dev_set_drvdata(_dev, NULL);
+ the_controller = NULL;
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+
+/* USB suspend (controlled by the host) and system suspend (controlled
+ * by the PXA) don't necessarily work well together. If USB is active,
+ * the 48 MHz clock is required; so the system can't enter 33 MHz idle
+ * mode, or any deeper PM saving state.
+ *
+ * For now, we punt and forcibly disconnect from the USB host when PXA
+ * enters any suspend state. While we're disconnected, we always disable
+ * the 48MHz USB clock ... allowing PXA sleep and/or 33 MHz idle states.
+ * Boards without software pullup control shouldn't use those states.
+ * VBUS IRQs should probably be ignored so that the PXA device just acts
+ * "dead" to USB hosts until system resume.
+ */
+static int pxa2xx_udc_suspend(struct device *dev, u32 state, u32 level)
+{
+ struct pxa2xx_udc *udc = dev_get_drvdata(dev);
+
+ if (level == SUSPEND_POWER_DOWN) {
+ if (!udc->mach->udc_command)
+ WARN("USB host won't detect disconnect!\n");
+ pullup(udc, 0);
}
- dev_set_drvdata(_dev, 0);
- the_controller = 0;
return 0;
}
+static int pxa2xx_udc_resume(struct device *dev, u32 level)
+{
+ struct pxa2xx_udc *udc = dev_get_drvdata(dev);
+
+ if (level == RESUME_POWER_ON)
+ pullup(udc, 1);
+ return 0;
+}
+
+#else
+#define pxa2xx_udc_suspend NULL
+#define pxa2xx_udc_resume NULL
+#endif
+
/*-------------------------------------------------------------------------*/
static struct device_driver udc_driver = {
@@ -2536,10 +2625,8 @@ static struct device_driver udc_driver = {
.bus = &platform_bus_type,
.probe = pxa2xx_udc_probe,
.remove = __exit_p(pxa2xx_udc_remove),
-
- // FIXME power management support
- // .suspend = ... disable UDC
- // .resume = ... re-enable UDC
+ .suspend = pxa2xx_udc_suspend,
+ .resume = pxa2xx_udc_resume,
};
static int __init udc_init(void)
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index f3d6853852c3e..1f3a7d999da7e 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -40,6 +40,9 @@
#define UDCCFR_AREN (1 << 7) /* ACK response enable (now) */
#define UDCCFR_ACM (1 << 2) /* ACK control mode (wait for AREN) */
+/* latest pxa255 errata define new "must be one" bits in UDCCFR */
+#define UDCCFR_MB1 (0xff & ~(UDCCFR_AREN|UDCCFR_ACM))
+
/*-------------------------------------------------------------------------*/
struct pxa2xx_udc;
@@ -120,7 +123,8 @@ struct pxa2xx_udc {
enum ep0_state ep0state;
struct udc_stats stats;
unsigned got_irq : 1,
- got_disc : 1,
+ vbus : 1,
+ pullup : 1,
has_cfr : 1,
req_pending : 1,
req_std : 1,
@@ -143,14 +147,7 @@ struct pxa2xx_udc {
#ifdef DEBUG
#define HEX_DISPLAY(n) if (machine_is_lubbock()) { LUB_HEXLED = (n); }
-
-#define LED_CONNECTED_ON if (machine_is_lubbock()) { \
- DISCRETE_LED_ON(D26); }
-#define LED_CONNECTED_OFF if(machine_is_lubbock()) { \
- DISCRETE_LED_OFF(D26); LUB_HEXLED = 0; }
-#define LED_EP0_ON if (machine_is_lubbock()) { DISCRETE_LED_ON(D25); }
-#define LED_EP0_OFF if (machine_is_lubbock()) { DISCRETE_LED_OFF(D25); }
-#endif /* DEBUG */
+#endif
#endif
@@ -161,14 +158,20 @@ struct pxa2xx_udc {
#define HEX_DISPLAY(n) do {} while(0)
#endif
+#ifdef DEBUG
+#include <asm/leds.h>
+
+#define LED_CONNECTED_ON leds_event(led_green_on)
+#define LED_CONNECTED_OFF do { \
+ leds_event(led_green_off); \
+ HEX_DISPLAY(0); \
+ } while(0)
+#endif
+
#ifndef LED_CONNECTED_ON
#define LED_CONNECTED_ON do {} while(0)
#define LED_CONNECTED_OFF do {} while(0)
#endif
-#ifndef LED_EP0_ON
-#define LED_EP0_ON do {} while (0)
-#define LED_EP0_OFF do {} while (0)
-#endif
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index f70f72bf1be56..6c5197850edc1 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -74,7 +74,7 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging");
static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
/* Driver Version */
-static const u32 rndis_driver_version = __constant_cpu_to_le32 (1);
+static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1);
/* Function Prototypes */
static int rndis_init_response (int configNr, rndis_init_msg_type *buf);
@@ -92,7 +92,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
{
int retval = -ENOTSUPP;
u32 length = 0;
- u32 *tmp;
+ __le32 *tmp;
int i, count;
rndis_query_cmplt_type *resp;
@@ -110,7 +110,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
length = sizeof (oid_supported_list);
count = length / sizeof (u32);
- tmp = (u32 *) ((u8 *)resp + 24);
+ tmp = (__le32 *) ((u8 *)resp + 24);
for (i = 0; i < count; i++)
tmp[i] = cpu_to_le32 (oid_supported_list[i]);
retval = 0;
@@ -126,7 +126,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
* reddite ergo quae sunt Caesaris Caesari
* et quae sunt Dei Deo!
*/
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -134,7 +134,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MEDIA_SUPPORTED:
DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].medium);
retval = 0;
break;
@@ -144,7 +144,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
length = 4;
/* one medium, one transport... (maybe you do it better) */
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].medium);
retval = 0;
break;
@@ -154,11 +154,11 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -169,9 +169,9 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
length = 4;
if (rndis_per_dev_params [configNr].media_state
== NDIS_MEDIA_STATE_DISCONNECTED)
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
else
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].speed);
retval = 0;
break;
@@ -181,7 +181,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
retval = 0;
}
@@ -192,7 +192,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
retval = 0;
}
@@ -202,7 +202,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_VENDOR_ID:
DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].vendorID);
retval = 0;
break;
@@ -220,7 +220,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
length = 4;
/* Created as LE */
- *((u32 *) resp + 6) = rndis_driver_version;
+ *((__le32 *) resp + 6) = rndis_driver_version;
retval = 0;
break;
@@ -228,7 +228,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_CURRENT_PACKET_FILTER:
DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params[configNr].filter);
retval = 0;
break;
@@ -237,7 +237,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MAXIMUM_TOTAL_SIZE:
DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = __constant_cpu_to_le32(
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32(
RNDIS_MAX_TOTAL_SIZE);
retval = 0;
break;
@@ -246,7 +246,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MEDIA_CONNECT_STATUS:
DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.media_state);
retval = 0;
@@ -255,7 +255,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_PHYSICAL_MEDIUM:
DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -266,7 +266,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MAC_OPTIONS: /* from WinME */
DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = __constant_cpu_to_le32(
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32(
NDIS_MAC_OPTION_RECEIVE_SERIALIZED
| NDIS_MAC_OPTION_FULL_DUPLEX);
retval = 0;
@@ -279,13 +279,13 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].stats->tx_packets -
rndis_per_dev_params [configNr].stats->tx_errors -
rndis_per_dev_params [configNr].stats->tx_dropped);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -295,13 +295,13 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].stats->rx_packets -
rndis_per_dev_params [configNr].stats->rx_errors -
rndis_per_dev_params [configNr].stats->rx_dropped);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -311,12 +311,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->tx_errors);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -325,12 +325,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_RCV_ERROR:
DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_errors);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -339,12 +339,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_RCV_NO_BUFFER:
DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_dropped);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -359,7 +359,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
*/
if (rndis_per_dev_params [configNr].stats) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
(rndis_per_dev_params [configNr]
.stats->tx_packets -
rndis_per_dev_params [configNr]
@@ -369,7 +369,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
* 123);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -379,7 +379,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
/* dito */
if (rndis_per_dev_params [configNr].stats) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
(rndis_per_dev_params [configNr]
.stats->tx_packets -
rndis_per_dev_params [configNr]
@@ -389,7 +389,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
/ 123);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -397,12 +397,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MULTICAST_BYTES_XMIT:
DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->multicast*1234);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -410,12 +410,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MULTICAST_FRAMES_XMIT:
DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->multicast);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -423,12 +423,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_BROADCAST_BYTES_XMIT:
DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->tx_packets/42*255);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -436,37 +436,37 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_BROADCAST_FRAMES_XMIT:
DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->tx_packets/42);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
case OID_GEN_DIRECTED_BYTES_RCV:
DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
case OID_GEN_DIRECTED_FRAMES_RCV:
DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
case OID_GEN_MULTICAST_BYTES_RCV:
DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->multicast * 1111);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -474,12 +474,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MULTICAST_FRAMES_RCV:
DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->multicast);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -487,12 +487,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_BROADCAST_BYTES_RCV:
DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_packets/42*255);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -500,12 +500,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_BROADCAST_FRAMES_RCV:
DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_packets/42);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -513,19 +513,19 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_RCV_CRC_ERROR:
DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_crc_errors);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
case OID_GEN_TRANSMIT_QUEUE_LENGTH:
DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
#endif /* RNDIS_OPTIONAL_STATS */
@@ -542,7 +542,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
length);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -564,7 +564,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
length = 4;
/* Multicast base address only */
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);
retval = 0;
break;
@@ -573,7 +573,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
length = 4;
/* Multicast base address only */
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (1);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (1);
retval = 0;
break;
@@ -589,7 +589,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
if (rndis_per_dev_params [configNr].stats)
{
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_frame_errors);
retval = 0;
@@ -600,7 +600,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_802_3_XMIT_ONE_COLLISION:
DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -608,7 +608,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_802_3_XMIT_MORE_COLLISIONS:
DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -734,7 +734,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
* PROMISCUOUS, DIRECTED,
* MULTICAST, ALL_MULTICAST, BROADCAST
*/
- params->filter = cpu_to_le32p((u32 *)buf);
+ params->filter = le32_to_cpup((__le32 *)buf);
DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
__FUNCTION__, params->filter);
@@ -866,7 +866,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
resp->MessageLength = __constant_cpu_to_le32 (24);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
- if (gen_ndis_query_resp (configNr, cpu_to_le32 (buf->OID), r)) {
+ if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), r)) {
/* OID not supported */
resp->Status = __constant_cpu_to_le32 (
RNDIS_STATUS_NOT_SUPPORTED);
@@ -893,8 +893,8 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
resp = (rndis_set_cmplt_type *) r->buf;
if (!resp) return -ENOMEM;
- BufLength = cpu_to_le32 (buf->InformationBufferLength);
- BufOffset = cpu_to_le32 (buf->InformationBufferOffset);
+ BufLength = le32_to_cpu (buf->InformationBufferLength);
+ BufOffset = le32_to_cpu (buf->InformationBufferOffset);
#ifdef VERBOSE
DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
@@ -911,7 +911,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
resp->MessageLength = __constant_cpu_to_le32 (16);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
- if (gen_ndis_set_resp (configNr, cpu_to_le32 (buf->OID),
+ if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID),
((u8 *) buf) + 8 + BufOffset, BufLength, r))
resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
@@ -1030,15 +1030,16 @@ void rndis_set_host_mac (int configNr, const u8 *addr)
*/
int rndis_msg_parser (u8 configNr, u8 *buf)
{
- u32 MsgType, MsgLength, *tmp;
+ u32 MsgType, MsgLength;
+ __le32 *tmp;
struct rndis_params *params;
if (!buf)
return -ENOMEM;
- tmp = (u32 *) buf;
- MsgType = cpu_to_le32p(tmp++);
- MsgLength = cpu_to_le32p(tmp++);
+ tmp = (__le32 *) buf;
+ MsgType = le32_to_cpup(tmp++);
+ MsgLength = le32_to_cpup(tmp++);
if (configNr >= RNDIS_MAX_CONFIGS)
return -ENOTSUPP;
@@ -1187,15 +1188,16 @@ int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
void rndis_add_hdr (struct sk_buff *skb)
{
- if (!skb) return;
- skb_push (skb, sizeof (struct rndis_packet_msg_type));
- memset (skb->data, 0, sizeof (struct rndis_packet_msg_type));
- *((u32 *) skb->data) = __constant_cpu_to_le32 (1);
- *((u32 *) skb->data + 1) = cpu_to_le32(skb->len);
- *((u32 *) skb->data + 2) = __constant_cpu_to_le32 (36);
- *((u32 *) skb->data + 3) = cpu_to_le32(skb->len - 44);
-
- return;
+ struct rndis_packet_msg_type *header;
+
+ if (!skb)
+ return;
+ header = (void *) skb_push (skb, sizeof *header);
+ memset (header, 0, sizeof *header);
+ header->MessageType = __constant_cpu_to_le32 (1);
+ header->MessageLength = cpu_to_le32(skb->len);
+ header->DataOffset = __constant_cpu_to_le32 (36);
+ header->OOBDataOffset = cpu_to_le32(skb->len - 44);
}
void rndis_free_response (int configNr, u8 *buf)
@@ -1253,15 +1255,16 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length)
int rndis_rm_hdr (u8 *buf, u32 *length)
{
- u32 i, messageLen, dataOffset, *tmp;
+ u32 i, messageLen, dataOffset;
+ __le32 *tmp;
- tmp = (u32 *) buf;
+ tmp = (__le32 *) buf;
if (!buf || !length) return -1;
- if (cpu_to_le32p(tmp++) != 1) return -1;
+ if (le32_to_cpup(tmp++) != 1) return -1;
- messageLen = cpu_to_le32p(tmp++);
- dataOffset = cpu_to_le32p(tmp++) + 8;
+ messageLen = le32_to_cpup(tmp++);
+ dataOffset = le32_to_cpup(tmp++) + 8;
if (messageLen < dataOffset || messageLen > *length) return -1;
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index fa7d90854d6fb..822501852c50b 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -154,139 +154,139 @@ static const u32 oid_supported_list [] =
typedef struct rndis_init_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 MajorVersion;
- u32 MinorVersion;
- u32 MaxTransferSize;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 MajorVersion;
+ __le32 MinorVersion;
+ __le32 MaxTransferSize;
} rndis_init_msg_type;
typedef struct rndis_init_cmplt_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 Status;
- u32 MajorVersion;
- u32 MinorVersion;
- u32 DeviceFlags;
- u32 Medium;
- u32 MaxPacketsPerTransfer;
- u32 MaxTransferSize;
- u32 PacketAlignmentFactor;
- u32 AFListOffset;
- u32 AFListSize;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 Status;
+ __le32 MajorVersion;
+ __le32 MinorVersion;
+ __le32 DeviceFlags;
+ __le32 Medium;
+ __le32 MaxPacketsPerTransfer;
+ __le32 MaxTransferSize;
+ __le32 PacketAlignmentFactor;
+ __le32 AFListOffset;
+ __le32 AFListSize;
} rndis_init_cmplt_type;
typedef struct rndis_halt_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
} rndis_halt_msg_type;
typedef struct rndis_query_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 OID;
- u32 InformationBufferLength;
- u32 InformationBufferOffset;
- u32 DeviceVcHandle;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 OID;
+ __le32 InformationBufferLength;
+ __le32 InformationBufferOffset;
+ __le32 DeviceVcHandle;
} rndis_query_msg_type;
typedef struct rndis_query_cmplt_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 Status;
- u32 InformationBufferLength;
- u32 InformationBufferOffset;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 Status;
+ __le32 InformationBufferLength;
+ __le32 InformationBufferOffset;
} rndis_query_cmplt_type;
typedef struct rndis_set_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 OID;
- u32 InformationBufferLength;
- u32 InformationBufferOffset;
- u32 DeviceVcHandle;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 OID;
+ __le32 InformationBufferLength;
+ __le32 InformationBufferOffset;
+ __le32 DeviceVcHandle;
} rndis_set_msg_type;
typedef struct rndis_set_cmplt_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 Status;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 Status;
} rndis_set_cmplt_type;
typedef struct rndis_reset_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 Reserved;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 Reserved;
} rndis_reset_msg_type;
typedef struct rndis_reset_cmplt_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 Status;
- u32 AddressingReset;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 Status;
+ __le32 AddressingReset;
} rndis_reset_cmplt_type;
typedef struct rndis_indicate_status_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 Status;
- u32 StatusBufferLength;
- u32 StatusBufferOffset;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 Status;
+ __le32 StatusBufferLength;
+ __le32 StatusBufferOffset;
} rndis_indicate_status_msg_type;
typedef struct rndis_keepalive_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
} rndis_keepalive_msg_type;
typedef struct rndis_keepalive_cmplt_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 Status;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 Status;
} rndis_keepalive_cmplt_type;
struct rndis_packet_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 DataOffset;
- u32 DataLength;
- u32 OOBDataOffset;
- u32 OOBDataLength;
- u32 NumOOBDataElements;
- u32 PerPacketInfoOffset;
- u32 PerPacketInfoLength;
- u32 VcHandle;
- u32 Reserved;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 DataOffset;
+ __le32 DataLength;
+ __le32 OOBDataOffset;
+ __le32 OOBDataLength;
+ __le32 NumOOBDataElements;
+ __le32 PerPacketInfoOffset;
+ __le32 PerPacketInfoLength;
+ __le32 VcHandle;
+ __le32 Reserved;
};
struct rndis_config_parameter
{
- u32 ParameterNameOffset;
- u32 ParameterNameLength;
- u32 ParameterType;
- u32 ParameterValueOffset;
- u32 ParameterValueLength;
+ __le32 ParameterNameOffset;
+ __le32 ParameterNameLength;
+ __le32 ParameterType;
+ __le32 ParameterValueOffset;
+ __le32 ParameterValueLength;
};
/* implementation specific */
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 1e2e1ee955323..2af3f785d5a11 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1461,6 +1461,9 @@ static int gs_bind(struct usb_gadget *gadget)
} else if (gadget_is_s3c2410(gadget)) {
gs_device_desc.bcdDevice =
__constant_cpu_to_le16(GS_VERSION_NUM|0x0012);
+ } else if (gadget_is_at91(gadget)) {
+ gs_device_desc.bcdDevice =
+ __constant_cpu_to_le16(GS_VERSION_NUM|0x0013);
} else {
printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
gadget->name);
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
index e1ca71bcc3966..b1735767660b6 100644
--- a/drivers/usb/gadget/usbstring.c
+++ b/drivers/usb/gadget/usbstring.c
@@ -20,7 +20,7 @@
#include <asm/unaligned.h>
-static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
+static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
{
int count = 0;
u8 c;
@@ -126,7 +126,7 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
/* string descriptors have length, tag, then UTF16-LE text */
len = min ((size_t) 126, strlen (s->s));
memset (buf + 2, 0, 2 * len); /* zero all the bytes */
- len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
+ len = utf8_to_utf16le(s->s, (__le16 *)&buf[2], len);
if (len < 0)
return -EINVAL;
buf [0] = (len + 1) * 2;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 98b5c0854201c..6e49432071a1d 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -919,6 +919,9 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
struct zero_dev *dev = get_gadget_data (gadget);
struct usb_request *req = dev->req;
int value = -EOPNOTSUPP;
+ u16 w_index = ctrl->wIndex;
+ u16 w_value = ctrl->wValue;
+ u16 w_length = ctrl->wLength;
/* usually this stores reply data in the pre-allocated ep0 buffer,
* but config change events will reconfigure hardware.
@@ -929,17 +932,17 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_REQ_GET_DESCRIPTOR:
if (ctrl->bRequestType != USB_DIR_IN)
goto unknown;
- switch (ctrl->wValue >> 8) {
+ switch (w_value >> 8) {
case USB_DT_DEVICE:
- value = min (ctrl->wLength, (u16) sizeof device_desc);
+ value = min (w_length, (u16) sizeof device_desc);
memcpy (req->buf, &device_desc, value);
break;
#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_DT_DEVICE_QUALIFIER:
if (!gadget->is_dualspeed)
break;
- value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
+ value = min (w_length, (u16) sizeof dev_qualifier);
memcpy (req->buf, &dev_qualifier, value);
break;
@@ -950,10 +953,10 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
#endif /* CONFIG_USB_GADGET_DUALSPEED */
case USB_DT_CONFIG:
value = config_buf (gadget, req->buf,
- ctrl->wValue >> 8,
- ctrl->wValue & 0xff);
+ w_value >> 8,
+ w_value & 0xff);
if (value >= 0)
- value = min (ctrl->wLength, (u16) value);
+ value = min (w_length, (u16) value);
break;
case USB_DT_STRING:
@@ -963,9 +966,9 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
* any UTF-8 characters
*/
value = usb_gadget_get_string (&stringtab,
- ctrl->wValue & 0xff, req->buf);
+ w_value & 0xff, req->buf);
if (value >= 0)
- value = min (ctrl->wLength, (u16) value);
+ value = min (w_length, (u16) value);
break;
}
break;
@@ -981,14 +984,14 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
else
VDBG (dev, "HNP inactive\n");
spin_lock (&dev->lock);
- value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
+ value = zero_set_config (dev, w_value, GFP_ATOMIC);
spin_unlock (&dev->lock);
break;
case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != USB_DIR_IN)
goto unknown;
*(u8 *)req->buf = dev->config;
- value = min (ctrl->wLength, (u16) 1);
+ value = min (w_length, (u16) 1);
break;
/* until we add altsetting support, or other interfaces,
@@ -999,7 +1002,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (ctrl->bRequestType != USB_RECIP_INTERFACE)
goto unknown;
spin_lock (&dev->lock);
- if (dev->config && ctrl->wIndex == 0 && ctrl->wValue == 0) {
+ if (dev->config && w_index == 0 && w_value == 0) {
u8 config = dev->config;
/* resets interface configuration, forgets about
@@ -1020,12 +1023,12 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
goto unknown;
if (!dev->config)
break;
- if (ctrl->wIndex != 0) {
+ if (w_index != 0) {
value = -EDOM;
break;
}
*(u8 *)req->buf = 0;
- value = min (ctrl->wLength, (u16) 1);
+ value = min (w_length, (u16) 1);
break;
/*
@@ -1036,23 +1039,23 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case 0x5b: /* control WRITE test -- fill the buffer */
if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
goto unknown;
- if (ctrl->wValue || ctrl->wIndex)
+ if (w_value || w_index)
break;
/* just read that many bytes into the buffer */
- if (ctrl->wLength > USB_BUFSIZ)
+ if (w_length > USB_BUFSIZ)
break;
- value = ctrl->wLength;
+ value = w_length;
break;
case 0x5c: /* control READ test -- return the buffer */
if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
goto unknown;
- if (ctrl->wValue || ctrl->wIndex)
+ if (w_value || w_index)
break;
/* expect those bytes are still in the buffer; send back */
- if (ctrl->wLength > USB_BUFSIZ
- || ctrl->wLength != req->length)
+ if (w_length > USB_BUFSIZ
+ || w_length != req->length)
break;
- value = ctrl->wLength;
+ value = w_length;
break;
default:
@@ -1060,14 +1063,13 @@ unknown:
VDBG (dev,
"unknown control req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest,
- ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+ w_value, w_index, w_length);
}
/* respond with data transfer before status phase? */
if (value >= 0) {
req->length = value;
- req->zero = value < ctrl->wLength
- && (value % gadget->ep0->maxpacket) == 0;
+ req->zero = value < w_length;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
DBG (dev, "ep_queue --> %d\n", value);
@@ -1193,6 +1195,8 @@ autoconf_fail:
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
} else if (gadget_is_s3c2410(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
+ } else if (gadget_is_at91(gadget)) {
+ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
} else {
/* gadget zero is so simple (for now, no altsettings) that
* it SHOULD NOT have problems with bulk-capable hardware.
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index b0443f3f6cb15..a63bb792e2c7e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -212,7 +212,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
command |= CMD_RESET;
dbg_cmd (ehci, "reset", command);
writel (command, &ehci->regs->command);
- ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
ehci->next_statechange = jiffies;
retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
@@ -231,7 +231,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
u32 temp;
#ifdef DEBUG
- if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+ if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
BUG ();
#endif
@@ -240,7 +240,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
temp &= STS_ASS | STS_PSS;
if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
temp, 16 * 125) != 0) {
- ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return;
}
@@ -252,7 +252,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
/* hardware can take 16 microframes to turn off ... */
if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
0, 16 * 125) != 0) {
- ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return;
}
}
@@ -615,7 +615,7 @@ done2:
register_reboot_notifier (&ehci->reboot_notifier);
}
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
writel (FLAG_CF, &ehci->regs->configured_flag);
readl (&ehci->regs->command); /* unblock posted write */
@@ -635,8 +635,8 @@ done2:
* Before this point the HC was idle/ready. After, khubd
* and device drivers may start it running.
*/
- if (first && hcd_register_root (udev, hcd) != 0) {
- if (hcd->state == USB_STATE_RUNNING)
+ if (first && usb_hcd_register_root_hub (udev, hcd) != 0) {
+ if (hcd->state == HC_STATE_RUNNING)
ehci_quiesce (ehci);
ehci_reset (ehci);
usb_put_dev (udev);
@@ -672,7 +672,7 @@ static void ehci_stop (struct usb_hcd *hcd)
del_timer_sync (&ehci->watchdog);
spin_lock_irq(&ehci->lock);
- if (HCD_IS_RUNNING (hcd->state))
+ if (HC_IS_RUNNING (hcd->state))
ehci_quiesce (ehci);
ehci_reset (ehci);
@@ -839,7 +839,7 @@ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
* misplace IRQs, and should let us run completely without IRQs.
* such lossage has been observed on both VT6202 and VT8235.
*/
- if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
+ if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
(ehci->async->qh_next.ptr != NULL ||
ehci->periodic_sched != 0))
timer_action (ehci, TIMER_IO_WATCHDOG);
@@ -1000,7 +1000,7 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* if we need to use IAA and it's busy, defer */
if (qh->qh_state == QH_STATE_LINKED
&& ehci->reclaim
- && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
+ && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
struct ehci_qh *last;
for (last = ehci->reclaim;
@@ -1011,7 +1011,7 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
last->reclaim = qh;
/* bypass IAA if the hc can't care */
- } else if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
+ } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
end_unlink_async (ehci, NULL);
/* something else might have unlinked the qh by now */
@@ -1059,7 +1059,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
/* reschedule QH iff another request is queued */
if (!list_empty (&qh->qtd_list)
- && HCD_IS_RUNNING (hcd->state)) {
+ && HC_IS_RUNNING (hcd->state)) {
int status;
status = qh_schedule (ehci, qh);
@@ -1115,7 +1115,7 @@ rescan:
goto idle_timeout;
}
- if (!HCD_IS_RUNNING (hcd->state))
+ if (!HC_IS_RUNNING (hcd->state))
qh->qh_state = QH_STATE_IDLE;
switch (qh->qh_state) {
case QH_STATE_LINKED:
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 5d22713149940..2373537fabed3 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -42,9 +42,9 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
spin_lock_irq (&ehci->lock);
/* stop schedules, clean any completed work */
- if (HCD_IS_RUNNING(hcd->state)) {
+ if (HC_IS_RUNNING(hcd->state)) {
ehci_quiesce (ehci);
- hcd->state = USB_STATE_QUIESCING;
+ hcd->state = HC_STATE_QUIESCING;
}
ehci->command = readl (&ehci->regs->command);
if (ehci->reclaim)
@@ -73,7 +73,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
/* turn off now-idle HC */
ehci_halt (ehci);
- hcd->state = HCD_STATE_SUSPENDED;
+ hcd->state = HC_STATE_SUSPENDED;
ehci->next_statechange = jiffies + msecs_to_jiffies(10);
spin_unlock_irq (&ehci->lock);
@@ -145,7 +145,7 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
}
ehci->next_statechange = jiffies + msecs_to_jiffies(5);
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
/* Now we can safely re-enable irqs */
if (intr_enable)
@@ -212,7 +212,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
unsigned long flags;
/* if !USB_SUSPEND, root hub timers won't get shut down ... */
- if (!HCD_IS_RUNNING(hcd->state))
+ if (!HC_IS_RUNNING(hcd->state))
return 0;
/* init status to no-changes */
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index e9300dbcd2295..7df9b9af54f60 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -338,23 +338,24 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
if ((token & QTD_STS_HALT) != 0) {
stopped = 1;
- /* magic dummy for some short reads; qh won't advance */
+ /* magic dummy for some short reads; qh won't advance.
+ * that silicon quirk can kick in with this dummy too.
+ */
} else if (IS_SHORT_READ (token)
- && (qh->hw_alt_next & QTD_MASK)
- == ehci->async->hw_alt_next) {
+ && !(qtd->hw_alt_next & EHCI_LIST_END)) {
stopped = 1;
goto halt;
}
/* stop scanning when we reach qtds the hc is using */
} else if (likely (!stopped
- && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
+ && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
break;
} else {
stopped = 1;
- if (unlikely (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)))
+ if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)))
urb->status = -ESHUTDOWN;
/* ignore active urbs unless some previous qtd
@@ -522,7 +523,7 @@ qh_urb_transaction (
else
buf = 0;
- // FIXME this 'buf' check break some zlps...
+ /* for zero length DATA stages, STATUS is always IN */
if (!buf || is_input)
token |= (1 /* "in" */ << 8);
/* else it's already initted to "out" pid (0 << 8) */
@@ -780,7 +781,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
(void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
cmd |= CMD_ASE | CMD_RUN;
writel (cmd, &ehci->regs->command);
- ehci_to_hcd(ehci)->state = USB_STATE_RUNNING;
+ ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
/* posted write need not be known to HC yet ... */
}
}
@@ -959,7 +960,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
qh_completions (ehci, qh, regs);
if (!list_empty (&qh->qtd_list)
- && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+ && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
qh_link_async (ehci, qh);
else {
qh_put (qh); // refcount from async list
@@ -967,7 +968,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
/* it's not free to turn the async schedule on/off; leave it
* active but idle for a while once it empties.
*/
- if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)
+ if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)
&& ehci->async->qh_next.qh == NULL)
timer_action (ehci, TIMER_ASYNC_OFF);
}
@@ -998,7 +999,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* stop async schedule right now? */
if (unlikely (qh == ehci->async)) {
/* can't get here without STS_ASS set */
- if (ehci_to_hcd(ehci)->state != USB_STATE_HALT) {
+ if (ehci_to_hcd(ehci)->state != HC_STATE_HALT) {
writel (cmd & ~CMD_ASE, &ehci->regs->command);
wmb ();
// handshake later, if we need to
@@ -1018,7 +1019,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
prev->qh_next = qh->qh_next;
wmb ();
- if (unlikely (ehci_to_hcd(ehci)->state == USB_STATE_HALT)) {
+ if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) {
/* if (unlikely (qh->reclaim != 0))
* this will recurse, probably not much
*/
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 9cbde95682188..f6c86354e3049 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -208,7 +208,7 @@ static int tt_no_collision (
here = here.qh->qh_next;
continue;
case Q_TYPE_SITD:
- if (same_tt (dev, here.itd->urb->dev)) {
+ if (same_tt (dev, here.sitd->urb->dev)) {
u16 mask;
mask = le32_to_cpu (here.sitd
@@ -218,7 +218,7 @@ static int tt_no_collision (
if (mask & uf_mask)
break;
}
- type = Q_NEXT_TYPE (here.qh->hw_next);
+ type = Q_NEXT_TYPE (here.sitd->hw_next);
here = here.sitd->sitd_next;
continue;
// case Q_TYPE_FSTN:
@@ -249,14 +249,14 @@ static int enable_periodic (struct ehci_hcd *ehci)
*/
status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125);
if (status != 0) {
- ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return status;
}
cmd = readl (&ehci->regs->command) | CMD_PSE;
writel (cmd, &ehci->regs->command);
/* posted write ... PSS happens later */
- ehci_to_hcd(ehci)->state = USB_STATE_RUNNING;
+ ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
/* make sure ehci_work scans these */
ehci->next_uframe = readl (&ehci->regs->frame_index)
@@ -274,7 +274,7 @@ static int disable_periodic (struct ehci_hcd *ehci)
*/
status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
if (status != 0) {
- ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return status;
}
@@ -1180,7 +1180,10 @@ fail:
return status;
ready:
+ /* report high speed start in uframes; full speed, in frames */
urb->start_frame = stream->next_uframe;
+ if (!stream->highspeed)
+ urb->start_frame >>= 3;
return 0;
}
@@ -1504,18 +1507,17 @@ sitd_sched_init (
/* might need to cross a buffer page within a td */
packet->bufp = buf;
- buf += length;
- packet->buf1 = buf & ~0x0fff;
+ packet->buf1 = (buf + length) & ~0x0fff;
if (packet->buf1 != (buf & ~(u64)0x0fff))
packet->cross = 1;
/* OUT uses multiple start-splits */
if (stream->bEndpointAddress & USB_DIR_IN)
continue;
- length = 1 + (length / 188);
- packet->buf1 |= length;
+ length = (length + 187) / 188;
if (length > 1) /* BEGIN vs ALL */
- packet->buf1 |= 1 << 3;
+ length |= 1 << 3;
+ packet->buf1 |= length;
}
}
@@ -1610,10 +1612,9 @@ sitd_patch (
sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32);
sitd->hw_buf [1] = cpu_to_le32 (uf->buf1);
- if (uf->cross) {
+ if (uf->cross)
bufp += 4096;
- sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
- }
+ sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
sitd->index = index;
}
@@ -1650,7 +1651,7 @@ sitd_link_urb (
ehci_to_hcd(ehci)->self.bandwidth_allocated
+= stream->bandwidth;
ehci_vdbg (ehci,
- "sched dev%s ep%d%s-iso [%d] %dms/%04x\n",
+ "sched devp %s ep%d%s-iso [%d] %dms/%04x\n",
urb->dev->devpath, stream->bEndpointAddress & 0x0f,
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
(next_uframe >> 3) % ehci->periodic_size,
@@ -1697,7 +1698,7 @@ sitd_link_urb (
/*-------------------------------------------------------------------------*/
#define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
- | SITD_STS_XACT | SITD_STS_MMF | SITD_STS_STS)
+ | SITD_STS_XACT | SITD_STS_MMF)
static unsigned
sitd_complete (
@@ -1780,12 +1781,6 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
unsigned long flags;
struct ehci_iso_stream *stream;
- // FIXME remove when csplits behave
- if (usb_pipein(urb->pipe)) {
- ehci_dbg (ehci, "no iso-IN split transactions yet\n");
- return -ENOMEM;
- }
-
/* Get iso_stream head */
stream = iso_stream_find (ehci, urb);
if (stream == NULL) {
@@ -1864,7 +1859,7 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
* Touches as few pages as possible: cache-friendly.
*/
now_uframe = ehci->next_uframe;
- if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+ if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
clock = readl (&ehci->regs->frame_index);
else
clock = now_uframe + mod - 1;
@@ -1898,7 +1893,7 @@ restart:
union ehci_shadow temp;
int live;
- live = HCD_IS_RUNNING (ehci_to_hcd(ehci)->state);
+ live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state);
switch (type) {
case Q_TYPE_QH:
/* handle any completions */
@@ -1987,7 +1982,7 @@ restart:
if (now_uframe == clock) {
unsigned now;
- if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+ if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
break;
ehci->next_uframe = now_uframe;
now = readl (&ehci->regs->frame_index) % mod;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 671fe3810a1a7..67988dba9eb73 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -430,7 +430,7 @@ struct ehci_iso_packet {
__le32 transaction; /* itd->hw_transaction[i] |= */
u8 cross; /* buf crosses pages */
/* for full speed OUT splits */
- u16 buf1;
+ u32 buf1;
};
/* temporary schedule data for packets from iso urbs (both speeds)
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 6e3ad024a75ab..62f53a2138082 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -193,6 +193,10 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
maybe_print_eds (controller, "donehead",
ohci_readl (controller, &regs->donehead), next, size);
+
+ /* broken fminterval means traffic won't flow! */
+ ohci_dbg (controller, "fminterval %08x\n",
+ ohci_readl (controller, &regs->fminterval));
}
#define dbg_port_sw(hc,num,value,next,size) \
@@ -620,9 +624,11 @@ show_registers (struct class_device *class_dev, char *buf)
ohci_dbg_sw (ohci, &next, &size,
"bus %s, device %s\n"
+ "%s\n"
"%s version " DRIVER_VERSION "\n",
hcd->self.controller->bus->name,
hcd->self.controller->bus_id,
+ hcd->product_desc,
hcd_name);
if (bus->controller->power.power_state) {
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 179c7583e6512..1e27f10c1592c 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -252,7 +252,7 @@ static int ohci_urb_enqueue (
spin_lock_irqsave (&ohci->lock, flags);
/* don't submit to a dead HC */
- if (!HCD_IS_RUNNING(hcd->state)) {
+ if (!HC_IS_RUNNING(hcd->state)) {
retval = -ENODEV;
goto fail;
}
@@ -320,7 +320,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
#endif
spin_lock_irqsave (&ohci->lock, flags);
- if (HCD_IS_RUNNING(hcd->state)) {
+ if (HC_IS_RUNNING(hcd->state)) {
urb_priv_t *urb_priv;
/* Unless an IRQ completed the unlink while it was being
@@ -367,7 +367,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
rescan:
spin_lock_irqsave (&ohci->lock, flags);
- if (!HCD_IS_RUNNING (hcd->state)) {
+ if (!HC_IS_RUNNING (hcd->state)) {
sanitize:
ed->state = ED_IDLE;
finish_unlinks (ohci, 0, NULL);
@@ -587,7 +587,6 @@ retry:
// flush those writes
(void) ohci_readl (ohci, &ohci->regs->control);
}
- ohci_writel (ohci, ohci->fminterval, &ohci->regs->fminterval);
/* Tell the controller where the control and bulk lists are
* The lists are empty now. */
@@ -620,7 +619,7 @@ retry:
ohci->hc_control &= OHCI_CTRL_RWC;
ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
- ohci_to_hcd(ohci)->state = USB_STATE_RUNNING;
+ ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
/* wake on ConnectStatusChange, matching external hubs */
ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status);
@@ -656,7 +655,7 @@ retry:
// POTPGT delay is bits 24-31, in 2 ms units.
mdelay ((temp >> 23) & 0x1fe);
bus = &ohci_to_hcd(ohci)->self;
- ohci_to_hcd(ohci)->state = USB_STATE_RUNNING;
+ ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
ohci_dump (ohci, 1);
@@ -675,7 +674,7 @@ retry:
}
udev->speed = USB_SPEED_FULL;
- if (hcd_register_root (udev, ohci_to_hcd(ohci)) != 0) {
+ if (usb_hcd_register_root_hub (udev, ohci_to_hcd(ohci)) != 0) {
usb_put_dev (udev);
disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS;
@@ -728,16 +727,17 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
if (ints & OHCI_INTR_RD) {
ohci_vdbg (ohci, "resume detect\n");
- schedule_work(&ohci->rh_resume);
+ if (hcd->state != HC_STATE_QUIESCING)
+ schedule_work(&ohci->rh_resume);
}
if (ints & OHCI_INTR_WDH) {
- if (HCD_IS_RUNNING(hcd->state))
+ if (HC_IS_RUNNING(hcd->state))
ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
spin_lock (&ohci->lock);
dl_done_list (ohci, ptregs);
spin_unlock (&ohci->lock);
- if (HCD_IS_RUNNING(hcd->state))
+ if (HC_IS_RUNNING(hcd->state))
ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
}
@@ -750,11 +750,11 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
if (ohci->ed_rm_list)
finish_unlinks (ohci, ohci_frame_no(ohci), ptregs);
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
- && HCD_IS_RUNNING(hcd->state))
+ && HC_IS_RUNNING(hcd->state))
ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock);
- if (HCD_IS_RUNNING(hcd->state)) {
+ if (HC_IS_RUNNING(hcd->state)) {
ohci_writel (ohci, ints, &regs->intrstatus);
ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
// flush those writes
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 1c296c3adcbae..e2fc4129dfc6e 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -73,7 +73,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
ohci_dbg (ohci, "suspend root hub\n");
/* First stop any processing */
- hcd->state = USB_STATE_QUIESCING;
+ hcd->state = HC_STATE_QUIESCING;
if (ohci->hc_control & OHCI_SCHED_ENABLES) {
int limit;
@@ -119,7 +119,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
done:
if (status == 0)
- hcd->state = HCD_STATE_SUSPENDED;
+ hcd->state = HC_STATE_SUSPENDED;
spin_unlock_irqrestore (&ohci->lock, flags);
return status;
}
@@ -147,7 +147,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
/* this can happen after suspend-to-disk */
- if (hcd->state == USB_STATE_RESUMING) {
+ if (hcd->state == HC_STATE_RESUMING) {
ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
ohci->hc_control);
status = -EBUSY;
@@ -169,7 +169,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
ohci_info (ohci, "wakeup\n");
break;
case OHCI_USB_OPER:
- ohci_dbg (ohci, "odd resume\n");
+ ohci_dbg (ohci, "already resumed\n");
status = 0;
break;
default: /* RESET, we lost power */
@@ -197,8 +197,8 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
&ohci->regs->roothub.portstatus [temp]);
}
- /* Some controllers (lucent) need extra-long delays */
- hcd->state = USB_STATE_RESUMING;
+ /* Some controllers (lucent erratum) need extra-long delays */
+ hcd->state = HC_STATE_RESUMING;
mdelay (20 /* usb 11.5.1.10 */ + 15);
temp = ohci_readl (ohci, &ohci->regs->control);
@@ -216,6 +216,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
ohci_writel (ohci, 0, &ohci->regs->ed_periodcurrent);
ohci_writel (ohci, (u32) ohci->hcca_dma, &ohci->regs->hcca);
+ /* Sometimes PCI D3 suspend trashes frame timings ... */
periodic_reinit (ohci);
/* interrupts might have been disabled */
@@ -272,7 +273,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
(void) ohci_readl (ohci, &ohci->regs->control);
}
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
return 0;
}
@@ -313,7 +314,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
* letting khubd or root hub timer see state changes.
*/
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
- || !HCD_IS_RUNNING(hcd->state)) {
+ || !HC_IS_RUNNING(hcd->state)) {
can_suspend = 0;
goto done;
}
@@ -378,7 +379,7 @@ done:
) {
ohci_vdbg (ohci, "autosuspend\n");
(void) ohci_hub_suspend (hcd);
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
usb_unlock_device (hcd->self.root_hub);
}
#endif
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index b75a2a6113412..90285f180f87a 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -2,16 +2,14 @@
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2005 David Brownell
* (C) Copyright 2002 Hewlett-Packard Company
*
* OMAP Bus Glue
*
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for OMAP from ohci-sa1111.c by Tony Lindgren <tony@atomide.com>
+ * Modified for OMAP by Tony Lindgren <tony@atomide.com>
* Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc.
+ * and on ohci-sa1111.c by Christopher Hoover <ch@hpl.hp.com>
*
* This file is licenced under the GPL.
*/
@@ -26,8 +24,20 @@
#include <asm/arch/gpio.h>
#include <asm/arch/fpga.h>
#include <asm/arch/usb.h>
+#include <asm/hardware/clock.h>
+
+
+/* OMAP-1510 OHCI has its own MMU for DMA */
+#define OMAP1510_LB_MEMSIZE 32 /* Should be same as SDRAM size */
+#define OMAP1510_LB_CLOCK_DIV 0xfffec10c
+#define OMAP1510_LB_MMU_CTL 0xfffec208
+#define OMAP1510_LB_MMU_LCK 0xfffec224
+#define OMAP1510_LB_MMU_LD_TLB 0xfffec228
+#define OMAP1510_LB_MMU_CAM_H 0xfffec22c
+#define OMAP1510_LB_MMU_CAM_L 0xfffec230
+#define OMAP1510_LB_MMU_RAM_H 0xfffec234
+#define OMAP1510_LB_MMU_RAM_L 0xfffec238
-#include "ohci-omap.h"
#ifndef CONFIG_ARCH_OMAP
#error "This file is OMAP bus glue. CONFIG_OMAP must be defined."
@@ -52,45 +62,17 @@ static inline int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
extern int usb_disabled(void);
extern int ocpi_enable(void);
-/*
- * OHCI clock initialization for OMAP-1510 and 16xx
- */
-static int omap_ohci_clock_power(int on)
+static struct clk *usb_host_ck;
+
+static void omap_ohci_clock_power(int on)
{
if (on) {
- /* for 1510, 48MHz DPLL is set up in usb init */
-
- if (cpu_is_omap16xx()) {
- /* Enable OHCI */
- omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_OTG_REQ,
- ULPD_SOFT_REQ);
-
- /* USB host clock request if not using OTG */
- omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_REQ,
- ULPD_SOFT_REQ);
-
- omap_writel(omap_readl(ULPD_STATUS_REQ) | USB_HOST_DPLL_REQ,
- ULPD_STATUS_REQ);
- }
-
- /* Enable 48MHz clock to USB */
- omap_writel(omap_readl(ULPD_CLOCK_CTRL) | USB_MCLK_EN,
- ULPD_CLOCK_CTRL);
-
- omap_writel(omap_readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK),
- ARM_IDLECT2);
-
- omap_writel(omap_readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN,
- MOD_CONF_CTRL_0);
+ clk_enable(usb_host_ck);
+ /* guesstimate for T5 == 1x 32K clock + APLL lock time */
+ udelay(100);
} else {
- /* Disable 48MHz clock to USB */
- omap_writel(omap_readl(ULPD_CLOCK_CTRL) & ~USB_MCLK_EN,
- ULPD_CLOCK_CTRL);
-
- /* FIXME: The DPLL stays on for now */
+ clk_disable(usb_host_ck);
}
-
- return 0;
}
/*
@@ -204,7 +186,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
/* boards can use OTG transceivers in non-OTG modes */
need_transceiver = need_transceiver
- || machine_is_omap_h2();
+ || machine_is_omap_h2() || machine_is_omap_h3();
if (cpu_is_omap16xx())
ocpi_enable();
@@ -261,7 +243,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
omap_cfg_reg(W4_USB_HIGHZ);
}
ohci_writel(ohci, rh, &ohci->regs->roothub.a);
- // distrust_firmware = 0;
+ distrust_firmware = 0;
}
/* FIXME khubd hub requests should manage power switching */
@@ -278,21 +260,14 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
static void omap_stop_hc(struct platform_device *pdev)
{
dev_dbg(&pdev->dev, "stopping USB Controller\n");
-
- /*
- * FIXME: Put the USB host controller into reset.
- */
-
- /*
- * FIXME: Stop the USB clock.
- */
- //omap_disable_device(dev);
-
+ omap_ohci_clock_power(0);
}
/*-------------------------------------------------------------------------*/
+void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
+
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -309,7 +284,7 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
struct platform_device *pdev)
{
int retval;
- struct usb_hcd *hcd;
+ struct usb_hcd *hcd = 0;
struct ohci_hcd *ohci;
if (pdev->num_resources != 2) {
@@ -319,14 +294,20 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
}
if (pdev->resource[0].flags != IORESOURCE_MEM
- || pdev->resource[1].flags != IORESOURCE_IRQ) {
+ || pdev->resource[1].flags != IORESOURCE_IRQ) {
printk(KERN_ERR "hcd probe: invalid resource type\n");
return -ENODEV;
}
+ usb_host_ck = clk_get(0, "usb_hhc_ck");
+ if (IS_ERR(usb_host_ck))
+ return PTR_ERR(usb_host_ck);
+
hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
- if (!hcd)
- return -ENOMEM;
+ if (!hcd) {
+ retval = -ENOMEM;
+ goto err0;
+ }
hcd->rsrc_start = pdev->resource[0].start;
hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
@@ -336,9 +317,7 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
goto err1;
}
- /* FIXME: Cast to pointer from integer of different size!
- * Needs ioremap */
- hcd->regs = (void __iomem *) (u32) hcd->rsrc_start;
+ hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start);
ohci = hcd_to_ohci(hcd);
ohci_hcd_init(ohci);
@@ -347,20 +326,21 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
if (retval < 0)
goto err2;
- retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
+ retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), SA_INTERRUPT);
if (retval == 0)
return retval;
omap_stop_hc(pdev);
- err2:
+err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
+err1:
usb_put_hcd(hcd);
+err0:
+ clk_put(usb_host_ck);
return retval;
}
-/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
/**
@@ -381,6 +361,7 @@ void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
omap_stop_hc(pdev);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
+ clk_put(usb_host_ck);
}
/*-------------------------------------------------------------------------*/
@@ -397,7 +378,7 @@ ohci_omap_start (struct usb_hcd *hcd)
writel(OHCI_CTRL_RWC, &ohci->regs->control);
if ((ret = ohci_run (ohci)) < 0) {
- err ("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start\n");
ohci_stop (hcd);
return ret;
}
@@ -466,13 +447,14 @@ static int ohci_hcd_omap_drv_remove(struct device *dev)
(void) otg_set_host(ohci->transceiver, 0);
put_device(ohci->transceiver->dev);
}
+ dev_set_drvdata(dev, NULL);
return 0;
}
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef CONFIG_PM
/* states match PCI usage, always suspending the root hub except that
* 4 ~= D3cold (ACPI D3) with clock off (resume sees reset).
@@ -493,13 +475,12 @@ static int ohci_omap_suspend(struct device *dev, u32 state, u32 level)
status = ohci_hub_suspend(ohci_to_hcd(ohci));
if (status == 0) {
if (state >= 4) {
- /* power off + reset */
- OTG_SYSCON_2_REG &= ~UHOST_EN;
+ omap_ohci_clock_power(0);
ohci_to_hcd(ohci)->self.root_hub->state =
USB_STATE_SUSPENDED;
state = 4;
}
- ohci_to_hcd(ohci)->state = HCD_STATE_SUSPENDED;
+ ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
dev->power.power_state = state;
}
up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
@@ -521,7 +502,7 @@ static int ohci_omap_resume(struct device *dev, u32 level)
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
ohci->next_statechange = jiffies;
- OTG_SYSCON_2_REG |= UHOST_EN;
+ omap_ohci_clock_power(1);
/* FALLTHROUGH */
default:
dev_dbg(dev, "resume from %d\n", dev->power.power_state);
@@ -552,7 +533,7 @@ static struct device_driver ohci_hcd_omap_driver = {
.bus = &platform_bus_type,
.probe = ohci_hcd_omap_drv_probe,
.remove = ohci_hcd_omap_drv_remove,
-#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef CONFIG_PM
.suspend = ohci_omap_suspend,
.resume = ohci_omap_resume,
#endif
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 14c2e932dd890..c90114a772776 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -172,7 +172,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
{
int branch;
- if (ohci_to_hcd(ohci)->state == USB_STATE_QUIESCING)
+ if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING)
return -EAGAIN;
ed->state = ED_OPER;
@@ -663,7 +663,7 @@ static void td_submit_urb (
/* NOTE: mishandles transfers >8K, some >4K */
td_fill (ohci, info, data, data_len, urb, cnt++);
}
- info = is_out
+ info = (is_out || data_len == 0)
? TD_CC | TD_DP_IN | TD_T_DATA1
: TD_CC | TD_DP_OUT | TD_T_DATA1;
td_fill (ohci, info, data, 0, urb, cnt++);
@@ -923,7 +923,7 @@ rescan_all:
/* only take off EDs that the HC isn't using, accounting for
* frame counter wraps and EDs with partially retired TDs
*/
- if (likely (regs && HCD_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
+ if (likely (regs && HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
if (tick_before (tick, ed->tick)) {
skip_ed:
last = &ed->ed_next;
@@ -1005,7 +1005,7 @@ rescan_this:
/* but if there's work queued, reschedule */
if (!list_empty (&ed->td_list)) {
- if (HCD_IS_RUNNING(ohci_to_hcd(ohci)->state))
+ if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state))
ed_schedule (ohci, ed);
}
@@ -1014,8 +1014,8 @@ rescan_this:
}
/* maybe reenable control and bulk lists */
- if (HCD_IS_RUNNING(ohci_to_hcd(ohci)->state)
- && ohci_to_hcd(ohci)->state != USB_STATE_QUIESCING
+ if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state)
+ && ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING
&& !ohci->ed_rm_list) {
u32 command = 0, control = 0;
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 94ad4b47f9de4..2ba6e2b0210c9 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -594,17 +594,21 @@ static inline u16 ohci_hwPSW(const struct ohci_hcd *ohci,
static inline void disable (struct ohci_hcd *ohci)
{
- ohci_to_hcd(ohci)->state = USB_STATE_HALT;
+ ohci_to_hcd(ohci)->state = HC_STATE_HALT;
}
#define FI 0x2edf /* 12000 bits per frame (-1) */
#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
+#define FIT (1 << 31)
#define LSTHRESH 0x628 /* lowspeed bit threshold */
-static inline void periodic_reinit (struct ohci_hcd *ohci)
+static void periodic_reinit (struct ohci_hcd *ohci)
{
- u32 fi = ohci->fminterval & 0x0ffff;
+ u32 fi = ohci->fminterval & 0x03fff;
+ u32 fit = ohci_readl(ohci, &ohci->regs->fminterval) & FIT;
+ ohci_writel (ohci, (fit ^ FIT) | ohci->fminterval,
+ &ohci->regs->fminterval);
ohci_writel (ohci, ((9 * fi) / 10) & 0x3fff,
&ohci->regs->periodicstart);
}
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index b40a4039e1935..d309e292198ed 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -101,12 +101,12 @@ static void port_power(struct sl811 *sl811, int is_on)
sl811->port1 = (1 << USB_PORT_FEAT_POWER);
sl811->irq_enable = SL11H_INTMASK_INSRMV;
- hcd->self.controller->power.power_state = PM_SUSPEND_ON;
+ hcd->self.controller->power.power_state = PMSG_ON;
} else {
sl811->port1 = 0;
sl811->irq_enable = 0;
- hcd->state = USB_STATE_HALT;
- hcd->self.controller->power.power_state = PM_SUSPEND_DISK;
+ hcd->state = HC_STATE_HALT;
+ hcd->self.controller->power.power_state = PMSG_SUSPEND;
}
sl811->ctrl1 = 0;
sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
@@ -834,7 +834,7 @@ static int sl811h_urb_enqueue(
/* don't submit to a dead or disabled port */
if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
- || !HCD_IS_RUNNING(hcd->state)) {
+ || !HC_IS_RUNNING(hcd->state)) {
retval = -ENODEV;
goto fail;
}
@@ -1562,12 +1562,12 @@ sl811h_start(struct usb_hcd *hcd)
return -ENOMEM;
udev->speed = USB_SPEED_FULL;
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
if (sl811->board)
hcd->can_wakeup = sl811->board->can_wakeup;
- if (hcd_register_root(udev, hcd) != 0) {
+ if (usb_hcd_register_root_hub(udev, hcd) != 0) {
usb_put_dev(udev);
sl811h_stop(hcd);
return -ENODEV;
@@ -1772,7 +1772,7 @@ sl811h_probe(struct device *dev)
*/
static int
-sl811h_suspend(struct device *dev, u32 state, u32 phase)
+sl811h_suspend(struct device *dev, pm_message_t state, u32 phase)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct sl811 *sl811 = hcd_to_sl811(hcd);
@@ -1809,7 +1809,7 @@ sl811h_resume(struct device *dev, u32 phase)
return 0;
}
- dev->power.power_state = PM_SUSPEND_ON;
+ dev->power.power_state = PMSG_ON;
return sl811h_hub_resume(hcd);
}
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index eeb7073a225b2..24c73c5a34354 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -406,7 +406,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
struct uhci_td *td;
struct list_head *tmp, *head;
- spin_lock_irqsave(&uhci->schedule_lock, flags);
+ spin_lock_irqsave(&uhci->lock, flags);
out += sprintf(out, "HC status\n");
out += uhci_show_status(uhci, out, len - (out - buf));
@@ -492,7 +492,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
if (debug > 2)
out += uhci_show_lists(uhci, out, len - (out - buf));
- spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+ spin_unlock_irqrestore(&uhci->lock, flags);
return out - buf;
}
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 00376bda34bfd..324a1a9bbdb2d 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -89,7 +89,7 @@ static char *errbuf;
static kmem_cache_t *uhci_up_cachep; /* urb_priv */
-static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci);
+static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
static void hc_state_transitions(struct uhci_hcd *uhci);
/* If a transfer is still active after this much time, turn off FSBR */
@@ -113,15 +113,9 @@ static void stall_callback(unsigned long ptr)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
struct urb_priv *up;
unsigned long flags;
- int called_uhci_finish_completion = 0;
-
- spin_lock_irqsave(&uhci->schedule_lock, flags);
- if (!list_empty(&uhci->urb_remove_list) &&
- uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) {
- uhci_remove_pending_urbps(uhci);
- uhci_finish_completion(hcd, NULL);
- called_uhci_finish_completion = 1;
- }
+
+ spin_lock_irqsave(&uhci->lock, flags);
+ uhci_scan_schedule(uhci, NULL);
list_for_each_entry(up, &uhci->urb_list, urb_list) {
struct urb *u = up->urb;
@@ -134,11 +128,6 @@ static void stall_callback(unsigned long ptr)
spin_unlock(&u->lock);
}
- spin_unlock_irqrestore(&uhci->schedule_lock, flags);
-
- /* Wake up anyone waiting for an URB to complete */
- if (called_uhci_finish_completion)
- wake_up_all(&uhci->waitqh);
/* Really disable FSBR */
if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
@@ -149,9 +138,10 @@ static void stall_callback(unsigned long ptr)
/* Poll for and perform state transitions */
hc_state_transitions(uhci);
if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
- uhci_check_resume(uhci);
+ uhci_check_ports(uhci);
init_stall_timer(hcd);
+ spin_unlock_irqrestore(&uhci->lock, flags);
}
static int init_stall_timer(struct usb_hcd *hcd)
@@ -172,8 +162,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
unsigned long io_addr = uhci->io_addr;
unsigned short status;
- struct urb_priv *urbp, *tmp;
- unsigned int age;
/*
* Read the interrupt status, and write it back to clear the
@@ -202,37 +190,9 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (status & USBSTS_RD)
uhci->resume_detect = 1;
- spin_lock(&uhci->schedule_lock);
-
- age = uhci_get_current_frame_number(uhci);
- if (age != uhci->qh_remove_age)
- uhci_free_pending_qhs(uhci);
- if (age != uhci->td_remove_age)
- uhci_free_pending_tds(uhci);
- if (age != uhci->urb_remove_age)
- uhci_remove_pending_urbps(uhci);
-
- if (list_empty(&uhci->urb_remove_list) &&
- list_empty(&uhci->td_remove_list) &&
- list_empty(&uhci->qh_remove_list))
- uhci_clear_next_interrupt(uhci);
- else
- uhci_set_next_interrupt(uhci);
-
- /* Walk the list of pending URBs to see which ones completed
- * (must be _safe because uhci_transfer_result() dequeues URBs) */
- list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) {
- struct urb *urb = urbp->urb;
-
- /* Checks the status and does all of the magic necessary */
- uhci_transfer_result(uhci, urb);
- }
- uhci_finish_completion(hcd, regs);
-
- spin_unlock(&uhci->schedule_lock);
-
- /* Wake up anyone waiting for an URB to complete */
- wake_up_all(&uhci->waitqh);
+ spin_lock(&uhci->lock);
+ uhci_scan_schedule(uhci, regs);
+ spin_unlock(&uhci->lock);
return IRQ_HANDLED;
}
@@ -256,6 +216,7 @@ static void reset_hc(struct uhci_hcd *uhci)
/* Another 10ms delay */
msleep(10);
uhci->resume_detect = 0;
+ uhci->is_stopped = UHCI_IS_STOPPED;
}
static void suspend_hc(struct uhci_hcd *uhci)
@@ -266,6 +227,12 @@ static void suspend_hc(struct uhci_hcd *uhci)
uhci->state = UHCI_SUSPENDED;
uhci->resume_detect = 0;
outw(USBCMD_EGSM, io_addr + USBCMD);
+
+ /* FIXME: Wait for the controller to actually stop */
+ uhci_get_current_frame_number(uhci);
+ uhci->is_stopped = UHCI_IS_STOPPED;
+
+ uhci_scan_schedule(uhci, NULL);
}
static void wakeup_hc(struct uhci_hcd *uhci)
@@ -280,6 +247,7 @@ static void wakeup_hc(struct uhci_hcd *uhci)
outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD);
uhci->state = UHCI_RESUMING_1;
uhci->state_end = jiffies + msecs_to_jiffies(20);
+ uhci->is_stopped = 0;
break;
case UHCI_RESUMING_1: /* End global resume */
@@ -386,11 +354,13 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
}
/*
- * returns the current frame number for a USB bus/controller.
+ * Store the current frame number in uhci->frame_number if the controller
+ * is runnning
*/
-static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci)
+static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
{
- return inw(uhci->io_addr + USBFRNUM);
+ if (!uhci->is_stopped)
+ uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
}
static int start_hc(struct uhci_hcd *uhci)
@@ -413,6 +383,9 @@ static int start_hc(struct uhci_hcd *uhci)
msleep(1);
}
+ /* Mark controller as running before we enable interrupts */
+ uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+
/* Turn on PIRQ and all interrupts */
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
USBLEGSUP_DEFAULT);
@@ -427,8 +400,8 @@ static int start_hc(struct uhci_hcd *uhci)
uhci->state = UHCI_RUNNING_GRACE;
uhci->state_end = jiffies + HZ;
outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
+ uhci->is_stopped = 0;
- uhci_to_hcd(uhci)->state = USB_STATE_RUNNING;
return 0;
}
@@ -524,7 +497,7 @@ static int uhci_start(struct usb_hcd *hcd)
uhci->fsbr = 0;
uhci->fsbrtimeout = 0;
- spin_lock_init(&uhci->schedule_lock);
+ spin_lock_init(&uhci->lock);
INIT_LIST_HEAD(&uhci->qh_remove_list);
INIT_LIST_HEAD(&uhci->td_remove_list);
@@ -678,7 +651,7 @@ static int uhci_start(struct usb_hcd *hcd)
udev->speed = USB_SPEED_FULL;
- if (hcd_register_root(udev, hcd) != 0) {
+ if (usb_hcd_register_root_hub(udev, hcd) != 0) {
dev_err(uhci_dev(uhci), "unable to start root hub\n");
retval = -ENOMEM;
goto err_start_root_hub;
@@ -733,26 +706,11 @@ static void uhci_stop(struct usb_hcd *hcd)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
del_timer_sync(&uhci->stall_timer);
-
- /*
- * At this point, we're guaranteed that no new connects can be made
- * to this bus since there are no more parents
- */
-
reset_hc(uhci);
- spin_lock_irq(&uhci->schedule_lock);
- uhci_free_pending_qhs(uhci);
- uhci_free_pending_tds(uhci);
- uhci_remove_pending_urbps(uhci);
- uhci_finish_completion(hcd, NULL);
-
- uhci_free_pending_qhs(uhci);
- uhci_free_pending_tds(uhci);
- spin_unlock_irq(&uhci->schedule_lock);
-
- /* Wake up anyone waiting for an URB to complete */
- wake_up_all(&uhci->waitqh);
+ spin_lock_irq(&uhci->lock);
+ uhci_scan_schedule(uhci, NULL);
+ spin_unlock_irq(&uhci->lock);
release_uhci(uhci);
}
@@ -762,13 +720,19 @@ static int uhci_suspend(struct usb_hcd *hcd, u32 state)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ spin_lock_irq(&uhci->lock);
+
/* Don't try to suspend broken motherboards, reset instead */
- if (suspend_allowed(uhci)) {
+ if (suspend_allowed(uhci))
suspend_hc(uhci);
- uhci->saved_framenumber =
- inw(uhci->io_addr + USBFRNUM) & 0x3ff;
- } else
+ else {
+ spin_unlock_irq(&uhci->lock);
reset_hc(uhci);
+ spin_lock_irq(&uhci->lock);
+ uhci_scan_schedule(uhci, NULL);
+ }
+
+ spin_unlock_irq(&uhci->lock);
return 0;
}
@@ -779,6 +743,8 @@ static int uhci_resume(struct usb_hcd *hcd)
pci_set_master(to_pci_dev(uhci_dev(uhci)));
+ spin_lock_irq(&uhci->lock);
+
if (uhci->state == UHCI_SUSPENDED) {
/*
@@ -789,7 +755,7 @@ static int uhci_resume(struct usb_hcd *hcd)
*/
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
0);
- outw(uhci->saved_framenumber, uhci->io_addr + USBFRNUM);
+ outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
USBINTR_SP, uhci->io_addr + USBINTR);
@@ -797,11 +763,15 @@ static int uhci_resume(struct usb_hcd *hcd)
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
USBLEGSUP_DEFAULT);
} else {
+ spin_unlock_irq(&uhci->lock);
reset_hc(uhci);
if ((rc = start_hc(uhci)) != 0)
return rc;
+ spin_lock_irq(&uhci->lock);
}
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
+
+ spin_unlock_irq(&uhci->lock);
return 0;
}
#endif
@@ -817,7 +787,17 @@ static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
{
- return uhci_get_current_frame_number(hcd_to_uhci(hcd));
+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ int frame_number;
+ unsigned long flags;
+
+ /* Minimize latency by avoiding the spinlock */
+ local_irq_save(flags);
+ rmb();
+ frame_number = (uhci->is_stopped ? uhci->frame_number :
+ inw(uhci->io_addr + USBFRNUM));
+ local_irq_restore(flags);
+ return frame_number;
}
static const char hcd_name[] = "uhci_hcd";
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index fee7c52dcc317..02255d69e1fef 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -358,39 +358,44 @@ struct uhci_hcd {
struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
- spinlock_t schedule_lock;
- struct uhci_frame_list *fl; /* P: uhci->schedule_lock */
+ spinlock_t lock;
+ struct uhci_frame_list *fl; /* P: uhci->lock */
int fsbr; /* Full-speed bandwidth reclamation */
unsigned long fsbrtimeout; /* FSBR delay */
enum uhci_state state; /* FIXME: needs a spinlock */
unsigned long state_end; /* Time of next transition */
- int resume_detect; /* Need a Global Resume */
- unsigned int saved_framenumber; /* Save during PM suspend */
+ unsigned int frame_number; /* As of last check */
+ unsigned int is_stopped;
+#define UHCI_IS_STOPPED 9999 /* Larger than a frame # */
- /* Support for port suspend/resume */
+ unsigned int scan_in_progress:1; /* Schedule scan is running */
+ unsigned int need_rescan:1; /* Redo the schedule scan */
+ unsigned int resume_detect:1; /* Need a Global Resume */
+
+ /* Support for port suspend/resume/reset */
unsigned long port_c_suspend; /* Bit-arrays of ports */
unsigned long suspended_ports;
unsigned long resuming_ports;
- unsigned long resume_timeout; /* Time to stop signalling */
+ unsigned long ports_timeout; /* Time to stop signalling */
/* Main list of URB's currently controlled by this HC */
- struct list_head urb_list; /* P: uhci->schedule_lock */
+ struct list_head urb_list; /* P: uhci->lock */
/* List of QH's that are done, but waiting to be unlinked (race) */
- struct list_head qh_remove_list; /* P: uhci->schedule_lock */
+ struct list_head qh_remove_list; /* P: uhci->lock */
unsigned int qh_remove_age; /* Age in frames */
/* List of TD's that are done, but waiting to be freed (race) */
- struct list_head td_remove_list; /* P: uhci->schedule_lock */
+ struct list_head td_remove_list; /* P: uhci->lock */
unsigned int td_remove_age; /* Age in frames */
/* List of asynchronously unlinked URB's */
- struct list_head urb_remove_list; /* P: uhci->schedule_lock */
+ struct list_head urb_remove_list; /* P: uhci->lock */
unsigned int urb_remove_age; /* Age in frames */
/* List of URB's awaiting completion callback */
- struct list_head complete_list; /* P: uhci->schedule_lock */
+ struct list_head complete_list; /* P: uhci->lock */
int rh_numports;
@@ -436,13 +441,13 @@ struct urb_priv {
* Locking in uhci.c
*
* Almost everything relating to the hardware schedule and processing
- * of URBs is protected by uhci->schedule_lock. urb->status is protected
- * by urb->lock; that's the one exception.
+ * of URBs is protected by uhci->lock. urb->status is protected by
+ * urb->lock; that's the one exception.
*
- * To prevent deadlocks, never lock uhci->schedule_lock while holding
- * urb->lock. The safe order of locking is:
+ * To prevent deadlocks, never lock uhci->lock while holding urb->lock.
+ * The safe order of locking is:
*
- * #1 uhci->schedule_lock
+ * #1 uhci->lock
* #2 urb->lock
*/
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 1feccf2f03b53..4c45ba8390f8a 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -66,7 +66,6 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
/* UHCI controllers don't automatically stop resume signalling after 20 msec,
* so we have to poll and check timeouts in order to take care of it.
- * FIXME: Synchronize access to these fields by a spinlock.
*/
static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
unsigned long port_addr)
@@ -87,22 +86,37 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
}
}
-static void uhci_check_resume(struct uhci_hcd *uhci)
+static void uhci_check_ports(struct uhci_hcd *uhci)
{
unsigned int port;
unsigned long port_addr;
+ int status;
for (port = 0; port < uhci->rh_numports; ++port) {
port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
- if (unlikely(inw(port_addr) & USBPORTSC_RD)) {
+ status = inw(port_addr);
+ if (unlikely(status & USBPORTSC_PR)) {
+ if (time_after_eq(jiffies, uhci->ports_timeout)) {
+ CLR_RH_PORTSTAT(USBPORTSC_PR);
+ udelay(10);
+
+ /* If the port was enabled before, turning
+ * reset on caused a port enable change.
+ * Turning reset off causes a port connect
+ * status change. Clear these changes. */
+ CLR_RH_PORTSTAT(USBPORTSC_CSC | USBPORTSC_PEC);
+ SET_RH_PORTSTAT(USBPORTSC_PE);
+ }
+ }
+ if (unlikely(status & USBPORTSC_RD)) {
if (!test_bit(port, &uhci->resuming_ports)) {
/* Port received a wakeup request */
set_bit(port, &uhci->resuming_ports);
- uhci->resume_timeout = jiffies +
+ uhci->ports_timeout = jiffies +
msecs_to_jiffies(20);
} else if (time_after_eq(jiffies,
- uhci->resume_timeout)) {
+ uhci->ports_timeout)) {
uhci_finish_suspend(uhci, port, port_addr);
}
}
@@ -118,7 +132,9 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
unsigned int port = wIndex - 1;
unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
u16 wPortChange, wPortStatus;
+ unsigned long flags;
+ spin_lock_irqsave(&uhci->lock, flags);
switch (typeReq) {
case GetHubStatus:
@@ -128,9 +144,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (port >= uhci->rh_numports)
goto err;
- if (uhci->resuming_ports)
- uhci_check_resume(uhci);
-
+ uhci_check_ports(uhci);
status = inw(port_addr);
/* Intel controllers report the OverCurrent bit active on.
@@ -203,15 +217,12 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
OK(0);
case USB_PORT_FEAT_RESET:
SET_RH_PORTSTAT(USBPORTSC_PR);
- mdelay(50); /* USB v1.1 7.1.7.3 */
- CLR_RH_PORTSTAT(USBPORTSC_PR);
- udelay(10);
/* Reset terminates Resume signalling */
uhci_finish_suspend(uhci, port, port_addr);
- SET_RH_PORTSTAT(USBPORTSC_PE);
- mdelay(10);
- CLR_RH_PORTSTAT(USBPORTSC_PEC|USBPORTSC_CSC);
+
+ /* USB v2.0 7.1.7.5 */
+ uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
OK(0);
case USB_PORT_FEAT_POWER:
/* UHCI has no power switching */
@@ -238,8 +249,6 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (test_bit(port, &uhci->suspended_ports) &&
!test_and_set_bit(port,
&uhci->resuming_ports)) {
- uhci->resume_timeout = jiffies +
- msecs_to_jiffies(20);
SET_RH_PORTSTAT(USBPORTSC_RD);
/* The controller won't allow RD to be set
@@ -249,6 +258,10 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (!(inw(port_addr) & USBPORTSC_RD))
uhci_finish_suspend(uhci, port,
port_addr);
+ else
+ /* USB v2.0 7.1.7.7 */
+ uhci->ports_timeout = jiffies +
+ msecs_to_jiffies(20);
}
OK(0);
case USB_PORT_FEAT_C_SUSPEND:
@@ -280,6 +293,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
err:
retval = -EPIPE;
}
+ spin_unlock_irqrestore(&uhci->lock, flags);
return retval;
}
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 5a301ff13d84d..2a7c19501f248 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -264,7 +264,6 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
{
struct uhci_qh *pqh;
__le32 newlink;
- unsigned int age;
if (!qh)
return;
@@ -310,10 +309,10 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
list_del_init(&qh->urbp->queue_list);
qh->urbp = NULL;
- age = uhci_get_current_frame_number(uhci);
- if (age != uhci->qh_remove_age) {
+ uhci_get_current_frame_number(uhci);
+ if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) {
uhci_free_pending_qhs(uhci);
- uhci->qh_remove_age = age;
+ uhci->qh_remove_age = uhci->frame_number;
}
/* Check to see if the remove list is empty. Set the IOC bit */
@@ -492,7 +491,6 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
{
struct uhci_td *td, *tmp;
struct urb_priv *urbp;
- unsigned int age;
urbp = (struct urb_priv *)urb->hcpriv;
if (!urbp)
@@ -502,10 +500,10 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list "
"or uhci->remove_list!\n", urb);
- age = uhci_get_current_frame_number(uhci);
- if (age != uhci->td_remove_age) {
+ uhci_get_current_frame_number(uhci);
+ if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) {
uhci_free_pending_tds(uhci);
- uhci->td_remove_age = age;
+ uhci->td_remove_age = uhci->frame_number;
}
/* Check to see if the remove list is empty. Set the IOC bit */
@@ -1063,11 +1061,11 @@ static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb)
limits = isochronous_find_limits(uhci, urb, &start, &end);
if (urb->transfer_flags & URB_ISO_ASAP) {
- if (limits)
- urb->start_frame =
- (uhci_get_current_frame_number(uhci) +
- 10) & (UHCI_NUMFRAMES - 1);
- else
+ if (limits) {
+ uhci_get_current_frame_number(uhci);
+ urb->start_frame = (uhci->frame_number + 10)
+ & (UHCI_NUMFRAMES - 1);
+ } else
urb->start_frame = end;
} else {
urb->start_frame &= (UHCI_NUMFRAMES - 1);
@@ -1184,7 +1182,7 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
struct urb *eurb;
int bustime;
- spin_lock_irqsave(&uhci->schedule_lock, flags);
+ spin_lock_irqsave(&uhci->lock, flags);
ret = urb->status;
if (ret != -EINPROGRESS) /* URB already unlinked! */
@@ -1242,7 +1240,7 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
ret = 0;
out:
- spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+ spin_unlock_irqrestore(&uhci->lock, flags);
return ret;
}
@@ -1371,9 +1369,8 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
unsigned long flags;
struct urb_priv *urbp;
- unsigned int age;
- spin_lock_irqsave(&uhci->schedule_lock, flags);
+ spin_lock_irqsave(&uhci->lock, flags);
urbp = urb->hcpriv;
if (!urbp) /* URB was never linked! */
goto done;
@@ -1381,10 +1378,10 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
uhci_unlink_generic(uhci, urb);
- age = uhci_get_current_frame_number(uhci);
- if (age != uhci->urb_remove_age) {
+ uhci_get_current_frame_number(uhci);
+ if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) {
uhci_remove_pending_urbps(uhci);
- uhci->urb_remove_age = age;
+ uhci->urb_remove_age = uhci->frame_number;
}
/* If we're the first, set the next interrupt bit */
@@ -1393,7 +1390,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
done:
- spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+ spin_unlock_irqrestore(&uhci->lock, flags);
return 0;
}
@@ -1455,28 +1452,27 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci)
static void
uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
-__releases(uhci->schedule_lock)
-__acquires(uhci->schedule_lock)
+__releases(uhci->lock)
+__acquires(uhci->lock)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
uhci_destroy_urb_priv(uhci, urb);
- spin_unlock(&uhci->schedule_lock);
+ spin_unlock(&uhci->lock);
usb_hcd_giveback_urb(hcd, urb, regs);
- spin_lock(&uhci->schedule_lock);
+ spin_lock(&uhci->lock);
}
-static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs)
+static void uhci_finish_completion(struct uhci_hcd *uhci, struct pt_regs *regs)
{
- struct uhci_hcd *uhci = hcd_to_uhci(hcd);
struct urb_priv *urbp, *tmp;
list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) {
struct urb *urb = urbp->urb;
list_del_init(&urbp->urb_list);
- uhci_finish_urb(hcd, urb, regs);
+ uhci_finish_urb(uhci_to_hcd(uhci), urb, regs);
}
}
@@ -1486,3 +1482,58 @@ static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
/* Splice the urb_remove_list onto the end of the complete_list */
list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev);
}
+
+/* Process events in the schedule, but only in one thread at a time */
+static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+{
+ struct urb_priv *urbp, *tmp;
+
+ /* Don't allow re-entrant calls */
+ if (uhci->scan_in_progress) {
+ uhci->need_rescan = 1;
+ return;
+ }
+ uhci->scan_in_progress = 1;
+ rescan:
+ uhci->need_rescan = 0;
+
+ uhci_get_current_frame_number(uhci);
+
+ if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age)
+ uhci_free_pending_qhs(uhci);
+ if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age)
+ uhci_free_pending_tds(uhci);
+ if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age)
+ uhci_remove_pending_urbps(uhci);
+
+ /* Walk the list of pending URBs to see which ones completed
+ * (must be _safe because uhci_transfer_result() dequeues URBs) */
+ list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) {
+ struct urb *urb = urbp->urb;
+
+ /* Checks the status and does all of the magic necessary */
+ uhci_transfer_result(uhci, urb);
+ }
+ uhci_finish_completion(uhci, regs);
+
+ /* If the controller is stopped, we can finish these off right now */
+ if (uhci->is_stopped) {
+ uhci_free_pending_qhs(uhci);
+ uhci_free_pending_tds(uhci);
+ uhci_remove_pending_urbps(uhci);
+ }
+
+ if (uhci->need_rescan)
+ goto rescan;
+ uhci->scan_in_progress = 0;
+
+ if (list_empty(&uhci->urb_remove_list) &&
+ list_empty(&uhci->td_remove_list) &&
+ list_empty(&uhci->qh_remove_list))
+ uhci_clear_next_interrupt(uhci);
+ else
+ uhci_set_next_interrupt(uhci);
+
+ /* Wake up anyone waiting for an URB to complete */
+ wake_up_all(&uhci->waitqh);
+}
diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig
index df508cb14c89d..95ce703110d27 100644
--- a/drivers/usb/image/Kconfig
+++ b/drivers/usb/image/Kconfig
@@ -28,14 +28,3 @@ config USB_MICROTEK
The scanner will appear as a scsi generic device to the rest
of the system. Scsi support is required.
This driver can be compiled as a module, called microtek.
-
-config USB_HPUSBSCSI
- tristate "HP53xx USB scanner support"
- depends on USB && SCSI && BROKEN
- help
- Say Y here if you want support for the HP 53xx series of scanners
- and the Minolta Scan Dual.
- The scanner will be accessible as a SCSI device.
- Please note that recent versions of SANE use usbfs, not this driver.
- This can be compiled as a module, called hpusbscsi.
-
diff --git a/drivers/usb/image/Makefile b/drivers/usb/image/Makefile
index f01a73959c4e1..4148ae306352b 100644
--- a/drivers/usb/image/Makefile
+++ b/drivers/usb/image/Makefile
@@ -3,5 +3,4 @@
#
obj-$(CONFIG_USB_MDC800) += mdc800.o
-obj-$(CONFIG_USB_HPUSBSCSI) += hpusbscsi.o
obj-$(CONFIG_USB_MICROTEK) += microtek.o
diff --git a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c
deleted file mode 100644
index 47a864b29f3d9..0000000000000
--- a/drivers/usb/image/hpusbscsi.c
+++ /dev/null
@@ -1,523 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-#include <linux/usb.h>
-#include <asm/atomic.h>
-#include <linux/blkdev.h>
-#include "../../scsi/scsi.h"
-#include <scsi/scsi_host.h>
-
-#include "hpusbscsi.h"
-
-#define DEBUG(x...) \
- printk( KERN_DEBUG x )
-
-static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATURE"};
-
-#define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__)
-
-static Scsi_Host_Template hpusbscsi_scsi_host_template = {
- .module = THIS_MODULE,
- .name = "hpusbscsi",
- .proc_name = "hpusbscsi",
- .queuecommand = hpusbscsi_scsi_queuecommand,
- .eh_abort_handler = hpusbscsi_scsi_abort,
- .eh_host_reset_handler = hpusbscsi_scsi_host_reset,
- .sg_tablesize = SG_ALL,
- .can_queue = 1,
- .this_id = -1,
- .cmd_per_lun = 1,
- .use_clustering = 1,
- .emulated = 1,
-};
-
-static int
-hpusbscsi_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *dev = interface_to_usbdev(intf);
- struct usb_host_interface *altsetting = intf->cur_altsetting;
- struct hpusbscsi *new;
- int error = -ENOMEM;
- int i;
-
- if (altsetting->desc.bNumEndpoints != 3) {
- printk (KERN_ERR "Wrong number of endpoints\n");
- return -ENODEV;
- }
-
- new = kmalloc(sizeof(struct hpusbscsi), GFP_KERNEL);
- if (!new)
- return -ENOMEM;
- memset(new, 0, sizeof(struct hpusbscsi));
- new->dataurb = usb_alloc_urb(0, GFP_KERNEL);
- if (!new->dataurb)
- goto out_kfree;
- new->controlurb = usb_alloc_urb(0, GFP_KERNEL);
- if (!new->controlurb)
- goto out_free_dataurb;
-
- new->dev = dev;
- init_waitqueue_head(&new->pending);
- init_waitqueue_head(&new->deathrow);
-
- error = -ENODEV;
- for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
- if ((altsetting->endpoint[i].desc.
- bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK) {
- if (altsetting->endpoint[i].desc.
- bEndpointAddress & USB_DIR_IN) {
- new->ep_in =
- altsetting->endpoint[i].desc.
- bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- } else {
- new->ep_out =
- altsetting->endpoint[i].desc.
- bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- }
- } else {
- new->ep_int =
- altsetting->endpoint[i].desc.
- bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- new->interrupt_interval= altsetting->endpoint[i].desc.
- bInterval;
- }
- }
-
- /* build and submit an interrupt URB for status byte handling */
- usb_fill_int_urb(new->controlurb, new->dev,
- usb_rcvintpipe(new->dev, new->ep_int),
- &new->scsi_state_byte, 1,
- control_interrupt_callback,new,
- new->interrupt_interval);
-
- if (usb_submit_urb(new->controlurb, GFP_KERNEL) < 0)
- goto out_free_controlurb;
-
- /* In host->hostdata we store a pointer to desc */
- new->host = scsi_host_alloc(&hpusbscsi_scsi_host_template, sizeof(new));
- if (!new->host)
- goto out_kill_controlurb;
-
- new->host->hostdata[0] = (unsigned long)new;
- scsi_add_host(new->host, &intf->dev); /* XXX handle failure */
- scsi_scan_host(new->host);
-
- new->sense_command[0] = REQUEST_SENSE;
- new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
-
- usb_set_intfdata(intf, new);
- return 0;
-
- out_kill_controlurb:
- usb_kill_urb(new->controlurb);
- out_free_controlurb:
- usb_free_urb(new->controlurb);
- out_free_dataurb:
- usb_free_urb(new->dataurb);
- out_kfree:
- kfree(new);
- return error;
-}
-
-static void
-hpusbscsi_usb_disconnect(struct usb_interface *intf)
-{
- struct hpusbscsi *desc = usb_get_intfdata(intf);
-
- usb_set_intfdata(intf, NULL);
-
- scsi_remove_host(desc->host);
- usb_kill_urb(desc->controlurb);
- scsi_host_put(desc->host);
-
- usb_free_urb(desc->controlurb);
- usb_free_urb(desc->dataurb);
- kfree(desc);
-}
-
-static struct usb_device_id hpusbscsi_usb_ids[] = {
- {USB_DEVICE (0x03f0, 0x0701)}, /* HP 53xx */
- {USB_DEVICE (0x03f0, 0x0801)}, /* HP 7400 */
- {USB_DEVICE (0x0638, 0x0268)}, /*iVina 1200U */
- {USB_DEVICE (0x0638, 0x026a)}, /*Scan Dual II */
- {USB_DEVICE (0x0638, 0x0A13)}, /*Avision AV600U */
- {USB_DEVICE (0x0638, 0x0A16)}, /*Avision DS610CU Scancopier */
- {USB_DEVICE (0x0638, 0x0A18)}, /*Avision AV600U Plus */
- {USB_DEVICE (0x0638, 0x0A23)}, /*Avision AV220 */
- {USB_DEVICE (0x0638, 0x0A24)}, /*Avision AV210 */
- {USB_DEVICE (0x0686, 0x4004)}, /*Minolta Elite II */
- {} /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, hpusbscsi_usb_ids);
-MODULE_LICENSE("GPL");
-
-
-static struct usb_driver hpusbscsi_usb_driver = {
- .owner = THIS_MODULE,
- .name ="hpusbscsi",
- .probe =hpusbscsi_usb_probe,
- .disconnect =hpusbscsi_usb_disconnect,
- .id_table =hpusbscsi_usb_ids,
-};
-
-/* module initialisation */
-
-static int __init
-hpusbscsi_init (void)
-{
- return usb_register(&hpusbscsi_usb_driver);
-}
-
-static void __exit
-hpusbscsi_exit (void)
-{
- usb_deregister(&hpusbscsi_usb_driver);
-}
-
-module_init (hpusbscsi_init);
-module_exit (hpusbscsi_exit);
-
-static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
-{
- struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
- usb_complete_t usb_callback;
- int res;
-
- /* we don't answer for anything but our single device on any faked host controller */
- if ( srb->device->lun || srb->device->id || srb->device->channel ) {
- if (callback) {
- srb->result = DID_BAD_TARGET;
- callback(srb);
- }
- goto out;
- }
-
- /* Now we need to decide which callback to give to the urb we send the command with */
-
- if (!srb->bufflen) {
- if (srb->cmnd[0] == REQUEST_SENSE){
- hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
- usb_callback = request_sense_callback;
- } else {
- usb_callback = simple_command_callback;
- }
- } else {
- if (likely(srb->use_sg)) {
- usb_callback = scatter_gather_callback;
- hpusbscsi->fragment = 0;
- } else {
- usb_callback = simple_payload_callback;
- }
- /* Now we find out which direction data is to be transferred in */
- hpusbscsi->current_data_pipe = DIRECTION_IS_IN(srb->cmnd[0]) ?
- usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in)
- :
- usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out)
- ;
- }
-
-
- TRACE_STATE;
-
- /* We zero the sense buffer to avoid confusing user space */
- memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
-
- hpusbscsi->state = HP_STATE_BEGINNING;
- TRACE_STATE;
-
- /* We prepare the urb for writing out the scsi command */
- usb_fill_bulk_urb(
- hpusbscsi->dataurb,
- hpusbscsi->dev,
- usb_sndbulkpipe(hpusbscsi->dev,hpusbscsi->ep_out),
- srb->cmnd,
- srb->cmd_len,
- usb_callback,
- hpusbscsi
- );
- hpusbscsi->scallback = callback;
- hpusbscsi->srb = srb;
-
- res = usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC);
- if (unlikely(res)) {
- hpusbscsi->state = HP_STATE_FREE;
- TRACE_STATE;
- if (likely(callback != NULL)) {
- srb->result = DID_ERROR;
- callback(srb);
- }
- }
-
-out:
- return 0;
-}
-
-static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb)
-{
- struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
-
- printk(KERN_DEBUG"SCSI reset requested.\n");
- //usb_reset_device(hpusbscsi->dev);
- //printk(KERN_DEBUG"SCSI reset completed.\n");
- hpusbscsi->state = HP_STATE_FREE;
-
- return 0;
-}
-
-static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb)
-{
- struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
- printk(KERN_DEBUG"Requested is canceled.\n");
-
- usb_kill_urb(hpusbscsi->dataurb);
- usb_kill_urb(hpusbscsi->controlurb);
- hpusbscsi->state = HP_STATE_FREE;
-
- return SCSI_ABORT_PENDING;
-}
-
-/* usb interrupt handlers - they are all running IN INTERRUPT ! */
-
-static void handle_usb_error (struct hpusbscsi *hpusbscsi)
-{
- if (likely(hpusbscsi->scallback != NULL)) {
- hpusbscsi->srb->result = DID_ERROR;
- hpusbscsi->scallback(hpusbscsi->srb);
- }
- hpusbscsi->state = HP_STATE_FREE;
-}
-
-static void control_interrupt_callback (struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- u8 scsi_state;
-
-DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
- if(unlikely(u->status < 0)) {
- if (likely(hpusbscsi->state != HP_STATE_FREE))
- handle_usb_error(hpusbscsi);
- if (u->status == -ECONNRESET || u->status == -ENOENT || u->status == -ESHUTDOWN)
- return;
- else
- goto resub;
- }
-
- scsi_state = hpusbscsi->scsi_state_byte;
- if (hpusbscsi->state != HP_STATE_ERROR) {
- hpusbscsi->srb->result &= SCSI_ERR_MASK;
- hpusbscsi->srb->result |= scsi_state;
- }
-
- if (scsi_state == CHECK_CONDITION << 1) {
- if (hpusbscsi->state == HP_STATE_WAIT) {
- issue_request_sense(hpusbscsi);
- } else {
- /* we request sense after an eventual data transfer */
- hpusbscsi->state = HP_STATE_ERROR;
- }
- }
-
- if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT && scsi_state != CHECK_CONDITION <<1 )
- /* we do a callback to the scsi layer if and only if all data has been transferred */
- hpusbscsi->scallback(hpusbscsi->srb);
-
- TRACE_STATE;
- switch (hpusbscsi->state) {
- case HP_STATE_WAIT:
- hpusbscsi->state = HP_STATE_FREE;
- TRACE_STATE;
- break;
- case HP_STATE_WORKING:
- case HP_STATE_BEGINNING:
- hpusbscsi->state = HP_STATE_PREMATURE;
- TRACE_STATE;
- break;
- case HP_STATE_ERROR:
- break;
- default:
- printk(KERN_ERR"hpusbscsi: Unexpected status report.\n");
- TRACE_STATE;
- hpusbscsi->state = HP_STATE_FREE;
- TRACE_STATE;
- break;
- }
-resub:
- usb_submit_urb(u, GFP_ATOMIC);
-}
-
-static void simple_command_callback(struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- if (unlikely(u->status<0)) {
- handle_usb_error(hpusbscsi);
- return;
- }
- TRACE_STATE;
- if (hpusbscsi->state != HP_STATE_PREMATURE) {
- TRACE_STATE;
- hpusbscsi->state = HP_STATE_WAIT;
- } else {
- if (likely(hpusbscsi->scallback != NULL))
- hpusbscsi->scallback(hpusbscsi->srb);
- hpusbscsi->state = HP_STATE_FREE;
- TRACE_STATE;
- }
-}
-
-static void scatter_gather_callback(struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- struct scatterlist *sg = hpusbscsi->srb->buffer;
- usb_complete_t callback;
- int res;
-
- DEBUG("Going through scatter/gather\n");
- if (unlikely(u->status < 0)) {
- handle_usb_error(hpusbscsi);
- return;
- }
-
- if (hpusbscsi->fragment + 1 != hpusbscsi->srb->use_sg)
- callback = scatter_gather_callback;
- else
- callback = simple_done;
-
- TRACE_STATE;
- if (hpusbscsi->state != HP_STATE_PREMATURE)
- hpusbscsi->state = HP_STATE_WORKING;
- TRACE_STATE;
-
- usb_fill_bulk_urb(
- u,
- hpusbscsi->dev,
- hpusbscsi->current_data_pipe,
- page_address(sg[hpusbscsi->fragment].page) +
- sg[hpusbscsi->fragment].offset,
- sg[hpusbscsi->fragment++].length,
- callback,
- hpusbscsi
- );
-
- res = usb_submit_urb(u, GFP_ATOMIC);
- if (unlikely(res))
- handle_usb_error(hpusbscsi);
- TRACE_STATE;
-}
-
-static void simple_done (struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-
- if (unlikely(u->status < 0)) {
- handle_usb_error(hpusbscsi);
- return;
- }
- DEBUG("Data transfer done\n");
- TRACE_STATE;
- if (hpusbscsi->state != HP_STATE_PREMATURE) {
- if (unlikely(u->status < 0)) {
- handle_usb_error(hpusbscsi);
- } else {
- if (hpusbscsi->state != HP_STATE_ERROR) {
- hpusbscsi->state = HP_STATE_WAIT;
- } else {
- issue_request_sense(hpusbscsi);
- }
- }
- } else {
- if (likely(hpusbscsi->scallback != NULL))
- hpusbscsi->scallback(hpusbscsi->srb);
- hpusbscsi->state = HP_STATE_FREE;
- }
-}
-
-static void simple_payload_callback (struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- int res;
-
- if (unlikely(u->status<0)) {
- handle_usb_error(hpusbscsi);
- return;
- }
-
- usb_fill_bulk_urb(
- u,
- hpusbscsi->dev,
- hpusbscsi->current_data_pipe,
- hpusbscsi->srb->buffer,
- hpusbscsi->srb->bufflen,
- simple_done,
- hpusbscsi
- );
-
- res = usb_submit_urb(u, GFP_ATOMIC);
- if (unlikely(res)) {
- handle_usb_error(hpusbscsi);
- return;
- }
- TRACE_STATE;
- if (hpusbscsi->state != HP_STATE_PREMATURE) {
- hpusbscsi->state = HP_STATE_WORKING;
- TRACE_STATE;
- }
-}
-
-static void request_sense_callback (struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-
- if (u->status<0) {
- handle_usb_error(hpusbscsi);
- return;
- }
-
- usb_fill_bulk_urb(
- u,
- hpusbscsi->dev,
- hpusbscsi->current_data_pipe,
- hpusbscsi->srb->sense_buffer,
- SCSI_SENSE_BUFFERSIZE,
- simple_done,
- hpusbscsi
- );
-
- if (0 > usb_submit_urb(u, GFP_ATOMIC)) {
- handle_usb_error(hpusbscsi);
- return;
- }
- if (hpusbscsi->state != HP_STATE_PREMATURE && hpusbscsi->state != HP_STATE_ERROR)
- hpusbscsi->state = HP_STATE_WORKING;
-}
-
-static void issue_request_sense (struct hpusbscsi *hpusbscsi)
-{
- usb_fill_bulk_urb(
- hpusbscsi->dataurb,
- hpusbscsi->dev,
- usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out),
- &hpusbscsi->sense_command,
- SENSE_COMMAND_SIZE,
- request_sense_callback,
- hpusbscsi
- );
-
- hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
-
- if (0 > usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC)) {
- handle_usb_error(hpusbscsi);
- }
-}
-
-
diff --git a/drivers/usb/image/hpusbscsi.h b/drivers/usb/image/hpusbscsi.h
deleted file mode 100644
index bdfae769adea7..0000000000000
--- a/drivers/usb/image/hpusbscsi.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Header file for the hpusbscsi driver */
-/* (C) Copyright 2001 Oliver Neukum */
-/* sponsored by the Linux Usb Project */
-/* large parts based on or taken from code by John Fremlin and Matt Dharm */
-/* this file is licensed under the GPL */
-
-/* A big thanks to Jose for untiring testing */
-
-typedef void (*scsi_callback)(Scsi_Cmnd *);
-
-#define SENSE_COMMAND_SIZE 6
-#define HPUSBSCSI_SENSE_LENGTH 0x16
-
-struct hpusbscsi
-{
- struct usb_device *dev; /* NULL indicates unplugged device */
- int ep_out;
- int ep_in;
- int ep_int;
- int interrupt_interval;
- int number;
- int fragment;
- struct Scsi_Host *host;
-
- scsi_callback scallback;
- Scsi_Cmnd *srb;
-
-
- wait_queue_head_t pending;
- wait_queue_head_t deathrow;
-
- struct urb *dataurb;
- struct urb *controlurb;
-
-
- int state;
- int current_data_pipe;
- u8 sense_command[SENSE_COMMAND_SIZE];
- u8 scsi_state_byte;
-};
-
-#define SCSI_ERR_MASK ~0x3fu
-
-static const unsigned char scsi_command_direction[256/8] = {
- 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
- 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-#define DIRECTION_IS_IN(x) ((scsi_command_direction[x>>3] >> (x & 7)) & 1)
-
-static void simple_command_callback(struct urb *u, struct pt_regs *regs);
-static void scatter_gather_callback(struct urb *u, struct pt_regs *regs);
-static void simple_payload_callback (struct urb *u, struct pt_regs *regs);
-static void request_sense_callback (struct urb *u, struct pt_regs *regs);
-static void control_interrupt_callback (struct urb *u, struct pt_regs *regs);
-static void simple_done (struct urb *u, struct pt_regs *regs);
-static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback);
-static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
-static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
-static void issue_request_sense (struct hpusbscsi *hpusbscsi);
-
-/* defines for internal driver state */
-#define HP_STATE_FREE 0 /*ready for next request */
-#define HP_STATE_BEGINNING 1 /*command being transferred */
-#define HP_STATE_WORKING 2 /* data transfer stage */
-#define HP_STATE_ERROR 3 /* error has been reported */
-#define HP_STATE_WAIT 4 /* waiting for status transfer */
-#define HP_STATE_PREMATURE 5 /* status prematurely reported */
-
-
-
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index fe32608b43471..de0d32f6618de 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -703,6 +703,7 @@ static int mts_usb_probe(struct usb_interface *intf,
int ep_in_set[3]; /* this will break if we have more than three endpoints
which is why we check */
int *ep_in_current = ep_in_set;
+ int err_retval = -ENOMEM;
struct mts_desc * new_desc;
struct vendor_product const* p;
@@ -809,7 +810,10 @@ static int mts_usb_probe(struct usb_interface *intf,
goto out_free_urb;
new_desc->host->hostdata[0] = (unsigned long)new_desc;
- scsi_add_host(new_desc->host, NULL); /* XXX handle failure */
+ if (scsi_add_host(new_desc->host, NULL)) {
+ err_retval = -EIO;
+ goto out_free_urb;
+ }
scsi_scan_host(new_desc->host);
usb_set_intfdata(intf, new_desc);
@@ -820,7 +824,7 @@ static int mts_usb_probe(struct usb_interface *intf,
out_kfree:
kfree(new_desc);
out:
- return -ENOMEM;
+ return err_retval;
}
static void mts_usb_disconnect (struct usb_interface *intf)
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index c912f56ff4212..d7fea9ea301b8 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -794,7 +794,7 @@ exit:
* manufacturing revisions. In any event, we consider these
* IDs to not be model-specific nor unique.
*/
-struct usb_device_id aiptek_ids[] = {
+static const struct usb_device_id aiptek_ids[] = {
{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x01)},
{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x10)},
{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x20)},
diff --git a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
index 61994e7322daf..ba41fc7b95c21 100644
--- a/drivers/usb/media/ibmcam.c
+++ b/drivers/usb/media/ibmcam.c
@@ -1036,7 +1036,8 @@ static enum ParseState ibmcam_model4_128x96_parse_lines(
* History:
* 1/21/00 Created.
*/
-void ibmcam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame)
+static void ibmcam_ProcessIsocData(struct uvd *uvd,
+ struct usbvideo_frame *frame)
{
enum ParseState newstate;
long copylen = 0;
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
index 45c9323a1f386..26aa914bc541a 100644
--- a/drivers/usb/media/pwc/pwc-ctrl.c
+++ b/drivers/usb/media/pwc/pwc-ctrl.c
@@ -151,7 +151,7 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
value, \
pdev->vcinterface, \
- &buf, buflen, HZ / 2)
+ &buf, buflen, 500)
#define RecvControlMsg(request, value, buflen) \
usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \
@@ -159,7 +159,7 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
value, \
pdev->vcinterface, \
- &buf, buflen, HZ / 2)
+ &buf, buflen, 500)
#if PWC_DEBUG
@@ -194,7 +194,7 @@ static inline int send_video_command(struct usb_device *udev, int index, void *b
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
VIDEO_OUTPUT_CONTROL_FORMATTER,
index,
- buf, buflen, HZ);
+ buf, buflen, 1000);
}
@@ -341,7 +341,7 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
{
- const struct Kiara_table_entry *pChoose = 0;
+ const struct Kiara_table_entry *pChoose = NULL;
int fps, ret;
unsigned char buf[12];
struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}};
@@ -1087,7 +1087,7 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
return 0;
}
-int pwc_mpt_reset(struct pwc_device *pdev, int flags)
+static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
{
unsigned char buf;
diff --git a/drivers/usb/media/pwc/pwc-dec23.c b/drivers/usb/media/pwc/pwc-dec23.c
index 0a7ebd00cf1c7..98fa3f7a9eff4 100644
--- a/drivers/usb/media/pwc/pwc-dec23.c
+++ b/drivers/usb/media/pwc/pwc-dec23.c
@@ -87,7 +87,7 @@ static void fill_table_d000(unsigned char *p)
* Timon: 0 <= ver <= 15
*
*/
-void fill_table_color(unsigned int version, const unsigned int *romtable,
+static void fill_table_color(unsigned int version, const unsigned int *romtable,
unsigned char *p0004,
unsigned char *p8004)
{
@@ -150,7 +150,7 @@ void fill_table_color(unsigned int version, const unsigned int *romtable,
* precision = (pdev->xx + pdev->yy)
*
*/
-void fill_table_dc00_d800(unsigned int precision, unsigned int *pdc00, unsigned int *pd800)
+static void fill_table_dc00_d800(unsigned int precision, unsigned int *pdc00, unsigned int *pd800)
{
int i;
unsigned int offset1, offset2;
diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
index 502e78c2fea30..100a5a4f03a32 100644
--- a/drivers/usb/media/pwc/pwc-if.c
+++ b/drivers/usb/media/pwc/pwc-if.c
@@ -141,7 +141,7 @@ static struct {
static int pwc_video_open(struct inode *inode, struct file *file);
static int pwc_video_close(struct inode *inode, struct file *file);
-static ssize_t pwc_video_read(struct file *file, char *buf,
+static ssize_t pwc_video_read(struct file *file, char __user * buf,
size_t count, loff_t *ppos);
static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
static int pwc_video_ioctl(struct inode *inode, struct file *file,
@@ -322,7 +322,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
case 730:
case 740:
case 750:
- Trace(TRACE_MEMORY,"private_data(%d)\n",sizeof(struct pwc_dec23_private));
+ Trace(TRACE_MEMORY,"private_data(%Zd)\n",sizeof(struct pwc_dec23_private));
kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */
break;
case 645:
@@ -618,7 +618,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
int i, fst, flen;
int awake;
struct pwc_frame_buf *fbuf;
- unsigned char *fillptr = 0, *iso_buf = 0;
+ unsigned char *fillptr = NULL, *iso_buf = NULL;
awake = 0;
pdev = (struct pwc_device *)urb->context;
@@ -844,7 +844,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
pdev->vmax_packet_size = -1;
for (i = 0; i < idesc->desc.bNumEndpoints; i++)
if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
- pdev->vmax_packet_size = idesc->endpoint[i].desc.wMaxPacketSize;
+ pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
break;
}
@@ -1170,7 +1170,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
device is tricky anyhow.
*/
-static ssize_t pwc_video_read(struct file *file, char *buf,
+static ssize_t pwc_video_read(struct file *file, char __user * buf,
size_t count, loff_t *ppos)
{
struct video_device *vdev = file->private_data;
@@ -1179,7 +1179,7 @@ static ssize_t pwc_video_read(struct file *file, char *buf,
DECLARE_WAITQUEUE(wait, current);
int bytes_to_read;
- Trace(TRACE_READ, "video_read(0x%p, %p, %d) called.\n", vdev, buf, count);
+ Trace(TRACE_READ, "video_read(0x%p, %p, %Zd) called.\n", vdev, buf, count);
if (vdev == NULL)
return -EFAULT;
pdev = vdev->priv;
@@ -1653,7 +1653,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
/* Check if we can handle this device */
Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n",
- udev->descriptor.idVendor, udev->descriptor.idProduct,
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct),
intf->altsetting->desc.bInterfaceNumber);
/* the interfaces are probed one by one. We are only interested in the
@@ -1663,8 +1664,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
if (intf->altsetting->desc.bInterfaceNumber > 0)
return -ENODEV;
- vendor_id = udev->descriptor.idVendor;
- product_id = udev->descriptor.idProduct;
+ vendor_id = le16_to_cpu(udev->descriptor.idVendor);
+ product_id = le16_to_cpu(udev->descriptor.idProduct);
if (vendor_id == 0x0471) {
switch (product_id) {
@@ -1915,7 +1916,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev->vdev->owner = THIS_MODULE;
video_set_drvdata(pdev->vdev, pdev);
- pdev->release = udev->descriptor.bcdDevice;
+ pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
/* Now search device_hint[] table for a match, so we can hint a node number. */
@@ -2027,7 +2028,7 @@ static int pwc_atoi(const char *s)
* Initialization code & module stuff
*/
-static char *size = NULL;
+static char size[10];
static int fps = 0;
static int fbufs = 0;
static int mbufs = 0;
@@ -2036,23 +2037,23 @@ static int compression = -1;
static int leds[2] = { -1, -1 };
static char *dev_hint[MAX_DEV_HINTS] = { };
-MODULE_PARM(size, "s");
+module_param_string(size, size, sizeof(size), 0);
MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
-MODULE_PARM(fps, "i");
+module_param(fps, int, 0000);
MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
-MODULE_PARM(fbufs, "i");
+module_param(fbufs, int, 0000);
MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
-MODULE_PARM(mbufs, "i");
+module_param(mbufs, int, 0000);
MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
-MODULE_PARM(trace, "i");
+module_param(trace, int, 0000);
MODULE_PARM_DESC(trace, "For debugging purposes");
-MODULE_PARM(power_save, "i");
+module_param(power_save, bool, 0000);
MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
-MODULE_PARM(compression, "i");
+module_param(compression, int, 0000);
MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
-MODULE_PARM(leds, "2i");
+module_param_array(leds, int, NULL, 0000);
MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-MODULE_PARM(dev_hint, "0-20s");
+module_param_array(dev_hint, charp, NULL, 0000);
MODULE_PARM_DESC(dev_hint, "Device node hints");
MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
@@ -2078,7 +2079,7 @@ static int __init usb_pwc_init(void)
Info("Default framerate set to %d.\n", default_fps);
}
- if (size) {
+ if (size[0]) {
/* string; try matching with array */
for (sz = 0; sz < PSZ_MAX; sz++) {
if (!strcmp(sizenames[sz], size)) { /* Found! */
diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
index 543d465e7dfa9..298484aa27d24 100644
--- a/drivers/usb/media/usbvideo.c
+++ b/drivers/usb/media/usbvideo.c
@@ -1814,12 +1814,12 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
{
int i, j;
- if (uvd->debug > 1)
- info("%s($%p)", __FUNCTION__, uvd);
-
if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
return;
+ if (uvd->debug > 1)
+ info("%s($%p)", __FUNCTION__, uvd);
+
/* Unschedule all of the iso td's */
for (i=0; i < USBVIDEO_NUMSBUF; i++) {
usb_kill_urb(uvd->sbuf[i].urb);
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 66920ab9faf65..c8155209bf4b4 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -30,6 +30,7 @@ typedef struct _INTEL_HEX_RECORD
#define EMI26_VENDOR_ID 0x086a /* Emagic Soft-und Hardware GmBH */
#define EMI26_PRODUCT_ID 0x0100 /* EMI 2|6 without firmware */
+#define EMI26B_PRODUCT_ID 0x0102 /* EMI 2|6 without firmware */
#define ANCHOR_LOAD_INTERNAL 0xA0 /* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */
#define ANCHOR_LOAD_EXTERNAL 0xA3 /* This command is not implemented in the core. Requires firmware */
@@ -203,6 +204,7 @@ wraperr:
static struct usb_device_id id_table [] = {
{ USB_DEVICE(EMI26_VENDOR_ID, EMI26_PRODUCT_ID) },
+ { USB_DEVICE(EMI26_VENDOR_ID, EMI26B_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 9a5cd6facfa73..26f77e29c7a61 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -40,6 +40,7 @@
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/smp_lock.h>
+#include <linux/wait.h>
#include "rio500_usb.h"
@@ -264,6 +265,7 @@ static ssize_t
write_rio(struct file *file, const char __user *buffer,
size_t count, loff_t * ppos)
{
+ DEFINE_WAIT(wait);
struct rio_usb_data *rio = &rio_instance;
unsigned long copy_size;
@@ -319,7 +321,9 @@ write_rio(struct file *file, const char __user *buffer,
errn = -ETIME;
goto error;
}
- interruptible_sleep_on_timeout(&rio-> wait_q, NAK_TIMEOUT);
+ prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(NAK_TIMEOUT);
+ finish_wait(&rio->wait_q, &wait);
continue;
} else if (!result && partial) {
obuf += partial;
@@ -349,6 +353,7 @@ error:
static ssize_t
read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
{
+ DEFINE_WAIT(wait);
struct rio_usb_data *rio = &rio_instance;
ssize_t read_count;
unsigned int partial;
@@ -399,8 +404,9 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
err("read_rio: maxretry timeout");
return -ETIME;
}
- interruptible_sleep_on_timeout(&rio->wait_q,
- NAK_TIMEOUT);
+ prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(NAK_TIMEOUT);
+ finish_wait(&rio->wait_q, &wait);
continue;
} else if (result != -EREMOTEIO) {
up(&(rio->lock));
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 718136a6c9ff1..be163b3301674 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -564,7 +564,7 @@ static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
struct sisusb_packet *packet)
{
int ret;
- int bytes_transferred = 0;
+ ssize_t bytes_transferred = 0;
__le32 tmp;
if (len == 6)
@@ -601,7 +601,7 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
unsigned int tflags)
{
int ret;
- int bytes_transferred = 0;
+ ssize_t bytes_transferred = 0;
__le32 tmp;
if (len == 6)
@@ -983,7 +983,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
msgcount++;
if (msgcount < 500)
printk(KERN_ERR
- "sisusbvga[%d]: Wrote %d of "
+ "sisusbvga[%d]: Wrote %Zd of "
"%d bytes, error %d\n",
sisusb->minor, *bytes_written,
length, ret);
@@ -1381,7 +1381,8 @@ sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data)
static int
sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
{
- int ret, i, j;
+ int ret, i;
+ ssize_t j;
if (address < sisusb->vrambase)
return 1;
@@ -2271,7 +2272,7 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
/* fops */
-int
+static int
sisusb_open(struct inode *inode, struct file *file)
{
struct sisusb_usb_data *sisusb;
@@ -2361,7 +2362,7 @@ sisusb_delete(struct kref *kref)
kfree(sisusb);
}
-int
+static int
sisusb_release(struct inode *inode, struct file *file)
{
struct sisusb_usb_data *sisusb;
@@ -2399,7 +2400,7 @@ sisusb_release(struct inode *inode, struct file *file)
return 0;
}
-ssize_t
+static ssize_t
sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
struct sisusb_usb_data *sisusb;
@@ -2540,7 +2541,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
return errno ? errno : bytes_read;
}
-ssize_t
+static ssize_t
sisusb_write(struct file *file, const char __user *buffer, size_t count,
loff_t *ppos)
{
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 4297f4e133e00..dcdf9b4abb7cc 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -1,14 +1,16 @@
/*****************************************************************************
* USBLCD Kernel Driver *
- * See http://www.usblcd.de for Hardware and Documentation. *
- * Version 1.03 *
- * (C) 2002 Adams IT Services <info@usblcd.de> *
+ * Version 1.05 *
+ * (C) 2005 Georges Toth <g.toth@e-biz.lu> *
* *
* This file is licensed under the GPL. See COPYING in the package. *
- * Based on rio500.c by Cesar Miquel (miquel@df.uba.ar) which is based on *
- * hp_scanner.c by David E. Nelson (dnelson@jump.net) *
+ * Based on usb-skeleton.c 2.0 by Greg Kroah-Hartman (greg@kroah.com) *
* *
- * 23.7.02 RA changed minor device number to the official assigned one *
+ * *
+ * 28.02.05 Complete rewrite of the original usblcd.c driver, *
+ * based on usb_skeleton.c. *
+ * This new driver allows more than one USB-LCD to be connected *
+ * and controlled, at once *
*****************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
@@ -18,74 +20,129 @@
#include <asm/uaccess.h>
#include <linux/usb.h>
-#define DRIVER_VERSION "USBLCD Driver Version 1.04"
+#define DRIVER_VERSION "USBLCD Driver Version 1.05"
#define USBLCD_MINOR 144
#define IOCTL_GET_HARD_VERSION 1
#define IOCTL_GET_DRV_VERSION 2
-/* stall/wait timeout for USBLCD */
-#define NAK_TIMEOUT (10*HZ)
-#define IBUF_SIZE 0x1000
-#define OBUF_SIZE 0x10000
+static struct usb_device_id id_table [] = {
+ { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, },
+ { },
+};
+MODULE_DEVICE_TABLE (usb, id_table);
+
-struct lcd_usb_data {
- struct usb_device *lcd_dev; /* init: probe_lcd */
- unsigned int ifnum; /* Interface number of the USB device */
- int isopen; /* nz if open */
- int present; /* Device is present on the bus */
- char *obuf, *ibuf; /* transfer buffers */
- char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
- wait_queue_head_t wait_q; /* for timeouts */
+struct usb_lcd {
+ struct usb_device * udev; /* init: probe_lcd */
+ struct usb_interface * interface; /* the interface for this device */
+ unsigned char * bulk_in_buffer; /* the buffer to receive data */
+ size_t bulk_in_size; /* the size of the receive buffer */
+ __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
+ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
+ struct kref kref;
};
+#define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
-static struct lcd_usb_data lcd_instance;
+static struct usb_driver lcd_driver;
-static int open_lcd(struct inode *inode, struct file *file)
+
+static void lcd_delete(struct kref *kref)
{
- struct lcd_usb_data *lcd = &lcd_instance;
+ struct usb_lcd *dev = to_lcd_dev(kref);
+
+ usb_put_dev(dev->udev);
+ kfree (dev->bulk_in_buffer);
+ kfree (dev);
+}
- if (lcd->isopen || !lcd->present) {
- return -EBUSY;
+
+static int lcd_open(struct inode *inode, struct file *file)
+{
+ struct usb_lcd *dev;
+ struct usb_interface *interface;
+ int subminor;
+ int retval = 0;
+
+ subminor = iminor(inode);
+
+ interface = usb_find_interface(&lcd_driver, subminor);
+ if (!interface) {
+ err ("USBLCD: %s - error, can't find device for minor %d",
+ __FUNCTION__, subminor);
+ retval = -ENODEV;
+ goto exit;
}
- lcd->isopen = 1;
- init_waitqueue_head(&lcd->wait_q);
+ dev = usb_get_intfdata(interface);
+ if (!dev) {
+ retval = -ENODEV;
+ goto exit;
+ }
- info("USBLCD opened.");
+ /* increment our usage count for the device */
+ kref_get(&dev->kref);
- return 0;
+ /* save our object in the file's private structure */
+ file->private_data = dev;
+
+exit:
+ return retval;
}
-static int close_lcd(struct inode *inode, struct file *file)
+static int lcd_release(struct inode *inode, struct file *file)
{
- struct lcd_usb_data *lcd = &lcd_instance;
+ struct usb_lcd *dev;
- lcd->isopen = 0;
+ dev = (struct usb_lcd *)file->private_data;
+ if (dev == NULL)
+ return -ENODEV;
- info("USBLCD closed.");
+ /* decrement the count on our device */
+ kref_put(&dev->kref, lcd_delete);
return 0;
}
-static int
-ioctl_lcd(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static ssize_t lcd_read(struct file *file, char __user * buffer, size_t count, loff_t *ppos)
{
- struct lcd_usb_data *lcd = &lcd_instance;
+ struct usb_lcd *dev;
+ int retval = 0;
+
+ dev = (struct usb_lcd *)file->private_data;
+
+ /* do a blocking bulk read to get data from the device */
+ retval = usb_bulk_msg(dev->udev,
+ usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+ dev->bulk_in_buffer,
+ min(dev->bulk_in_size, count),
+ &count, 10000);
+
+ /* if the read was successful, copy the data to userspace */
+ if (!retval) {
+ if (copy_to_user(buffer, dev->bulk_in_buffer, count))
+ retval = -EFAULT;
+ else
+ retval = count;
+ }
+
+ return retval;
+}
+
+static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct usb_lcd *dev;
u16 bcdDevice;
char buf[30];
- /* Sanity check to make sure lcd is connected, powered, etc */
- if (lcd == NULL ||
- lcd->present == 0 ||
- lcd->lcd_dev == NULL)
- return -1;
-
+ dev = (struct usb_lcd *)file->private_data;
+ if (dev == NULL)
+ return -ENODEV;
+
switch (cmd) {
case IOCTL_GET_HARD_VERSION:
- bcdDevice = le16_to_cpu((lcd->lcd_dev)->descriptor.bcdDevice);
+ bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice);
sprintf(buf,"%1d%1d.%1d%1d",
(bcdDevice & 0xF000)>>12,
(bcdDevice & 0xF00)>>8,
@@ -107,269 +164,240 @@ ioctl_lcd(struct inode *inode, struct file *file, unsigned int cmd,
return 0;
}
-static ssize_t
-write_lcd(struct file *file, const char __user *buffer,
- size_t count, loff_t * ppos)
+static void lcd_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
- struct lcd_usb_data *lcd = &lcd_instance;
-
- unsigned long copy_size;
- unsigned long bytes_written = 0;
- unsigned int partial;
-
- int result = 0;
- int maxretry;
+ struct usb_lcd *dev;
- /* Sanity check to make sure lcd is connected, powered, etc */
- if (lcd == NULL ||
- lcd->present == 0 ||
- lcd->lcd_dev == NULL)
- return -1;
+ dev = (struct usb_lcd *)urb->context;
- do {
- unsigned long thistime;
- char *obuf = lcd->obuf;
-
- thistime = copy_size =
- (count >= OBUF_SIZE) ? OBUF_SIZE : count;
- if (copy_from_user(lcd->obuf, buffer, copy_size))
- return -EFAULT;
- maxretry = 5;
- while (thistime) {
- if (!lcd->lcd_dev)
- return -ENODEV;
- if (signal_pending(current)) {
- return bytes_written ? bytes_written : -EINTR;
- }
-
- result = usb_bulk_msg(lcd->lcd_dev,
- usb_sndbulkpipe(lcd->lcd_dev, 1),
- obuf, thistime, &partial, 10000);
-
- dbg("write stats: result:%d thistime:%lu partial:%u",
- result, thistime, partial);
-
- if (result == -ETIMEDOUT) { /* NAK - so hold for a while */
- if (!maxretry--) {
- return -ETIME;
- }
- interruptible_sleep_on_timeout(&lcd-> wait_q, NAK_TIMEOUT);
- continue;
- } else if (!result && partial) {
- obuf += partial;
- thistime -= partial;
- } else
- break;
- };
- if (result) {
- err("Write Whoops - %x", result);
- return -EIO;
- }
- bytes_written += copy_size;
- count -= copy_size;
- buffer += copy_size;
- } while (count > 0);
+ /* sync/async unlink faults aren't errors */
+ if (urb->status &&
+ !(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN)) {
+ dbg("USBLCD: %s - nonzero write bulk status received: %d",
+ __FUNCTION__, urb->status);
+ }
- return bytes_written ? bytes_written : -EIO;
+ /* free up our allocated buffer */
+ usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+ urb->transfer_buffer, urb->transfer_dma);
}
-static ssize_t
-read_lcd(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
+static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos)
{
- struct lcd_usb_data *lcd = &lcd_instance;
- ssize_t read_count;
- unsigned int partial;
- int this_read;
- int result;
- int maxretry = 10;
- char *ibuf = lcd->ibuf;
-
- /* Sanity check to make sure lcd is connected, powered, etc */
- if (lcd == NULL ||
- lcd->present == 0 ||
- lcd->lcd_dev == NULL)
- return -1;
-
- read_count = 0;
+ struct usb_lcd *dev;
+ int retval = 0;
+ struct urb *urb = NULL;
+ char *buf = NULL;
+
+ dev = (struct usb_lcd *)file->private_data;
+
+ /* verify that we actually have some data to write */
+ if (count == 0)
+ goto exit;
+
+ /* create a urb, and a buffer for it, and copy the data to the urb */
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
+ if (!buf) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ if (copy_from_user(buf, user_buffer, count)) {
+ retval = -EFAULT;
+ goto error;
+ }
+
+ /* initialize the urb properly */
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
+ buf, count, lcd_write_bulk_callback, dev);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /* send the data out the bulk port */
+ retval = usb_submit_urb(urb, GFP_KERNEL);
+ if (retval) {
+ err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval);
+ goto error;
+ }
+
+ /* release our reference to this urb, the USB core will eventually free it entirely */
+ usb_free_urb(urb);
- while (count > 0) {
- if (signal_pending(current)) {
- return read_count ? read_count : -EINTR;
- }
- if (!lcd->lcd_dev)
- return -ENODEV;
- this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
-
- result = usb_bulk_msg(lcd->lcd_dev,
- usb_rcvbulkpipe(lcd->lcd_dev, 0),
- ibuf, this_read, &partial,
- 8000);
-
- dbg(KERN_DEBUG "read stats: result:%d this_read:%u partial:%u",
- result, this_read, partial);
-
- if (partial) {
- count = this_read = partial;
- } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
- if (!maxretry--) {
- err("read_lcd: maxretry timeout");
- return -ETIME;
- }
- interruptible_sleep_on_timeout(&lcd->wait_q,
- NAK_TIMEOUT);
- continue;
- } else if (result != -EREMOTEIO) {
- err("Read Whoops - result:%u partial:%u this_read:%u",
- result, partial, this_read);
- return -EIO;
- } else {
- return (0);
- }
+exit:
+ return count;
- if (this_read) {
- if (copy_to_user(buffer, ibuf, this_read))
- return -EFAULT;
- count -= this_read;
- read_count += this_read;
- buffer += this_read;
- }
- }
- return read_count;
+error:
+ usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
+ usb_free_urb(urb);
+ return retval;
}
-static struct
-file_operations usb_lcd_fops = {
- .owner = THIS_MODULE,
- .read = read_lcd,
- .write = write_lcd,
- .ioctl = ioctl_lcd,
- .open = open_lcd,
- .release = close_lcd,
+static struct file_operations lcd_fops = {
+ .owner = THIS_MODULE,
+ .read = lcd_read,
+ .write = lcd_write,
+ .open = lcd_open,
+ .ioctl = lcd_ioctl,
+ .release = lcd_release,
};
-static struct usb_class_driver usb_lcd_class = {
- .name = "usb/lcd%d",
- .fops = &usb_lcd_fops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- .minor_base = USBLCD_MINOR,
+/*
+ * * usb class driver info in order to get a minor number from the usb core,
+ * * and to have the device registered with devfs and the driver core
+ * */
+static struct usb_class_driver lcd_class = {
+ .name = "usb/lcd%d",
+ .fops = &lcd_fops,
+ .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+ .minor_base = USBLCD_MINOR,
};
-static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id)
+static int lcd_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
- struct usb_device *dev = interface_to_usbdev(intf);
- struct lcd_usb_data *lcd = &lcd_instance;
+ struct usb_lcd *dev = NULL;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ size_t buffer_size;
int i;
- int retval;
+ int retval = -ENOMEM;
- if (le16_to_cpu(dev->descriptor.idProduct) != 0x0001) {
- warn(KERN_INFO "USBLCD model not supported.");
- return -ENODEV;
+ /* allocate memory for our device state and initialize it */
+ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ err("Out of memory");
+ goto error;
}
+ memset(dev, 0x00, sizeof(*dev));
+ kref_init(&dev->kref);
+
+ dev->udev = usb_get_dev(interface_to_usbdev(interface));
+ dev->interface = interface;
- if (lcd->present == 1) {
- warn(KERN_INFO "Multiple USBLCDs are not supported!");
+ if (le16_to_cpu(dev->udev->descriptor.idProduct) != 0x0001) {
+ warn(KERN_INFO "USBLCD model not supported.");
return -ENODEV;
}
+
+ /* set up the endpoint information */
+ /* use only the first bulk-in and bulk-out endpoints */
+ iface_desc = interface->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+
+ if (!dev->bulk_in_endpointAddr &&
+ (endpoint->bEndpointAddress & USB_DIR_IN) &&
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_BULK)) {
+ /* we found a bulk in endpoint */
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ dev->bulk_in_size = buffer_size;
+ dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+ dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!dev->bulk_in_buffer) {
+ err("Could not allocate bulk_in_buffer");
+ goto error;
+ }
+ }
- i = le16_to_cpu(dev->descriptor.bcdDevice);
-
- info("USBLCD Version %1d%1d.%1d%1d found at address %d",
- (i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
- dev->devnum);
-
-
-
- lcd->present = 1;
- lcd->lcd_dev = dev;
-
- if (!(lcd->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
- err("probe_lcd: Not enough memory for the output buffer");
- return -ENOMEM;
+ if (!dev->bulk_out_endpointAddr &&
+ !(endpoint->bEndpointAddress & USB_DIR_IN) &&
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_BULK)) {
+ /* we found a bulk out endpoint */
+ dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
+ }
}
- dbg("probe_lcd: obuf address:%p", lcd->obuf);
-
- if (!(lcd->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
- err("probe_lcd: Not enough memory for the input buffer");
- kfree(lcd->obuf);
- return -ENOMEM;
+ if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
+ err("Could not find both bulk-in and bulk-out endpoints");
+ goto error;
}
- dbg("probe_lcd: ibuf address:%p", lcd->ibuf);
- retval = usb_register_dev(intf, &usb_lcd_class);
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(interface, dev);
+
+ /* we can register the device now, as it is ready */
+ retval = usb_register_dev(interface, &lcd_class);
if (retval) {
+ /* something prevented us from registering this driver */
err("Not able to get a minor for this device.");
- kfree(lcd->obuf);
- kfree(lcd->ibuf);
- return -ENOMEM;
+ usb_set_intfdata(interface, NULL);
+ goto error;
}
- usb_set_intfdata (intf, lcd);
+ i = le16_to_cpu(dev->udev->descriptor.bcdDevice);
+
+ info("USBLCD Version %1d%1d.%1d%1d found at address %d",
+ (i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
+ dev->udev->devnum);
+
+ /* let the user know what node this device is now attached to */
+ info("USB LCD device now attached to USBLCD-%d", interface->minor);
return 0;
+
+error:
+ if (dev)
+ kref_put(&dev->kref, lcd_delete);
+ return retval;
}
-static void disconnect_lcd(struct usb_interface *intf)
+static void lcd_disconnect(struct usb_interface *interface)
{
- struct lcd_usb_data *lcd = usb_get_intfdata (intf);
+ struct usb_lcd *dev;
+ int minor = interface->minor;
- usb_set_intfdata (intf, NULL);
- if (lcd) {
- usb_deregister_dev(intf, &usb_lcd_class);
+ /* prevent skel_open() from racing skel_disconnect() */
+ lock_kernel();
- if (lcd->isopen) {
- lcd->isopen = 0;
- /* better let it finish - the release will do whats needed */
- lcd->lcd_dev = NULL;
- return;
- }
- kfree(lcd->ibuf);
- kfree(lcd->obuf);
+ dev = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
- info("USBLCD disconnected.");
-
- lcd->present = 0;
- }
-}
+ /* give back our minor */
+ usb_deregister_dev(interface, &lcd_class);
+
+ unlock_kernel();
-static struct usb_device_id id_table [] = {
- { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, },
- {},
-};
+ /* decrement our usage count */
+ kref_put(&dev->kref, lcd_delete);
-MODULE_DEVICE_TABLE (usb, id_table);
+ info("USB LCD #%d now disconnected", minor);
+}
static struct usb_driver lcd_driver = {
.owner = THIS_MODULE,
.name = "usblcd",
- .probe = (void *)probe_lcd,
- .disconnect = disconnect_lcd,
+ .probe = lcd_probe,
+ .disconnect = lcd_disconnect,
.id_table = id_table,
};
static int __init usb_lcd_init(void)
{
- int retval;
- retval = usb_register(&lcd_driver);
- if (retval)
- goto out;
-
- info("%s (C) Adams IT Services http://www.usblcd.de", DRIVER_VERSION);
- info("USBLCD support registered.");
-out:
- return retval;
+ int result;
+
+ result = usb_register(&lcd_driver);
+ if (result)
+ err("usb_register failed. Error number %d", result);
+
+ return result;
}
-static void __exit usb_lcd_cleanup(void)
+static void __exit usb_lcd_exit(void)
{
- struct lcd_usb_data *lcd = &lcd_instance;
-
- lcd->present = 0;
usb_deregister(&lcd_driver);
}
module_init(usb_lcd_init);
-module_exit(usb_lcd_cleanup);
+module_exit(usb_lcd_exit);
-MODULE_AUTHOR("Adams IT Services <info@usblcd.de>");
+MODULE_AUTHOR("Georges Toth <g.toth@e-biz.lu>");
MODULE_DESCRIPTION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 0928ffc990d71..3104f28f6aa8d 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -851,7 +851,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
*/
urb = kmalloc (param->sglen * sizeof (struct urb *), SLAB_KERNEL);
if (!urb)
- goto cleanup;
+ return -ENOMEM;
memset (urb, 0, param->sglen * sizeof (struct urb *));
for (i = 0; i < param->sglen; i++) {
int pipe = usb_rcvctrlpipe (udev, 0);
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 8eff8f92c15f3..755a4570477fd 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -261,6 +261,7 @@ static ssize_t mon_text_read(struct file *file, char __user *buf,
struct mon_event_text *ep;
int cnt, limit;
char *pbuf;
+ char udir, utype;
int data_len, i;
add_wait_queue(&rp->wait, &waita);
@@ -290,9 +291,18 @@ static ssize_t mon_text_read(struct file *file, char __user *buf,
pbuf = rp->printf_buf;
limit = rp->printf_size;
+ udir = usb_pipein(ep->pipe) ? 'i' : 'o';
+ switch (usb_pipetype(ep->pipe)) {
+ case PIPE_ISOCHRONOUS: utype = 'Z'; break;
+ case PIPE_INTERRUPT: utype = 'I'; break;
+ case PIPE_CONTROL: utype = 'C'; break;
+ default: /* PIPE_BULK */ utype = 'B';
+ }
cnt += snprintf(pbuf + cnt, limit - cnt,
- "%lx %u %c %08x %d %d",
- ep->id, ep->tstamp, ep->type, ep->pipe, ep->status, ep->length);
+ "%lx %u %c %c%c:%03u:%02u %d %d",
+ ep->id, ep->tstamp, ep->type,
+ utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe),
+ ep->status, ep->length);
if ((data_len = ep->length) > 0) {
if (ep->data_flag == 0) {
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index 095d00732af7d..c8be912f24e1a 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -664,7 +664,8 @@ static void catc_set_multicast_list(struct net_device *netdev)
}
}
-void catc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void catc_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
{
struct catc *catc = netdev_priv(dev);
strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN);
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 8c5b4ab5be322..a9a7cf4a38ebd 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -594,7 +594,7 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs)
struct sk_buff *skb;
- if(unlikely(urb->status == -ECONNRESET || urb->status == -ECONNABORTED || urb->status == -ESHUTDOWN))
+ if(unlikely(urb->status == -ECONNRESET || urb->status == -ESHUTDOWN))
/* we are killed - set a flag and wake the disconnect handler */
{
kaweth->end = 1;
diff --git a/drivers/usb/net/kawethfw.h b/drivers/usb/net/kawethfw.h
index 2b35baeac717a..cf85fcb0d1a6b 100644
--- a/drivers/usb/net/kawethfw.h
+++ b/drivers/usb/net/kawethfw.h
@@ -551,7 +551,7 @@ static __u8 kaweth_new_code_fix[] =
};
-const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code);
-const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix);
-const int len_kaweth_new_code = sizeof(kaweth_new_code);
-const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix);
+static const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code);
+static const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix);
+static const int len_kaweth_new_code = sizeof(kaweth_new_code);
+static const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix);
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 113dbf468ffab..f6c19d73b7da9 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -85,6 +85,11 @@ module_param(mii_mode, bool, 0);
MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
+/* use ethtool to change the level for any given device */
+static int msg_level = -1;
+module_param (msg_level, int, 0);
+MODULE_PARM_DESC (msg_level, "Override default message level");
+
MODULE_DEVICE_TABLE(usb, pegasus_ids);
static int update_eth_regs_async(pegasus_t *);
@@ -110,7 +115,9 @@ static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
case -ENOENT:
break;
default:
- warn("%s: status %d", __FUNCTION__, urb->status);
+ if (netif_msg_drv(pegasus))
+ dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ __FUNCTION__, urb->status);
}
pegasus->flags &= ~ETH_REGS_CHANGED;
wake_up(&pegasus->ctrl_wait);
@@ -125,7 +132,9 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
- warn("%s: looks like we're out of memory", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
+ __FUNCTION__);
return -ENOMEM;
}
add_wait_queue(&pegasus->ctrl_wait, &wait);
@@ -152,7 +161,9 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
/* using ATOMIC, we'd never wake up if we slept */
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
- err("%s: BAD CTRLs %d", __FUNCTION__, ret);
+ if (netif_msg_drv(pegasus))
+ dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ __FUNCTION__, ret);
goto out;
}
@@ -174,7 +185,9 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
- warn("%s: looks like we're out of memory", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
+ __FUNCTION__);
return -ENOMEM;
}
memcpy(buffer, data, size);
@@ -202,7 +215,9 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
set_current_state(TASK_UNINTERRUPTIBLE);
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
- err("%s: BAD CTRL %d", __FUNCTION__, ret);
+ if (netif_msg_drv(pegasus))
+ dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ __FUNCTION__, ret);
goto out;
}
@@ -222,7 +237,9 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
tmp = kmalloc(1, GFP_KERNEL);
if (!tmp) {
- warn("%s: looks like we're out of memory", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
+ __FUNCTION__);
return -ENOMEM;
}
memcpy(tmp, &data, 1);
@@ -249,7 +266,9 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
set_current_state(TASK_UNINTERRUPTIBLE);
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
- err("%s: BAD CTRL %d", __FUNCTION__, ret);
+ if (netif_msg_drv(pegasus))
+ dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ __FUNCTION__, ret);
goto out;
}
@@ -278,8 +297,9 @@ static int update_eth_regs_async(pegasus_t * pegasus)
pegasus->eth_regs, 3, ctrl_callback, pegasus);
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC)))
- err("%s: BAD CTRL %d, flgs %x", __FUNCTION__, ret,
- pegasus->flags);
+ if (netif_msg_drv(pegasus))
+ dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ __FUNCTION__, ret);
return ret;
}
@@ -289,21 +309,23 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
int i;
__u8 data[4] = { phy, 0, 0, indx };
__le16 regdi;
+ int ret;
- set_register(pegasus, PhyCtrl, 0);
- set_registers(pegasus, PhyAddr, sizeof (data), data);
- set_register(pegasus, PhyCtrl, (indx | PHY_READ));
+ ret = set_register(pegasus, PhyCtrl, 0);
+ ret = set_registers(pegasus, PhyAddr, sizeof (data), data);
+ ret = set_register(pegasus, PhyCtrl, (indx | PHY_READ));
for (i = 0; i < REG_TIMEOUT; i++) {
- get_registers(pegasus, PhyCtrl, 1, data);
+ ret = get_registers(pegasus, PhyCtrl, 1, data);
if (data[0] & PHY_DONE)
break;
}
if (i < REG_TIMEOUT) {
- get_registers(pegasus, PhyData, 2, &regdi);
+ ret = get_registers(pegasus, PhyData, 2, &regdi);
*regd = le16_to_cpu(regdi);
return 1;
}
- warn("%s: failed", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
return 0;
}
@@ -311,7 +333,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
static int mdio_read(struct net_device *dev, int phy_id, int loc)
{
pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev);
- __le16 res;
+ u16 res;
read_mii_word(pegasus, phy_id, loc, &res);
return (int)res;
@@ -321,20 +343,23 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
{
int i;
__u8 data[4] = { phy, 0, 0, indx };
+ int ret;
- *(data + 1) = cpu_to_le16p(&regd);
- set_register(pegasus, PhyCtrl, 0);
- set_registers(pegasus, PhyAddr, sizeof(data), data);
- set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
+ data[1] = (u8) regd;
+ data[2] = (u8) (regd >> 8);
+ ret = set_register(pegasus, PhyCtrl, 0);
+ ret = set_registers(pegasus, PhyAddr, sizeof(data), data);
+ ret = set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
for (i = 0; i < REG_TIMEOUT; i++) {
- get_registers(pegasus, PhyCtrl, 1, data);
+ ret = get_registers(pegasus, PhyCtrl, 1, data);
if (data[0] & PHY_DONE)
break;
}
if (i < REG_TIMEOUT)
return 0;
- warn("%s: failed", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
return 1;
}
@@ -350,23 +375,25 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
int i;
__u8 tmp;
__le16 retdatai;
+ int ret;
- set_register(pegasus, EpromCtrl, 0);
- set_register(pegasus, EpromOffset, index);
- set_register(pegasus, EpromCtrl, EPROM_READ);
+ ret = set_register(pegasus, EpromCtrl, 0);
+ ret = set_register(pegasus, EpromOffset, index);
+ ret = set_register(pegasus, EpromCtrl, EPROM_READ);
for (i = 0; i < REG_TIMEOUT; i++) {
- get_registers(pegasus, EpromCtrl, 1, &tmp);
+ ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
if (tmp & EPROM_DONE)
break;
}
if (i < REG_TIMEOUT) {
- get_registers(pegasus, EpromData, 2, &retdatai);
+ ret = get_registers(pegasus, EpromData, 2, &retdatai);
*retdata = le16_to_cpu(retdatai);
return 0;
}
- warn("%s: failed", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
return -1;
}
@@ -374,40 +401,44 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
static inline void enable_eprom_write(pegasus_t * pegasus)
{
__u8 tmp;
+ int ret;
- get_registers(pegasus, EthCtrl2, 1, &tmp);
- set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
+ ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
+ ret = set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
}
static inline void disable_eprom_write(pegasus_t * pegasus)
{
__u8 tmp;
+ int ret;
- get_registers(pegasus, EthCtrl2, 1, &tmp);
- set_register(pegasus, EpromCtrl, 0);
- set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
+ ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
+ ret = set_register(pegasus, EpromCtrl, 0);
+ ret = set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
}
static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
{
int i;
__u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
+ int ret;
- set_registers(pegasus, EpromOffset, 4, d);
+ ret = set_registers(pegasus, EpromOffset, 4, d);
enable_eprom_write(pegasus);
- set_register(pegasus, EpromOffset, index);
- set_registers(pegasus, EpromData, 2, &data);
- set_register(pegasus, EpromCtrl, EPROM_WRITE);
+ ret = set_register(pegasus, EpromOffset, index);
+ ret = set_registers(pegasus, EpromData, 2, &data);
+ ret = set_register(pegasus, EpromCtrl, EPROM_WRITE);
for (i = 0; i < REG_TIMEOUT; i++) {
- get_registers(pegasus, EpromCtrl, 1, &tmp);
+ ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
if (tmp & EPROM_DONE)
break;
}
disable_eprom_write(pegasus);
if (i < REG_TIMEOUT)
return 0;
- warn("%s: failed", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
return -1;
}
#endif /* PEGASUS_WRITE_EEPROM */
@@ -426,9 +457,10 @@ static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
static void set_ethernet_addr(pegasus_t * pegasus)
{
__u8 node_id[6];
+ int ret;
get_node_id(pegasus, node_id);
- set_registers(pegasus, EthID, sizeof (node_id), node_id);
+ ret = set_registers(pegasus, EthID, sizeof (node_id), node_id);
memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
}
@@ -436,19 +468,20 @@ static inline int reset_mac(pegasus_t * pegasus)
{
__u8 data = 0x8;
int i;
+ int ret;
- set_register(pegasus, EthCtrl1, data);
+ ret = set_register(pegasus, EthCtrl1, data);
for (i = 0; i < REG_TIMEOUT; i++) {
- get_registers(pegasus, EthCtrl1, 1, &data);
+ ret = get_registers(pegasus, EthCtrl1, 1, &data);
if (~data & 0x08) {
if (loopback & 1)
break;
if (mii_mode && (pegasus->features & HAS_HOME_PNA))
- set_register(pegasus, Gpio1, 0x34);
+ ret = set_register(pegasus, Gpio1, 0x34);
else
- set_register(pegasus, Gpio1, 0x26);
- set_register(pegasus, Gpio0, pegasus->features);
- set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
+ ret = set_register(pegasus, Gpio1, 0x26);
+ ret = set_register(pegasus, Gpio0, pegasus->features);
+ ret = set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
break;
}
}
@@ -457,8 +490,8 @@ static inline int reset_mac(pegasus_t * pegasus)
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
- set_register(pegasus, Gpio0, 0x24);
- set_register(pegasus, Gpio0, 0x26);
+ ret = set_register(pegasus, Gpio0, 0x24);
+ ret = set_register(pegasus, Gpio0, 0x26);
}
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
__u16 auxmode;
@@ -474,6 +507,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
__u16 linkpart;
__u8 data[4];
pegasus_t *pegasus = netdev_priv(dev);
+ int ret;
read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart);
data[0] = 0xc9;
@@ -487,7 +521,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
data[2] = (loopback & 1) ? 0x09 : 0x01;
memcpy(pegasus->eth_regs, data, sizeof (data));
- set_registers(pegasus, EthCtrl0, 3, data);
+ ret = set_registers(pegasus, EthCtrl0, 3, data);
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
@@ -550,48 +584,56 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
pegasus_t *pegasus = urb->context;
struct net_device *net;
int rx_status, count = urb->actual_length;
+ u8 *buf = urb->transfer_buffer;
__u16 pkt_len;
- if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
+ if (!pegasus)
return;
net = pegasus->net;
- if (!netif_device_present(net))
+ if (!netif_device_present(net) || !netif_running(net))
return;
switch (urb->status) {
case 0:
break;
case -ETIMEDOUT:
- dbg("%s: reset MAC", net->name);
+ if (netif_msg_rx_err(pegasus))
+ pr_debug("%s: reset MAC\n", net->name);
pegasus->flags &= ~PEGASUS_RX_BUSY;
break;
case -EPIPE: /* stall, or disconnect from TT */
/* FIXME schedule work to clear the halt */
- warn("%s: no rx stall recovery", net->name);
+ if (netif_msg_rx_err(pegasus))
+ printk(KERN_WARNING "%s: no rx stall recovery\n",
+ net->name);
return;
case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
- dbg("%s: rx unlink, %d", net->name, urb->status);
+ if (netif_msg_ifdown(pegasus))
+ pr_debug("%s: rx unlink, %d\n", net->name, urb->status);
return;
default:
- dbg("%s: RX status %d", net->name, urb->status);
+ if (netif_msg_rx_err(pegasus))
+ pr_debug("%s: RX status %d\n", net->name, urb->status);
goto goon;
}
- if (!count)
+ if (!count || count < 4)
goto goon;
- rx_status = le32_to_cpu(*(__le32 *) (urb->transfer_buffer + count - 4));
- if (rx_status & 0x000e0000) {
- dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
+ rx_status = buf[count - 2];
+ if (rx_status & 0x1e) {
+ if (netif_msg_rx_err(pegasus))
+ pr_debug("%s: RX packet error %x\n",
+ net->name, rx_status);
pegasus->stats.rx_errors++;
- if (rx_status & 0x060000)
+ if (rx_status & 0x06) // long or runt
pegasus->stats.rx_length_errors++;
- if (rx_status & 0x080000)
+ if (rx_status & 0x08)
pegasus->stats.rx_crc_errors++;
- if (rx_status & 0x100000)
+ if (rx_status & 0x10) // extra bits
pegasus->stats.rx_frame_errors++;
goto goon;
}
@@ -600,7 +642,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
pkt_len &= 0x0fff;
pegasus->rx_skb->data += 2;
} else {
- pkt_len = (rx_status & 0xfff) - 8;
+ pkt_len = buf[count - 3] << 8;
+ pkt_len += buf[count - 4];
+ pkt_len &= 0xfff;
+ pkt_len -= 8;
}
/*
@@ -658,7 +703,9 @@ static void rx_fixup(unsigned long data)
pegasus->rx_skb = pull_skb(pegasus);
}
if (pegasus->rx_skb == NULL) {
- warn("wow, low on memory");
+ if (netif_msg_rx_err(pegasus))
+ printk(KERN_WARNING "%s: low on memory\n",
+ pegasus->net->name);
tasklet_schedule(&pegasus->rx_tl);
goto done;
}
@@ -682,25 +729,29 @@ static void write_bulk_callback(struct urb *urb, struct pt_regs *regs)
pegasus_t *pegasus = urb->context;
struct net_device *net = pegasus->net;
- if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
+ if (!pegasus)
return;
- if (!netif_device_present(net))
+ if (!netif_device_present(net) || !netif_running(net))
return;
switch (urb->status) {
case -EPIPE:
/* FIXME schedule_work() to clear the tx halt */
netif_stop_queue(net);
- warn("%s: no tx stall recovery", net->name);
+ if (netif_msg_tx_err(pegasus))
+ printk(KERN_WARNING "%s: no tx stall recovery\n",
+ net->name);
return;
case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
- dbg("%s: tx unlink, %d", net->name, urb->status);
+ if (netif_msg_ifdown(pegasus))
+ pr_debug("%s: tx unlink, %d\n", net->name, urb->status);
return;
default:
- info("%s: TX status %d", net->name, urb->status);
+ if (netif_msg_tx_err(pegasus))
+ pr_info("%s: TX status %d\n", net->name, urb->status);
/* FALL THROUGH */
case 0:
break;
@@ -731,7 +782,9 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
/* some Pegasus-I products report LOTS of data
* toggle errors... avoid log spamming
*/
- pr_debug("%s: intr status %d\n", net->name, urb->status);
+ if (netif_msg_timer(pegasus))
+ pr_debug("%s: intr status %d\n", net->name,
+ urb->status);
}
if (urb->actual_length >= 6) {
@@ -763,7 +816,7 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
}
status = usb_submit_urb(urb, SLAB_ATOMIC);
- if (status)
+ if (status && netif_msg_timer(pegasus))
printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n",
net->name, status);
}
@@ -771,7 +824,8 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
static void pegasus_tx_timeout(struct net_device *net)
{
pegasus_t *pegasus = netdev_priv(net);
- printk(KERN_WARNING "%s: tx timeout\n", net->name);
+ if (netif_msg_timer(pegasus))
+ printk(KERN_WARNING "%s: tx timeout\n", net->name);
pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(pegasus->tx_urb);
pegasus->stats.tx_errors++;
@@ -793,7 +847,9 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
pegasus->tx_buff, count,
write_bulk_callback, pegasus);
if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
- warn("failed tx_urb %d", res);
+ if (netif_msg_tx_err(pegasus))
+ printk(KERN_WARNING "%s: fail tx, %d\n",
+ net->name, res);
switch (res) {
case -EPIPE: /* stall, or disconnect from TT */
/* cleanup should already have been scheduled */
@@ -822,8 +878,9 @@ static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
static inline void disable_net_traffic(pegasus_t * pegasus)
{
int tmp = 0;
+ int ret;
- set_registers(pegasus, EthCtrl0, 2, &tmp);
+ ret = set_registers(pegasus, EthCtrl0, 2, &tmp);
}
static inline void get_interrupt_interval(pegasus_t * pegasus)
@@ -832,8 +889,10 @@ static inline void get_interrupt_interval(pegasus_t * pegasus)
read_eprom_word(pegasus, 4, (__u16 *) data);
if (data[1] < 0x80) {
- info("intr interval will be changed from %ums to %ums",
- data[1], 0x80);
+ if (netif_msg_timer(pegasus))
+ dev_info(&pegasus->intf->dev,
+ "intr interval changed from %ums to %ums\n",
+ data[1], 0x80);
data[1] = 0x80;
#ifdef PEGASUS_WRITE_EEPROM
write_eprom_word(pegasus, 4, *(__u16 *) data);
@@ -845,7 +904,7 @@ static inline void get_interrupt_interval(pegasus_t * pegasus)
static void set_carrier(struct net_device *net)
{
pegasus_t *pegasus = netdev_priv(net);
- __le16 tmp;
+ u16 tmp;
if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
return;
@@ -912,24 +971,32 @@ static int pegasus_open(struct net_device *net)
if (!pegasus->rx_skb)
return -ENOMEM;
- set_registers(pegasus, EthID, 6, net->dev_addr);
+ res = set_registers(pegasus, EthID, 6, net->dev_addr);
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1),
pegasus->rx_skb->data, PEGASUS_MTU + 8,
read_bulk_callback, pegasus);
- if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL)))
- warn("%s: failed rx_urb %d", __FUNCTION__, res);
+ if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) {
+ if (netif_msg_ifup(pegasus))
+ pr_debug("%s: failed rx_urb, %d", net->name, res);
+ goto exit;
+ }
+
usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
usb_rcvintpipe(pegasus->usb, 3),
pegasus->intr_buff, sizeof (pegasus->intr_buff),
intr_callback, pegasus, pegasus->intr_interval);
- if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)))
- warn("%s: failed intr_urb %d", __FUNCTION__, res);
- netif_start_queue(net);
- pegasus->flags |= PEGASUS_RUNNING;
+ if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) {
+ if (netif_msg_ifup(pegasus))
+ pr_debug("%s: failed intr_urb, %d\n", net->name, res);
+ usb_kill_urb(pegasus->rx_urb);
+ goto exit;
+ }
if ((res = enable_net_traffic(net, pegasus->usb))) {
- err("can't enable_net_traffic() - %d", res);
+ if (netif_msg_ifup(pegasus))
+ pr_debug("%s: can't enable_net_traffic() - %d\n",
+ net->name, res);
res = -EIO;
usb_kill_urb(pegasus->rx_urb);
usb_kill_urb(pegasus->intr_urb);
@@ -937,6 +1004,9 @@ static int pegasus_open(struct net_device *net)
goto exit;
}
set_carrier(net);
+ netif_start_queue(net);
+ if (netif_msg_ifup(pegasus))
+ pr_debug("%s: open\n", net->name);
res = 0;
exit:
return res;
@@ -946,7 +1016,6 @@ static int pegasus_close(struct net_device *net)
{
pegasus_t *pegasus = netdev_priv(net);
- pegasus->flags &= ~PEGASUS_RUNNING;
netif_stop_queue(net);
if (!(pegasus->flags & PEGASUS_UNPLUG))
disable_net_traffic(pegasus);
@@ -956,7 +1025,8 @@ static int pegasus_close(struct net_device *net)
return 0;
}
-void pegasus_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void pegasus_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
{
pegasus_t *pegasus = netdev_priv(dev);
strncpy(info->driver, driver_name, sizeof (info->driver) - 1);
@@ -989,6 +1059,7 @@ pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
reg78 |= 0x80;
if (wol->wolopts & WAKE_PHY)
reg78 |= 0x40;
+ /* FIXME this 0x10 bit still needs to get set in the chip... */
if (wol->wolopts)
pegasus->eth_regs[0] |= 0x10;
else
@@ -1041,13 +1112,13 @@ static u32 pegasus_get_link(struct net_device *dev)
static u32 pegasus_get_msglevel(struct net_device *dev)
{
pegasus_t *pegasus = netdev_priv(dev);
- return pegasus->msg_level;
+ return pegasus->msg_enable;
}
static void pegasus_set_msglevel(struct net_device *dev, u32 v)
{
pegasus_t *pegasus = netdev_priv(dev);
- pegasus->msg_level = v;
+ pegasus->msg_enable = v;
}
static struct ethtool_ops ops = {
@@ -1093,12 +1164,14 @@ static void pegasus_set_multicast(struct net_device *net)
if (net->flags & IFF_PROMISC) {
pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
- pr_info("%s: Promiscuous mode enabled.\n", net->name);
+ if (netif_msg_link(pegasus))
+ pr_info("%s: Promiscuous mode enabled.\n", net->name);
} else if ((net->mc_count > multicast_filter_limit) ||
(net->flags & IFF_ALLMULTI)) {
pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
- pr_info("%s: set allmulti\n", net->name);
+ if (netif_msg_link(pegasus))
+ pr_info("%s: set allmulti\n", net->name);
} else {
pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
@@ -1127,17 +1200,18 @@ static __u8 mii_phy_probe(pegasus_t * pegasus)
static inline void setup_pegasus_II(pegasus_t * pegasus)
{
__u8 data = 0xa5;
+ int ret;
- set_register(pegasus, Reg1d, 0);
- set_register(pegasus, Reg7b, 1);
+ ret = set_register(pegasus, Reg1d, 0);
+ ret = set_register(pegasus, Reg7b, 1);
mdelay(100);
if ((pegasus->features & HAS_HOME_PNA) && mii_mode)
- set_register(pegasus, Reg7b, 0);
+ ret = set_register(pegasus, Reg7b, 0);
else
- set_register(pegasus, Reg7b, 2);
+ ret = set_register(pegasus, Reg7b, 2);
- set_register(pegasus, 0x83, data);
- get_registers(pegasus, 0x83, 1, &data);
+ ret = set_register(pegasus, 0x83, data);
+ ret = get_registers(pegasus, 0x83, 1, &data);
if (data == 0xa5) {
pegasus->chip = 0x8513;
@@ -1145,21 +1219,21 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
pegasus->chip = 0;
}
- set_register(pegasus, 0x80, 0xc0);
- set_register(pegasus, 0x83, 0xff);
- set_register(pegasus, 0x84, 0x01);
+ ret = set_register(pegasus, 0x80, 0xc0);
+ ret = set_register(pegasus, 0x83, 0xff);
+ ret = set_register(pegasus, 0x84, 0x01);
if (pegasus->features & HAS_HOME_PNA && mii_mode)
- set_register(pegasus, Reg81, 6);
+ ret = set_register(pegasus, Reg81, 6);
else
- set_register(pegasus, Reg81, 2);
+ ret = set_register(pegasus, Reg81, 2);
}
-struct workqueue_struct *pegasus_workqueue = NULL;
+static struct workqueue_struct *pegasus_workqueue = NULL;
#define CARRIER_CHECK_DELAY (2 * HZ)
-void check_carrier(void *data)
+static void check_carrier(void *data)
{
pegasus_t *pegasus = data;
set_carrier(pegasus->net);
@@ -1181,7 +1255,7 @@ static int pegasus_probe(struct usb_interface *intf,
usb_get_dev(dev);
net = alloc_etherdev(sizeof(struct pegasus));
if (!net) {
- err("out of memory allocating device structure");
+ dev_err(&intf->dev, "can't allocate %s\n", "device");
goto out;
}
@@ -1190,13 +1264,16 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus->dev_index = dev_index;
init_waitqueue_head(&pegasus->ctrl_wait);
- if (!alloc_urbs(pegasus))
+ if (!alloc_urbs(pegasus)) {
+ dev_err(&intf->dev, "can't allocate %s\n", "urbs");
goto out1;
+ }
tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus);
+ pegasus->intf = intf;
pegasus->usb = dev;
pegasus->net = net;
SET_MODULE_OWNER(net);
@@ -1215,6 +1292,8 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus->mii.phy_id_mask = 0x1f;
pegasus->mii.reg_num_mask = 0x1f;
spin_lock_init(&pegasus->rx_pool_lock);
+ pegasus->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
+ | NETIF_MSG_PROBE | NETIF_MSG_LINK);
pegasus->features = usb_dev_id[dev_index].private;
get_interrupt_interval(pegasus);
@@ -1241,8 +1320,15 @@ static int pegasus_probe(struct usb_interface *intf,
res = register_netdev(net);
if (res)
goto out3;
- queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, CARRIER_CHECK_DELAY);
- pr_info("%s: %s\n", net->name, usb_dev_id[dev_index].name);
+ queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
+ CARRIER_CHECK_DELAY);
+
+ dev_info(&intf->dev, "%s, %s, %02x:%02x:%02x:%02x:%02x:%02x\n",
+ net->name,
+ usb_dev_id[dev_index].name,
+ net->dev_addr [0], net->dev_addr [1],
+ net->dev_addr [2], net->dev_addr [3],
+ net->dev_addr [4], net->dev_addr [5]);
return 0;
out3:
@@ -1263,7 +1349,7 @@ static void pegasus_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (!pegasus) {
- warn("unregistering non-existent device");
+ dev_dbg(&intf->dev, "unregistering non-bound device?\n");
return;
}
diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
index db427f772e043..13ccedef5c7e0 100644
--- a/drivers/usb/net/pegasus.h
+++ b/drivers/usb/net/pegasus.h
@@ -29,7 +29,6 @@
#define DEFAULT_GPIO_SET 0x26
#define PEGASUS_PRESENT 0x00000001
-#define PEGASUS_RUNNING 0x00000002
#define PEGASUS_TX_BUSY 0x00000004
#define PEGASUS_RX_BUSY 0x00000008
#define CTRL_URB_RUNNING 0x00000010
@@ -86,12 +85,13 @@ enum pegasus_registers {
typedef struct pegasus {
struct usb_device *usb;
+ struct usb_interface *intf;
struct net_device *net;
struct net_device_stats stats;
struct mii_if_info mii;
unsigned flags;
unsigned features;
- u32 msg_level;
+ u32 msg_enable;
u32 wolopts;
int dev_index;
int intr_interval;
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index a59446558b078..dd8b4456ea35e 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -185,13 +185,14 @@ struct usbnet {
// i/o info: pipes etc
unsigned in, out;
+ struct usb_host_endpoint *status;
unsigned maxpacket;
struct timer_list delay;
// protocol/interface state
struct net_device *net;
struct net_device_stats stats;
- int msg_level;
+ int msg_enable;
unsigned long data [5];
struct mii_if_info mii;
@@ -200,6 +201,7 @@ struct usbnet {
struct sk_buff_head rxq;
struct sk_buff_head txq;
struct sk_buff_head done;
+ struct urb *interrupt;
struct tasklet_struct bh;
struct work_struct kevent;
@@ -207,6 +209,7 @@ struct usbnet {
# define EVENT_TX_HALT 0
# define EVENT_RX_HALT 1
# define EVENT_RX_MEMORY 2
+# define EVENT_STS_SPLIT 3
};
// device-specific info used by the driver
@@ -237,6 +240,9 @@ struct driver_info {
/* see if peer is connected ... can sleep */
int (*check_connect)(struct usbnet *);
+ /* for status polling */
+ void (*status)(struct usbnet *, struct urb *);
+
/* fixup rx packet (strip framing) */
int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
@@ -272,9 +278,9 @@ struct skb_data { // skb->cb is one of these
static const char driver_name [] = "usbnet";
/* use ethtool to change the level for any given device */
-static int msg_level = 1;
+static int msg_level = -1;
module_param (msg_level, int, 0);
-MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
+MODULE_PARM_DESC (msg_level, "Override default message level");
#ifdef DEBUG
@@ -290,9 +296,7 @@ MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
#define devinfo(usbnet, fmt, arg...) \
- do { if ((usbnet)->msg_level >= 1) \
printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
- } while (0)
/*-------------------------------------------------------------------------*/
@@ -312,38 +316,52 @@ static int
get_endpoints (struct usbnet *dev, struct usb_interface *intf)
{
int tmp;
- struct usb_host_interface *alt;
- struct usb_host_endpoint *in, *out;
+ struct usb_host_interface *alt = NULL;
+ struct usb_host_endpoint *in = NULL, *out = NULL;
+ struct usb_host_endpoint *status = NULL;
for (tmp = 0; tmp < intf->num_altsetting; tmp++) {
unsigned ep;
- in = out = NULL;
+ in = out = status = NULL;
alt = intf->altsetting + tmp;
/* take the first altsetting with in-bulk + out-bulk;
+ * remember any status endpoint, just in case;
* ignore other endpoints and altsetttings.
*/
for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) {
struct usb_host_endpoint *e;
+ int intr = 0;
e = alt->endpoint + ep;
- if (e->desc.bmAttributes != USB_ENDPOINT_XFER_BULK)
+ switch (e->desc.bmAttributes) {
+ case USB_ENDPOINT_XFER_INT:
+ if (!(e->desc.bEndpointAddress & USB_DIR_IN))
+ continue;
+ intr = 1;
+ /* FALLTHROUGH */
+ case USB_ENDPOINT_XFER_BULK:
+ break;
+ default:
continue;
+ }
if (e->desc.bEndpointAddress & USB_DIR_IN) {
- if (!in)
+ if (!intr && !in)
in = e;
+ else if (intr && !status)
+ status = e;
} else {
if (!out)
out = e;
}
- if (in && out)
- goto found;
}
+ if (in && out)
+ break;
}
- return -EINVAL;
+ if (!alt || !in || !out)
+ return -EINVAL;
-found:
if (alt->desc.bAlternateSetting != 0
|| !(dev->driver_info->flags & FLAG_NO_SETINT)) {
tmp = usb_set_interface (dev->udev, alt->desc.bInterfaceNumber,
@@ -356,9 +374,48 @@ found:
in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
dev->out = usb_sndbulkpipe (dev->udev,
out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+ dev->status = status;
return 0;
}
+static void intr_complete (struct urb *urb, struct pt_regs *regs);
+
+static int init_status (struct usbnet *dev, struct usb_interface *intf)
+{
+ char *buf = NULL;
+ unsigned pipe = 0;
+ unsigned maxp;
+ unsigned period;
+
+ if (!dev->driver_info->status)
+ return 0;
+
+ pipe = usb_rcvintpipe (dev->udev,
+ dev->status->desc.bEndpointAddress
+ & USB_ENDPOINT_NUMBER_MASK);
+ maxp = usb_maxpacket (dev->udev, pipe, 0);
+
+ /* avoid 1 msec chatter: min 8 msec poll rate */
+ period = max ((int) dev->status->desc.bInterval,
+ (dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
+
+ buf = kmalloc (maxp, SLAB_KERNEL);
+ if (buf) {
+ dev->interrupt = usb_alloc_urb (0, SLAB_KERNEL);
+ if (!dev->interrupt) {
+ kfree (buf);
+ return -ENOMEM;
+ } else {
+ usb_fill_int_urb(dev->interrupt, dev->udev, pipe,
+ buf, maxp, intr_complete, dev, period);
+ dev_dbg(&intf->dev,
+ "status ep%din, %d bytes period %d\n",
+ usb_pipeendpoint(pipe), maxp, period);
+ }
+ }
+ return 0;
+}
+
static void skb_return (struct usbnet *dev, struct sk_buff *skb)
{
int status;
@@ -368,13 +425,12 @@ static void skb_return (struct usbnet *dev, struct sk_buff *skb)
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;
-#ifdef VERBOSE
- devdbg (dev, "< rx, len %d, type 0x%x",
- skb->len + sizeof (struct ethhdr), skb->protocol);
-#endif
+ if (netif_msg_rx_status (dev))
+ devdbg (dev, "< rx, len %d, type 0x%x",
+ skb->len + sizeof (struct ethhdr), skb->protocol);
memset (skb->cb, 0, sizeof (struct skb_data));
status = netif_rx (skb);
- if (status != NET_RX_SUCCESS)
+ if (status != NET_RX_SUCCESS && netif_msg_rx_err (dev))
devdbg (dev, "netif_rx status %d", status);
}
@@ -1414,6 +1470,29 @@ next_desc:
usb_driver_release_interface (&usbnet_driver, info->data);
return status;
}
+
+ /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */
+ dev->status = NULL;
+ if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
+ struct usb_endpoint_descriptor *desc;
+
+ dev->status = &info->control->cur_altsetting->endpoint [0];
+ desc = &dev->status->desc;
+ if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
+ || !(desc->bEndpointAddress & USB_DIR_IN)
+ || (le16_to_cpu(desc->wMaxPacketSize)
+ < sizeof (struct usb_cdc_notification))
+ || !desc->bInterval) {
+ dev_dbg (&intf->dev, "bad notification endpoint\n");
+ dev->status = NULL;
+ }
+ }
+ if (rndis && !dev->status) {
+ dev_dbg (&intf->dev, "missing RNDIS status endpoint\n");
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface (&usbnet_driver, info->data);
+ return -ENODEV;
+ }
return 0;
bad_desc:
@@ -1442,6 +1521,56 @@ static void cdc_unbind (struct usbnet *dev, struct usb_interface *intf)
}
}
+
+static void dumpspeed (struct usbnet *dev, __le32 *speeds)
+{
+ if (netif_msg_timer (dev))
+ devinfo (dev, "link speeds: %u kbps up, %u kbps down",
+ __le32_to_cpu(speeds[0]) / 1000,
+ __le32_to_cpu(speeds[1]) / 1000);
+}
+
+static void cdc_status (struct usbnet *dev, struct urb *urb)
+{
+ struct usb_cdc_notification *event;
+
+ if (urb->actual_length < sizeof *event)
+ return;
+
+ /* SPEED_CHANGE can get split into two 8-byte packets */
+ if (test_and_clear_bit (EVENT_STS_SPLIT, &dev->flags)) {
+ dumpspeed (dev, (__le32 *) urb->transfer_buffer);
+ return;
+ }
+
+ event = urb->transfer_buffer;
+ switch (event->bNotificationType) {
+ case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+ if (netif_msg_timer (dev))
+ devdbg (dev, "CDC: carrier %s",
+ event->wValue ? "on" : "off");
+ if (event->wValue)
+ netif_carrier_on(dev->net);
+ else
+ netif_carrier_off(dev->net);
+ break;
+ case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */
+ if (netif_msg_timer (dev))
+ devdbg (dev, "CDC: speed change (len %d)",
+ urb->actual_length);
+ if (urb->actual_length != (sizeof *event + 8))
+ set_bit (EVENT_STS_SPLIT, &dev->flags);
+ else
+ dumpspeed (dev, (__le32 *) &event[1]);
+ break;
+ // case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: /* RNDIS; or unsolicited */
+ default:
+ deverr (dev, "CDC: unexpected notification %02x!",
+ event->bNotificationType);
+ break;
+ }
+}
+
#endif /* NEED_GENERIC_CDC */
@@ -1520,6 +1649,7 @@ static const struct driver_info cdc_info = {
// .check_connect = cdc_check_connect,
.bind = cdc_bind,
.unbind = cdc_unbind,
+ .status = cdc_status,
};
#endif /* CONFIG_USB_CDCETHER */
@@ -2051,7 +2181,8 @@ static void nc_dump_registers (struct usbnet *dev)
static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
{
-#ifdef DEBUG
+ if (!netif_msg_link (dev))
+ return;
devdbg (dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;"
" this%s%s;"
" other%s%s; r/o 0x%x",
@@ -2069,7 +2200,6 @@ static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
(usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
usbctl & ~USBCTL_WRITABLE_MASK
);
-#endif
}
/*-------------------------------------------------------------------------*/
@@ -2096,7 +2226,8 @@ static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
static inline void nc_dump_status (struct usbnet *dev, u16 status)
{
-#ifdef DEBUG
+ if (!netif_msg_link (dev))
+ return;
devdbg (dev, "net1080 %s-%s status 0x%x:"
" this (%c) PKT=%d%s%s%s;"
" other PKT=%d%s%s%s; unspec 0x%x",
@@ -2119,7 +2250,6 @@ static inline void nc_dump_status (struct usbnet *dev, u16 status)
status & STATUS_UNSPEC_MASK
);
-#endif
}
/*-------------------------------------------------------------------------*/
@@ -2134,15 +2264,10 @@ static inline void nc_dump_status (struct usbnet *dev, u16 status)
static inline void nc_dump_ttl (struct usbnet *dev, u16 ttl)
{
-#ifdef DEBUG
- devdbg (dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
- dev->udev->bus->bus_name, dev->udev->devpath,
- ttl,
-
- TTL_THIS (ttl),
- TTL_OTHER (ttl)
- );
-#endif
+ if (netif_msg_link (dev))
+ devdbg (dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ ttl, TTL_THIS (ttl), TTL_OTHER (ttl));
}
/*-------------------------------------------------------------------------*/
@@ -2164,14 +2289,14 @@ static int net1080_reset (struct usbnet *dev)
goto done;
}
status = *vp;
- // nc_dump_status (dev, status);
+ nc_dump_status (dev, status);
if ((retval = nc_register_read (dev, REG_USBCTL, vp)) < 0) {
dbg ("can't read USBCTL, %d", retval);
goto done;
}
usbctl = *vp;
- // nc_dump_usbctl (dev, usbctl);
+ nc_dump_usbctl (dev, usbctl);
nc_register_write (dev, REG_USBCTL,
USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
@@ -2187,7 +2312,7 @@ static int net1080_reset (struct usbnet *dev)
MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) );
dbg ("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS);
- if (dev->msg_level >= 2)
+ if (netif_msg_link (dev))
devinfo (dev, "port %c, peer %sconnected",
(status & STATUS_PORT_A) ? 'A' : 'B',
(status & STATUS_CONN_OTHER) ? "" : "dis"
@@ -2268,7 +2393,8 @@ static void nc_ensure_sync (struct usbnet *dev)
return;
}
- devdbg (dev, "flush net1080; too many framing errors");
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "flush net1080; too many framing errors");
dev->frame_errors = 0;
}
}
@@ -2526,11 +2652,17 @@ static const struct driver_info blob_info = {
* For the current version of that driver, the main way that framing is
* nonstandard (also from perspective of the CDC ethernet model!) is a
* crc32, added to help detect when some sa1100 usb-to-memory DMA errata
- * haven't been fully worked around.
+ * haven't been fully worked around. Also, all Zaurii use the same
+ * default Ethernet address.
*
* PXA based models use the same framing, and also can't implement
* set_interface properly.
*
+ * All known Zaurii lie about their standards conformance. Most lie by
+ * saying they support CDC Ethernet. Some lie and say they support CDC
+ * MDLM (as if for access to cell phone modems). Someone, please beat
+ * on Sharp for a while with a cluestick.
+ *
*-------------------------------------------------------------------------*/
static struct sk_buff *
@@ -2582,6 +2714,13 @@ static const struct driver_info zaurus_pxa_info = {
};
#define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info)
+static const struct driver_info zaurus_pxa_mdlm_info = {
+ .description = "Sharp Zaurus, PXA-255 based",
+ .flags = FLAG_FRAMING_Z,
+ .check_connect = always_connected,
+ .tx_fixup = zaurus_tx_fixup,
+};
+
static const struct driver_info olympus_mxl_info = {
.description = "Olympus R1000",
.flags = FLAG_FRAMING_Z,
@@ -2715,7 +2854,8 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
size = (sizeof (struct ethhdr) + dev->net->mtu);
if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
- devdbg (dev, "no rx skb");
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "no rx skb");
defer_kevent (dev, EVENT_RX_MEMORY);
usb_free_urb (urb);
return;
@@ -2745,18 +2885,21 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
defer_kevent (dev, EVENT_RX_MEMORY);
break;
case -ENODEV:
- devdbg (dev, "device gone");
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "device gone");
netif_device_detach (dev->net);
break;
default:
- devdbg (dev, "rx submit, %d", retval);
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "rx submit, %d", retval);
tasklet_schedule (&dev->bh);
break;
case 0:
__skb_queue_tail (&dev->rxq, skb);
}
} else {
- devdbg (dev, "rx: stopped");
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "rx: stopped");
retval = -ENOLINK;
}
spin_unlock_irqrestore (&dev->rxq.lock, lockflags);
@@ -2779,7 +2922,8 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
if (skb->len)
skb_return (dev, skb);
else {
- devdbg (dev, "drop");
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "drop");
error:
dev->stats.rx_errors++;
skb_queue_tail (&dev->done, skb);
@@ -2806,7 +2950,8 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
entry->state = rx_cleanup;
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
- devdbg (dev, "rx length %d", skb->len);
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "rx length %d", skb->len);
}
break;
@@ -2822,9 +2967,8 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
// software-driven interface shutdown
case -ECONNRESET: // async unlink
case -ESHUTDOWN: // hardware gone
-#ifdef VERBOSE
- devdbg (dev, "rx shutdown, code %d", urb_status);
-#endif
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "rx shutdown, code %d", urb_status);
goto block;
// we get controller i/o faults during khubd disconnect() delays.
@@ -2836,7 +2980,8 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
dev->stats.rx_errors++;
if (!timer_pending (&dev->delay)) {
mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
- devdbg (dev, "rx throttle %d", urb_status);
+ if (netif_msg_link (dev))
+ devdbg (dev, "rx throttle %d", urb_status);
}
block:
entry->state = rx_cleanup;
@@ -2852,7 +2997,8 @@ block:
default:
entry->state = rx_cleanup;
dev->stats.rx_errors++;
- devdbg (dev, "rx status %d", urb_status);
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "rx status %d", urb_status);
break;
}
@@ -2866,9 +3012,43 @@ block:
}
usb_free_urb (urb);
}
-#ifdef VERBOSE
- devdbg (dev, "no read resubmitted");
-#endif /* VERBOSE */
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "no read resubmitted");
+}
+
+static void intr_complete (struct urb *urb, struct pt_regs *regs)
+{
+ struct usbnet *dev = urb->context;
+ int status = urb->status;
+
+ switch (status) {
+ /* success */
+ case 0:
+ dev->driver_info->status(dev, urb);
+ break;
+
+ /* software-driven interface shutdown */
+ case -ENOENT: // urb killed
+ case -ESHUTDOWN: // hardware gone
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "intr shutdown, code %d", status);
+ return;
+
+ /* NOTE: not throttling like RX/TX, since this endpoint
+ * already polls infrequently
+ */
+ default:
+ devdbg (dev, "intr status %d", status);
+ break;
+ }
+
+ if (!netif_running (dev->net))
+ return;
+
+ memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
+ status = usb_submit_urb (urb, GFP_ATOMIC);
+ if (status != 0 && netif_msg_timer (dev))
+ deverr(dev, "intr resubmit --> %d", status);
}
/*-------------------------------------------------------------------------*/
@@ -2917,7 +3097,7 @@ static int usbnet_stop (struct net_device *net)
netif_stop_queue (net);
- if (dev->msg_level >= 2)
+ if (netif_msg_ifdown (dev))
devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
dev->stats.rx_packets, dev->stats.tx_packets,
dev->stats.rx_errors, dev->stats.tx_errors
@@ -2933,11 +3113,14 @@ static int usbnet_stop (struct net_device *net)
&& skb_queue_len (&dev->txq)
&& skb_queue_len (&dev->done)) {
msleep(UNLINK_TIMEOUT_MS);
- devdbg (dev, "waited for %d urb completions", temp);
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "waited for %d urb completions", temp);
}
dev->wait = NULL;
remove_wait_queue (&unlink_wakeup, &wait);
+ usb_kill_urb(dev->interrupt);
+
/* deferred work (task, timer, softirq) must also stop.
* can't flush_scheduled_work() until we drop rtnl (later),
* else workers could deadlock; so make workers a NOP.
@@ -2963,21 +3146,34 @@ static int usbnet_open (struct net_device *net)
// put into "known safe" state
if (info->reset && (retval = info->reset (dev)) < 0) {
- devinfo (dev, "open reset fail (%d) usbnet usb-%s-%s, %s",
- retval,
- dev->udev->bus->bus_name, dev->udev->devpath,
+ if (netif_msg_ifup (dev))
+ devinfo (dev,
+ "open reset fail (%d) usbnet usb-%s-%s, %s",
+ retval,
+ dev->udev->bus->bus_name, dev->udev->devpath,
info->description);
goto done;
}
// insist peer be connected
if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
- devdbg (dev, "can't open; %d", retval);
+ if (netif_msg_ifup (dev))
+ devdbg (dev, "can't open; %d", retval);
goto done;
}
+ /* start any status interrupt transfer */
+ if (dev->interrupt) {
+ retval = usb_submit_urb (dev->interrupt, GFP_KERNEL);
+ if (retval < 0) {
+ if (netif_msg_ifup (dev))
+ deverr (dev, "intr submit %d", retval);
+ goto done;
+ }
+ }
+
netif_start_queue (net);
- if (dev->msg_level >= 2) {
+ if (netif_msg_ifup (dev)) {
char *framing;
if (dev->driver_info->flags & FLAG_FRAMING_NC)
@@ -3034,14 +3230,14 @@ static u32 usbnet_get_msglevel (struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
- return dev->msg_level;
+ return dev->msg_enable;
}
static void usbnet_set_msglevel (struct net_device *net, u32 level)
{
struct usbnet *dev = netdev_priv(net);
- dev->msg_level = level;
+ dev->msg_enable = level;
}
static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
@@ -3074,10 +3270,11 @@ kevent (void *data)
if (test_bit (EVENT_TX_HALT, &dev->flags)) {
unlink_urbs (dev, &dev->txq);
status = usb_clear_halt (dev->udev, dev->out);
- if (status < 0 && status != -EPIPE)
- deverr (dev, "can't clear tx halt, status %d",
- status);
- else {
+ if (status < 0 && status != -EPIPE) {
+ if (netif_msg_tx_err (dev))
+ deverr (dev, "can't clear tx halt, status %d",
+ status);
+ } else {
clear_bit (EVENT_TX_HALT, &dev->flags);
netif_wake_queue (dev->net);
}
@@ -3085,10 +3282,11 @@ kevent (void *data)
if (test_bit (EVENT_RX_HALT, &dev->flags)) {
unlink_urbs (dev, &dev->rxq);
status = usb_clear_halt (dev->udev, dev->in);
- if (status < 0 && status != -EPIPE)
- deverr (dev, "can't clear rx halt, status %d",
- status);
- else {
+ if (status < 0 && status != -EPIPE) {
+ if (netif_msg_rx_err (dev))
+ deverr (dev, "can't clear rx halt, status %d",
+ status);
+ } else {
clear_bit (EVENT_RX_HALT, &dev->flags);
tasklet_schedule (&dev->bh);
}
@@ -3133,6 +3331,11 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
defer_kevent (dev, EVENT_TX_HALT);
break;
+ /* software-driven interface shutdown */
+ case -ECONNRESET: // async unlink
+ case -ESHUTDOWN: // hardware gone
+ break;
+
// like rx, tx gets controller i/o faults during khubd delays
// and so it uses the same throttling mechanism.
case -EPROTO: // ehci
@@ -3141,12 +3344,15 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
if (!timer_pending (&dev->delay)) {
mod_timer (&dev->delay,
jiffies + THROTTLE_JIFFIES);
- devdbg (dev, "tx throttle %d", urb->status);
+ if (netif_msg_link (dev))
+ devdbg (dev, "tx throttle %d",
+ urb->status);
}
netif_stop_queue (dev->net);
break;
default:
- devdbg (dev, "tx err %d", entry->urb->status);
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "tx err %d", entry->urb->status);
break;
}
}
@@ -3189,14 +3395,16 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
if (info->tx_fixup) {
skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
if (!skb) {
- devdbg (dev, "can't tx_fixup skb");
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "can't tx_fixup skb");
goto drop;
}
}
length = skb->len;
if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) {
- devdbg (dev, "no urb");
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "no urb");
goto drop;
}
@@ -3254,7 +3462,8 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
defer_kevent (dev, EVENT_TX_HALT);
break;
default:
- devdbg (dev, "tx: submit urb err %d", retval);
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "tx: submit urb err %d", retval);
break;
case 0:
net->trans_start = jiffies;
@@ -3265,18 +3474,17 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
spin_unlock_irqrestore (&dev->txq.lock, flags);
if (retval) {
- devdbg (dev, "drop, code %d", retval);
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "drop, code %d", retval);
drop:
retval = NET_XMIT_SUCCESS;
dev->stats.tx_dropped++;
if (skb)
dev_kfree_skb_any (skb);
usb_free_urb (urb);
-#ifdef VERBOSE
- } else {
+ } else if (netif_msg_tx_queued (dev)) {
devdbg (dev, "> tx, len %d, type 0x%x",
length, skb->protocol);
-#endif
}
return retval;
}
@@ -3333,7 +3541,7 @@ static void usbnet_bh (unsigned long param)
if (urb != NULL)
rx_submit (dev, urb, GFP_ATOMIC);
}
- if (temp != dev->rxq.qlen)
+ if (temp != dev->rxq.qlen && netif_msg_link (dev))
devdbg (dev, "rxqlen %d --> %d",
temp, dev->rxq.qlen);
if (dev->rxq.qlen < qlen)
@@ -3367,9 +3575,10 @@ static void usbnet_disconnect (struct usb_interface *intf)
xdev = interface_to_usbdev (intf);
- devinfo (dev, "unregister usbnet usb-%s-%s, %s",
- xdev->bus->bus_name, xdev->devpath,
- dev->driver_info->description);
+ if (netif_msg_probe (dev))
+ devinfo (dev, "unregister usbnet usb-%s-%s, %s",
+ xdev->bus->bus_name, xdev->devpath,
+ dev->driver_info->description);
net = dev->net;
unregister_netdev (net);
@@ -3423,7 +3632,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
dev = netdev_priv(net);
dev->udev = xdev;
dev->driver_info = info;
- dev->msg_level = msg_level;
+ dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
+ | NETIF_MSG_PROBE | NETIF_MSG_LINK);
skb_queue_head_init (&dev->rxq);
skb_queue_head_init (&dev->txq);
skb_queue_head_init (&dev->done);
@@ -3442,7 +3652,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
#if 0
// dma_supported() is deeply broken on almost all architectures
// possible with some EHCI controllers
- if (dma_supported (&udev->dev, 0xffffffffffffffffULL))
+ if (dma_supported (&udev->dev, DMA_64BIT_MASK))
net->features |= NETIF_F_HIGHDMA;
#endif
@@ -3479,6 +3689,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
status = 0;
}
+
+ if (status == 0 && dev->status)
+ status = init_status (dev, udev);
if (status < 0)
goto out1;
@@ -3488,9 +3701,14 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
status = register_netdev (net);
if (status)
goto out3;
- devinfo (dev, "register usbnet at usb-%s-%s, %s",
- xdev->bus->bus_name, xdev->devpath,
- dev->driver_info->description);
+ if (netif_msg_probe (dev))
+ devinfo (dev, "register usbnet at usb-%s-%s, %s, "
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ xdev->bus->bus_name, xdev->devpath,
+ dev->driver_info->description,
+ net->dev_addr [0], net->dev_addr [1],
+ net->dev_addr [2], net->dev_addr [3],
+ net->dev_addr [4], net->dev_addr [5]);
// ok, it's ready to go.
usb_set_intfdata (udev, dev);
@@ -3729,6 +3947,7 @@ static const struct usb_device_id products [] = {
* Same idea as above, but different framing.
*
* PXA-2xx based models are also lying-about-cdc.
+ * Some models don't even tell the same lies ...
*
* NOTE: OpenZaurus versions with 2.6 kernels won't use these entries,
* unlike the older ones with 2.4 "embedix" kernels.
@@ -3786,9 +4005,25 @@ static const struct usb_device_id products [] = {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
+ /* reported with some C860 units */
.idProduct = 0x9050, /* C-860 */
ZAURUS_MASTER_INTERFACE,
.driver_info = ZAURUS_PXA_INFO,
+#ifdef CONFIG_USB_ZAURUS
+ /* at least some (reports vary) C-860 units have very different
+ * lies about their standards support.
+ */
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ /* reported with some C860 units */
+ .idProduct = 0x9031, /* C-860 */
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ .driver_info = (unsigned long) &zaurus_pxa_mdlm_info,
+#endif
},
/* Olympus has some models with a Zaurus-compatible option.
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index 6b3301e013a21..938025e2c6469 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -673,7 +673,7 @@ static int zd1201_enable(struct zd1201 *zd)
return 0;
err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0);
- if (!err);
+ if (!err)
zd->mac_enabled = 1;
if (zd->monitor)
@@ -690,7 +690,7 @@ static int zd1201_disable(struct zd1201 *zd)
return 0;
if (zd->monitor) {
err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
- if (err);
+ if (err)
return err;
}
diff --git a/drivers/usb/net/zd1201.h b/drivers/usb/net/zd1201.h
index 4386956a5c1c3..1627c71e80525 100644
--- a/drivers/usb/net/zd1201.h
+++ b/drivers/usb/net/zd1201.h
@@ -141,7 +141,7 @@ struct zd1201_frag {
#define ZD1201_RATEB5 4 /* 5.5 really, but 5 is shorter :) */
#define ZD1201_RATEB11 8
-#define ZD1201_CNFAUTHENTICATION_OPENSYSTEM 0
-#define ZD1201_CNFAUTHENTICATION_SHAREDKEY 1
+#define ZD1201_CNFAUTHENTICATION_OPENSYSTEM 0x0001
+#define ZD1201_CNFAUTHENTICATION_SHAREDKEY 0x0002
#endif /* _INCLUDE_ZD1201_H_ */
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 67275dd601207..b869076d9c7c8 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -89,6 +89,16 @@ config USB_SERIAL_DIGI_ACCELEPORT
To compile this driver as a module, choose M here: the
module will be called digi_acceleport.
+config USB_SERIAL_CP2101
+ tristate "USB CP2101 UART Bridge Controller"
+ depends on USB_SERIAL && EXPERIMENTAL
+ help
+ Say Y here if you want to use a CP2101/CP2102 based USB to RS232
+ converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cp2101.
+
config USB_SERIAL_CYPRESS_M8
tristate "USB Cypress M8 USB Serial Driver"
depends on USB_SERIAL && EXPERIMENTAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 1432b18125a65..351b81855b185 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -12,6 +12,7 @@ usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o
usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y)
obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
+obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o
obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
new file mode 100644
index 0000000000000..7e9bb63eb466d
--- /dev/null
+++ b/drivers/usb/serial/cp2101.c
@@ -0,0 +1,591 @@
+/*
+ * Silicon Laboratories CP2101/CP2102 USB to RS232 serial adaptor driver
+ *
+ * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk)
+ *
+ * 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/errno.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/usb.h>
+#include <asm/uaccess.h>
+#include "usb-serial.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.03"
+#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
+
+/*
+ * Function Prototypes
+ */
+static int cp2101_open(struct usb_serial_port*, struct file*);
+static void cp2101_cleanup(struct usb_serial_port*);
+static void cp2101_close(struct usb_serial_port*, struct file*);
+static void cp2101_get_termios(struct usb_serial_port*);
+static void cp2101_set_termios(struct usb_serial_port*, struct termios*);
+static void cp2101_break_ctl(struct usb_serial_port*, int);
+static int cp2101_startup (struct usb_serial *);
+static void cp2101_shutdown(struct usb_serial*);
+
+
+static int debug;
+
+static struct usb_device_id id_table [] = {
+ {USB_DEVICE(0x10c4, 0xea60) }, /*Silicon labs factory default*/
+ {USB_DEVICE(0x10ab, 0x10c5) }, /*Siemens MC60 Cable*/
+ { } /* Terminating Entry*/
+};
+
+MODULE_DEVICE_TABLE (usb, id_table);
+
+static struct usb_driver cp2101_driver = {
+ .owner = THIS_MODULE,
+ .name = "CP2101",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+};
+
+static struct usb_serial_device_type cp2101_device = {
+ .owner = THIS_MODULE,
+ .name = "CP2101",
+ .id_table = id_table,
+ .num_interrupt_in = 0,
+ .num_bulk_in = 0,
+ .num_bulk_out = 0,
+ .num_ports = 1,
+ .open = cp2101_open,
+ .close = cp2101_close,
+ .break_ctl = cp2101_break_ctl,
+ .set_termios = cp2101_set_termios,
+ .attach = cp2101_startup,
+ .shutdown = cp2101_shutdown,
+};
+
+/*Config request types*/
+#define REQTYPE_HOST_TO_DEVICE 0x41
+#define REQTYPE_DEVICE_TO_HOST 0xc1
+
+/*Config SET requests. To GET, add 1 to the request number*/
+#define CP2101_UART 0x00 /*Enable / Disable*/
+#define CP2101_BAUDRATE 0x01 /*(BAUD_RATE_GEN_FREQ / baudrate)*/
+#define CP2101_BITS 0x03 /*0x(0)(data bits)(parity)(stop bits)*/
+#define CP2101_BREAK 0x05 /*On / Off*/
+#define CP2101_DTRRTS 0x07 /*101 / 202 ???*/
+#define CP2101_CONFIG_16 0x13 /*16 bytes of config data ???*/
+#define CP2101_CONFIG_6 0x19 /*6 bytes of config data ???*/
+
+/*CP2101_UART*/
+#define UART_ENABLE 0x0001
+#define UART_DISABLE 0x0000
+
+/*CP2101_BAUDRATE*/
+#define BAUD_RATE_GEN_FREQ 0x384000
+
+/*CP2101_BITS*/
+#define BITS_DATA_MASK 0X0f00
+#define BITS_DATA_6 0X0600
+#define BITS_DATA_7 0X0700
+#define BITS_DATA_8 0X0800
+#define BITS_DATA_9 0X0900
+
+#define BITS_PARITY_MASK 0x00f0
+#define BITS_PARITY_NONE 0x0000
+#define BITS_PARITY_ODD 0x0010
+#define BITS_PARITY_EVEN 0x0020
+#define BITS_PARITY_MARK 0x0030
+#define BITS_PARITY_SPACE 0x0040
+
+#define BITS_STOP_MASK 0x000f
+#define BITS_STOP_1 0x0000
+#define BITS_STOP_1_5 0x0001
+#define BITS_STOP_2 0x0002
+#define BREAK_ON 0x0000
+#define BREAK_OFF 0x0001
+
+
+static int cp2101_get_config(struct usb_serial_port* port, u8 request)
+{
+ struct usb_serial *serial = port->serial;
+ unsigned char buf[4];
+ unsigned int value;
+ int result, i;
+
+ /*For get requests, the request number must be incremented*/
+ request++;
+
+ /*Issue the request, attempting to read 4 bytes*/
+ result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0),
+ request, REQTYPE_DEVICE_TO_HOST, 0x0000,
+ 0, buf, 4, 300);
+
+ if (result < 0) {
+ dev_err(&port->dev, "%s - Unable to send config request, "
+ "request=0x%x result=%d\n",
+ __FUNCTION__, request, result);
+ return result;
+ }
+
+ /*Assemble each byte read into an integer value*/
+ value = 0;
+ for (i=0; i<4 && i<result; i++)
+ value |= (buf[i] << (i * 8));
+
+ dbg( " %s - request=0x%x result=%d value=0x%x",
+ __FUNCTION__, request, result, value);
+
+ return value;
+}
+
+static int cp2101_set_config(struct usb_serial_port* port, u8 request, u16 value)
+{
+ struct usb_serial *serial = port->serial;
+ int result;
+ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ request, REQTYPE_HOST_TO_DEVICE, value,
+ 0, NULL, 0, 300);
+
+ if (result <0) {
+ dev_err(&port->dev, "%s - Unable to send config request, "
+ "request=0x%x value=0x%x result=%d\n",
+ __FUNCTION__, request, value, result);
+ return result;
+ }
+
+ dbg(" %s - request=0x%x value=0x%x result=%d",
+ __FUNCTION__, request, value, result);
+
+ return 0;
+}
+
+static int cp2101_open (struct usb_serial_port *port, struct file *filp)
+{
+ struct usb_serial *serial = port->serial;
+ int result;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (cp2101_set_config(port, CP2101_UART, UART_ENABLE)) {
+ dev_err(&port->dev, "%s - Unable to enable UART\n",
+ __FUNCTION__);
+ return -EPROTO;
+ }
+
+ /* Start reading from the device */
+ usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ serial->type->read_bulk_callback,
+ port);
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result) {
+ dev_err(&port->dev, "%s - failed resubmitting read urb, "
+ "error %d\n", __FUNCTION__, result);
+ return result;
+ }
+
+ /*Configure the termios structure*/
+ cp2101_get_termios(port);
+
+ return 0;
+}
+
+static void cp2101_cleanup (struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (serial->dev) {
+ /* shutdown any bulk reads that might be going on */
+ if (serial->num_bulk_out)
+ usb_kill_urb(port->write_urb);
+ if (serial->num_bulk_in)
+ usb_kill_urb(port->read_urb);
+ }
+}
+
+static void cp2101_close (struct usb_serial_port *port, struct file * filp)
+{
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ /* shutdown our urbs */
+ dbg("%s - shutting down urbs", __FUNCTION__);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
+
+ cp2101_set_config(port, CP2101_UART, UART_DISABLE);
+}
+
+/* cp2101_get_termios*/
+/* Reads the baud rate, data bits, parity and stop bits from the device*/
+/* Corrects any unsupported values*/
+/* Configures the termios structure to reflect the state of the device*/
+static void cp2101_get_termios (struct usb_serial_port *port)
+{
+ unsigned int cflag;
+ int baud;
+ int bits;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if ((!port->tty) || (!port->tty->termios)) {
+ dbg("%s - no tty structures", __FUNCTION__);
+ return;
+ }
+ cflag = port->tty->termios->c_cflag;
+
+ baud = cp2101_get_config(port, CP2101_BAUDRATE);
+ /*Convert to baudrate*/
+ if (baud)
+ baud = BAUD_RATE_GEN_FREQ / baud;
+
+ dbg("%s - baud rate = %d", __FUNCTION__, baud);
+ cflag &= ~CBAUD;
+ switch (baud) {
+ /* The baud rates which are commented out below
+ * appear to be supported by the device
+ * but are non-standard
+ */
+ case 600: cflag |= B600; break;
+ case 1200: cflag |= B1200; break;
+ case 1800: cflag |= B1800; break;
+ case 2400: cflag |= B2400; break;
+ case 4800: cflag |= B4800; break;
+ /*case 7200: cflag |= B7200; break;*/
+ case 9600: cflag |= B9600; break;
+ /*case 14400: cflag |= B14400; break;*/
+ case 19200: cflag |= B19200; break;
+ /*case 28800: cflag |= B28800; break;*/
+ case 38400: cflag |= B38400; break;
+ /*case 55854: cflag |= B55054; break;*/
+ case 57600: cflag |= B57600; break;
+ case 115200: cflag |= B115200; break;
+ /*case 127117: cflag |= B127117; break;*/
+ case 230400: cflag |= B230400; break;
+ case 460800: cflag |= B460800; break;
+ case 921600: cflag |= B921600; break;
+ /*case 3686400: cflag |= B3686400; break;*/
+ default:
+ dbg("%s - Baud rate is not supported, "
+ "using 9600 baud", __FUNCTION__);
+ cflag |= B9600;
+ cp2101_set_config(port, CP2101_BAUDRATE,
+ (BAUD_RATE_GEN_FREQ/9600));
+ break;
+ }
+
+ bits = cp2101_get_config(port, CP2101_BITS);
+ cflag &= ~CSIZE;
+ switch(bits & BITS_DATA_MASK) {
+ case BITS_DATA_6:
+ dbg("%s - data bits = 6", __FUNCTION__);
+ cflag |= CS6;
+ break;
+ case BITS_DATA_7:
+ dbg("%s - data bits = 7", __FUNCTION__);
+ cflag |= CS7;
+ break;
+ case BITS_DATA_8:
+ dbg("%s - data bits = 8", __FUNCTION__);
+ cflag |= CS8;
+ break;
+ case BITS_DATA_9:
+ dbg("%s - data bits = 9 (not supported, "
+ "using 8 data bits)", __FUNCTION__);
+ cflag |= CS8;
+ bits &= ~BITS_DATA_MASK;
+ bits |= BITS_DATA_8;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ default:
+ dbg("%s - Unknown number of data bits, "
+ "using 8", __FUNCTION__);
+ cflag |= CS8;
+ bits &= ~BITS_DATA_MASK;
+ bits |= BITS_DATA_8;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ }
+
+ switch(bits & BITS_PARITY_MASK) {
+ case BITS_PARITY_NONE:
+ dbg("%s - parity = NONE", __FUNCTION__);
+ cflag &= ~PARENB;
+ break;
+ case BITS_PARITY_ODD:
+ dbg("%s - parity = ODD", __FUNCTION__);
+ cflag |= (PARENB|PARODD);
+ break;
+ case BITS_PARITY_EVEN:
+ dbg("%s - parity = EVEN", __FUNCTION__);
+ cflag &= ~PARODD;
+ cflag |= PARENB;
+ break;
+ case BITS_PARITY_MARK:
+ dbg("%s - parity = MARK (not supported, "
+ "disabling parity)", __FUNCTION__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ case BITS_PARITY_SPACE:
+ dbg("%s - parity = SPACE (not supported, "
+ "disabling parity)", __FUNCTION__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ default:
+ dbg("%s - Unknown parity mode, "
+ "disabling parity", __FUNCTION__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ }
+
+ cflag &= ~CSTOPB;
+ switch(bits & BITS_STOP_MASK) {
+ case BITS_STOP_1:
+ dbg("%s - stop bits = 1", __FUNCTION__);
+ break;
+ case BITS_STOP_1_5:
+ dbg("%s - stop bits = 1.5 (not supported, "
+ "using 1 stop bit", __FUNCTION__);
+ bits &= ~BITS_STOP_MASK;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ case BITS_STOP_2:
+ dbg("%s - stop bits = 2", __FUNCTION__);
+ cflag |= CSTOPB;
+ break;
+ default:
+ dbg("%s - Unknown number of stop bits, "
+ "using 1 stop bit", __FUNCTION__);
+ bits &= ~BITS_STOP_MASK;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ }
+
+ port->tty->termios->c_cflag = cflag;
+}
+
+static void cp2101_set_termios (struct usb_serial_port *port,
+ struct termios *old_termios)
+{
+ unsigned int cflag, old_cflag=0;
+ int baud=0;
+ int bits;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if ((!port->tty) || (!port->tty->termios)) {
+ dbg("%s - no tty structures", __FUNCTION__);
+ return;
+ }
+ cflag = port->tty->termios->c_cflag;
+
+ /* check that they really want us to change something */
+ if (old_termios) {
+ if ((cflag == old_termios->c_cflag) &&
+ (RELEVANT_IFLAG(port->tty->termios->c_iflag)
+ == RELEVANT_IFLAG(old_termios->c_iflag))) {
+ dbg("%s - nothing to change...", __FUNCTION__);
+ return;
+ }
+
+ old_cflag = old_termios->c_cflag;
+ }
+
+ /* If the baud rate is to be updated*/
+ if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
+ switch (cflag & CBAUD) {
+ /* The baud rates which are commented out below
+ * appear to be supported by the device
+ * but are non-standard
+ */
+ case B0: baud = 0; break;
+ case B600: baud = 600; break;
+ case B1200: baud = 1200; break;
+ case B1800: baud = 1800; break;
+ case B2400: baud = 2400; break;
+ case B4800: baud = 4800; break;
+ /*case B7200: baud = 7200; break;*/
+ case B9600: baud = 9600; break;
+ /*ase B14400: baud = 14400; break;*/
+ case B19200: baud = 19200; break;
+ /*case B28800: baud = 28800; break;*/
+ case B38400: baud = 38400; break;
+ /*case B55854: baud = 55054; break;*/
+ case B57600: baud = 57600; break;
+ case B115200: baud = 115200; break;
+ /*case B127117: baud = 127117; break;*/
+ case B230400: baud = 230400; break;
+ case B460800: baud = 460800; break;
+ case B921600: baud = 921600; break;
+ /*case B3686400: baud = 3686400; break;*/
+ default:
+ dev_err(&port->dev, "cp2101 driver does not "
+ "support the baudrate requested\n");
+ break;
+ }
+
+ if (baud) {
+ dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
+ baud);
+ if (cp2101_set_config(port, CP2101_BAUDRATE,
+ (BAUD_RATE_GEN_FREQ / baud)))
+ dev_err(&port->dev, "Baud rate requested not "
+ "supported by device\n");
+ }
+ }
+
+ /*If the number of data bits is to be updated*/
+ if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
+ bits = cp2101_get_config(port, CP2101_BITS);
+ bits &= ~BITS_DATA_MASK;
+ switch (cflag & CSIZE) {
+ case CS6:
+ bits |= BITS_DATA_6;
+ dbg("%s - data bits = 6", __FUNCTION__);
+ break;
+ case CS7:
+ bits |= BITS_DATA_7;
+ dbg("%s - data bits = 7", __FUNCTION__);
+ break;
+ case CS8:
+ bits |= BITS_DATA_8;
+ dbg("%s - data bits = 8", __FUNCTION__);
+ break;
+ /*case CS9:
+ bits |= BITS_DATA_9;
+ dbg("%s - data bits = 9", __FUNCTION__);
+ break;*/
+ default:
+ dev_err(&port->dev, "cp2101 driver does not "
+ "support the number of bits requested,"
+ " using 8 bit mode\n");
+ bits |= BITS_DATA_8;
+ break;
+ }
+ if (cp2101_set_config(port, CP2101_BITS, bits))
+ dev_err(&port->dev, "Number of data bits requested "
+ "not supported by device\n");
+ }
+
+ if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) {
+ bits = cp2101_get_config(port, CP2101_BITS);
+ bits &= ~BITS_PARITY_MASK;
+ if (cflag & PARENB) {
+ if (cflag & PARODD) {
+ bits |= BITS_PARITY_ODD;
+ dbg("%s - parity = ODD", __FUNCTION__);
+ } else {
+ bits |= BITS_PARITY_EVEN;
+ dbg("%s - parity = EVEN", __FUNCTION__);
+ }
+ }
+ if (cp2101_set_config(port, CP2101_BITS, bits))
+ dev_err(&port->dev, "Parity mode not supported "
+ "by device\n");
+ }
+
+ if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
+ bits = cp2101_get_config(port, CP2101_BITS);
+ bits &= ~BITS_STOP_MASK;
+ if (cflag & CSTOPB) {
+ bits |= BITS_STOP_2;
+ dbg("%s - stop bits = 2", __FUNCTION__);
+ } else {
+ bits |= BITS_STOP_1;
+ dbg("%s - stop bits = 1", __FUNCTION__);
+ }
+ if (cp2101_set_config(port, CP2101_BITS, bits))
+ dev_err(&port->dev, "Number of stop bits requested "
+ "not supported by device\n");
+ }
+}
+
+static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
+{
+ u16 state;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+ if (break_state == 0)
+ state = BREAK_OFF;
+ else
+ state = BREAK_ON;
+ dbg("%s - turning break %s", __FUNCTION__,
+ state==BREAK_OFF ? "off" : "on");
+ cp2101_set_config(port, CP2101_BREAK, state);
+}
+
+static int cp2101_startup (struct usb_serial *serial)
+{
+ /*CP2101 buffers behave strangely unless device is reset*/
+ usb_reset_device(serial->dev);
+ return 0;
+}
+
+static void cp2101_shutdown (struct usb_serial *serial)
+{
+ int i;
+
+ dbg("%s", __FUNCTION__);
+
+ /* stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+ cp2101_cleanup(serial->port[i]);
+ }
+}
+
+static int __init cp2101_init (void)
+{
+ int retval;
+
+ retval = usb_serial_register(&cp2101_device);
+ if (retval)
+ return retval; /*Failed to register*/
+
+ retval = usb_register(&cp2101_driver);
+ if (retval) {
+ /*Failed to register*/
+ usb_serial_deregister(&cp2101_device);
+ return retval;
+ }
+
+ /*Success*/
+ info(DRIVER_DESC " " DRIVER_VERSION);
+ return 0;
+}
+
+static void __exit cp2101_exit (void)
+{
+ usb_deregister (&cp2101_driver);
+ usb_serial_deregister (&cp2101_device);
+}
+
+module_init(cp2101_init);
+module_exit(cp2101_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable verbose debugging messages");
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 4b59d75dbfb91..25f92788a6d42 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -246,6 +246,7 @@
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
+#include <linux/wait.h>
#include "usb-serial.h"
/* Defines */
@@ -573,23 +574,14 @@ static inline long cond_wait_interruptible_timeout_irqrestore(
wait_queue_head_t *q, long timeout,
spinlock_t *lock, unsigned long flags )
{
+ DEFINE_WAIT(wait);
- wait_queue_t wait;
-
-
- init_waitqueue_entry( &wait, current );
-
- set_current_state( TASK_INTERRUPTIBLE );
-
- add_wait_queue( q, &wait );
-
- spin_unlock_irqrestore( lock, flags );
-
+ prepare_to_wait(q, &wait, TASK_UNINTERRUPTIBLE);
+ spin_unlock_irqrestore(lock, flags);
timeout = schedule_timeout(timeout);
+ finish_wait(q, &wait);
- remove_wait_queue( q, &wait );
-
- return( timeout );
+ return timeout;
}
@@ -1528,7 +1520,7 @@ dbg( "digi_open: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_cou
static void digi_close( struct usb_serial_port *port, struct file *filp )
{
-
+ DEFINE_WAIT(wait);
int ret;
unsigned char buf[32];
struct tty_struct *tty = port->tty;
@@ -1604,8 +1596,9 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co
dbg( "digi_close: write oob failed, ret=%d", ret );
/* wait for final commands on oob port to complete */
- interruptible_sleep_on_timeout( &priv->dp_flush_wait,
- DIGI_CLOSE_TIMEOUT );
+ prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_UNINTERRUPTIBLE);
+ schedule_timeout(DIGI_CLOSE_TIMEOUT);
+ finish_wait(&priv->dp_flush_wait, &wait);
/* shutdown any outstanding bulk writes */
usb_kill_urb(port->write_urb);
@@ -2002,7 +1995,7 @@ opcode, line, status, val );
} else if( opcode == DIGI_CMD_IFLUSH_FIFO ) {
- wake_up_interruptible( &priv->dp_flush_wait );
+ wake_up( &priv->dp_flush_wait );
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 5b575ec7bdce7..4afd905fe2fe4 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -626,6 +626,13 @@ static struct usb_driver ftdi_driver = {
.id_table = id_table_combined,
};
+static char *ftdi_chip_name[] = {
+ [SIO] = "SIO", /* the serial part of FT8U100AX */
+ [FT8U232AM] = "FT8U232AM",
+ [FT232BM] = "FT232BM",
+ [FT2232C] = "FT2232C",
+};
+
/* Constants for read urb and write urb */
#define BUFSZ 512
@@ -1004,7 +1011,6 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
struct ftdi_private *priv = usb_get_serial_port_data(port);
__u32 div_value = 0;
int div_okay = 1;
- char *chip_name = "";
int baud;
/*
@@ -1049,7 +1055,6 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
if (!baud) baud = 9600;
switch(priv->chip_type) {
case SIO: /* SIO chip */
- chip_name = "SIO";
switch(baud) {
case 300: div_value = ftdi_sio_b300; break;
case 600: div_value = ftdi_sio_b600; break;
@@ -1069,7 +1074,6 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
}
break;
case FT8U232AM: /* 8U232AM chip */
- chip_name = "FT8U232AM";
if (baud <= 3000000) {
div_value = ftdi_232am_baud_to_divisor(baud);
} else {
@@ -1080,11 +1084,6 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
break;
case FT232BM: /* FT232BM chip */
case FT2232C: /* FT2232C chip */
- if (priv->chip_type == FT2232C) {
- chip_name = "FT2232C";
- } else {
- chip_name = "FT232BM";
- }
if (baud <= 3000000) {
div_value = ftdi_232bm_baud_to_divisor(baud);
} else {
@@ -1097,7 +1096,8 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
if (div_okay) {
dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s",
- __FUNCTION__, baud, (unsigned long)div_value, chip_name);
+ __FUNCTION__, baud, (unsigned long)div_value,
+ ftdi_chip_name[priv->chip_type]);
}
return(div_value);
@@ -1187,7 +1187,7 @@ check_and_exit:
* ***************************************************************************
*/
-ssize_t show_latency_timer(struct device *dev, char *buf)
+static ssize_t show_latency_timer(struct device *dev, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1214,7 +1214,8 @@ ssize_t show_latency_timer(struct device *dev, char *buf)
}
/* Write a new value of the latency timer, in units of milliseconds. */
-ssize_t store_latency_timer(struct device *dev, const char *valbuf, size_t count)
+static ssize_t store_latency_timer(struct device *dev, const char *valbuf,
+ size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1244,7 +1245,8 @@ ssize_t store_latency_timer(struct device *dev, const char *valbuf, size_t count
/* Write an event character directly to the FTDI register. The ASCII
value is in the low 8 bits, with the enable bit in the 9th bit. */
-ssize_t store_event_char(struct device *dev, const char *valbuf, size_t count)
+static ssize_t store_event_char(struct device *dev, const char *valbuf,
+ size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1272,10 +1274,10 @@ ssize_t store_event_char(struct device *dev, const char *valbuf, size_t count)
return count;
}
-static DEVICE_ATTR(latency_timer, S_IWUGO | S_IRUGO, show_latency_timer, store_latency_timer);
-static DEVICE_ATTR(event_char, S_IWUGO, NULL, store_event_char);
+static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
+static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
-void create_sysfs_attrs(struct usb_serial *serial)
+static void create_sysfs_attrs(struct usb_serial *serial)
{
struct ftdi_private *priv;
struct usb_device *udev;
@@ -1285,14 +1287,18 @@ void create_sysfs_attrs(struct usb_serial *serial)
priv = usb_get_serial_port_data(serial->port[0]);
udev = serial->dev;
- if (priv->chip_type == FT232BM) {
- dbg("sysfs attributes for FT232BM");
+ /* XXX I've no idea if the original SIO supports the event_char
+ * sysfs parameter, so I'm playing it safe. */
+ if (priv->chip_type != SIO) {
+ dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
device_create_file(&udev->dev, &dev_attr_event_char);
- device_create_file(&udev->dev, &dev_attr_latency_timer);
+ if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
+ device_create_file(&udev->dev, &dev_attr_latency_timer);
+ }
}
}
-void remove_sysfs_attrs(struct usb_serial *serial)
+static void remove_sysfs_attrs(struct usb_serial *serial)
{
struct ftdi_private *priv;
struct usb_device *udev;
@@ -1302,9 +1308,12 @@ void remove_sysfs_attrs(struct usb_serial *serial)
priv = usb_get_serial_port_data(serial->port[0]);
udev = serial->dev;
- if (priv->chip_type == FT232BM) {
+ /* XXX see create_sysfs_attrs */
+ if (priv->chip_type != SIO) {
device_remove_file(&udev->dev, &dev_attr_event_char);
- device_remove_file(&udev->dev, &dev_attr_latency_timer);
+ if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
+ device_remove_file(&udev->dev, &dev_attr_latency_timer);
+ }
}
}
@@ -1406,6 +1415,8 @@ static int ftdi_8U232AM_startup (struct usb_serial *serial)
priv->chip_type = FT8U232AM;
priv->baud_base = 48000000 / 2; /* Would be / 16, but FTDI supports 0.125, 0.25 and 0.5 divisor fractions! */
+ create_sysfs_attrs(serial);
+
return (0);
} /* ftdi_8U232AM_startup */
@@ -1457,6 +1468,8 @@ static int ftdi_FT2232C_startup (struct usb_serial *serial)
}
priv->baud_base = 48000000 / 2; /* Would be / 16, but FT2232C supports multiple of 0.125 divisor fractions! */
+ create_sysfs_attrs(serial);
+
return (0);
} /* ftdi_FT2232C_startup */
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 1655085d13eb1..2ef614d5c8f2b 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -614,8 +614,8 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
*
* return <0 on error, 0 if packet is incomplete or > 0 if packet was sent
*/
-int gsp_send(struct garmin_data * garmin_data_p, const unsigned char *buf,
- int count)
+static int gsp_send(struct garmin_data * garmin_data_p,
+ const unsigned char *buf, int count)
{
const unsigned char *src;
unsigned char *dst;
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index ef6a67fc22887..11105d74f461d 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -457,7 +457,7 @@ static struct usb_serial_device_type ipw_device = {
-int usb_ipw_init(void)
+static int usb_ipw_init(void)
{
int retval;
@@ -473,7 +473,7 @@ int usb_ipw_init(void)
return 0;
}
-void usb_ipw_exit(void)
+static void usb_ipw_exit(void)
{
usb_deregister(&usb_ipw_driver);
usb_serial_deregister(&ipw_device);
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index ed64cb2fca0ce..49c602a0b4dfc 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -236,7 +236,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
0, /* value */
0, /* index */
status_buf, KLSI_STATUSBUF_LEN,
- 10*HZ
+ 10000
);
if (rc < 0)
err("Reading line status failed (error = %d)", rc);
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 425ea7d2c6f75..50b6369647d25 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -195,16 +195,16 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value)
}
} else {
switch (value) {
- case B300: value = 300;
- case B600: value = 600;
- case B1200: value = 1200;
- case B2400: value = 2400;
- case B4800: value = 4800;
- case B9600: value = 9600;
- case B19200: value = 19200;
- case B38400: value = 38400;
- case B57600: value = 57600;
- case B115200: value = 115200;
+ case B300: value = 300; break;
+ case B600: value = 600; break;
+ case B1200: value = 1200; break;
+ case B2400: value = 2400; break;
+ case B4800: value = 4800; break;
+ case B9600: value = 9600; break;
+ case B19200: value = 19200; break;
+ case B38400: value = 38400; break;
+ case B57600: value = 57600; break;
+ case B115200: value = 115200; break;
default:
err("MCT USB-RS232: unsupported baudrate request 0x%x,"
" using default of B9600", value);
@@ -646,7 +646,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
else
new_state &= ~(TIOCM_DTR | TIOCM_RTS);
if (new_state != control_state) {
- mct_u232_set_modem_ctrl(serial, control_state);
+ mct_u232_set_modem_ctrl(serial, new_state);
control_state = new_state;
}
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 2836dfed6be12..4536f63faaeaa 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1418,11 +1418,11 @@ void usb_serial_deregister(struct usb_serial_device_type *device)
/* If the usb-serial core is built into the core, the usb-serial drivers
need these symbols to load properly as modules. */
-EXPORT_SYMBOL(usb_serial_register);
-EXPORT_SYMBOL(usb_serial_deregister);
-EXPORT_SYMBOL(usb_serial_probe);
-EXPORT_SYMBOL(usb_serial_disconnect);
-EXPORT_SYMBOL(usb_serial_port_softint);
+EXPORT_SYMBOL_GPL(usb_serial_register);
+EXPORT_SYMBOL_GPL(usb_serial_deregister);
+EXPORT_SYMBOL_GPL(usb_serial_probe);
+EXPORT_SYMBOL_GPL(usb_serial_disconnect);
+EXPORT_SYMBOL_GPL(usb_serial_port_softint);
/* Module information */
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 39a8886c5a203..69d313e98fadb 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -243,6 +243,8 @@ static struct usb_device_id id_table [] = {
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
+ { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID),
+ .driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ }, /* optional parameter entry */
{ } /* Terminating entry */
};
@@ -287,6 +289,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) },
+ { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID) },
{ }, /* optional parameter entry */
{ } /* Terminating entry */
};
@@ -386,6 +389,7 @@ struct visor_private {
int bytes_in;
int bytes_out;
int outstanding_urbs;
+ int throttled;
};
/* number of outstanding urbs to prevent userspace DoS from happening */
@@ -415,6 +419,7 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
priv->bytes_in = 0;
priv->bytes_out = 0;
priv->outstanding_urbs = 0;
+ priv->throttled = 0;
spin_unlock_irqrestore(&priv->lock, flags);
/*
@@ -602,6 +607,7 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
struct tty_struct *tty;
unsigned long flags;
int i;
+ int throttled;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -627,18 +633,21 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
}
spin_lock_irqsave(&priv->lock, flags);
priv->bytes_in += urb->actual_length;
+ throttled = priv->throttled;
spin_unlock_irqrestore(&priv->lock, flags);
- /* Continue trying to always read */
- usb_fill_bulk_urb (port->read_urb, port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev,
- port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer,
- port->read_urb->transfer_buffer_length,
- visor_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+ /* Continue trying to always read if we should */
+ if (!throttled) {
+ usb_fill_bulk_urb (port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ visor_read_bulk_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+ }
return;
}
@@ -683,16 +692,26 @@ exit:
static void visor_throttle (struct usb_serial_port *port)
{
+ struct visor_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
dbg("%s - port %d", __FUNCTION__, port->number);
- usb_kill_urb(port->read_urb);
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->throttled = 1;
+ spin_unlock_irqrestore(&priv->lock, flags);
}
static void visor_unthrottle (struct usb_serial_port *port)
{
+ struct visor_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->throttled = 0;
+ spin_unlock_irqrestore(&priv->lock, flags);
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
index 2effcd0f7a197..a2fa2c61a009f 100644
--- a/drivers/usb/serial/visor.h
+++ b/drivers/usb/serial/visor.h
@@ -58,6 +58,9 @@
#define KYOCERA_VENDOR_ID 0x0C88
#define KYOCERA_7135_ID 0x0021
+#define FOSSIL_VENDOR_ID 0x0E67
+#define FOSSIL_ABACUS_ID 0x0002
+
/****************************************************************************
* Handspring Visor Vendor specific request codes (bRequest values)
* A big thank you to Handspring for providing the following information.
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 38e0dee7533ee..f1f1c0608c22a 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -31,28 +31,6 @@ config USB_STORAGE_DEBUG
Say Y here in order to have the USB Mass Storage code generate
verbose debugging messages.
-config USB_STORAGE_RW_DETECT
- bool "USB Mass Storage Write-Protected Media Detection (EXPERIMENTAL)"
- depends on USB_STORAGE && EXPERIMENTAL
- help
- Say Y here in order to have the USB Mass Storage code indicate to
- the SCSI layer that using MODE SENSE(6) and MODE SENSE(10) to
- determine if the media is write-protected is a good thing to do.
-
- Many devices have historically had trouble with these commands,
- hence the default 2.6.x behavior has been to suppress their use.
- 2.4.x used these commands with (at best) mixed results, often
- crashing the firmware of the device. However, the SCSI layer now
- issues these commands in a manner more consistent with other
- "popular" OSes, in an attempt to improve compatibility.
-
- Saying Y here allows these commands to be sent to a USB device.
- If you find a device this doesn't work for, switch to N and let
- us know at <usb-storage@lists.one-eyed-alien.net>
-
- If you say N here, the kernel will assume that all disk-like USB
- devices are write-enabled.
-
config USB_STORAGE_DATAFAB
bool "Datafab Compact Flash Reader support (EXPERIMENTAL)"
depends on USB_STORAGE && EXPERIMENTAL
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 94798eb1a525f..54e3e6c7ecd86 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -57,9 +57,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "datafab.h"
diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
index c4f4bcf36785f..cd2096acc723e 100644
--- a/drivers/usb/storage/debug.h
+++ b/drivers/usb/storage/debug.h
@@ -47,8 +47,6 @@
#include <linux/config.h>
#include <linux/kernel.h>
-struct scsi_cmnd;
-
#define USB_STORAGE "usb-storage: "
#ifdef CONFIG_USB_STORAGE_DEBUG
diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c
index 12c15f19a4f33..92b69e4c80478 100644
--- a/drivers/usb/storage/dpcm.c
+++ b/drivers/usb/storage/dpcm.c
@@ -34,9 +34,9 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "dpcm.h"
#include "sddr09.h"
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index 9df27f05d21cb..30e96050fe0c6 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -34,9 +34,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "freecom.h"
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index ff5549a744edd..5b06f9240d05c 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -39,6 +39,8 @@
#include <linux/sched.h>
#include <linux/errno.h>
+
+#include "usb.h"
#include "initializers.h"
#include "debug.h"
#include "transport.h"
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index d6ac358bb86e1..ecb328aa9ea1b 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -54,9 +54,9 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "scsiglue.h"
#include "isd200.h"
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index 24464ece5134c..aff9d51c327cd 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -54,9 +54,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "jumpshot.h"
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index a0ca60a08b2bb..9ad30428d2dd5 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -47,8 +47,9 @@
#include <linux/highmem.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
-#include "protocol.h"
+
#include "usb.h"
+#include "protocol.h"
#include "debug.h"
#include "scsiglue.h"
#include "transport.h"
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index 7aa460d3b7df8..02bff01ab09c3 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -41,9 +41,6 @@
#ifndef _PROTOCOL_H_
#define _PROTOCOL_H_
-struct scsi_cmnd;
-struct us_data;
-
/* Sub Classes */
#define US_SC_RBC 0x01 /* Typically, flash devices */
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 13200aed4f946..22e48a2b0bd18 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -53,10 +53,9 @@
#include <scsi/scsi_devinfo.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_eh.h>
-#include <scsi/scsi_host.h>
-#include "scsiglue.h"
#include "usb.h"
+#include "scsiglue.h"
#include "debug.h"
#include "transport.h"
#include "protocol.h"
@@ -83,7 +82,7 @@ static int slave_alloc (struct scsi_device *sdev)
static int slave_configure(struct scsi_device *sdev)
{
- struct us_data *us = (struct us_data *) sdev->host->hostdata[0];
+ struct us_data *us = host_to_us(sdev->host);
/* Scatter-gather buffers (all but the last) must have a length
* divisible by the bulk maxpacket size. Otherwise a data packet
@@ -137,18 +136,20 @@ static int slave_configure(struct scsi_device *sdev)
* 192 bytes (that's what Windows uses). */
sdev->use_192_bytes_for_3f = 1;
+ /* Some devices don't like MODE SENSE with page=0x3f,
+ * which is the command used for checking if a device
+ * is write-protected. Now that we tell the sd driver
+ * to do a 192-byte transfer with this command the
+ * majority of devices work fine, but a few still can't
+ * handle it. The sd driver will simply assume those
+ * devices are write-enabled. */
+ if (us->flags & US_FL_NO_WP_DETECT)
+ sdev->skip_ms_page_3f = 1;
+
/* A number of devices have problems with MODE SENSE for
* page x08, so we will skip it. */
sdev->skip_ms_page_8 = 1;
-#ifndef CONFIG_USB_STORAGE_RW_DETECT
- /* Some devices may not like MODE SENSE with page=0x3f.
- * Now that we're using 192-byte transfers this may no
- * longer be a problem. So this will be a configuration
- * option. */
- sdev->skip_ms_page_3f = 1;
-#endif
-
/* Some disks return the total number of blocks in response
* to READ CAPACITY rather than the highest block number.
* If this device makes that mistake, tell the sd driver. */
@@ -173,14 +174,13 @@ static int slave_configure(struct scsi_device *sdev)
}
/* queue a command */
-/* This is always called with scsi_lock(srb->host) held */
+/* This is always called with scsi_lock(host) held */
static int queuecommand(struct scsi_cmnd *srb,
void (*done)(struct scsi_cmnd *))
{
- struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
+ struct us_data *us = host_to_us(srb->device->host);
US_DEBUGP("%s called\n", __FUNCTION__);
- srb->host_scribble = (unsigned char *)us;
/* check for state-transition errors */
if (us->srb != NULL) {
@@ -210,11 +210,10 @@ static int queuecommand(struct scsi_cmnd *srb,
***********************************************************************/
/* Command timeout and abort */
-/* This is always called with scsi_lock(srb->host) held */
-static int command_abort(struct scsi_cmnd *srb )
+/* This is always called with scsi_lock(host) held */
+static int command_abort(struct scsi_cmnd *srb)
{
- struct Scsi_Host *host = srb->device->host;
- struct us_data *us = (struct us_data *) host->hostdata[0];
+ struct us_data *us = host_to_us(srb->device->host);
US_DEBUGP("%s called\n", __FUNCTION__);
@@ -234,13 +233,13 @@ static int command_abort(struct scsi_cmnd *srb )
set_bit(US_FLIDX_ABORTING, &us->flags);
usb_stor_stop_transport(us);
}
- scsi_unlock(host);
+ scsi_unlock(us_to_host(us));
/* Wait for the aborted command to finish */
wait_for_completion(&us->notify);
/* Reacquire the lock and allow USB transfers to resume */
- scsi_lock(host);
+ scsi_lock(us_to_host(us));
clear_bit(US_FLIDX_ABORTING, &us->flags);
clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
return SUCCESS;
@@ -248,15 +247,15 @@ static int command_abort(struct scsi_cmnd *srb )
/* This invokes the transport reset mechanism to reset the state of the
* device */
-/* This is always called with scsi_lock(srb->host) held */
+/* This is always called with scsi_lock(host) held */
static int device_reset(struct scsi_cmnd *srb)
{
- struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
+ struct us_data *us = host_to_us(srb->device->host);
int result;
US_DEBUGP("%s called\n", __FUNCTION__);
- scsi_unlock(srb->device->host);
+ scsi_unlock(us_to_host(us));
/* lock the device pointers and do the reset */
down(&(us->dev_semaphore));
@@ -268,22 +267,22 @@ static int device_reset(struct scsi_cmnd *srb)
up(&(us->dev_semaphore));
/* lock the host for the return */
- scsi_lock(srb->device->host);
+ scsi_lock(us_to_host(us));
return result;
}
/* This resets the device's USB port. */
/* It refuses to work if there's more than one interface in
* the device, so that other users are not affected. */
-/* This is always called with scsi_lock(srb->host) held */
+/* This is always called with scsi_lock(host) held */
static int bus_reset(struct scsi_cmnd *srb)
{
- struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
+ struct us_data *us = host_to_us(srb->device->host);
int result, rc;
US_DEBUGP("%s called\n", __FUNCTION__);
- scsi_unlock(srb->device->host);
+ scsi_unlock(us_to_host(us));
/* The USB subsystem doesn't handle synchronisation between
* a device's several drivers. Therefore we reset only devices
@@ -311,7 +310,7 @@ static int bus_reset(struct scsi_cmnd *srb)
up(&(us->dev_semaphore));
/* lock the host for the return */
- scsi_lock(srb->device->host);
+ scsi_lock(us_to_host(us));
return result < 0 ? FAILED : SUCCESS;
}
@@ -321,11 +320,12 @@ static int bus_reset(struct scsi_cmnd *srb)
void usb_stor_report_device_reset(struct us_data *us)
{
int i;
+ struct Scsi_Host *host = us_to_host(us);
- scsi_report_device_reset(us->host, 0, 0);
+ scsi_report_device_reset(host, 0, 0);
if (us->flags & US_FL_SCM_MULT_TARG) {
- for (i = 1; i < us->host->max_id; ++i)
- scsi_report_device_reset(us->host, 0, i);
+ for (i = 1; i < host->max_id; ++i)
+ scsi_report_device_reset(host, 0, i);
}
}
@@ -337,41 +337,41 @@ void usb_stor_report_device_reset(struct us_data *us)
#undef SPRINTF
#define SPRINTF(args...) \
do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
-#define DO_FLAG(a) \
- do { if (us->flags & US_FL_##a) pos += sprintf(pos, " " #a); } while(0)
-static int proc_info (struct Scsi_Host *hostptr, char *buffer, char **start, off_t offset,
- int length, int inout)
+static int proc_info (struct Scsi_Host *host, char *buffer,
+ char **start, off_t offset, int length, int inout)
{
- struct us_data *us;
+ struct us_data *us = host_to_us(host);
char *pos = buffer;
+ const char *string;
/* if someone is sending us data, just throw it away */
if (inout)
return length;
- us = (struct us_data*)hostptr->hostdata[0];
-
/* print the controller name */
- SPRINTF(" Host scsi%d: usb-storage\n", hostptr->host_no);
+ SPRINTF(" Host scsi%d: usb-storage\n", host->host_no);
/* print product, vendor, and serial number strings */
if (us->pusb_dev->manufacturer)
- SPRINTF(" Vendor: %s\n", us->pusb_dev->manufacturer);
+ string = us->pusb_dev->manufacturer;
else if (us->unusual_dev->vendorName)
- SPRINTF(" Vendor: %s\n", us->unusual_dev->vendorName);
+ string = us->unusual_dev->vendorName;
else
- SPRINTF(" Vendor: Unknown\n");
+ string = "Unknown";
+ SPRINTF(" Vendor: %s\n", string);
if (us->pusb_dev->product)
- SPRINTF(" Product: %s\n", us->pusb_dev->product);
+ string = us->pusb_dev->product;
else if (us->unusual_dev->productName)
- SPRINTF(" Product: %s\n", us->unusual_dev->productName);
+ string = us->unusual_dev->productName;
else
- SPRINTF(" Product: Unknown\n");
+ string = "Unknown";
+ SPRINTF(" Product: %s\n", string);
if (us->pusb_dev->serial)
- SPRINTF("Serial Number: %s\n", us->pusb_dev->serial);
+ string = us->pusb_dev->serial;
else
- SPRINTF("Serial Number: None\n");
+ string = "None";
+ SPRINTF("Serial Number: %s\n", string);
/* show the protocol and transport */
SPRINTF(" Protocol: %s\n", us->protocol_name);
@@ -381,10 +381,10 @@ static int proc_info (struct Scsi_Host *hostptr, char *buffer, char **start, off
if (pos < buffer + length) {
pos += sprintf(pos, " Quirks:");
- DO_FLAG(SINGLE_LUN);
- DO_FLAG(SCM_MULT_TARG);
- DO_FLAG(FIX_INQUIRY);
- DO_FLAG(FIX_CAPACITY);
+#define US_FLAG(name, value) \
+ if (us->flags & value) pos += sprintf(pos, " " #name);
+US_DO_ALL_FLAGS
+#undef US_FLAG
*(pos++) = '\n';
}
@@ -490,15 +490,6 @@ struct scsi_host_template usb_stor_host_template = {
.module = THIS_MODULE
};
-/* For a device that is "Not Ready" */
-unsigned char usb_stor_sense_notready[18] = {
- [0] = 0x70, /* current error */
- [2] = 0x02, /* not ready */
- [7] = 0x0a, /* additional length */
- [12] = 0x04, /* not ready */
- [13] = 0x03 /* manual intervention */
-};
-
/* To Report "Illegal Request: Invalid Field in CDB */
unsigned char usb_stor_sense_invalidCDB[18] = {
[0] = 0x70, /* current error */
diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
index 70df2a7bc1fa3..d0a49af026c42 100644
--- a/drivers/usb/storage/scsiglue.h
+++ b/drivers/usb/storage/scsiglue.h
@@ -41,14 +41,8 @@
#ifndef _SCSIGLUE_H_
#define _SCSIGLUE_H_
-#include <scsi/scsi_host.h>
-
-struct us_data;
-struct scsi_cmnd;
-
extern void usb_stor_report_device_reset(struct us_data *us);
-extern unsigned char usb_stor_sense_notready[18];
extern unsigned char usb_stor_sense_invalidCDB[18];
extern struct scsi_host_template usb_stor_host_template;
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index ff81b40c2c69c..0ea2f5ab66ba2 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -48,9 +48,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "sddr09.h"
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index 10270f42a658e..229ca181716b5 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -31,9 +31,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "sddr55.h"
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index f6839e17e790a..7eff03d9b041c 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -51,9 +51,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "shuttle_usbat.h"
@@ -61,7 +61,10 @@
#define LSB_of(s) ((s)&0xFF)
#define MSB_of(s) ((s)>>8)
-int transferred = 0;
+static int transferred = 0;
+
+static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);
+static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
/*
* Convenience function to produce an ATAPI read/write sectors command
@@ -872,8 +875,8 @@ static int usbat_identify_device(struct us_data *us,
/*
* Set the transport function based on the device type
*/
-int usbat_set_transport(struct us_data *us,
- struct usbat_info *info)
+static int usbat_set_transport(struct us_data *us,
+ struct usbat_info *info)
{
int rc;
@@ -1417,7 +1420,7 @@ int init_usbat(struct us_data *us)
/*
* Transport for the HP 8200e
*/
-int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
+static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
{
int result;
unsigned char *status = us->iobuf;
@@ -1560,7 +1563,7 @@ int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
/*
* Transport for USBAT02-based CompactFlash and similar storage devices
*/
-int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
+static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
{
int rc;
struct usbat_info *info = (struct usbat_info *) (us->extra);
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
index 32fec067d518a..5b8e867e2ae5d 100644
--- a/drivers/usb/storage/shuttle_usbat.h
+++ b/drivers/usb/storage/shuttle_usbat.h
@@ -105,10 +105,6 @@
#define USBAT_FEAT_ET1 0x02
#define USBAT_FEAT_ET2 0x01
-/* Transport functions */
-int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
-int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);
-
extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us);
extern int init_usbat(struct us_data *us);
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index b4047f3a01cd7..d2c3d2fa082e9 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -54,10 +54,10 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
#include "scsiglue.h"
-#include "usb.h"
#include "debug.h"
@@ -383,7 +383,8 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
* This routine always uses us->recv_intr_pipe as the pipe and
* us->ep_bInterval as the interrupt interval.
*/
-int usb_stor_intr_transfer(struct us_data *us, void *buf, unsigned int length)
+static int usb_stor_intr_transfer(struct us_data *us, void *buf,
+ unsigned int length)
{
int result;
unsigned int pipe = us->recv_intr_pipe;
@@ -436,7 +437,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
* This function does basically the same thing as usb_stor_bulk_transfer_buf()
* above, but it uses the usbcore scatter-gather library.
*/
-int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
struct scatterlist *sg, int num_sg, unsigned int length,
unsigned int *act_len)
{
@@ -1138,11 +1139,11 @@ static int usb_stor_reset_common(struct us_data *us,
* RESETTING bit, and clear the ABORTING bit so that the reset
* may proceed.
*/
- scsi_lock(us->host);
+ scsi_lock(us_to_host(us));
usb_stor_report_device_reset(us);
set_bit(US_FLIDX_RESETTING, &us->flags);
clear_bit(US_FLIDX_ABORTING, &us->flags);
- scsi_unlock(us->host);
+ scsi_unlock(us_to_host(us));
/* A 20-second timeout may seem rather long, but a LaCie
* StudioDrive USB2 device takes 16+ seconds to get going
@@ -1158,7 +1159,7 @@ static int usb_stor_reset_common(struct us_data *us,
/* Give the device some time to recover from the reset,
* but don't delay disconnect processing. */
- wait_event_interruptible_timeout(us->dev_reset_wait,
+ wait_event_interruptible_timeout(us->delay_wait,
test_bit(US_FLIDX_DISCONNECTING, &us->flags),
HZ*6);
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 0f12370bd34ed..e25f8d8fc7419 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -43,9 +43,6 @@
#include <linux/config.h>
#include <linux/blkdev.h>
-#include "usb.h"
-
-struct scsi_cmnd;
/* Protocols */
@@ -169,13 +166,8 @@ extern int usb_stor_clear_halt(struct us_data *us, unsigned int pipe);
extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size);
-extern int usb_stor_intr_transfer(struct us_data *us, void *buf,
- unsigned int length);
extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, unsigned int *act_len);
-extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
- struct scatterlist *sg, int num_sg, unsigned int length,
- unsigned int *act_len);
extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, int use_sg, int *residual);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 0fc20b8778032..d53f777c4f50f 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -130,6 +130,15 @@ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
+/* BENQ DC5330
+ * Reported by Manuel Fombuena <mfombuena@ya.com> and
+ * Frank Copeland <fjc@thingy.apana.org.au> */
+UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100,
+ "Tekom Technologies, Inc",
+ "300_CAMERA",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
/* Reported by Simon Levitt <simon@whattf.com>
* This entry needs Sub and Proto fields */
UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100,
@@ -340,7 +349,7 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
"Sony",
"DSC-S30/S70/S75/505V/F505/F707/F717/P8",
US_SC_SCSI, US_PR_DEVICE, NULL,
- US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE ),
+ US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
/* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0500,
@@ -365,6 +374,13 @@ UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110,
0 ),
#endif
+/* Submitted by Olaf Hering, <olh@suse.de> SuSE Bugzilla #49049 */
+UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x0501,
+ "Sony",
+ "USB Floppy Drive",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100,
"Sony",
"Memorystick MSAC-US1",
@@ -508,6 +524,12 @@ UNUSUAL_DEV( 0x05ac, 0x1203, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+UNUSUAL_DEV( 0x05ac, 0x1205, 0x0001, 0x0001,
+ "Apple",
+ "iPod",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
#ifdef CONFIG_USB_STORAGE_JUMPSHOT
UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001,
"Lexar",
@@ -612,20 +634,6 @@ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN ),
-UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009,
- "Sandisk",
- "ImageMate SDDR-31",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_IGNORE_SER ),
-
-#ifdef CONFIG_USB_STORAGE_USBAT
-UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005,
- "Sandisk",
- "ImageMate SDDR-05b",
- US_SC_SCSI, US_PR_SCM_ATAPI, init_usbat,
- US_FL_SINGLE_LUN),
-#endif
-
UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100,
"Sandisk",
"ImageMate SDDR-12",
@@ -697,6 +705,13 @@ UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
US_SC_SCSI, US_PR_DATAFAB, NULL,
0 ),
+/* Reported by Josef Reisinger <josef.reisinger@netcologne.de> */
+UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff,
+ "Datafab/Unknown",
+ "MD2/MD3 Disk enclosure",
+ US_SC_SCSI, US_PR_DATAFAB, NULL,
+ US_FL_SINGLE_LUN ),
+
UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
"Datafab/Unknown",
"Datafab-based Reader",
@@ -931,6 +946,13 @@ UNUSUAL_DEV( 0x0ea0, 0x6828, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Michael Stattmann <michael@stattmann.com> */
+UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
+ "Sony Ericsson",
+ "V800-Vodafone 802",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_NO_WP_DETECT ),
+
/* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
* Tested on hardware version 1.10.
* Entry is needed only for the initializer function override.
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 2dab9de757836..35c1ca6b5a8eb 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -51,6 +51,9 @@
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/suspend.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -89,10 +92,6 @@
#endif
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
/* Some informational data */
MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
MODULE_DESCRIPTION("USB Mass Storage driver for Linux");
@@ -103,6 +102,13 @@ module_param(delay_use, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
+/* These are used to make sure the module doesn't unload before all the
+ * threads have exited.
+ */
+static atomic_t total_threads = ATOMIC_INIT(0);
+static DECLARE_COMPLETION(threads_gone);
+
+
static int storage_probe(struct usb_interface *iface,
const struct usb_device_id *id);
@@ -225,7 +231,7 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
{ NULL }
};
-struct usb_driver usb_storage_driver = {
+static struct usb_driver usb_storage_driver = {
.owner = THIS_MODULE,
.name = "usb-storage",
.probe = storage_probe,
@@ -278,7 +284,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,
static int usb_stor_control_thread(void * __us)
{
struct us_data *us = (struct us_data *)__us;
- struct Scsi_Host *host = us->host;
+ struct Scsi_Host *host = us_to_host(us);
lock_kernel();
@@ -287,11 +293,13 @@ static int usb_stor_control_thread(void * __us)
* so get rid of all our resources.
*/
daemonize("usb-storage");
-
current->flags |= PF_NOFREEZE;
-
unlock_kernel();
+ /* acquire a reference to the host, so it won't be deallocated
+ * until we're ready to exit */
+ scsi_host_get(host);
+
/* signal that we've started the thread */
complete(&(us->notify));
@@ -305,9 +313,9 @@ static int usb_stor_control_thread(void * __us)
/* lock the device pointers */
down(&(us->dev_semaphore));
- /* if us->srb is NULL, we are being asked to exit */
- if (us->srb == NULL) {
- US_DEBUGP("-- exit command received\n");
+ /* if the device has disconnected, we are free to exit */
+ if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+ US_DEBUGP("-- exiting\n");
up(&(us->dev_semaphore));
break;
}
@@ -321,12 +329,6 @@ static int usb_stor_control_thread(void * __us)
goto SkipForAbort;
}
- /* don't do anything if we are disconnecting */
- if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
- US_DEBUGP("No command during disconnect\n");
- goto SkipForDisconnect;
- }
-
scsi_unlock(host);
/* reject the command if the direction indicator
@@ -394,7 +396,6 @@ SkipForAbort:
complete(&(us->notify));
/* finished working on this command */
-SkipForDisconnect:
us->srb = NULL;
scsi_unlock(host);
@@ -402,6 +403,8 @@ SkipForDisconnect:
up(&(us->dev_semaphore));
} /* for (;;) */
+ scsi_host_put(host);
+
/* notify the exit routine that we're actually exiting now
*
* complete()/wait_for_completion() is similar to up()/down(),
@@ -416,7 +419,7 @@ SkipForDisconnect:
* This is important in preemption kernels, which transfer the flow
* of execution immediately upon a complete().
*/
- complete_and_exit(&(us->notify), 0);
+ complete_and_exit(&threads_gone, 0);
}
/***********************************************************************
@@ -757,20 +760,6 @@ static int usb_stor_acquire_resources(struct us_data *us)
up(&us->dev_semaphore);
- /*
- * Since this is a new device, we need to register a SCSI
- * host definition with the higher SCSI layers.
- */
- us->host = scsi_host_alloc(&usb_stor_host_template, sizeof(us));
- if (!us->host) {
- printk(KERN_WARNING USB_STORAGE
- "Unable to allocate the scsi host\n");
- return -EBUSY;
- }
-
- /* Set the hostdata to prepare for scanning */
- us->host->hostdata[0] = (unsigned long) us;
-
/* Start up our control thread */
p = kernel_thread(usb_stor_control_thread, us, CLONE_VM);
if (p < 0) {
@@ -779,6 +768,7 @@ static int usb_stor_acquire_resources(struct us_data *us)
return p;
}
us->pid = p;
+ atomic_inc(&total_threads);
/* Wait for the thread to start */
wait_for_completion(&(us->notify));
@@ -787,37 +777,16 @@ static int usb_stor_acquire_resources(struct us_data *us)
}
/* Release all our dynamic resources */
-void usb_stor_release_resources(struct us_data *us)
+static void usb_stor_release_resources(struct us_data *us)
{
US_DEBUGP("-- %s\n", __FUNCTION__);
- /* Kill the control thread. The SCSI host must already have been
- * removed so it won't try to queue any more commands.
+ /* Tell the control thread to exit. The SCSI host must
+ * already have been removed so it won't try to queue
+ * any more commands.
*/
- if (us->pid) {
-
- /* Wait for the thread to be idle */
- down(&us->dev_semaphore);
- US_DEBUGP("-- sending exit command to thread\n");
-
- /* If the SCSI midlayer queued a final command just before
- * scsi_remove_host() was called, us->srb might not be
- * NULL. We can overwrite it safely, because the midlayer
- * will not wait for the command to finish. Also the
- * control thread will already have been awakened.
- * That's okay, an extra up() on us->sema won't hurt.
- *
- * Enqueue the command, wake up the thread, and wait for
- * notification that it has exited.
- */
- scsi_lock(us->host);
- us->srb = NULL;
- scsi_unlock(us->host);
- up(&us->dev_semaphore);
-
- up(&us->sema);
- wait_for_completion(&us->notify);
- }
+ US_DEBUGP("-- sending exit command to thread\n");
+ up(&us->sema);
/* Call the destructor routine, if it exists */
if (us->extra_destructor) {
@@ -825,16 +794,9 @@ void usb_stor_release_resources(struct us_data *us)
us->extra_destructor(us->extra);
}
- /* Finish the host removal sequence */
- if (us->host)
- scsi_host_put(us->host);
-
/* Free the extra data and the URB */
- if (us->extra)
- kfree(us->extra);
- if (us->current_urb)
- usb_free_urb(us->current_urb);
-
+ kfree(us->extra);
+ usb_free_urb(us->current_urb);
}
/* Dissociate from the USB device */
@@ -852,9 +814,6 @@ static void dissociate_dev(struct us_data *us)
/* Remove our private data from the interface */
usb_set_intfdata(us->pusb_intf, NULL);
-
- /* Free the structure itself */
- kfree(us);
}
/* Thread to carry out delayed SCSI-device scanning */
@@ -870,6 +829,13 @@ static int usb_stor_scan_thread(void * __us)
daemonize("usb-stor-scan");
unlock_kernel();
+ /* Acquire a reference to the host, so it won't be deallocated
+ * until we're ready to exit */
+ scsi_host_get(us_to_host(us));
+
+ /* Signal that we've started the thread */
+ complete(&(us->notify));
+
printk(KERN_DEBUG
"usb-storage: device found at %d\n", us->pusb_dev->devnum);
@@ -878,7 +844,7 @@ static int usb_stor_scan_thread(void * __us)
printk(KERN_DEBUG "usb-storage: waiting for device "
"to settle before scanning\n");
retry:
- wait_event_interruptible_timeout(us->scsi_scan_wait,
+ wait_event_interruptible_timeout(us->delay_wait,
test_bit(US_FLIDX_DISCONNECTING, &us->flags),
delay_use * HZ);
if (current->flags & PF_FREEZE) {
@@ -889,11 +855,14 @@ retry:
/* If the device is still connected, perform the scanning */
if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
- scsi_scan_host(us->host);
+ scsi_scan_host(us_to_host(us));
printk(KERN_DEBUG "usb-storage: device scan complete\n");
+
+ /* Should we unbind if no devices were detected? */
}
- complete_and_exit(&us->scsi_scan_done, 0);
+ scsi_host_put(us_to_host(us));
+ complete_and_exit(&threads_gone, 0);
}
@@ -901,25 +870,30 @@ retry:
static int storage_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
+ struct Scsi_Host *host;
struct us_data *us;
const int id_index = id - storage_usb_ids;
int result;
US_DEBUGP("USB Mass Storage device detected\n");
- /* Allocate the us_data structure and initialize the mutexes */
- us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL);
- if (!us) {
- printk(KERN_WARNING USB_STORAGE "Out of memory\n");
+ /*
+ * Ask the SCSI layer to allocate a host structure, with extra
+ * space at the end for our private us_data structure.
+ */
+ host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));
+ if (!host) {
+ printk(KERN_WARNING USB_STORAGE
+ "Unable to allocate the scsi host\n");
return -ENOMEM;
}
+
+ us = host_to_us(host);
memset(us, 0, sizeof(struct us_data));
init_MUTEX(&(us->dev_semaphore));
init_MUTEX_LOCKED(&(us->sema));
init_completion(&(us->notify));
- init_waitqueue_head(&us->dev_reset_wait);
- init_waitqueue_head(&us->scsi_scan_wait);
- init_completion(&us->scsi_scan_done);
+ init_waitqueue_head(&us->delay_wait);
/* Associate the us_data structure with the USB device */
result = associate_dev(us, intf);
@@ -972,7 +946,7 @@ static int storage_probe(struct usb_interface *intf,
result = usb_stor_acquire_resources(us);
if (result)
goto BadDevice;
- result = scsi_add_host(us->host, &intf->dev);
+ result = scsi_add_host(host, &intf->dev);
if (result) {
printk(KERN_WARNING USB_STORAGE
"Unable to add the scsi host\n");
@@ -984,17 +958,23 @@ static int storage_probe(struct usb_interface *intf,
if (result < 0) {
printk(KERN_WARNING USB_STORAGE
"Unable to start the device-scanning thread\n");
- scsi_remove_host(us->host);
+ scsi_remove_host(host);
goto BadDevice;
}
+ atomic_inc(&total_threads);
+
+ /* Wait for the thread to start */
+ wait_for_completion(&(us->notify));
return 0;
/* We come here if there are any problems */
BadDevice:
US_DEBUGP("storage_probe() failed\n");
+ set_bit(US_FLIDX_DISCONNECTING, &us->flags);
usb_stor_release_resources(us);
dissociate_dev(us);
+ scsi_host_put(host);
return result;
}
@@ -1006,24 +986,26 @@ static void storage_disconnect(struct usb_interface *intf)
US_DEBUGP("storage_disconnect() called\n");
/* Prevent new USB transfers, stop the current command, and
- * interrupt a device-reset delay */
+ * interrupt a SCSI-scan or device-reset delay */
set_bit(US_FLIDX_DISCONNECTING, &us->flags);
usb_stor_stop_transport(us);
- wake_up(&us->dev_reset_wait);
+ wake_up(&us->delay_wait);
- /* Interrupt the SCSI-device-scanning thread's time delay, and
- * wait for the thread to finish */
- wake_up(&us->scsi_scan_wait);
- wait_for_completion(&us->scsi_scan_done);
+ /* It doesn't matter if the SCSI-scanning thread is still running.
+ * The thread will exit when it sees the DISCONNECTING flag. */
/* Wait for the current command to finish, then remove the host */
down(&us->dev_semaphore);
up(&us->dev_semaphore);
- scsi_remove_host(us->host);
+ scsi_remove_host(us_to_host(us));
/* Wait for everything to become idle and release all our resources */
usb_stor_release_resources(us);
dissociate_dev(us);
+
+ /* Drop our reference to the host; the SCSI core will free it
+ * (and "us" along with it) when the refcount becomes 0. */
+ scsi_host_put(us_to_host(us));
}
/***********************************************************************
@@ -1053,6 +1035,16 @@ static void __exit usb_stor_exit(void)
*/
US_DEBUGP("-- calling usb_deregister()\n");
usb_deregister(&usb_storage_driver) ;
+
+ /* Don't return until all of our control and scanning threads
+ * have exited. Since each thread signals threads_gone as its
+ * last act, we have to call wait_for_completion the right number
+ * of times.
+ */
+ while (atomic_read(&total_threads) > 0) {
+ wait_for_completion(&threads_gone);
+ atomic_dec(&total_threads);
+ }
}
module_init(usb_stor_init);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 68b5283206528..625b7aa980741 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -48,6 +48,7 @@
#include <linux/blkdev.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
+#include <scsi/scsi_host.h>
struct us_data;
struct scsi_cmnd;
@@ -65,18 +66,35 @@ struct us_unusual_dev {
unsigned int flags;
};
-/* Flag definitions: these entries are static */
-#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */
-#define US_FL_MODE_XLATE 0 /* [no longer used] */
-#define US_FL_NEED_OVERRIDE 0x00000004 /* unusual_devs entry is necessary */
-#define US_FL_IGNORE_SER 0 /* [no longer used] */
-#define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */
-#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs faking */
-#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */
-#define US_FL_IGNORE_RESIDUE 0x00000100 /* reported residue is wrong */
-#define US_FL_BULK32 0x00000200 /* Uses 32-byte CBW length */
-#define US_FL_NOT_LOCKABLE 0x00000400 /* PREVENT/ALLOW not supported */
-#define US_FL_GO_SLOW 0x00000800 /* Need delay after Command phase */
+/*
+ * Static flag definitions. We use this roundabout technique so that the
+ * proc_info() routine can automatically display a message for each flag.
+ */
+#define US_DO_ALL_FLAGS \
+ US_FLAG(SINGLE_LUN, 0x00000001) \
+ /* allow access to only LUN 0 */ \
+ US_FLAG(NEED_OVERRIDE, 0x00000002) \
+ /* unusual_devs entry is necessary */ \
+ US_FLAG(SCM_MULT_TARG, 0x00000004) \
+ /* supports multiple targets */ \
+ US_FLAG(FIX_INQUIRY, 0x00000008) \
+ /* INQUIRY response needs faking */ \
+ US_FLAG(FIX_CAPACITY, 0x00000010) \
+ /* READ CAPACITY response too big */ \
+ US_FLAG(IGNORE_RESIDUE, 0x00000020) \
+ /* reported residue is wrong */ \
+ US_FLAG(BULK32, 0x00000040) \
+ /* Uses 32-byte CBW length */ \
+ US_FLAG(NOT_LOCKABLE, 0x00000080) \
+ /* PREVENT/ALLOW not supported */ \
+ US_FLAG(GO_SLOW, 0x00000100) \
+ /* Need delay after Command phase */ \
+ US_FLAG(NO_WP_DETECT, 0x00000200) \
+ /* Don't check for write-protect */ \
+
+#define US_FLAG(name, value) US_FL_##name = value ,
+enum { US_DO_ALL_FLAGS };
+#undef US_FLAG
/* Dynamic flag definitions: used in set_bit() etc. */
#define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */
@@ -139,7 +157,6 @@ struct us_data {
proto_cmnd proto_handler; /* protocol handler */
/* SCSI interfaces */
- struct Scsi_Host *host; /* our dummy host data */
struct scsi_cmnd *srb; /* current srb */
/* thread information */
@@ -154,19 +171,22 @@ struct us_data {
dma_addr_t iobuf_dma;
/* mutual exclusion and synchronization structures */
- struct semaphore sema; /* to sleep thread on */
- struct completion notify; /* thread begin/end */
- wait_queue_head_t dev_reset_wait; /* wait during reset */
- wait_queue_head_t scsi_scan_wait; /* wait before scanning */
- struct completion scsi_scan_done; /* scan thread end */
+ struct semaphore sema; /* to sleep thread on */
+ struct completion notify; /* thread begin/end */
+ wait_queue_head_t delay_wait; /* wait during scan, reset */
/* subdriver information */
void *extra; /* Any extra data */
extra_data_destructor extra_destructor;/* extra data destructor */
};
-/* The structure which defines our driver */
-extern struct usb_driver usb_storage_driver;
+/* Convert between us_data and the corresponding Scsi_Host */
+static struct Scsi_Host inline *us_to_host(struct us_data *us) {
+ return container_of((void *) us, struct Scsi_Host, hostdata);
+}
+static struct us_data inline *host_to_us(struct Scsi_Host *host) {
+ return (struct us_data *) host->hostdata;
+}
/* Function to fill an inquiry response. See usb.c for details */
extern void fill_inquiry_response(struct us_data *us,
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index f6821e39e2bda..2a1c5965de222 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -74,6 +74,11 @@ config FB_SOFT_CURSOR
This is used by drivers that don't provide their own (accelerated)
version.
+config FB_MACMODES
+ tristate
+ depends on FB
+ default n
+
config FB_MODE_HELPERS
bool "Enable Video Mode Handling Helpers"
depends on FB
@@ -323,6 +328,7 @@ config FB_OF
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES
help
Say Y if you want support with Open Firmware for your graphics
board.
@@ -334,6 +340,7 @@ config FB_CONTROL
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES
help
This driver supports a frame buffer for the graphics adapter in the
Power Macintosh 7300 and others.
@@ -345,6 +352,7 @@ config FB_PLATINUM
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES
help
This driver supports a frame buffer for the "platinum" graphics
adapter in some Power Macintoshes.
@@ -356,6 +364,7 @@ config FB_VALKYRIE
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES
help
This driver supports a frame buffer for the "valkyrie" graphics
adapter in some Power Macintoshes.
@@ -384,6 +393,7 @@ config FB_IMSTT
depends on (FB = y) && PCI
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC
help
The IMS Twin Turbo is a PCI-based frame buffer card bundled with
many Macintosh and compatible computers.
@@ -436,6 +446,7 @@ config FB_MAC
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES
# bool ' Apple DAFB display support' CONFIG_FB_DAFB
config FB_HP300
@@ -619,12 +630,11 @@ config FB_NVIDIA
help
This driver supports graphics boards with the nVidia chips, TNT
and newer. For very old chipsets, such as the RIVA128, then use
- the the rivafb.
+ the rivafb.
Say Y if you have such a graphics board.
To compile this driver as a module, choose M here: the
module will be called nvidiafb.
- none yet
config FB_NVIDIA_I2C
bool "Enable DDC Support"
@@ -754,6 +764,7 @@ config FB_MATROX
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
select FB_TILEBLITTING
+ select FB_MACMODES if PPC_PMAC
---help---
Say Y here if you have a Matrox Millennium, Matrox Millennium II,
Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
@@ -893,6 +904,7 @@ config FB_RADEON_OLD
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ 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
@@ -910,6 +922,7 @@ config FB_RADEON
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC_OF
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
@@ -948,6 +961,7 @@ config FB_ATY128
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC_PMAC
help
This driver supports graphics boards with the ATI Rage128 chips.
Say Y if you have such a graphics board and read
@@ -963,6 +977,7 @@ config FB_ATY
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC
help
This driver supports graphics boards with the ATI Mach64 chips.
Say Y if you have such a graphics board.
@@ -1433,6 +1448,18 @@ config FB_PXA_PARAMETERS
<file:Documentation/fb/pxafb.txt> describes the available parameters.
+config FB_S1D13XXX
+ tristate "Epson S1D13XXX framebuffer support"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ help
+ Support for S1D13XXX framebuffer device family (currently only
+ working with S1D13806). Product specs at
+ <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>
+
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index bf04cfb000bda..92265b741dc3a 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
obj-$(CONFIG_FB_SOFT_CURSOR) += softcursor.o
+obj-$(CONFIG_FB_MACMODES) += macmodes.o
# Hardware specific drivers go first
obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o
@@ -29,8 +30,8 @@ obj-$(CONFIG_FB_PM3) += pm3fb.o
obj-$(CONFIG_FB_MATROX) += matrox/
obj-$(CONFIG_FB_RIVA) += riva/ vgastate.o
obj-$(CONFIG_FB_NVIDIA) += nvidia/
-obj-$(CONFIG_FB_ATY) += aty/
-obj-$(CONFIG_FB_ATY128) += aty/
+obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
+obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
obj-$(CONFIG_FB_RADEON) += aty/
obj-$(CONFIG_FB_SIS) += sis/
obj-$(CONFIG_FB_KYRO) += kyro/
@@ -41,9 +42,9 @@ 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
-obj-$(CONFIG_FB_CONTROL) += controlfb.o macmodes.o
-obj-$(CONFIG_FB_PLATINUM) += platinumfb.o macmodes.o
-obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o macmodes.o
+obj-$(CONFIG_FB_CONTROL) += controlfb.o
+obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
+obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
obj-$(CONFIG_FB_CT65550) += chipsfb.o
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
@@ -61,7 +62,7 @@ obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
obj-$(CONFIG_FB_ACORN) += acornfb.o
obj-$(CONFIG_FB_ATARI) += atafb.o
-obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o
+obj-$(CONFIG_FB_MAC) += macfb.o
obj-$(CONFIG_FB_HGA) += hgafb.o
obj-$(CONFIG_FB_IGA) += igafb.o
obj-$(CONFIG_FB_APOLLO) += dnfb.o
@@ -88,6 +89,7 @@ obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o
obj-$(CONFIG_FB_TX3912) += tx3912fb.o
+obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_VESA) += vesafb.o
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index ed87832d789c4..f4729f4df8cec 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -604,7 +604,7 @@ static int __init asiliantfb_init(void)
if (fb_get_options("asiliantfb", NULL))
return -ENODEV;
- return pci_module_init(&asiliantfb_driver);
+ return pci_register_driver(&asiliantfb_driver);
}
module_init(asiliantfb_init);
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 27a98feb7fc20..8a4ba3bb98728 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -166,7 +166,7 @@ static const char *r128_family[] __devinitdata = {
static int aty128_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static void aty128_remove(struct pci_dev *pdev);
-static int aty128_pci_suspend(struct pci_dev *pdev, u32 state);
+static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state);
static int aty128_pci_resume(struct pci_dev *pdev);
static int aty128_do_resume(struct pci_dev *pdev);
@@ -2327,7 +2327,7 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
}
}
-static int aty128_pci_suspend(struct pci_dev *pdev, u32 state)
+static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par;
@@ -2432,7 +2432,7 @@ static int aty128_do_resume(struct pci_dev *pdev)
par->lock_blank = 0;
aty128fb_blank(0, info);
- pdev->dev.power.power_state = 0;
+ pdev->dev.power.power_state = PMSG_ON;
printk(KERN_DEBUG "aty128fb: resumed !\n");
@@ -2461,7 +2461,7 @@ static int __init aty128fb_init(void)
aty128fb_setup(option);
#endif
- return pci_module_init(&aty128fb_driver);
+ return pci_register_driver(&aty128fb_driver);
}
static void __exit aty128fb_exit(void)
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 444adc3a35c52..8c42538dc8c12 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -100,8 +100,8 @@
/*
* Debug flags.
*/
-/*#undef DEBUG*/
-#define DEBUG
+#undef DEBUG
+/*#define DEBUG*/
/* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
/* - must be large enough to catch all GUI-Regs */
@@ -307,6 +307,7 @@ static int vram;
static int pll;
static int mclk;
static int xclk;
+static int comp_sync __initdata = -1;
static char *mode;
#ifdef CONFIG_PPC
@@ -2016,7 +2017,7 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par)
return timeout ? 0 : -EIO;
}
-static int atyfb_pci_suspend(struct pci_dev *pdev, u32 state)
+static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct atyfb_par *par = (struct atyfb_par *) info->par;
@@ -2091,7 +2092,7 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
release_console_sem();
- pdev->dev.power.power_state = 0;
+ pdev->dev.power.power_state = PMSG_ON;
return 0;
}
@@ -2527,6 +2528,13 @@ static int __init aty_init(struct fb_info *info, const char *name)
else
var.accel_flags |= FB_ACCELF_TEXT;
+ if (comp_sync != -1) {
+ if (!comp_sync)
+ var.sync &= ~FB_SYNC_COMP_HIGH_ACT;
+ else
+ var.sync |= FB_SYNC_COMP_HIGH_ACT;
+ }
+
if (var.yres == var.yres_virtual) {
u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
@@ -3427,8 +3435,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
err_release_io:
#ifdef __sparc__
- if (par->mmap_map)
- kfree(par->mmap_map);
+ kfree(par->mmap_map);
#else
if (par->ati_regbase)
iounmap(par->ati_regbase);
@@ -3436,7 +3443,7 @@ err_release_io:
iounmap(info->screen_base);
#endif
err_release_mem:
- if(par->aux_start)
+ if (par->aux_start)
release_mem_region(par->aux_start, par->aux_size);
release_mem_region(par->res_start, par->res_size);
@@ -3543,8 +3550,7 @@ static void __devexit atyfb_remove(struct fb_info *info)
#endif
#endif
#ifdef __sparc__
- if (par->mmap_map)
- kfree(par->mmap_map);
+ kfree(par->mmap_map);
#endif
if (par->aux_start)
release_mem_region(par->aux_start, par->aux_size);
@@ -3612,6 +3618,8 @@ static int __init atyfb_setup(char *options)
mclk = simple_strtoul(this_opt + 5, NULL, 0);
else if (!strncmp(this_opt, "xclk:", 5))
xclk = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "comp_sync:", 10))
+ comp_sync = simple_strtoul(this_opt+10, NULL, 0);
#ifdef CONFIG_PPC
else if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode =
@@ -3671,7 +3679,7 @@ static int __init atyfb_init(void)
#endif
#ifdef CONFIG_PCI
- pci_module_init(&atyfb_driver);
+ pci_register_driver(&atyfb_driver);
#endif
#ifdef CONFIG_ATARI
atyfb_atari_probe();
@@ -3701,6 +3709,9 @@ module_param(mclk, int, 0);
MODULE_PARM_DESC(mclk, "int: override memory clock");
module_param(xclk, int, 0);
MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
+module_param(comp_sync, int, 0);
+MODULE_PARM_DESC(comp_sync,
+ "Set composite sync signal to low (0) or high (1)");
module_param(mode, charp, 0);
MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
#ifdef CONFIG_MTRR
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
index dc8598dacbcb2..3ca27cb13caa0 100644
--- a/drivers/video/aty/radeon_accel.c
+++ b/drivers/video/aty/radeon_accel.c
@@ -189,32 +189,6 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
radeon_engine_flush (rinfo);
- /* Some ASICs have bugs with dynamic-on feature, which are
- * ASIC-version dependent, so we force all blocks on for now
- * -- from XFree86
- * We don't do that on macs, things just work here with dynamic
- * clocking... --BenH
- */
-#ifdef CONFIG_ALL_PPC
- if (_machine != _MACH_Pmac && rinfo->hasCRTC2)
-#else
- if (rinfo->has_CRTC2)
-#endif
- {
- u32 tmp;
-
- tmp = INPLL(SCLK_CNTL);
- OUTPLL(SCLK_CNTL, ((tmp & ~DYN_STOP_LAT_MASK) |
- CP_MAX_DYN_STOP_LAT |
- SCLK_FORCEON_MASK));
-
- if (rinfo->family == CHIP_FAMILY_RV200)
- {
- tmp = INPLL(SCLK_MORE_CNTL);
- OUTPLL(SCLK_MORE_CNTL, tmp | SCLK_MORE_FORCEON);
- }
- }
-
clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
mclk_cntl = INPLL(MCLK_CNTL);
@@ -274,8 +248,6 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
OUTPLL(MCLK_CNTL, mclk_cntl);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
}
void radeonfb_engine_init (struct radeonfb_info *rinfo)
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 7d1688a8900ec..e8eb124754b13 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -1,4 +1,3 @@
-
/*
* drivers/video/aty/radeon_base.c
*
@@ -530,11 +529,8 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
break;
}
- radeon_pll_workaround_before(rinfo);
ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
m = (INPLL(PPLL_REF_DIV) & 0x3ff);
@@ -1173,11 +1169,8 @@ static void radeon_save_state (struct radeonfb_info *rinfo,
save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
/* PLL regs */
- radeon_pll_workaround_before(rinfo);
save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f;
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
save->ppll_div_3 = INPLL(PPLL_DIV_3);
save->ppll_ref_div = INPLL(PPLL_REF_DIV);
}
@@ -1204,13 +1197,11 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
/* We still have to force a switch to selected PPLL div thanks to
* an XFree86 driver bug which will switch it away in some cases
* even when using UseFDev */
- radeon_pll_workaround_before(rinfo);
OUTREGP(CLOCK_CNTL_INDEX,
mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
~PPLL_DIV_SEL_MASK);
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
return;
}
}
@@ -1224,13 +1215,11 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
/* Switch to selected PPLL divider */
- radeon_pll_workaround_before(rinfo);
OUTREGP(CLOCK_CNTL_INDEX,
mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
~PPLL_DIV_SEL_MASK);
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
/* Set PPLL ref. div */
if (rinfo->family == CHIP_FAMILY_R300 ||
@@ -1754,8 +1743,7 @@ static int radeonfb_set_par(struct fb_info *info)
} else {
/* DFP */
newmode->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
- newmode->tmds_transmitter_cntl = (TMDS_RAN_PAT_RST | TMDS_ICHCSEL) &
- ~(TMDS_PLLRST);
+ newmode->tmds_transmitter_cntl &= ~(TMDS_PLLRST);
/* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */
if (IS_R300_VARIANT(rinfo) ||
(rinfo->family == CHIP_FAMILY_R200) || !rinfo->has_CRTC2)
@@ -2248,7 +2236,7 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;
rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0;
rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0;
-
+
/* Set base addrs */
rinfo->fb_base_phys = pci_resource_start (pdev, 0);
rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
@@ -2271,6 +2259,24 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
+ /*
+ * Check for errata
+ */
+ rinfo->errata = 0;
+ if (rinfo->family == CHIP_FAMILY_R300 &&
+ (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
+ == CFG_ATI_REV_A11)
+ rinfo->errata |= CHIP_ERRATA_R300_CG;
+
+ if (rinfo->family == CHIP_FAMILY_RV200 ||
+ rinfo->family == CHIP_FAMILY_RS200)
+ rinfo->errata |= CHIP_ERRATA_PLL_DUMMYREADS;
+
+ if (rinfo->family == CHIP_FAMILY_RV100 ||
+ rinfo->family == CHIP_FAMILY_RS100 ||
+ rinfo->family == CHIP_FAMILY_RS200)
+ rinfo->errata |= CHIP_ERRATA_PLL_DELAY;
+
#ifdef CONFIG_PPC_OF
/* On PPC, we obtain the OF device-node pointer to the firmware
* data for this chip
@@ -2310,13 +2316,6 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->mapped_vram/1024);
/*
- * Check for required workaround for PLL accesses
- */
- rinfo->R300_cg_workaround = (rinfo->family == CHIP_FAMILY_R300 &&
- (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
- == CFG_ATI_REV_A11);
-
- /*
* Map the BIOS ROM if any and retreive PLL parameters from
* the BIOS. We skip that on mobility chips as the real panel
* values we need aren't in the ROM but in the BIOS image in
@@ -2420,10 +2419,8 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
err_unmap_fb:
iounmap(rinfo->fb_base);
err_unmap_rom:
- if (rinfo->mon1_EDID)
- kfree(rinfo->mon1_EDID);
- if (rinfo->mon2_EDID)
- kfree(rinfo->mon2_EDID);
+ kfree(rinfo->mon1_EDID);
+ kfree(rinfo->mon2_EDID);
if (rinfo->mon1_modedb)
fb_destroy_modedb(rinfo->mon1_modedb);
fb_dealloc_cmap(&info->cmap);
@@ -2479,10 +2476,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
pci_release_regions(pdev);
- if (rinfo->mon1_EDID)
- kfree(rinfo->mon1_EDID);
- if (rinfo->mon2_EDID)
- kfree(rinfo->mon2_EDID);
+ kfree(rinfo->mon1_EDID);
+ kfree(rinfo->mon2_EDID);
if (rinfo->mon1_modedb)
fb_destroy_modedb(rinfo->mon1_modedb);
#ifdef CONFIG_FB_RADEON_I2C
@@ -2551,7 +2546,7 @@ static int __init radeonfb_init (void)
return -ENODEV;
radeonfb_setup(option);
#endif
- return pci_module_init (&radeonfb_driver);
+ return pci_register_driver (&radeonfb_driver);
}
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index e87ef153d87bb..762244164c81a 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -236,6 +236,12 @@ int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_e
if (edid)
break;
}
+ /* Release the DDC lines when done or the Apple Cinema HD display
+ * will switch off
+ */
+ OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN | VGA_DDC_DATA_OUT_EN));
+ (void)INREG(reg);
+
if (out_edid)
*out_edid = edid;
if (!edid) {
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index 2918d5ec36c89..ea7c863069184 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -618,11 +618,9 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
}
}
if (ignore_edid) {
- if (rinfo->mon1_EDID)
- kfree(rinfo->mon1_EDID);
+ kfree(rinfo->mon1_EDID);
rinfo->mon1_EDID = NULL;
- if (rinfo->mon2_EDID)
- kfree(rinfo->mon2_EDID);
+ kfree(rinfo->mon2_EDID);
rinfo->mon2_EDID = NULL;
}
@@ -657,11 +655,8 @@ static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)
&& rinfo->is_mobility) {
int ppll_div_sel;
u32 ppll_divn;
- radeon_pll_workaround_before(rinfo);
ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
ppll_divn = INPLL(PPLL_DIV_0 + ppll_div_sel);
rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
rinfo->panel_info.fbk_divider = ppll_divn & 0x7ff;
@@ -906,7 +901,7 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
*/
/*
- * This is used when looking for modes. We assign a "goodness" value
+ * This is used when looking for modes. We assign a "distance" value
* to a mode in the modedb depending how "close" it is from what we
* are looking for.
* Currently, we don't compare that much, we could do better but
@@ -915,13 +910,11 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
static int radeon_compare_modes(const struct fb_var_screeninfo *var,
const struct fb_videomode *mode)
{
- int goodness = 0;
+ int distance = 0;
- if (var->yres == mode->yres)
- goodness += 10;
- if (var->xres == mode->xres)
- goodness += 9;
- return goodness;
+ distance = mode->yres - var->yres;
+ distance += (mode->xres - var->xres)/2;
+ return distance;
}
/*
@@ -943,7 +936,7 @@ int radeon_match_mode(struct radeonfb_info *rinfo,
const struct fb_videomode *db = vesa_modes;
int i, dbsize = 34;
int has_rmx, native_db = 0;
- int goodness = 0;
+ int distance = INT_MAX;
const struct fb_videomode *candidate = NULL;
/* Start with a copy of the requested mode */
@@ -979,19 +972,19 @@ int radeon_match_mode(struct radeonfb_info *rinfo,
/* Now look for a mode in the database */
while (db) {
for (i = 0; i < dbsize; i++) {
- int g;
+ int d;
if (db[i].yres < src->yres)
continue;
if (db[i].xres < src->xres)
continue;
- g = radeon_compare_modes(src, &db[i]);
+ d = radeon_compare_modes(src, &db[i]);
/* If the new mode is at least as good as the previous one,
* then it's our new candidate
*/
- if (g >= goodness) {
+ if (d < distance) {
candidate = &db[i];
- goodness = g;
+ distance = d;
}
}
db = NULL;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index f29de21e6e92c..23c677e5093fd 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -1372,12 +1372,10 @@ static void radeon_pm_start_mclk_sclk(struct radeonfb_info *rinfo)
/* Reconfigure SPLL charge pump, VCO gain, duty cycle */
tmp = INPLL(pllSPLL_CNTL);
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
/* Set SPLL feedback divider */
tmp = INPLL(pllM_SPLL_REF_FB_DIV);
@@ -1409,12 +1407,10 @@ static void radeon_pm_start_mclk_sclk(struct radeonfb_info *rinfo)
/* Reconfigure MPLL charge pump, VCO gain, duty cycle */
tmp = INPLL(pllMPLL_CNTL);
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, pllMPLL_CNTL + PLL_WR_EN);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
/* Set MPLL feedback divider */
tmp = INPLL(pllM_SPLL_REF_FB_DIV);
@@ -1532,12 +1528,10 @@ static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
{
u32 tmp;
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, pllHTOTAL_CNTL + PLL_WR_EN);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA, 0);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
tmp = INPLL(pllVCLK_ECP_CNTL);
OUTPLL(pllVCLK_ECP_CNTL, tmp | 0x80);
@@ -1552,12 +1546,10 @@ static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
* probably useless since we already did it ...
*/
tmp = INPLL(pllPPLL_CNTL);
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
/* Restore our "reference" PPLL divider set by firmware
* according to proper spread spectrum calculations
@@ -1581,11 +1573,9 @@ static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
mdelay(5);
/* Switch pixel clock to firmware default div 0 */
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX+1, 0);
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
}
static void radeon_pm_m10_reconfigure_mc(struct radeonfb_info *rinfo)
@@ -2173,7 +2163,9 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
tmp = INPLL(MPLL_CNTL);
OUTREG8(CLOCK_CNTL_INDEX, MPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+ radeon_pll_errata_after_data(rinfo);
tmp = INPLL(M_SPLL_REF_FB_DIV);
OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x5900);
@@ -2194,7 +2186,9 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
tmp = INPLL(SPLL_CNTL);
OUTREG8(CLOCK_CNTL_INDEX, SPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+ radeon_pll_errata_after_data(rinfo);
tmp = INPLL(M_SPLL_REF_FB_DIV);
OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x780000);
@@ -2322,7 +2316,9 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
OUTREG(CRTC_H_SYNC_STRT_WID, 0x008e0580);
OUTREG(CRTC_H_TOTAL_DISP, 0x009f00d2);
OUTREG8(CLOCK_CNTL_INDEX, HTOTAL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA, 0);
+ radeon_pll_errata_after_data(rinfo);
OUTREG(CRTC_V_SYNC_STRT_WID, 0x00830403);
OUTREG(CRTC_V_TOTAL_DISP, 0x03ff0429);
OUTREG(FP_CRTC_H_TOTAL_DISP, 0x009f0033);
@@ -2344,10 +2340,15 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
INPLL(PPLL_REF_DIV);
OUTREG8(CLOCK_CNTL_INDEX, PPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, 0xbc);
+ radeon_pll_errata_after_data(rinfo);
tmp = INREG(CLOCK_CNTL_INDEX);
+ radeon_pll_errata_after_index(rinfo);
OUTREG(CLOCK_CNTL_INDEX, tmp & 0xff);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
OUTPLL(PPLL_DIV_0, 0x48090);
@@ -2521,7 +2522,7 @@ static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo)
static/*extern*/ int susdisking = 0;
-int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state)
+int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct radeonfb_info *rinfo = info->par;
@@ -2704,7 +2705,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
else if (rinfo->dynclk == 0)
radeon_pm_disable_dynamic_mode(rinfo);
- pdev->dev.power.power_state = 0;
+ pdev->dev.power.power_state = PMSG_ON;
bail:
release_console_sem();
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 17161784f54c8..659bc9f62244a 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -77,6 +77,15 @@ enum radeon_chip_flags {
CHIP_HAS_CRTC2 = 0x00040000UL,
};
+/*
+ * Errata workarounds
+ */
+enum radeon_errata {
+ CHIP_ERRATA_R300_CG = 0x00000001,
+ CHIP_ERRATA_PLL_DUMMYREADS = 0x00000002,
+ CHIP_ERRATA_PLL_DELAY = 0x00000004,
+};
+
/*
* Monitor types
@@ -295,6 +304,7 @@ struct radeonfb_info {
int chipset;
u8 family;
u8 rev;
+ unsigned int errata;
unsigned long video_ram;
unsigned long mapped_vram;
int vram_width;
@@ -305,7 +315,6 @@ struct radeonfb_info {
int has_CRTC2;
int is_mobility;
int is_IGP;
- int R300_cg_workaround;
int reversed_DAC;
int reversed_TMDS;
struct panel_info panel_info;
@@ -369,6 +378,21 @@ struct radeonfb_info {
* IO macros
*/
+/* Note about this function: we have some rare cases where we must not schedule,
+ * this typically happen with our special "wake up early" hook which allows us to
+ * wake up the graphic chip (and thus get the console back) before everything else
+ * on some machines that support that mecanism. At this point, interrupts are off
+ * and scheduling is not permitted
+ */
+static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
+{
+ if (rinfo->no_schedule || oops_in_progress)
+ mdelay(ms);
+ else
+ msleep(ms);
+}
+
+
#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)
@@ -390,107 +414,85 @@ static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
#define OUTREGP(addr,val,mask) _OUTREGP(rinfo, addr, val,mask)
-/* This function is required to workaround a hardware bug in some (all?)
- * revisions of the R300. This workaround should be called after every
- * CLOCK_CNTL_INDEX register access. If not, register reads afterward
- * may not be correct.
- */
-static inline void R300_cg_workardound(struct radeonfb_info *rinfo)
-{
- u32 save, tmp;
- save = INREG(CLOCK_CNTL_INDEX);
- tmp = save & ~(0x3f | PLL_WR_EN);
- OUTREG(CLOCK_CNTL_INDEX, tmp);
- tmp = INREG(CLOCK_CNTL_DATA);
- OUTREG(CLOCK_CNTL_INDEX, save);
-}
-
/*
- * PLL accesses suffer from various HW issues on the different chip
- * families. Some R300's need the above workaround, rv200 & friends
- * need a couple of dummy reads after any write of CLOCK_CNTL_INDEX,
- * and some RS100/200 need a dummy read before writing to
- * CLOCK_CNTL_INDEX as well. Instead of testing every chip revision,
- * we just unconditionally do the workarounds at once since PLL
- * accesses are far from beeing performance critical. Except for R300
- * one which stays separate for now
+ * Note about PLL register accesses:
+ *
+ * I have removed the spinlock on them on purpose. The driver now
+ * expects that it will only manipulate the PLL registers in normal
+ * task environment, where radeon_msleep() will be called, protected
+ * by a semaphore (currently the console semaphore) so that no conflict
+ * will happen on the PLL register index.
+ *
+ * With the latest changes to the VT layer, this is guaranteed for all
+ * calls except the actual drawing/blits which aren't supposed to use
+ * the PLL registers anyway
+ *
+ * This is very important for the workarounds to work properly. The only
+ * possible exception to this rule is the call to unblank(), which may
+ * be done at irq time if an oops is in progress.
*/
-
-static inline void radeon_pll_workaround_before(struct radeonfb_info *rinfo)
+static inline void radeon_pll_errata_after_index(struct radeonfb_info *rinfo)
{
+ if (!(rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS))
+ return;
+
+ (void)INREG(CLOCK_CNTL_DATA);
(void)INREG(CRTC_GEN_CNTL);
}
-static inline void radeon_pll_workaround_after(struct radeonfb_info *rinfo)
+static inline void radeon_pll_errata_after_data(struct radeonfb_info *rinfo)
{
- (void)INREG(CLOCK_CNTL_DATA);
- (void)INREG(CRTC_GEN_CNTL);
+ if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) {
+ /* we can't deal with posted writes here ... */
+ _radeon_msleep(rinfo, 5);
+ }
+ if (rinfo->errata & CHIP_ERRATA_R300_CG) {
+ u32 save, tmp;
+ save = INREG(CLOCK_CNTL_INDEX);
+ tmp = save & ~(0x3f | PLL_WR_EN);
+ OUTREG(CLOCK_CNTL_INDEX, tmp);
+ tmp = INREG(CLOCK_CNTL_DATA);
+ OUTREG(CLOCK_CNTL_INDEX, save);
+ }
}
static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
{
u32 data;
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
data = INREG(CLOCK_CNTL_DATA);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
return data;
}
-static inline u32 _INPLL(struct radeonfb_info *rinfo, u32 addr)
-{
- unsigned long flags;
- u32 data;
-
- spin_lock_irqsave(&rinfo->reg_lock, flags);
- data = __INPLL(rinfo, addr);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
- return data;
-}
-
-#define INPLL(addr) _INPLL(rinfo, addr)
-
-
static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index,
u32 val)
{
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
OUTREG(CLOCK_CNTL_DATA, val);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
}
-static inline void _OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val)
-{
- unsigned long flags;
- spin_lock_irqsave(&rinfo->reg_lock, flags);
- __OUTPLL(rinfo, index, val);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
-}
-static inline void _OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
- u32 val, u32 mask)
+static inline void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val, u32 mask)
{
- unsigned long flags;
unsigned int tmp;
- spin_lock_irqsave(&rinfo->reg_lock, flags);
tmp = __INPLL(rinfo, index);
tmp &= (mask);
tmp |= (val);
__OUTPLL(rinfo, index, tmp);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
-#define OUTPLL(index, val) _OUTPLL(rinfo, index, val)
-#define OUTPLLP(index, val, mask) _OUTPLLP(rinfo, index, val, mask)
+#define INPLL(addr) __INPLL(rinfo, addr)
+#define OUTPLL(index, val) __OUTPLL(rinfo, index, val)
+#define OUTPLLP(index, val, mask) __OUTPLLP(rinfo, index, val, mask)
#define BIOS_IN8(v) (readb(rinfo->bios_seg + (v)))
@@ -582,20 +584,6 @@ static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
printk(KERN_ERR "radeonfb: Idle Timeout !\n");
}
-/* Note about this function: we have some rare cases where we must not schedule,
- * this typically happen with our special "wake up early" hook which allows us to
- * wake up the graphic chip (and thus get the console back) before everything else
- * on some machines that support that mecanism. At this point, interrupts are off
- * and scheduling is not permitted
- */
-static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
-{
- if (rinfo->no_schedule)
- mdelay(ms);
- else
- msleep(ms);
-}
-
#define radeon_engine_idle() _radeon_engine_idle(rinfo)
#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
@@ -608,7 +596,7 @@ extern void radeon_delete_i2c_busses(struct radeonfb_info *rinfo);
extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid);
/* PM Functions */
-extern int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state);
+extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state);
extern int radeonfb_pci_resume(struct pci_dev *pdev);
extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk);
extern void radeonfb_pm_exit(struct radeonfb_info *rinfo);
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index a51f4d2b69d8b..ab98f225fe3ee 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -465,7 +465,7 @@ int __init chips_init(void)
if (fb_get_options("chipsfb", NULL))
return -ENODEV;
- return pci_module_init(&chipsfb_driver);
+ return pci_register_driver(&chipsfb_driver);
}
module_init(chips_init);
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 0255c61df6207..a3040429c27b7 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -2623,7 +2623,7 @@ static int __init cirrusfb_init(void)
error |= zorro_module_init(&cirrusfb_zorro_driver);
#endif
#ifdef CONFIG_PCI
- error |= pci_module_init(&cirrusfb_pci_driver);
+ error |= pci_register_driver(&cirrusfb_pci_driver);
#endif
return error;
}
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index b1d435940eb12..b28a4b0e395e6 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -199,7 +199,10 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
count -= cnt;
}
- if (buf)
+ /* buf is always NULL except when in monochrome mode, so in this case
+ it's a gain to check buf against NULL even though kfree() handles
+ NULL pointers just fine */
+ if (unlikely(buf))
kfree(buf);
}
@@ -273,8 +276,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC);
if (!dst)
return;
- if (ops->cursor_data)
- kfree(ops->cursor_data);
+ kfree(ops->cursor_data);
ops->cursor_data = dst;
update_attr(dst, src, attribute, vc);
src = dst;
@@ -321,8 +323,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
if (!mask)
return;
- if (ops->cursor_state.mask)
- kfree(ops->cursor_state.mask);
+ kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
p->cursor_shape = vc->vc_cursor_type;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index de92afb5eecf4..59e3b4b4e7e3e 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -107,15 +107,15 @@ enum {
};
struct display fb_display[MAX_NR_CONSOLES];
-signed char con2fb_map[MAX_NR_CONSOLES];
-signed char con2fb_map_boot[MAX_NR_CONSOLES];
+static signed char con2fb_map[MAX_NR_CONSOLES];
+static signed char con2fb_map_boot[MAX_NR_CONSOLES];
static int logo_height;
static int logo_lines;
/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
enums. */
static int logo_shown = FBCON_LOGO_CANSHOW;
/* Software scrollback */
-int fbcon_softback_size = 32768;
+static int fbcon_softback_size = 32768;
static unsigned long softback_buf, softback_curr;
static unsigned long softback_in;
static unsigned long softback_top, softback_end;
@@ -130,6 +130,8 @@ static char fontname[40];
/* current fb_info */
static int info_idx = -1;
+static const struct consw fb_con;
+
#define CM_SOFTBACK (8)
#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
@@ -204,8 +206,10 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp)
static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
{
+ struct fbcon_ops *ops = info->fbcon_par;
+
return (info->state != FBINFO_STATE_RUNNING ||
- vc->vc_mode != KD_TEXT);
+ vc->vc_mode != KD_TEXT || ops->graphics);
}
static inline int get_color(struct vc_data *vc, struct fb_info *info,
@@ -307,7 +311,8 @@ static void cursor_timer_handler(unsigned long dev_addr)
mod_timer(&ops->cursor_timer, jiffies + HZ/5);
}
-int __init fb_console_setup(char *this_opt)
+#ifndef MODULE
+static int __init fb_console_setup(char *this_opt)
{
char *options;
int i, j;
@@ -361,6 +366,7 @@ int __init fb_console_setup(char *this_opt)
}
__setup("fbcon=", fb_console_setup);
+#endif
static int search_fb_in_map(int idx)
{
@@ -593,9 +599,12 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
ops->currcon = fg_console;
- if (info->fbops->fb_set_par)
+ if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT))
info->fbops->fb_set_par(info);
+ ops->flags |= FBCON_FLAGS_INIT;
+ ops->graphics = 0;
+
if (vc)
fbcon_set_disp(info, &info->var, vc);
else
@@ -695,6 +704,7 @@ static int var_to_display(struct display *disp,
disp->green = var->green;
disp->blue = var->blue;
disp->transp = var->transp;
+ disp->rotate = var->rotate;
disp->mode = fb_match_mode(var, &info->modelist);
if (disp->mode == NULL)
/* This should not happen */
@@ -718,6 +728,7 @@ static void display_to_var(struct fb_var_screeninfo *var,
var->green = disp->green;
var->blue = disp->blue;
var->transp = disp->transp;
+ var->rotate = disp->rotate;
}
static const char *fbcon_startup(void)
@@ -763,6 +774,7 @@ static const char *fbcon_startup(void)
memset(ops, 0, sizeof(struct fbcon_ops));
ops->currcon = -1;
+ ops->graphics = 1;
info->fbcon_par = ops;
set_blitting_type(vc, info, NULL);
@@ -889,6 +901,7 @@ static const char *fbcon_startup(void)
static void fbcon_init(struct vc_data *vc, int init)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+ struct fbcon_ops *ops;
struct vc_data **default_mode = vc->vc_display_fg;
struct vc_data *svc = *default_mode;
struct display *t, *p = &fb_display[vc->vc_num];
@@ -939,6 +952,8 @@ static void fbcon_init(struct vc_data *vc, int init)
new_cols = info->var.xres / vc->vc_font.width;
new_rows = info->var.yres / vc->vc_font.height;
vc_resize(vc, new_cols, new_rows);
+
+ ops = info->fbcon_par;
/*
* We must always set the mode. The mode of the previous console
* driver could be in the same resolution but we are using different
@@ -946,9 +961,14 @@ static void fbcon_init(struct vc_data *vc, int init)
*
* We need to do it in fbcon_init() to prevent screen corruption.
*/
- if (CON_IS_VISIBLE(vc) && info->fbops->fb_set_par)
- info->fbops->fb_set_par(info);
+ if (CON_IS_VISIBLE(vc)) {
+ if (info->fbops->fb_set_par &&
+ !(ops->flags & FBCON_FLAGS_INIT))
+ info->fbops->fb_set_par(info);
+ ops->flags |= FBCON_FLAGS_INIT;
+ }
+ ops->graphics = 0;
if ((cap & FBINFO_HWACCEL_COPYAREA) &&
!(cap & FBINFO_HWACCEL_DISABLED))
@@ -1111,7 +1131,7 @@ static int scrollback_phys_max = 0;
static int scrollback_max = 0;
static int scrollback_current = 0;
-int update_var(int con, struct fb_info *info)
+static int update_var(int con, struct fb_info *info)
{
if (con == ((struct fbcon_ops *)info->fbcon_par)->currcon)
return fb_pan_display(info, &info->var);
@@ -1871,7 +1891,6 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
var.activate = FB_ACTIVATE_NOW |
FB_ACTIVATE_FORCE;
fb_set_var(info, &var);
- info->flags &= ~FBINFO_MISC_MODESWITCH;
}
var_to_display(p, &info->var, info);
}
@@ -1884,7 +1903,7 @@ static int fbcon_switch(struct vc_data *vc)
struct fb_info *info;
struct display *p = &fb_display[vc->vc_num];
struct fb_var_screeninfo var;
- int i, prev_console, do_set_par = 0;
+ int i, prev_console;
info = registered_fb[con2fb_map[vc->vc_num]];
@@ -1943,14 +1962,9 @@ static int fbcon_switch(struct vc_data *vc)
fb_set_var(info, &var);
if (prev_console != -1 &&
- registered_fb[con2fb_map[prev_console]] != info)
- do_set_par = 1;
-
- if (do_set_par || info->flags & FBINFO_MISC_MODESWITCH) {
- if (info->fbops->fb_set_par)
- info->fbops->fb_set_par(info);
- info->flags &= ~FBINFO_MISC_MODESWITCH;
- }
+ registered_fb[con2fb_map[prev_console]] != info &&
+ info->fbops->fb_set_par)
+ info->fbops->fb_set_par(info);
set_blitting_type(vc, info, p);
((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1;
@@ -2013,29 +2027,20 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
- int active = !fbcon_is_inactive(vc, info);
if (mode_switch) {
struct fb_var_screeninfo var = info->var;
-/*
- * HACK ALERT: Some hardware will require reinitializion at this stage,
- * others will require it to be done as late as possible.
- * For now, we differentiate this with the
- * FBINFO_MISC_MODESWITCHLATE bitflag. Worst case will be
- * hardware that requires it here and another one later.
- * A definitive solution may require fixing X or the VT
- * system.
- */
- if (info->flags & FBINFO_MISC_MODESWITCHLATE)
- info->flags |= FBINFO_MISC_MODESWITCH;
- if (!blank && !(info->flags & FBINFO_MISC_MODESWITCHLATE)) {
+ ops->graphics = 1;
+
+ if (!blank) {
var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
fb_set_var(info, &var);
+ ops->graphics = 0;
}
}
- if (active) {
+ if (!fbcon_is_inactive(vc, info)) {
if (ops->blank_state != blank) {
ops->blank_state = blank;
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
@@ -2326,6 +2331,9 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
if (fbcon_is_inactive(vc, info))
return -EINVAL;
+ if (!CON_IS_VISIBLE(vc))
+ return 0;
+
depth = fb_get_color_depth(&info->var);
if (depth > 3) {
for (i = j = 0; i < 16; i++) {
@@ -2733,7 +2741,7 @@ static int fbcon_event_notify(struct notifier_block *self,
* The console `switch' structure for the frame buffer based console
*/
-const struct consw fb_con = {
+static const struct consw fb_con = {
.owner = THIS_MODULE,
.con_startup = fbcon_startup,
.con_init = fbcon_init,
@@ -2763,7 +2771,7 @@ static struct notifier_block fbcon_event_notifier = {
.notifier_call = fbcon_event_notify,
};
-int __init fb_console_init(void)
+static int __init fb_console_init(void)
{
int i;
@@ -2791,7 +2799,7 @@ module_init(fb_console_init);
#ifdef MODULE
-void __exit fb_console_exit(void)
+static void __exit fb_console_exit(void)
{
acquire_console_sem();
fb_unregister_client(&fbcon_event_notifier);
@@ -2803,10 +2811,4 @@ module_exit(fb_console_exit);
#endif
-/*
- * Visible symbols for modules
- */
-
-EXPORT_SYMBOL(fb_con);
-
MODULE_LICENSE("GPL");
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 30e641160bf67..5d377860bce28 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -18,6 +18,8 @@
#include <asm/io.h>
+#define FBCON_FLAGS_INIT 1
+
/*
* This is the interface between the low-level console driver and the
* low-level frame buffer device
@@ -41,6 +43,7 @@ struct display {
u32 grayscale;
u32 nonstd;
u32 accel_flags;
+ u32 rotate;
struct fb_bitfield red;
struct fb_bitfield green;
struct fb_bitfield blue;
@@ -67,6 +70,8 @@ struct fbcon_ops {
int cursor_flash;
int cursor_reset;
int blank_state;
+ int graphics;
+ int flags;
char *cursor_data;
};
/*
@@ -156,13 +161,10 @@ struct fbcon_ops {
#define SCROLL_REDRAW 0x004
#define SCROLL_PAN_REDRAW 0x005
-extern int fb_console_init(void);
#ifdef CONFIG_FB_TILEBLITTING
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
struct display *p, struct fbcon_ops *ops);
#endif
extern void fbcon_set_bitops(struct fbcon_ops *ops);
-extern const struct consw fb_con;
-
#endif /* _VIDEO_FBCON_H */
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 4a26c828b798f..989e4d49e5bbe 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -564,7 +564,7 @@ static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
* The console `switch' structure for the MDA based console
*/
-const struct consw mda_con = {
+static const struct consw mda_con = {
.owner = THIS_MODULE,
.con_startup = mdacon_startup,
.con_init = mdacon_init,
@@ -591,7 +591,7 @@ int __init mda_console_init(void)
return take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0);
}
-void __exit mda_console_exit(void)
+static void __exit mda_console_exit(void)
{
give_up_console(&mda_con);
}
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 1c5961ce00517..d940f605acb68 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -798,11 +798,8 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
return 1;
out_err:
- if(raw)
- kfree(raw);
- if(cooked)
- kfree(cooked);
-
+ kfree(raw);
+ kfree(cooked);
return 0;
}
@@ -1058,7 +1055,7 @@ static void __init sti_init_roms(void)
/* Register drivers for native & PCI cards */
register_parisc_driver(&pa_sti_driver);
- pci_module_init(&pci_sti_driver);
+ pci_register_driver(&pci_sti_driver);
/* if we didn't find the given default sti, take the first one */
if (!default_sti)
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index a509863662309..8b1b7c687a991 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1668,7 +1668,7 @@ static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
}
}
-static int cyberpro_pci_suspend(struct pci_dev *dev, u32 state)
+static int cyberpro_pci_suspend(struct pci_dev *dev, pm_message_t state)
{
return 0;
}
@@ -1740,7 +1740,7 @@ static int __init cyber2000fb_init(void)
}
#endif
#ifdef CONFIG_PCI
- err = pci_module_init(&cyberpro_driver);
+ err = pci_register_driver(&cyberpro_driver);
if (!err)
ret = 0;
#endif
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 4a45e287ba459..25f460ca0daf1 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -446,8 +446,7 @@ int fb_show_logo(struct fb_info *info)
logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height,
GFP_KERNEL);
if (logo_new == NULL) {
- if (palette)
- kfree(palette);
+ kfree(palette);
if (saved_pseudo_palette)
info->pseudo_palette = saved_pseudo_palette;
return 0;
@@ -466,12 +465,10 @@ int fb_show_logo(struct fb_info *info)
info->fbops->fb_imageblit(info, &image);
}
- if (palette != NULL)
- kfree(palette);
+ kfree(palette);
if (saved_pseudo_palette != NULL)
info->pseudo_palette = saved_pseudo_palette;
- if (logo_new != NULL)
- kfree(logo_new);
+ kfree(logo_new);
return fb_logo.logo->height;
}
#else
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 905f2e132f43d..978def0135879 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -74,10 +74,9 @@ static struct broken_edid brokendb[] = {
},
};
-const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
+static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00
};
-const unsigned char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
static void copy_string(unsigned char *c, unsigned char *s)
{
@@ -589,8 +588,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
*/
void fb_destroy_modedb(struct fb_videomode *modedb)
{
- if (modedb)
- kfree(modedb);
+ kfree(modedb);
}
static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
@@ -872,18 +870,6 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
DPRINTK("========================================\n");
}
-char *get_EDID_from_firmware(struct device *dev)
-{
- unsigned char *pedid = NULL;
-
-#if defined(CONFIG_EDID_FIRMWARE) && defined(CONFIG_X86)
- pedid = edid_info.dummy;
- if (!pedid)
- return NULL;
-#endif
- return pedid;
-}
-
/*
* VESA Generalized Timing Formula (GTF)
*/
@@ -1193,10 +1179,6 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
{
specs = NULL;
}
-char *get_EDID_from_firmware(struct device *dev)
-{
- return NULL;
-}
void fb_destroy_modedb(struct fb_videomode *modedb)
{
}
@@ -1270,7 +1252,6 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
EXPORT_SYMBOL(fb_parse_edid);
EXPORT_SYMBOL(fb_edid_to_monspecs);
-EXPORT_SYMBOL(get_EDID_from_firmware);
EXPORT_SYMBOL(fb_get_mode);
EXPORT_SYMBOL(fb_validate_mode);
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index c51b4a7de7d41..9ec8781794c01 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -1492,7 +1492,7 @@ static struct fb_ops i810fb_ops __devinitdata = {
/***********************************************************************
* Power Management *
***********************************************************************/
-static int i810fb_suspend(struct pci_dev *dev, u32 state)
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
{
struct fb_info *info = pci_get_drvdata(dev);
struct i810fb_par *par = (struct i810fb_par *) info->par;
@@ -1524,7 +1524,7 @@ static int i810fb_suspend(struct pci_dev *dev, u32 state)
pci_disable_device(dev);
}
pci_save_state(dev);
- pci_set_power_state(dev, state);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
@@ -1538,7 +1538,7 @@ static int i810fb_resume(struct pci_dev *dev)
return 0;
pci_restore_state(dev);
- pci_set_power_state(dev, 0);
+ pci_set_power_state(dev, PCI_D0);
pci_enable_device(dev);
agp_bind_memory(par->i810_gtt.i810_fb_memory,
par->fb.offset);
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h
index 0f2caf3575f8a..43b4297b4d481 100644
--- a/drivers/video/i810/i810_main.h
+++ b/drivers/video/i810/i810_main.h
@@ -18,7 +18,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
const struct pci_device_id *entry);
static void __exit i810fb_remove_pci(struct pci_dev *dev);
static int i810fb_resume(struct pci_dev *dev);
-static int i810fb_suspend(struct pci_dev *dev, u32 state);
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
/*
* voffset - framebuffer offset in MiB from aperture start address. In order for
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 2da19ea040d0f..e326f44f652d7 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -536,8 +536,7 @@ int __init igafb_init(void)
if (!iga_init(info, par)) {
iounmap((void *)par->io_base);
iounmap(info->screen_base);
- if (par->mmap_map)
- kfree(par->mmap_map);
+ kfree(par->mmap_map);
kfree(info);
}
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index c1c9e073a12fd..5a72ca3c01385 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -1611,7 +1611,7 @@ static int __init imsttfb_init(void)
imsttfb_setup(option);
#endif
- return pci_module_init(&imsttfb_pci_driver);
+ return pci_register_driver(&imsttfb_pci_driver);
}
static void __exit imsttfb_exit(void)
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 75a874ce37b18..6a05b70008301 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -360,7 +360,7 @@ intelfb_init(void)
intelfb_setup(option);
#endif
- return pci_module_init(&intelfb_driver);
+ return pci_register_driver(&intelfb_driver);
}
static void __exit
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index 67f4deaa6a454..d8bac9e978421 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -802,7 +802,7 @@ static int __init kyrofb_init(void)
return -ENODEV;
kyrofb_setup(option);
#endif
- return pci_module_init(&kyrofb_pci_driver);
+ return pci_register_driver(&kyrofb_pci_driver);
}
static void __exit kyrofb_exit(void)
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index 3cd1145a6c662..de5a0f3836008 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -19,6 +19,7 @@
#include <linux/errno.h>
#include <linux/fb.h>
#include <linux/string.h>
+#include <linux/module.h>
#include "macmodes.h"
@@ -281,7 +282,7 @@ int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var)
var->vmode = mode->vmode;
return 0;
}
-
+EXPORT_SYMBOL(mac_vmode_to_var);
/**
* mac_var_to_vmode - convert var structure to MacOS vmode/cmode pair
@@ -326,7 +327,7 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
}
return -EINVAL;
}
-
+EXPORT_SYMBOL(mac_var_to_vmode);
/**
* mac_map_monitor_sense - Convert monitor sense to vmode
@@ -348,7 +349,7 @@ int mac_map_monitor_sense(int sense)
break;
return map->vmode;
}
-
+EXPORT_SYMBOL(mac_map_monitor_sense);
/**
* mac_find_mode - find a video mode
@@ -384,3 +385,5 @@ int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
return fb_find_mode(var, info, mode_option, db, dbsize,
&mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);
}
+EXPORT_SYMBOL(mac_find_mode);
+
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index 8f14c9b300c28..c7f3e1321224d 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -438,13 +438,21 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx,
} else if (step == 1) {
/* Special case for 1..8bit widths */
while (height--) {
- mga_writel(mmio, 0, *chardata);
+#if defined(__BIG_ENDIAN)
+ fb_writel((*chardata) << 24, mmio.vaddr);
+#else
+ fb_writel(*chardata, mmio.vaddr);
+#endif
chardata++;
}
} else if (step == 2) {
/* Special case for 9..15bit widths */
while (height--) {
- mga_writel(mmio, 0, *(u_int16_t*)chardata);
+#if defined(__BIG_ENDIAN)
+ fb_writel((*(u_int16_t*)chardata) << 16, mmio.vaddr);
+#else
+ fb_writel(*(u_int16_t*)chardata, mmio.vaddr);
+#endif
chardata += 2;
}
} else {
@@ -454,7 +462,7 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx,
for (i = 0; i < step; i += 4) {
/* Hope that there are at least three readable bytes beyond the end of bitmap */
- mga_writel(mmio, 0, get_unaligned((u_int32_t*)(chardata + i)));
+ fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr);
}
chardata += step;
}
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 942ec768abd97..85a0b25584527 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -170,14 +170,14 @@ static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) {
if ((unsigned long)src & 3) {
while (len >= 4) {
- writel(get_unaligned((u32 *)src), addr);
+ fb_writel(get_unaligned((u32 *)src), addr);
addr++;
len -= 4;
src += 4;
}
} else {
while (len >= 4) {
- writel(*(u32 *)src, addr);
+ fb_writel(*(u32 *)src, addr);
addr++;
len -= 4;
src += 4;
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 805f6831af0bc..fbf659b6dab01 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -404,8 +404,8 @@ static int my_atoi(const char *name)
*
*/
-int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
- const struct fb_videomode *mode, unsigned int bpp)
+static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+ const struct fb_videomode *mode, unsigned int bpp)
{
int err = 0;
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 085b4704a46ef..5d424a30270ac 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -1691,7 +1691,27 @@ static int __devinit neo_map_mmio(struct fb_info *info,
DBG("neo_map_mmio");
- info->fix.mmio_start = pci_resource_start(dev, 1);
+ switch (info->fix.accel) {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ info->fix.mmio_start = pci_resource_start(dev, 0)+
+ 0x100000;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2090:
+ case FB_ACCEL_NEOMAGIC_NM2093:
+ info->fix.mmio_start = pci_resource_start(dev, 0)+
+ 0x200000;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2160:
+ case FB_ACCEL_NEOMAGIC_NM2097:
+ case FB_ACCEL_NEOMAGIC_NM2200:
+ case FB_ACCEL_NEOMAGIC_NM2230:
+ case FB_ACCEL_NEOMAGIC_NM2360:
+ case FB_ACCEL_NEOMAGIC_NM2380:
+ info->fix.mmio_start = pci_resource_start(dev, 1);
+ break;
+ default:
+ info->fix.mmio_start = pci_resource_start(dev, 0);
+ }
info->fix.mmio_len = MMIO_SIZE;
if (!request_mem_region
@@ -2010,6 +2030,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
par->internal_display = internal;
par->external_display = external;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
switch (info->fix.accel) {
case FB_ACCEL_NEOMAGIC_NM2070:
@@ -2029,15 +2050,27 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
break;
case FB_ACCEL_NEOMAGIC_NM2200:
sprintf(info->fix.id, "MagicGraph 256AV");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2230:
sprintf(info->fix.id, "MagicGraph 256AV+");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2360:
sprintf(info->fix.id, "MagicGraph 256ZX");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2380:
sprintf(info->fix.id, "MagicGraph 256XL+");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
}
@@ -2049,9 +2082,6 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
info->fix.accel = id->driver_data;
info->fbops = &neofb_ops;
- info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
- FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_COPYAREA |
- FBINFO_HWACCEL_COPYAREA;
info->pseudo_palette = (void *) (par + 1);
return info;
}
diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c
index 8050ff979f9d7..f377a29ec97a6 100644
--- a/drivers/video/nvidia/nv_accel.c
+++ b/drivers/video/nvidia/nv_accel.c
@@ -1,12 +1,50 @@
+ /***************************************************************************\
+|* *|
+|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NOTICE TO USER: The source code is copyrighted under U.S. and *|
+|* international laws. Users and possessors of this source code are *|
+|* hereby granted a nonexclusive, royalty-free copyright license to *|
+|* use this code in individual and commercial software. *|
+|* *|
+|* Any use of this source code must include, in the user documenta- *|
+|* tion and internal comments to the code, notices to the end user *|
+|* as follows: *|
+|* *|
+|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
+|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
+|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
+|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
+|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
+|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
+|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
+|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
+|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
+|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
+|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
+|* *|
+|* U.S. Government End Users. This source code is a "commercial *|
+|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
+|* consisting of "commercial computer software" and "commercial *|
+|* computer software documentation," as such terms are used in *|
+|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
+|* ment only as a commercial end item. Consistent with 48 C.F.R. *|
+|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
+|* all U.S. Government End Users acquire the source code with only *|
+|* those rights set forth herein. *|
+|* *|
+ \***************************************************************************/
+
/*
- * linux/drivers/video/nvidia/nv_accel.c - nVidia Hardware Acceleration
- *
- * Copyright 2004 Antonino Daplas <adaplas@pol.net>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
*
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
*/
#include <linux/fb.h>
@@ -321,10 +359,10 @@ static void nvidiafb_mono_color_expand(struct fb_info *info,
struct nvidia_par *par = info->par;
u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel));
u32 dsize, width, *data = (u32 *) image->data, tmp;
- int i, j, k = 0;
+ int j, k = 0;
width = (image->width + 31) & ~31;
- dsize = width >> 5;
+ dsize = (width * image->height) >> 5;
if (info->var.bits_per_pixel == 8) {
fg = image->fg_color | mask;
@@ -344,8 +382,22 @@ static void nvidiafb_mono_color_expand(struct fb_info *info,
NVDmaNext(par, (image->height << 16) | width);
NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
- for (i = image->height; i--;) {
+ while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) {
+ NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0),
+ RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS);
+
+ for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) {
+ tmp = data[k++];
+ reverse_order(&tmp);
+ NVDmaNext(par, tmp);
+ }
+
+ dsize -= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS;
+ }
+
+ if (dsize) {
NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize);
+
for (j = dsize; j--;) {
tmp = data[k++];
reverse_order(&tmp);
diff --git a/drivers/video/nvidia/nv_dma.h b/drivers/video/nvidia/nv_dma.h
index 5cc42537d006f..a7ed1c0acbbbd 100644
--- a/drivers/video/nvidia/nv_dma.h
+++ b/drivers/video/nvidia/nv_dma.h
@@ -38,6 +38,16 @@
|* *|
\***************************************************************************/
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
#define SURFACE_FORMAT 0x00000300
#define SURFACE_FORMAT_DEPTH8 0x00000001
#define SURFACE_FORMAT_DEPTH15 0x00000002
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index ffecb23bca210..b989358437b37 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -36,6 +36,17 @@
|* those rights set forth herein. *|
|* *|
\***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.4 2003/11/03 05:11:25 tsi Exp $ */
#include <linux/pci.h>
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 9e49e9ee44190..3757c1407c190 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -146,7 +146,6 @@ void nvidia_create_i2c_busses(struct nvidia_par *par)
nvidia_setup_i2c_bus(&par->chan[2], "BUS3");
}
-#if 0
void nvidia_delete_i2c_busses(struct nvidia_par *par)
{
if (par->chan[0].par)
@@ -162,7 +161,6 @@ void nvidia_delete_i2c_busses(struct nvidia_par *par)
par->chan[2].par = NULL;
}
-#endif /* 0 */
static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan)
{
diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h
index 89a0ae89ea447..9da320986f4c9 100644
--- a/drivers/video/nvidia/nv_local.h
+++ b/drivers/video/nvidia/nv_local.h
@@ -37,6 +37,16 @@
|* *|
\***************************************************************************/
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
#ifndef __NV_LOCAL_H__
#define __NV_LOCAL_H__
@@ -77,9 +87,8 @@
#endif
#define WRITE_PUT(par, data) { \
- volatile u8 scratch; \
_NV_FENCE() \
- scratch = NV_RD08((par)->FbStart, 0); \
+ NV_RD08((par)->FbStart, 0); \
NV_WR32(&(par)->FIFO[0x0010], 0, (data) << 2); \
mb(); \
}
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
index 660ac29d723e1..7d12eb85310de 100644
--- a/drivers/video/nvidia/nv_of.c
+++ b/drivers/video/nvidia/nv_of.c
@@ -28,6 +28,7 @@
#include "nv_proto.h"
void nvidia_create_i2c_busses(struct nvidia_par *par) {}
+void nvidia_delete_i2c_busses(struct nvidia_par *par) {}
int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
{
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 0c5dd425eb5d8..42847ce1b8dd7 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -33,10 +33,12 @@ void NVLockUnlock(struct nvidia_par *par, int);
/* in nvidia-i2c.c */
#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF)
void nvidia_create_i2c_busses(struct nvidia_par *par);
+void nvidia_delete_i2c_busses(struct nvidia_par *par);
int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn,
u8 ** out_edid);
#else
#define nvidia_create_i2c_busses(...)
+#define nvidia_delete_i2c_busses(...)
#define nvidia_probe_i2c_connector(p, c, edid) \
do { \
*(edid) = NULL; \
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index ed2566cbe8c72..0bbdca2e0f911 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -37,6 +37,16 @@
|* *|
\***************************************************************************/
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
#include <video/vga.h>
#include <linux/delay.h>
#include <linux/pci.h>
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 2dfecddc308e3..3a6555a8aaa25 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -402,25 +402,25 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
/* command line data, set in nvidiafb_setup() */
-static int flatpanel __initdata = -1; /* Autodetect later */
-static int forceCRTC __initdata = -1;
-static int hwcur __initdata = 0;
-static int noaccel __initdata = 0;
-static int noscale __initdata = 0;
-static int paneltweak __initdata = 0;
+static int flatpanel __devinitdata = -1; /* Autodetect later */
+static int forceCRTC __devinitdata = -1;
+static int hwcur __devinitdata = 0;
+static int noaccel __devinitdata = 0;
+static int noscale __devinitdata = 0;
+static int paneltweak __devinitdata = 0;
#ifdef CONFIG_MTRR
-static int nomtrr __initdata = 0;
+static int nomtrr __devinitdata = 0;
#endif
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
-static struct fb_fix_screeninfo __initdata nvidiafb_fix = {
+static struct fb_fix_screeninfo __devinitdata nvidiafb_fix = {
.type = FB_TYPE_PACKED_PIXELS,
.xpanstep = 8,
.ypanstep = 1,
};
-static struct fb_var_screeninfo __initdata nvidiafb_default_var = {
+static struct fb_var_screeninfo __devinitdata nvidiafb_default_var = {
.xres = 640,
.yres = 480,
.xres_virtual = 640,
@@ -1191,6 +1191,7 @@ static int nvidiafb_check_var(struct fb_var_screeninfo *var,
var->yres_virtual = var->yres;
var->xres_virtual = vramlen / var->yres_virtual;
var->xres_virtual /= var->bits_per_pixel / 8;
+ var->xres_virtual &= ~63;
pitch = (var->xres_virtual *
var->bits_per_pixel + 7) / 8;
memlen = pitch * var->yres;
@@ -1301,7 +1302,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
| FBINFO_HWACCEL_IMAGEBLIT
| FBINFO_HWACCEL_FILLRECT
| FBINFO_HWACCEL_COPYAREA
- | FBINFO_HWACCEL_YPAN | FBINFO_MISC_MODESWITCHLATE;
+ | FBINFO_HWACCEL_YPAN;
fb_videomode_to_modelist(info->monspecs.modedb,
info->monspecs.modedb_len, &info->modelist);
@@ -1352,8 +1353,6 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
if (!hwcur)
info->fbops->fb_cursor = soft_cursor;
info->var.accel_flags = (!noaccel);
- par->FpScale = (!noscale);
- par->paneltweak = paneltweak;
switch (par->Architecture) {
case NV_ARCH_04:
@@ -1485,6 +1484,8 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
printk(KERN_INFO PFX "flatpanel support enabled\n");
par->CRTCnumber = forceCRTC;
+ par->FpScale = (!noscale);
+ par->paneltweak = paneltweak;
/* enable IO and mem if not already done */
pci_read_config_word(pd, PCI_COMMAND, &cmd);
@@ -1565,8 +1566,9 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
err_out_iounmap_fb:
iounmap(info->screen_base);
- err_out_free_base1:
fb_destroy_modedb(info->monspecs.modedb);
+ nvidia_delete_i2c_busses(par);
+ err_out_free_base1:
iounmap(par->REGS);
err_out_free_base0:
pci_release_regions(pd);
@@ -1596,9 +1598,10 @@ static void __exit nvidiafb_remove(struct pci_dev *pd)
info->fix.smem_len);
#endif /* CONFIG_MTRR */
+ iounmap(info->screen_base);
fb_destroy_modedb(info->monspecs.modedb);
+ nvidia_delete_i2c_busses(par);
iounmap(par->REGS);
- iounmap(info->screen_base);
pci_release_regions(pd);
pci_disable_device(pd);
kfree(info->pixmap.addr);
@@ -1614,7 +1617,7 @@ static void __exit nvidiafb_remove(struct pci_dev *pd)
* ------------------------------------------------------------------------- */
#ifndef MODULE
-static int __init nvidiafb_setup(char *options)
+static int __devinit nvidiafb_setup(char *options)
{
char *this_opt;
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 496624c277c1b..5dceddedf5075 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -747,7 +747,7 @@ static int pm2fb_set_par(struct fb_info *info)
}
if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_DOUBLE)
video |= PM2F_LINE_DOUBLE;
- if (info->var.activate==FB_ACTIVATE_NOW)
+ if ((info->var.activate & FB_ACTIVATE_MASK)==FB_ACTIVATE_NOW)
video |= PM2F_VIDEO_ENABLE;
par->video = video;
@@ -1282,7 +1282,7 @@ static int __init pm2fb_init(void)
pm2fb_setup(option);
#endif
- return pci_module_init(&pm2fb_driver);
+ return pci_register_driver(&pm2fb_driver);
}
module_init(pm2fb_init);
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 6741b522c0d36..31c547fd383bf 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -967,7 +967,7 @@ static struct pci_driver pvr2fb_pci_driver = {
static int __init pvr2fb_pci_init(void)
{
- return pci_module_init(&pvr2fb_pci_driver);
+ return pci_register_driver(&pvr2fb_pci_driver);
}
static void pvr2fb_pci_exit(void)
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 552a38e5f143f..483ad9bab5390 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1343,8 +1343,7 @@ int __init pxafb_probe(struct device *dev)
failed:
dev_set_drvdata(dev, NULL);
- if (fbi)
- kfree(fbi);
+ kfree(fbi);
return ret;
}
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index 3fad3f70b9d3d..d9a084e77a632 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -3150,7 +3150,7 @@ static int __init radeonfb_old_init (void)
return -ENODEV;
radeonfb_old_setup(option);
#endif
- return pci_module_init (&radeonfb_driver);
+ return pci_register_driver (&radeonfb_driver);
}
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 7a6e82567ff89..b0c886de04043 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1708,8 +1708,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
| FBINFO_HWACCEL_YPAN
| FBINFO_HWACCEL_COPYAREA
| FBINFO_HWACCEL_FILLRECT
- | FBINFO_HWACCEL_IMAGEBLIT
- | FBINFO_MISC_MODESWITCHLATE;
+ | FBINFO_HWACCEL_IMAGEBLIT;
/* Accel seems to not work properly on NV30 yet...*/
if ((par->riva.Architecture == NV_ARCH_30) || noaccel) {
@@ -2109,8 +2108,7 @@ static void __exit rivafb_remove(struct pci_dev *pd)
#ifdef CONFIG_FB_RIVA_I2C
riva_delete_i2c_busses(par);
- if (par->EDID)
- kfree(par->EDID);
+ kfree(par->EDID);
#endif
unregister_framebuffer(info);
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
new file mode 100644
index 0000000000000..b637c389e4f48
--- /dev/null
+++ b/drivers/video/s1d13xxxfb.c
@@ -0,0 +1,772 @@
+/* drivers/video/s1d13xxxfb.c
+ *
+ * (c) 2004 Simtec Electronics
+ * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * Driver for Epson S1D13xxx series framebuffer chips
+ *
+ * Adapted from
+ * linux/drivers/video/skeletonfb.c
+ * linux/drivers/video/epson1355fb.c
+ * linux/drivers/video/epson/s1d13xxxfb.c (2.4 driver by Epson)
+ *
+ * Note, currently only tested on S1D13806 with 16bit CRT.
+ * As such, this driver might still contain some hardcoded bits relating to
+ * S1D13806.
+ * Making it work on other S1D13XXX chips should merely be a matter of adding
+ * a few switch()s, some missing glue here and there maybe, and split header
+ * files.
+ *
+ * TODO: - handle dual screen display (CRT and LCD at the same time).
+ * - check_var(), mode change, etc.
+ * - PM untested.
+ * - Accelerated interfaces.
+ * - Probably not SMP safe :)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include <video/s1d13xxxfb.h>
+
+#define PFX "s1d13xxxfb: "
+
+#if 0
+#define dbg(fmt, args...) do { printk(KERN_INFO fmt, ## args); } while(0)
+#else
+#define dbg(fmt, args...) do { } while (0)
+#endif
+
+/*
+ * Here we define the default struct fb_fix_screeninfo
+ */
+static struct fb_fix_screeninfo __devinitdata s1d13xxxfb_fix = {
+ .id = S1D_FBID,
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_PSEUDOCOLOR,
+ .xpanstep = 0,
+ .ypanstep = 1,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
+};
+
+static inline u8
+s1d13xxxfb_readreg(struct s1d13xxxfb_par *par, u16 regno)
+{
+ return readb(par->regs + regno);
+}
+
+static inline void
+s1d13xxxfb_writereg(struct s1d13xxxfb_par *par, u16 regno, u8 value)
+{
+ writeb(value, par->regs + regno);
+}
+
+static inline void
+s1d13xxxfb_runinit(struct s1d13xxxfb_par *par,
+ const struct s1d13xxxfb_regval *initregs,
+ const unsigned int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if ((initregs[i].addr == S1DREG_DELAYOFF) ||
+ (initregs[i].addr == S1DREG_DELAYON))
+ mdelay((int)initregs[i].value);
+ else {
+ s1d13xxxfb_writereg(par, initregs[i].addr, initregs[i].value);
+ }
+ }
+
+ /* make sure the hardware can cope with us */
+ mdelay(1);
+}
+
+static inline void
+lcd_enable(struct s1d13xxxfb_par *par, int enable)
+{
+ u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+
+ if (enable)
+ mode |= 0x01;
+ else
+ mode &= ~0x01;
+
+ s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
+}
+
+static inline void
+crt_enable(struct s1d13xxxfb_par *par, int enable)
+{
+ u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+
+ if (enable)
+ mode |= 0x02;
+ else
+ mode &= ~0x02;
+
+ s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
+}
+
+/* framebuffer control routines */
+
+static inline void
+s1d13xxxfb_setup_pseudocolour(struct fb_info *info)
+{
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+ info->var.red.length = 4;
+ info->var.green.length = 4;
+ info->var.blue.length = 4;
+}
+
+static inline void
+s1d13xxxfb_setup_truecolour(struct fb_info *info)
+{
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->var.bits_per_pixel = 16;
+
+ info->var.red.length = 5;
+ info->var.red.offset = 11;
+
+ info->var.green.length = 6;
+ info->var.green.offset = 5;
+
+ info->var.blue.length = 5;
+ info->var.blue.offset = 0;
+}
+
+/**
+ * s1d13xxxfb_set_par - Alters the hardware state.
+ * @info: frame buffer structure
+ *
+ * Using the fb_var_screeninfo in fb_info we set the depth of the
+ * framebuffer. This function alters the par AND the
+ * fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
+ * fb_info since we are using that data. This means we depend on the
+ * data in var inside fb_info to be supported by the hardware.
+ * xxxfb_check_var is always called before xxxfb_set_par to ensure this.
+ *
+ * XXX TODO: write proper s1d13xxxfb_check_var(), without which that
+ * function is quite useless.
+ */
+static int
+s1d13xxxfb_set_par(struct fb_info *info)
+{
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ unsigned int val;
+
+ dbg("s1d13xxxfb_set_par: bpp=%d\n", info->var.bits_per_pixel);
+
+ if ((s1dfb->display & 0x01)) /* LCD */
+ val = s1d13xxxfb_readreg(s1dfb, S1DREG_LCD_DISP_MODE); /* read colour control */
+ else /* CRT */
+ val = s1d13xxxfb_readreg(s1dfb, S1DREG_CRT_DISP_MODE); /* read colour control */
+
+ val &= ~0x07;
+
+ switch (info->var.bits_per_pixel) {
+ case 4:
+ dbg("pseudo colour 4\n");
+ s1d13xxxfb_setup_pseudocolour(info);
+ val |= 2;
+ break;
+ case 8:
+ dbg("pseudo colour 8\n");
+ s1d13xxxfb_setup_pseudocolour(info);
+ val |= 3;
+ break;
+ case 16:
+ dbg("true colour\n");
+ s1d13xxxfb_setup_truecolour(info);
+ val |= 5;
+ break;
+
+ default:
+ dbg("bpp not supported!\n");
+ return -EINVAL;
+ }
+
+ dbg("writing %02x to display mode register\n", val);
+
+ if ((s1dfb->display & 0x01)) /* LCD */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LCD_DISP_MODE, val);
+ else /* CRT */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_CRT_DISP_MODE, val);
+
+ info->fix.line_length = info->var.xres * info->var.bits_per_pixel;
+ info->fix.line_length /= 8;
+
+ dbg("setting line_length to %d\n", info->fix.line_length);
+
+ dbg("done setup\n");
+
+ return 0;
+}
+
+/**
+ * s1d13xxxfb_setcolreg - sets a color register.
+ * @regno: Which register in the CLUT we are programming
+ * @red: The red value which can be up to 16 bits wide
+ * @green: The green value which can be up to 16 bits wide
+ * @blue: The blue value which can be up to 16 bits wide.
+ * @transp: If supported the alpha value which can be up to 16 bits wide.
+ * @info: frame buffer info structure
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ unsigned int pseudo_val;
+
+ if (regno >= S1D_PALETTE_SIZE)
+ return -EINVAL;
+
+ dbg("s1d13xxxfb_setcolreg: %d: rgb=%d,%d,%d, tr=%d\n",
+ regno, red, green, blue, transp);
+
+ if (info->var.grayscale)
+ red = green = blue = (19595*red + 38470*green + 7471*blue) >> 16;
+
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ if (regno >= 16)
+ return -EINVAL;
+
+ /* deal with creating pseudo-palette entries */
+
+ pseudo_val = (red >> 11) << info->var.red.offset;
+ pseudo_val |= (green >> 10) << info->var.green.offset;
+ pseudo_val |= (blue >> 11) << info->var.blue.offset;
+
+ dbg("s1d13xxxfb_setcolreg: pseudo %d, val %08x\n",
+ regno, pseudo_val);
+
+ ((u32 *)info->pseudo_palette)[regno] = pseudo_val;
+
+ break;
+ case FB_VISUAL_PSEUDOCOLOR:
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_ADDR, regno);
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, red);
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, green);
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, blue);
+
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ dbg("s1d13xxxfb_setcolreg: done\n");
+
+ return 0;
+}
+
+/**
+ * s1d13xxxfb_blank - blanks the display.
+ * @blank_mode: the blank mode we want.
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ * video mode which doesn't support it. Implements VESA suspend
+ * and powerdown modes on hardware that supports disabling hsync/vsync:
+ * blank_mode == 2: suspend vsync
+ * blank_mode == 3: suspend hsync
+ * blank_mode == 4: powerdown
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_blank(int blank_mode, struct fb_info *info)
+{
+ struct s1d13xxxfb_par *par = info->par;
+
+ dbg("s1d13xxxfb_blank: blank=%d, info=%p\n", blank_mode, info);
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ if ((par->display & 0x01) != 0)
+ lcd_enable(par, 1);
+ if ((par->display & 0x02) != 0)
+ crt_enable(par, 1);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ break;
+ case FB_BLANK_POWERDOWN:
+ lcd_enable(par, 0);
+ crt_enable(par, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* let fbcon do a soft blank for us */
+ return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
+}
+
+/**
+ * s1d13xxxfb_pan_display - Pans the display.
+ * @var: frame buffer variable screen structure
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Pan (or wrap, depending on the `vmode' field) the display using the
+ * `yoffset' field of the `var' structure (`xoffset' not yet supported).
+ * If the values don't fit, return -EINVAL.
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct s1d13xxxfb_par *par = info->par;
+ u32 start;
+
+ if (var->xoffset != 0) /* not yet ... */
+ return -EINVAL;
+
+ if (var->yoffset + info->var.yres > info->var.yres_virtual)
+ return -EINVAL;
+
+ start = (info->fix.line_length >> 1) * var->yoffset;
+
+ if ((par->display & 0x01)) {
+ /* LCD */
+ s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START0, (start & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START1, ((start >> 8) & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START2, ((start >> 16) & 0x0f));
+ } else {
+ /* CRT */
+ s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START0, (start & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START1, ((start >> 8) & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START2, ((start >> 16) & 0x0f));
+ }
+
+ return 0;
+}
+
+
+/* framebuffer information structures */
+
+static struct fb_ops s1d13xxxfb_fbops = {
+ .owner = THIS_MODULE,
+ .fb_set_par = s1d13xxxfb_set_par,
+ .fb_setcolreg = s1d13xxxfb_setcolreg,
+ .fb_blank = s1d13xxxfb_blank,
+
+ .fb_pan_display = s1d13xxxfb_pan_display,
+
+ /* to be replaced by any acceleration we can */
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor
+};
+
+static int s1d13xxxfb_width_tab[2][4] __devinitdata = {
+ {4, 8, 16, -1},
+ {9, 12, 18, -1},
+};
+
+/**
+ * s1d13xxxfb_fetch_hw_state - Configure the framebuffer according to
+ * hardware setup.
+ * @info: frame buffer structure
+ *
+ * We setup the framebuffer structures according to the current
+ * hardware setup. On some machines, the BIOS will have filled
+ * the chip registers with such info, on others, these values will
+ * have been written in some init procedure. In any case, the
+ * software values needs to match the hardware ones. This is what
+ * this function ensures.
+ *
+ * Note: some of the hardcoded values here might need some love to
+ * work on various chips, and might need to no longer be hardcoded.
+ */
+static void __devinit
+s1d13xxxfb_fetch_hw_state(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct s1d13xxxfb_par *par = info->par;
+ u8 panel, display;
+ u16 offset;
+ u32 xres, yres;
+ u32 xres_virtual, yres_virtual;
+ int bpp, lcd_bpp;
+ int is_color, is_dual, is_tft;
+ int lcd_enabled, crt_enabled;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+
+ /* general info */
+ par->display = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+ crt_enabled = (par->display & 0x02) != 0;
+ lcd_enabled = (par->display & 0x01) != 0;
+
+ if (lcd_enabled && crt_enabled)
+ printk(KERN_WARNING PFX "Warning: LCD and CRT detected, using LCD\n");
+
+ if (lcd_enabled)
+ display = s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_MODE);
+ else /* CRT */
+ display = s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_MODE);
+
+ bpp = display & 0x07;
+
+ switch (bpp) {
+ case 2: /* 4 bpp */
+ case 3: /* 8 bpp */
+ var->bits_per_pixel = 8;
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 5: /* 16 bpp */
+ s1d13xxxfb_setup_truecolour(info);
+ break;
+ default:
+ dbg("bpp: %i\n", bpp);
+ }
+ fb_alloc_cmap(&info->cmap, 256, 0);
+
+ /* LCD info */
+ panel = s1d13xxxfb_readreg(par, S1DREG_PANEL_TYPE);
+ is_color = (panel & 0x04) != 0;
+ is_dual = (panel & 0x02) != 0;
+ is_tft = (panel & 0x01) != 0;
+ lcd_bpp = s1d13xxxfb_width_tab[is_tft][(panel >> 4) & 3];
+
+ if (lcd_enabled) {
+ xres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_HWIDTH) + 1) * 8;
+ yres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT1) & 0x03) << 8) + 1);
+
+ offset = (s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF1) & 0x7) << 8));
+ } else { /* crt */
+ xres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_HWIDTH) + 1) * 8;
+ yres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT1) & 0x03) << 8) + 1);
+
+ offset = (s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF1) & 0x7) << 8));
+ }
+ xres_virtual = offset * 16 / var->bits_per_pixel;
+ yres_virtual = fix->smem_len / (offset * 2);
+
+ var->xres = xres;
+ var->yres = yres;
+ var->xres_virtual = xres_virtual;
+ var->yres_virtual = yres_virtual;
+ var->xoffset = var->yoffset = 0;
+
+ fix->line_length = offset * 2;
+
+ var->grayscale = !is_color;
+
+ var->activate = FB_ACTIVATE_NOW;
+
+ dbg(PFX "bpp=%d, lcd_bpp=%d, "
+ "crt_enabled=%d, lcd_enabled=%d\n",
+ var->bits_per_pixel, lcd_bpp, crt_enabled, lcd_enabled);
+ dbg(PFX "xres=%d, yres=%d, vxres=%d, vyres=%d "
+ "is_color=%d, is_dual=%d, is_tft=%d\n",
+ xres, yres, xres_virtual, yres_virtual, is_color, is_dual, is_tft);
+}
+
+
+static int __devexit
+s1d13xxxfb_remove(struct device *dev)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s1d13xxxfb_par *par = NULL;
+
+ if (info) {
+ par = info->par;
+ if (par && par->regs) {
+ /* disable output & enable powersave */
+ s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, 0x00);
+ s1d13xxxfb_writereg(par, S1DREG_PS_CNF, 0x11);
+ iounmap(par->regs);
+ }
+
+ fb_dealloc_cmap(&info->cmap);
+
+ if (info->screen_base)
+ iounmap(info->screen_base);
+
+ framebuffer_release(info);
+ }
+
+ release_mem_region(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start +1);
+ release_mem_region(pdev->resource[1].start,
+ pdev->resource[1].end - pdev->resource[1].start +1);
+ return 0;
+}
+
+static int __devinit
+s1d13xxxfb_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s1d13xxxfb_par *default_par;
+ struct fb_info *info;
+ struct s1d13xxxfb_pdata *pdata = NULL;
+ int ret = 0;
+ u8 revision;
+
+ dbg("probe called: device is %p\n", dev);
+
+ printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
+
+ /* enable platform-dependent hardware glue, if any */
+ if (dev->platform_data)
+ pdata = dev->platform_data;
+
+ if (pdata && pdata->platform_init_video)
+ pdata->platform_init_video();
+
+
+ if (pdev->num_resources != 2) {
+ dev_err(&pdev->dev, "invalid num_resources: %i\n",
+ pdev->num_resources);
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ /* resource[0] is VRAM, resource[1] is registers */
+ if (pdev->resource[0].flags != IORESOURCE_MEM
+ || pdev->resource[1].flags != IORESOURCE_MEM) {
+ dev_err(&pdev->dev, "invalid resource type\n");
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ if (!request_mem_region(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start +1, "s1d13xxxfb mem")) {
+ dev_dbg(dev, "request_mem_region failed\n");
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ if (!request_mem_region(pdev->resource[1].start,
+ pdev->resource[1].end - pdev->resource[1].start +1, "s1d13xxxfb regs")) {
+ dev_dbg(dev, "request_mem_region failed\n");
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ info = framebuffer_alloc(sizeof(struct s1d13xxxfb_par) + sizeof(u32) * 256, &pdev->dev);
+ if (!info) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ default_par = info->par;
+ default_par->regs = ioremap_nocache(pdev->resource[1].start,
+ pdev->resource[1].end - pdev->resource[1].start +1);
+ if (!default_par->regs) {
+ printk(KERN_ERR PFX "unable to map registers\n");
+ ret = -ENOMEM;
+ goto bail;
+ }
+ info->pseudo_palette = default_par->pseudo_palette;
+
+ info->screen_base = ioremap_nocache(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start +1);
+
+ if (!info->screen_base) {
+ printk(KERN_ERR PFX "unable to map framebuffer\n");
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE);
+ if ((revision >> 2) != S1D_CHIP_REV) {
+ printk(KERN_INFO PFX "chip not found: %i\n", (revision >> 2));
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ info->fix = s1d13xxxfb_fix;
+ info->fix.mmio_start = pdev->resource[1].start;
+ info->fix.mmio_len = pdev->resource[1].end - pdev->resource[1].start +1;
+ info->fix.smem_start = pdev->resource[0].start;
+ info->fix.smem_len = pdev->resource[0].end - pdev->resource[0].start +1;
+
+ printk(KERN_INFO PFX "regs mapped at 0x%p, fb %d KiB mapped at 0x%p\n",
+ default_par->regs, info->fix.smem_len / 1024, info->screen_base);
+
+ info->par = default_par;
+ info->fbops = &s1d13xxxfb_fbops;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+ /* perform "manual" chip initialization, if needed */
+ if (pdata && pdata->initregs)
+ s1d13xxxfb_runinit(info->par, pdata->initregs, pdata->initregssize);
+
+ s1d13xxxfb_fetch_hw_state(info);
+
+ if (register_framebuffer(info) < 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ dev_set_drvdata(&pdev->dev, info);
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ info->node, info->fix.id);
+
+ return 0;
+
+bail:
+ s1d13xxxfb_remove(dev);
+ return ret;
+
+}
+
+#ifdef CONFIG_PM
+static int s1d13xxxfb_suspend(struct device *dev, u32 state, u32 level)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ struct s1d13xxxfb_pdata *pdata = NULL;
+
+ /* disable display */
+ lcd_enable(s1dfb, 0);
+ crt_enable(s1dfb, 0);
+
+ if (dev->platform_data)
+ pdata = dev->platform_data;
+
+#if 0
+ if (!s1dfb->disp_save)
+ s1dfb->disp_save = kmalloc(info->fix.smem_len, GFP_KERNEL);
+
+ if (!s1dfb->disp_save) {
+ printk(KERN_ERR PFX "no memory to save screen");
+ return -ENOMEM;
+ }
+
+ memcpy_fromio(s1dfb->disp_save, info->screen_base, info->fix.smem_len);
+#else
+ s1dfb->disp_save = NULL;
+#endif
+
+ if (!s1dfb->regs_save)
+ s1dfb->regs_save = kmalloc(info->fix.mmio_len, GFP_KERNEL);
+
+ if (!s1dfb->regs_save) {
+ printk(KERN_ERR PFX "no memory to save registers");
+ return -ENOMEM;
+ }
+
+ /* backup all registers */
+ memcpy_fromio(s1dfb->regs_save, s1dfb->regs, info->fix.mmio_len);
+
+ /* now activate power save mode */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x11);
+
+ if (pdata && pdata->platform_suspend_video)
+ return pdata->platform_suspend_video();
+ else
+ return 0;
+}
+
+static int s1d13xxxfb_resume(struct device *dev, u32 level)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ struct s1d13xxxfb_pdata *pdata = NULL;
+
+ if (level != RESUME_ENABLE)
+ return 0;
+
+ /* awaken the chip */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10);
+
+ /* do not let go until SDRAM "wakes up" */
+ while ((s1d13xxxfb_readreg(s1dfb, S1DREG_PS_STATUS) & 0x01))
+ udelay(10);
+
+ if (dev->platform_data)
+ pdata = dev->platform_data;
+
+ if (s1dfb->regs_save) {
+ /* will write RO regs, *should* get away with it :) */
+ memcpy_toio(s1dfb->regs, s1dfb->regs_save, info->fix.mmio_len);
+ kfree(s1dfb->regs_save);
+ }
+
+ if (s1dfb->disp_save) {
+ memcpy_toio(info->screen_base, s1dfb->disp_save,
+ info->fix.smem_len);
+ kfree(s1dfb->disp_save); /* XXX kmalloc()'d when? */
+ }
+
+ if ((s1dfb->display & 0x01) != 0)
+ lcd_enable(s1dfb, 1);
+ if ((s1dfb->display & 0x02) != 0)
+ crt_enable(s1dfb, 1);
+
+ if (pdata && pdata->platform_resume_video)
+ return pdata->platform_resume_video();
+ else
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct device_driver s1d13xxxfb_driver = {
+ .name = S1D_DEVICENAME,
+ .bus = &platform_bus_type,
+ .probe = s1d13xxxfb_probe,
+ .remove = s1d13xxxfb_remove,
+#ifdef CONFIG_PM
+ .suspend = s1d13xxxfb_suspend,
+ .resume = s1d13xxxfb_resume
+#endif
+};
+
+
+static int __init
+s1d13xxxfb_init(void)
+{
+ if (fb_get_options("s1d13xxxfb", NULL))
+ return -ENODEV;
+
+ return driver_register(&s1d13xxxfb_driver);
+}
+
+
+static void __exit
+s1d13xxxfb_exit(void)
+{
+ driver_unregister(&s1d13xxxfb_driver);
+}
+
+module_init(s1d13xxxfb_init);
+module_exit(s1d13xxxfb_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Framebuffer driver for S1D13xxx devices");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, Thibaut VARENE <varenet@parisc-linux.org>");
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 33bedf94247ec..4f8043a71f21d 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1507,8 +1507,7 @@ static int __init sa1100fb_probe(struct device *dev)
failed:
dev_set_drvdata(dev, NULL);
- if (fbi)
- kfree(fbi);
+ kfree(fbi);
release_mem_region(0xb0100000, 0x10000);
return ret;
}
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 301cef041a4e0..e1c9c946be2dc 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1883,8 +1883,7 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
info->fbops = &savagefb_ops;
info->flags = FBINFO_DEFAULT |
FBINFO_HWACCEL_YPAN |
- FBINFO_HWACCEL_XPAN |
- FBINFO_MISC_MODESWITCHLATE;
+ FBINFO_HWACCEL_XPAN;
info->pseudo_palette = par->pseudo_palette;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 96a0d60e12ab8..b773c98f6513d 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -5640,7 +5640,7 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
/* Unmap */
iounmap(ivideo->video_vbase);
iounmap(ivideo->mmio_vbase);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+ vfree(ivideo->bios_abase);
/* Release mem regions */
release_mem_region(ivideo->video_base, ivideo->video_size);
@@ -5695,7 +5695,7 @@ SISINITSTATIC int __init sisfb_init(void)
sisfb_setup(options);
#endif
#endif
- return(pci_module_init(&sisfb_driver));
+ return(pci_register_driver(&sisfb_driver));
}
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index aa45515223587..663d53657fa4c 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -1575,7 +1575,7 @@ static int __devinit sstfb_init(void)
return -ENODEV;
sstfb_setup(option);
#endif
- return pci_module_init(&sstfb_driver);
+ return pci_register_driver(&sstfb_driver);
}
#ifdef MODULE
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index ded8cc87dfc43..c34ba39b6f7e7 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -1350,7 +1350,7 @@ static int __init tdfxfb_init(void)
tdfxfb_setup(option);
#endif
- return pci_module_init(&tdfxfb_driver);
+ return pci_register_driver(&tdfxfb_driver);
}
static void __exit tdfxfb_exit(void)
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 075c66de9af0e..3099630d0c3d0 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -1540,7 +1540,7 @@ tgafb_init(void)
return -ENODEV;
tgafb_setup(option);
#endif
- return pci_module_init(&tgafb_driver);
+ return pci_register_driver(&tgafb_driver);
}
/*
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 2ad715a6cb2ca..da8004e5d03de 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1163,7 +1163,7 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
fb_info.var = default_var;
fb_info.device = &dev->dev;
if (register_framebuffer(&fb_info) < 0) {
- output("Could not register Trident framebuffer\n");
+ printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n");
return -EINVAL;
}
output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
@@ -1264,7 +1264,7 @@ static int __init tridentfb_init(void)
tridentfb_setup(option);
#endif
output("Trident framebuffer %s initializing\n", VERSION);
- return pci_module_init(&tridentfb_pci_driver);
+ return pci_register_driver(&tridentfb_pci_driver);
}
static void __exit tridentfb_exit(void)
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 4e508df8212eb..b46454c55c91b 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -874,7 +874,7 @@ static int vga16fb_blank(int blank, struct fb_info *info)
return 0;
}
-void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
u32 dx = rect->dx, width = rect->width;
char oldindex = getindex();
@@ -928,7 +928,7 @@ void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
setindex(oldindex);
}
-void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
int x, x2, y2, vxres, vyres, width, height, line_ofs;
char __iomem *dst;
@@ -1003,7 +1003,7 @@ void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
}
}
-void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
char oldindex = getindex();
char oldmode = setmode(0x41);
@@ -1058,7 +1058,7 @@ void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
setindex(oldindex);
}
-void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
int x, x2, y2, old_dx, old_dy, vxres, vyres;
@@ -1166,7 +1166,7 @@ static unsigned int transl_l[] =
#endif
#endif
-void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
+static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
{
char oldindex = getindex();
char oldmode = setmode(0x40);
@@ -1197,7 +1197,7 @@ void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
setindex(oldindex);
}
-void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
+static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
{
char __iomem *where = info->screen_base + (image->dx/8) +
image->dy * info->fix.line_length;
@@ -1261,7 +1261,7 @@ void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
}
}
-void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
+static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
{
/*
* Draw logo
@@ -1306,7 +1306,7 @@ void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
}
}
-void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
if (image->depth == 1)
vga_imageblit_expand(info, image);
@@ -1329,7 +1329,8 @@ static struct fb_ops vga16fb_ops = {
.fb_cursor = soft_cursor,
};
-int vga16fb_setup(char *options)
+#ifndef MODULE
+static int vga16fb_setup(char *options)
{
char *this_opt;
@@ -1341,8 +1342,9 @@ int vga16fb_setup(char *options)
}
return 0;
}
+#endif
-int __init vga16fb_init(void)
+static int __init vga16fb_init(void)
{
int i;
int ret;
@@ -1427,9 +1429,7 @@ static void __exit vga16fb_exit(void)
/* XXX unshare VGA regions */
}
-#ifdef MODULE
MODULE_LICENSE("GPL");
-#endif
module_init(vga16fb_init);
module_exit(vga16fb_exit);
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 8c4de81629720..057e154c8858d 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -537,10 +537,8 @@ static void w100fb_clear_buffer(void)
{
int i;
for (i = 0; i < W100_BUF_NUM; i++) {
- if (gSaveImagePtr[i] != NULL) {
- kfree(gSaveImagePtr[i]);
- gSaveImagePtr[i] = NULL;
- }
+ kfree(gSaveImagePtr[i]);
+ gSaveImagePtr[i] = NULL;
}
}
diff --git a/fs/buffer.c b/fs/buffer.c
index f847c686dcaa4..f961605a904b1 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -878,7 +878,7 @@ int __set_page_dirty_buffers(struct page *page)
if (!TestSetPageDirty(page)) {
write_lock_irq(&mapping->tree_lock);
if (page->mapping) { /* Race with truncate? */
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
inc_page_state(nr_dirty);
radix_tree_tag_set(&mapping->page_tree,
page_index(page),
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index e7c34afa998a0..5316c8dd6bfff 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,9 +1,25 @@
+Version 1.31
+------------
+Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one
+transact response for an SMB request and search entry split across two frames.
+Fix updates of DOS attributes and time fields so that files on NT4 servers
+do not get marked delete on close. Display sizes of cifs buffer pools in
+cifs stats. Fix oops in unmount when cifsd thread being killed by
+shutdown. Add generic readv/writev and aio support. Report inode numbers
+consistently in readdir and lookup (when serverino mount option is
+specified use the inode number that the server reports - for both lookup
+and readdir, otherwise by default the locally generated inode number is used
+for inodes created in either path since servers are not always able to
+provide unique inode numbers when exporting multiple volumes from under one
+sharename).
+
Version 1.30
------------
Allow new nouser_xattr mount parm to disable xattr support for user namespace.
Do not flag user_xattr mount parm in dmesg. Retry failures setting file time
(mostly affects NT4 servers) by retry with handle based network operation.
Add new POSIX Query FS Info for returning statfs info more accurately.
+Handle passwords with multiple commas in them.
Version 1.29
------------
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index fcb9f5cccf6f3..db28b561cd4b5 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -199,13 +199,13 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
length += item_length;
buf += item_length;
item_length =
- sprintf(buf,"SMB Request/Response Buffer: %d\n",
- bufAllocCount.counter);
+ sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
+ bufAllocCount.counter,cifs_min_rcv + tcpSesAllocCount.counter);
length += item_length;
buf += item_length;
item_length =
- sprintf(buf,"SMB Small Req/Resp Buffer: %d\n",
- smBufAllocCount.counter);
+ sprintf(buf,"SMB Small Req/Resp Buffer: %d Pool size: %d\n",
+ smBufAllocCount.counter,cifs_min_small);
length += item_length;
buf += item_length;
item_length =
diff --git a/fs/cifs/cifsencrypt.h b/fs/cifs/cifsencrypt.h
index f0b8e787bd5c2..03e359b328611 100644
--- a/fs/cifs/cifsencrypt.h
+++ b/fs/cifs/cifsencrypt.h
@@ -28,7 +28,7 @@ extern void mdfour(unsigned char *out, unsigned char *in, int n);
extern void E_P16(unsigned char *p14, unsigned char *p16);
extern void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
extern void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
-extern void E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out);
+extern void E_old_pw_hash(unsigned char *, unsigned char *, unsigned char *);
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 44cc45607678a..5082fce3c566d 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -57,6 +57,7 @@ unsigned int multiuser_mount = 0;
unsigned int extended_security = 0;
unsigned int ntlmv2_support = 0;
unsigned int sign_CIFS_PDUs = 1;
+extern struct task_struct * oplockThread; /* remove sparse warning */
struct task_struct * oplockThread = NULL;
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
module_param(CIFSMaxBufSize, int, 0);
@@ -73,6 +74,12 @@ MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50
static DECLARE_COMPLETION(cifs_oplock_exited);
+extern mempool_t *cifs_sm_req_poolp;
+extern mempool_t *cifs_req_poolp;
+extern mempool_t *cifs_mid_poolp;
+
+extern kmem_cache_t *cifs_oplock_cachep;
+
static int
cifs_read_super(struct super_block *sb, void *data,
const char *devname, int silent)
@@ -229,9 +236,7 @@ static struct inode *
cifs_alloc_inode(struct super_block *sb)
{
struct cifsInodeInfo *cifs_inode;
- cifs_inode =
- (struct cifsInodeInfo *) kmem_cache_alloc(cifs_inode_cachep,
- SLAB_KERNEL);
+ cifs_inode = kmem_cache_alloc(cifs_inode_cachep, SLAB_KERNEL);
if (!cifs_inode)
return NULL;
cifs_inode->cifsAttrs = 0x20; /* default */
@@ -438,28 +443,13 @@ static ssize_t
cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size,
loff_t * poffset)
{
- if(file == NULL)
- return -EIO;
- else if(file->f_dentry == NULL)
+ if(file->f_dentry == NULL)
return -EIO;
else if(file->f_dentry->d_inode == NULL)
return -EIO;
cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
-#ifdef CONFIG_CIFS_EXPERIMENTAL
- /* check whether we can cache writes locally */
- if(file->f_dentry->d_sb) {
- struct cifs_sb_info *cifs_sb;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- if(cifs_sb != NULL) {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
- return cifs_user_read(file,read_data,
- read_size,poffset);
- }
- }
-#endif /* CIFS_EXPERIMENTAL */
-
if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
return generic_file_read(file,read_data,read_size,poffset);
} else {
@@ -483,28 +473,13 @@ cifs_write_wrapper(struct file * file, const char __user *write_data,
{
ssize_t written;
- if(file == NULL)
- return -EIO;
- else if(file->f_dentry == NULL)
+ if(file->f_dentry == NULL)
return -EIO;
else if(file->f_dentry->d_inode == NULL)
return -EIO;
cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
-#ifdef CONFIG_CIFS_EXPERIMENTAL /* BB fixme - fix user char * to kernel char * mapping here BB */
- /* check whether we can cache writes locally */
- if(file->f_dentry->d_sb) {
- struct cifs_sb_info *cifs_sb;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- if(cifs_sb != NULL) {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
- return cifs_user_write(file,write_data,
- write_size,poffset);
- }
- }
- }
-#endif /* CIFS_EXPERIMENTAL */
written = generic_file_write(file,write_data,write_size,poffset);
if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
if(file->f_dentry->d_inode->i_mapping) {
@@ -585,6 +560,26 @@ struct file_operations cifs_file_ops = {
.mmap = cifs_file_mmap,
.sendfile = generic_file_sendfile,
#ifdef CONFIG_CIFS_EXPERIMENTAL
+ .readv = generic_file_readv,
+ .writev = generic_file_writev,
+ .aio_read = generic_file_aio_read,
+ .aio_write = generic_file_aio_write,
+ .dir_notify = cifs_dir_notify,
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+};
+
+struct file_operations cifs_file_direct_ops = {
+ /* no mmap, no aio, no readv -
+ BB reevaluate whether they can be done with directio, no cache */
+ .read = cifs_user_read,
+ .write = cifs_user_write,
+ .open = cifs_open,
+ .release = cifs_close,
+ .lock = cifs_lock,
+ .fsync = cifs_fsync,
+ .flush = cifs_flush,
+ .sendfile = generic_file_sendfile, /* BB removeme BB */
+#ifdef CONFIG_CIFS_EXPERIMENTAL
.dir_notify = cifs_dir_notify,
#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
@@ -601,7 +596,7 @@ struct file_operations cifs_dir_ops = {
static void
cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
{
- struct cifsInodeInfo *cifsi = (struct cifsInodeInfo *) inode;
+ struct cifsInodeInfo *cifsi = inode;
if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR) {
@@ -654,7 +649,7 @@ cifs_init_request_bufs(void)
cifs_min_rcv = 1;
else if (cifs_min_rcv > 64) {
cifs_min_rcv = 64;
- cFYI(1,("cifs_min_rcv set to maximum (64)"));
+ cERROR(1,("cifs_min_rcv set to maximum (64)"));
}
cifs_req_poolp = mempool_create(cifs_min_rcv,
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 00943b866b0b6..451f18af32069 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -42,8 +42,10 @@ extern void cifs_delete_inode(struct inode *);
/* Functions related to inodes */
extern struct inode_operations cifs_dir_inode_ops;
-extern int cifs_create(struct inode *, struct dentry *, int, struct nameidata *);
-extern struct dentry *cifs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern int cifs_create(struct inode *, struct dentry *, int,
+ struct nameidata *);
+extern struct dentry * cifs_lookup(struct inode *, struct dentry *,
+ struct nameidata *);
extern int cifs_unlink(struct inode *, struct dentry *);
extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
extern int cifs_mknod(struct inode *, struct dentry *, int, dev_t);
@@ -60,6 +62,7 @@ extern struct inode_operations cifs_symlink_inode_ops;
/* Functions related to files and directories */
extern struct file_operations cifs_file_ops;
+extern struct file_operations cifs_file_direct_ops; /* if directio mount */
extern int cifs_open(struct inode *inode, struct file *file);
extern int cifs_close(struct inode *inode, struct file *file);
extern int cifs_closedir(struct inode *inode, struct file *file);
@@ -82,7 +85,8 @@ extern struct dentry_operations cifs_dentry_ops;
/* Functions related to symlinks */
extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd);
-extern int cifs_readlink(struct dentry *direntry, char __user *buffer, int buflen);
+extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
+ int buflen);
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
const char *symname);
extern int cifs_removexattr(struct dentry *, const char *);
@@ -90,5 +94,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
-#define CIFS_VERSION "1.30"
+#define CIFS_VERSION "1.31"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 87e8b3d760bd1..69aff1a7da9b3 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -176,6 +176,7 @@ struct cifsSesInfo {
enum statusEnum status;
__u32 sequence_number; /* needed for CIFS PDU signature */
__u16 ipc_tid; /* special tid for connection to IPC share */
+ __u16 flags;
char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
char *serverOS; /* name of operating system underlying the server */
char *serverNOS; /* name of network operating system that the server is running */
@@ -188,6 +189,8 @@ struct cifsSesInfo {
char domainName[MAX_USERNAME_SIZE + 1];
char * password;
};
+/* session flags */
+#define CIFS_SES_NT4 1
/*
* there is one of these for each connection to a resource on a particular
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index c5b7a560902e9..bcd4a6136f08a 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -36,6 +36,7 @@
#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */
#define SMB_COM_DELETE 0x06 /* trivial response */
#define SMB_COM_RENAME 0x07 /* trivial response */
+#define SMB_COM_SETATTR 0x09 /* trivial response */
#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */
#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/
#define SMB_COM_READ_ANDX 0x2E
@@ -865,6 +866,24 @@ typedef struct smb_com_create_directory_rsp {
__u16 ByteCount; /* bct = 0 */
} CREATE_DIRECTORY_RSP;
+typedef struct smb_com_setattr_req {
+ struct smb_hdr hdr; /* wct = 8 */
+ __le16 attr;
+ __le16 time_low;
+ __le16 time_high;
+ __le16 reserved[5]; /* must be zero */
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char fileName[1];
+} SETATTR_REQ;
+
+typedef struct smb_com_setattr_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} SETATTR_RSP;
+
+/* empty wct response to setattr */
+
/***************************************************/
/* NT Transact structure defintions follow */
/* Currently only ioctl and notify are implemented */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 42ec2ca6d5669..787eef4d86d37 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -137,10 +137,11 @@ extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage);
extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
const FILE_BASIC_INFO * data, __u16 fid);
-extern int CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon,
- char *fileName, FILE_BASIC_INFO * data,
+#if 0
+extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon,
+ char *fileName, __u16 dos_attributes,
const struct nls_table *nls_codepage);
-
+#endif /* possibly unneeded function */
extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
const char *fileName, __u64 size,int setAllocationSizeFlag,
const struct nls_table *nls_codepage);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index ef4d3267db456..df6a619a68213 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2613,23 +2613,86 @@ CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
int rc = 0;
TRANSACTION2_QPI_REQ *pSMB = NULL;
TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int name_len, bytes_returned;
+ __u16 params, byte_count;
- cFYI(1,("In GetSrvInodeNumber for %s",searchName));
+ cFYI(1,("In GetSrvInodeNum for %s",searchName));
if(tcon == NULL)
return -ENODEV;
- cFYI(1, ("In QPathInfo path %s", searchName));
GetInodeNumberRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
-/* BB add missing code here */
- if (pSMB)
- cifs_buf_release(pSMB);
-
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName,
+ PATH_MAX,nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, PATH_MAX);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max data count below from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
+ 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, ("error %d in QueryInternalInfo", rc));
+ } else {
+ /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ if (rc || (pSMBr->ByteCount < 2))
+ /* BB also check enough total bytes returned */
+ /* If rc should we check for EOPNOSUPP and
+ disable the srvino flag? or in caller? */
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+ struct file_internal_info * pfinfo;
+ /* BB Do we need a cast or hash here ? */
+ if(count < 8) {
+ cFYI(1, ("Illegal size ret in QryIntrnlInf"));
+ rc = -EIO;
+ goto GetInodeNumOut;
+ }
+ pfinfo = (struct file_internal_info *)
+ (data_offset + (char *) &pSMBr->hdr.Protocol);
+ *inode_number = pfinfo->UniqueId;
+ }
+ }
+GetInodeNumOut:
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto GetInodeNumberRetry;
return rc;
@@ -3526,85 +3589,58 @@ SetTimesRetry:
return rc;
}
+/* Can not be used to set time stamps yet (due to old DOS time format) */
+/* Can be used to set attributes */
+#if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
+ handling it anyway and NT4 was what we thought it would be needed for
+ Do not delete it until we prove whether needed for Win9x though */
int
-CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
- FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
+CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
+ __u16 dos_attrs, const struct nls_table *nls_codepage)
{
- TRANSACTION2_SPI_REQ *pSMB = NULL;
- TRANSACTION2_SPI_RSP *pSMBr = NULL;
- FILE_INFO_STANDARD *pfinfo;
- int name_len;
+ SETATTR_REQ *pSMB = NULL;
+ SETATTR_RSP *pSMBr = NULL;
int rc = 0;
- int bytes_returned = 0;
- char *data_offset;
- __u16 params, param_offset, count, offset, byte_count;
+ int bytes_returned;
+ int name_len;
- cFYI(1, ("In SetTimesLegacy"));
+ cFYI(1, ("In SetAttrLegacy"));
-SetTimesRetryLegacy:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+SetAttrLgcyRetry:
+ rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
- /* find define for this maxpathcomponent */
- , nls_codepage);
- name_len++; /* trailing null */
+ cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName,
+ PATH_MAX, nls_codepage);
+ name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
+ } else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(fileName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, fileName, name_len);
+ name_len++; /* trailing null */
+ strncpy(pSMB->fileName, fileName, name_len);
}
-/* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
- in parent function, from the better and ususal FILE_BASIC_INFO */
- params = 6 + name_len;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
- data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
- pfinfo = (FILE_INFO_STANDARD *)data_offset;
- /* BB add conversion for FILE_BASIC_INFO data struct to
- FILE_INFO_STANDARD finfo struct */
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- count = sizeof(FILE_INFO_STANDARD);
- 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->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
- pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += byte_count;
- pSMB->ByteCount = cpu_to_le16(byte_count);
+ pSMB->attr = cpu_to_le16(dos_attrs);
+ pSMB->BufferFormat = 0x04;
+ pSMB->hdr.smb_buf_length += name_len + 1;
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("SetPathInfo (times legacy) returned %d", rc));
+ cFYI(1, ("Error in LegacySetAttr = %d", rc));
}
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
- goto SetTimesRetryLegacy;
+ goto SetAttrLgcyRetry;
return rc;
}
+#endif /* temporarily unneeded SetAttr legacy function */
int
CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 155b08f8a37b4..40470b9d5477a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -543,9 +543,18 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
return 1;
}
} else if (strnicmp(data, "pass", 4) == 0) {
- if (!value || !*value) {
+ if (!value) {
vol->password = NULL;
continue;
+ } else if(value[0] == 0) {
+ /* check if string begins with double comma
+ since that would mean the password really
+ does start with a comma, and would not
+ indicate an empty string */
+ if(value[1] != separator[0]) {
+ vol->password = NULL;
+ continue;
+ }
}
temp_len = strlen(value);
/* removed password length check, NTLM passwords
@@ -560,15 +569,20 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
/* NB: password legally can have multiple commas and
the only illegal character in a password is null */
-
+
if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
/* reinsert comma */
value[temp_len] = separator[0];
temp_len+=2; /* move after the second comma */
while(value[temp_len] != 0) {
- if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
- /* single comma indicating start of next parm */
- break;
+ if (value[temp_len] == separator[0]) {
+ if (value[temp_len+1] == separator[0]) {
+ temp_len++; /* skip second comma */
+ } else {
+ /* single comma indicating start
+ of next parm */
+ break;
+ }
}
temp_len++;
}
@@ -576,10 +590,12 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
options = NULL;
} else {
value[temp_len] = 0;
- /* move options to point to start of next parm */
+ /* point option to start of next parm */
options = value + temp_len + 1;
}
- /* go from value to (value + temp_len) condensing double commas to singles */
+ /* go from value to value + temp_len condensing
+ double commas to singles. Note that this ends up
+ allocating a few bytes too many, which is ok */
vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
for(i=0,j=0;i<temp_len;i++,j++) {
vol->password[j] = value[i];
@@ -588,8 +604,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
i++;
}
}
- /* value[temp_len] is zeroed above so
- vol->password[temp_len] guaranteed to be null */
+ vol->password[j] = 0;
} else {
vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
strcpy(vol->password, value);
@@ -1182,6 +1197,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
if (volume_info.username) {
+ /* BB fixme parse for domain name here */
cFYI(1, ("Username: %s ", volume_info.username));
} else {
@@ -1564,7 +1580,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
- capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
+ capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+ CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
if (ses->capabilities & CAP_UNICODE) {
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
capabilities |= CAP_UNICODE;
@@ -1591,7 +1608,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr += CIFS_SESSION_KEY_SIZE;
if (ses->capabilities & CAP_UNICODE) {
- if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
+ if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
*bcc_ptr = 0;
bcc_ptr++;
}
@@ -1601,7 +1618,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bytes_returned =
cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
nls_codepage);
- bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
+ /* convert number of 16 bit words to bytes */
+ bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2; /* trailing null */
if (domain == NULL)
bytes_returned =
@@ -1618,8 +1636,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
- nls_codepage);
+ cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
+ 32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2;
bytes_returned =
@@ -1705,6 +1723,11 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr += 2 * (len + 1);
ses->serverNOS[2 * len] = 0;
ses->serverNOS[1 + (2 * len)] = 0;
+ if(strncmp(ses->serverNOS,
+ "NT LAN Manager 4",16) == 0) {
+ cFYI(1,("NT4 server"));
+ ses->flags |= CIFS_SES_NT4;
+ }
remaining_words -= len + 1;
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
@@ -2909,7 +2932,8 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
return 0;
} else if (rc == -ESHUTDOWN) {
cFYI(1,("Waking up socket by sending it signal"));
- send_sig(SIGKILL,cifsd_task,1);
+ if(cifsd_task)
+ send_sig(SIGKILL,cifsd_task,1);
rc = 0;
} /* else - we have an smb session
left on this socket do not kill cifsd */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index a7a4656392b20..dcab7cf1b53bf 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -35,8 +35,117 @@
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
-int
-cifs_open(struct inode *inode, struct file *file)
+static inline struct cifsFileInfo *cifs_init_private(
+ struct cifsFileInfo *private_data, struct inode *inode,
+ struct file *file, __u16 netfid)
+{
+ memset(private_data, 0, sizeof(struct cifsFileInfo));
+ private_data->netfid = netfid;
+ private_data->pid = current->tgid;
+ init_MUTEX(&private_data->fh_sem);
+ private_data->pfile = file; /* needed for writepage */
+ private_data->pInode = inode;
+ private_data->invalidHandle = FALSE;
+ private_data->closePend = FALSE;
+
+ return private_data;
+}
+
+static inline int cifs_convert_flags(unsigned int flags)
+{
+ if ((flags & O_ACCMODE) == O_RDONLY)
+ return GENERIC_READ;
+ else if ((flags & O_ACCMODE) == O_WRONLY)
+ return GENERIC_WRITE;
+ else if ((flags & O_ACCMODE) == O_RDWR) {
+ /* GENERIC_ALL is too much permission to request
+ can cause unnecessary access denied on create */
+ /* return GENERIC_ALL; */
+ return (GENERIC_READ | GENERIC_WRITE);
+ }
+
+ return 0x20197;
+}
+
+static inline int cifs_get_disposition(unsigned int flags)
+{
+ if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ return FILE_CREATE;
+ else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+ return FILE_OVERWRITE_IF;
+ else if ((flags & O_CREAT) == O_CREAT)
+ return FILE_OPEN_IF;
+ else
+ return FILE_OPEN;
+}
+
+/* all arguments to this function must be checked for validity in caller */
+static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
+ struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
+ struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
+ char *full_path, int xid)
+{
+ struct timespec temp;
+ int rc;
+
+ /* want handles we can use to read with first
+ in the list so we do not have to walk the
+ list to search for one in prepare_write */
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+ list_add_tail(&pCifsFile->flist,
+ &pCifsInode->openFileList);
+ } else {
+ list_add(&pCifsFile->flist,
+ &pCifsInode->openFileList);
+ }
+ write_unlock(&GlobalSMBSeslock);
+ write_unlock(&file->f_owner.lock);
+ if (pCifsInode->clientCanCacheRead) {
+ /* we have the inode open somewhere else
+ no need to discard cache data */
+ goto client_can_cache;
+ }
+
+ /* BB need same check in cifs_create too? */
+ /* if not oplocked, invalidate inode pages if mtime or file
+ size changed */
+ temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
+ if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) &&
+ (file->f_dentry->d_inode->i_size ==
+ (loff_t)le64_to_cpu(buf->EndOfFile))) {
+ cFYI(1, ("inode unchanged on server"));
+ } else {
+ if (file->f_dentry->d_inode->i_mapping) {
+ /* BB no need to lock inode until after invalidate
+ since namei code should already have it locked? */
+ filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
+ filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
+ }
+ cFYI(1, ("invalidating remote inode since open detected it "
+ "changed"));
+ invalidate_remote_inode(file->f_dentry->d_inode);
+ }
+
+client_can_cache:
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
+ full_path, inode->i_sb, xid);
+ else
+ rc = cifs_get_inode_info(&file->f_dentry->d_inode,
+ full_path, buf, inode->i_sb, xid);
+
+ if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ pCifsInode->clientCanCacheAll = TRUE;
+ pCifsInode->clientCanCacheRead = TRUE;
+ cFYI(1, ("Exclusive Oplock granted on inode %p",
+ file->f_dentry->d_inode));
+ } else if ((*oplock & 0xF) == OPLOCK_READ)
+ pCifsInode->clientCanCacheRead = TRUE;
+
+ return rc;
+}
+
+int cifs_open(struct inode *inode, struct file *file)
{
int rc = -EACCES;
int xid, oplock;
@@ -44,12 +153,12 @@ cifs_open(struct inode *inode, struct file *file)
struct cifsTconInfo *pTcon;
struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode;
- struct list_head * tmp;
+ struct list_head *tmp;
char *full_path = NULL;
- int desiredAccess = 0x20197;
+ int desiredAccess;
int disposition;
__u16 netfid;
- FILE_ALL_INFO * buf = NULL;
+ FILE_ALL_INFO *buf = NULL;
xid = GetXid();
@@ -57,48 +166,46 @@ cifs_open(struct inode *inode, struct file *file)
pTcon = cifs_sb->tcon;
if (file->f_flags & O_CREAT) {
- /* search inode for this file and fill in file->private_data = */
+ /* search inode for this file and fill in file->private_data */
pCifsInode = CIFS_I(file->f_dentry->d_inode);
read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &pCifsInode->openFileList) {
- pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);
- if((pCifsFile->pfile == NULL)&& (pCifsFile->pid == current->tgid)){
- /* mode set in cifs_create */
- pCifsFile->pfile = file; /* needed for writepage */
+ list_for_each(tmp, &pCifsInode->openFileList) {
+ pCifsFile = list_entry(tmp, struct cifsFileInfo,
+ flist);
+ if ((pCifsFile->pfile == NULL) &&
+ (pCifsFile->pid == current->tgid)) {
+ /* mode set in cifs_create */
+
+ /* needed for writepage */
+ pCifsFile->pfile = file;
+
file->private_data = pCifsFile;
break;
}
}
read_unlock(&GlobalSMBSeslock);
- if(file->private_data != NULL) {
+ if (file->private_data != NULL) {
rc = 0;
FreeXid(xid);
return rc;
} else {
- if(file->f_flags & O_EXCL)
- cERROR(1,("could not find file instance for new file %p ",file));
+ if (file->f_flags & O_EXCL)
+ cERROR(1, ("could not find file instance for "
+ "new file %p ", file));
}
}
down(&inode->i_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(file->f_dentry);
up(&inode->i_sb->s_vfs_rename_sem);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
- cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
- if ((file->f_flags & O_ACCMODE) == O_RDONLY)
- desiredAccess = GENERIC_READ;
- else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
- desiredAccess = GENERIC_WRITE;
- else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
- /* GENERIC_ALL is too much permission to request */
- /* can cause unnecessary access denied on create */
- /* desiredAccess = GENERIC_ALL; */
- desiredAccess = GENERIC_READ | GENERIC_WRITE;
- }
+ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
+ inode, file->f_flags, full_path));
+ desiredAccess = cifs_convert_flags(file->f_flags);
/*********************************************************************
* open flag mapping table:
@@ -124,14 +231,7 @@ cifs_open(struct inode *inode, struct file *file)
* O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
*********************************************************************/
- if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
- disposition = FILE_CREATE;
- else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
- disposition = FILE_OVERWRITE_IF;
- else if((file->f_flags & O_CREAT) == O_CREAT)
- disposition = FILE_OPEN_IF;
- else
- disposition = FILE_OPEN;
+ disposition = cifs_get_disposition(file->f_flags);
if (oplockEnabled)
oplock = REQ_OPLOCK;
@@ -140,125 +240,73 @@ cifs_open(struct inode *inode, struct file *file)
/* BB pass O_SYNC flag through on file attributes .. BB */
- /* Also refresh inode by passing in file_info buf returned by SMBOpen
- and calling get_inode_info with returned buf (at least
- helps non-Unix server case */
+ /* Also refresh inode by passing in file_info buf returned by SMBOpen
+ and calling get_inode_info with returned buf (at least helps
+ non-Unix server case) */
/* BB we can not do this if this is the second open of a file
- and the first handle has writebehind data, we might be
- able to simply do a filemap_fdatawrite/filemap_fdatawait first */
- buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
- if(buf== NULL) {
- if (full_path)
- kfree(full_path);
- FreeXid(xid);
- return -ENOMEM;
+ and the first handle has writebehind data, we might be
+ able to simply do a filemap_fdatawrite/filemap_fdatawait first */
+ buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+ if (!buf) {
+ rc = -ENOMEM;
+ goto out;
}
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
- CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
+ CREATE_NOT_DIR, &netfid, &oplock, buf,
+ cifs_sb->local_nls);
if (rc) {
cFYI(1, ("cifs_open returned 0x%x ", rc));
- cFYI(1, ("oplock: %d ", oplock));
+ goto out;
+ }
+ file->private_data =
+ kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+ if (file->private_data == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
+ write_lock(&file->f_owner.lock);
+ write_lock(&GlobalSMBSeslock);
+ list_add(&pCifsFile->tlist, &pTcon->openFileList);
+
+ pCifsInode = CIFS_I(file->f_dentry->d_inode);
+ if (pCifsInode) {
+ rc = cifs_open_inode_helper(inode, file, pCifsInode,
+ pCifsFile, pTcon,
+ &oplock, buf, full_path, xid);
} else {
- file->private_data =
- kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
- if (file->private_data) {
- memset(file->private_data, 0, sizeof(struct cifsFileInfo));
- pCifsFile = (struct cifsFileInfo *) file->private_data;
- pCifsFile->netfid = netfid;
- pCifsFile->pid = current->tgid;
- init_MUTEX(&pCifsFile->fh_sem);
- pCifsFile->pfile = file; /* needed for writepage */
- pCifsFile->pInode = inode;
- pCifsFile->invalidHandle = FALSE;
- pCifsFile->closePend = FALSE;
- write_lock(&file->f_owner.lock);
- write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist,&pTcon->openFileList);
- pCifsInode = CIFS_I(file->f_dentry->d_inode);
- if(pCifsInode) {
- /* want handles we can use to read with first */
- /* in the list so we do not have to walk the */
- /* list to search for one in prepare_write */
- if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
- list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList);
- } else {
- list_add(&pCifsFile->flist,&pCifsInode->openFileList);
- }
- write_unlock(&GlobalSMBSeslock);
- write_unlock(&file->f_owner.lock);
- if(pCifsInode->clientCanCacheRead) {
- /* we have the inode open somewhere else
- no need to discard cache data */
- } else {
- if(buf) {
- /* BB need same check in cifs_create too? */
-
- /* if not oplocked, invalidate inode pages if mtime
- or file size changed */
- struct timespec temp;
- temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
- if(timespec_equal(&file->f_dentry->d_inode->i_mtime,&temp) &&
- (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
- cFYI(1,("inode unchanged on server"));
- } else {
- if(file->f_dentry->d_inode->i_mapping) {
- /* BB no need to lock inode until after invalidate*/
- /* since namei code should already have it locked?*/
- filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
- filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
- }
- cFYI(1,("invalidating remote inode since open detected it changed"));
- invalidate_remote_inode(file->f_dentry->d_inode);
- }
- }
- }
- if (pTcon->ses->capabilities & CAP_UNIX)
- rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
- full_path, inode->i_sb,xid);
- else
- rc = cifs_get_inode_info(&file->f_dentry->d_inode,
- full_path, buf, inode->i_sb,xid);
-
- if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
- pCifsInode->clientCanCacheAll = TRUE;
- pCifsInode->clientCanCacheRead = TRUE;
- cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
- } else if((oplock & 0xF) == OPLOCK_READ)
- pCifsInode->clientCanCacheRead = TRUE;
- } else {
- write_unlock(&GlobalSMBSeslock);
- write_unlock(&file->f_owner.lock);
- }
- if(oplock & CIFS_CREATE_ACTION) {
- /* time to set mode which we can not set earlier due
- to problems creating new read-only files */
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
- CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
- (__u64)-1,
- (__u64)-1,
- 0 /* dev */,
- cifs_sb->local_nls);
- else {/* BB implement via Windows security descriptors */
- /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
- /* in the meantime could set r/o dos attribute when perms are eg:
- mode & 0222 == 0 */
- }
- }
+ write_unlock(&GlobalSMBSeslock);
+ write_unlock(&file->f_owner.lock);
+ }
+
+ if (oplock & CIFS_CREATE_ACTION) {
+ /* time to set mode which we can not set earlier due to
+ problems creating new read-only files */
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+ inode->i_mode,
+ (__u64)-1, (__u64)-1, 0 /* dev */,
+ cifs_sb->local_nls);
+ } else {
+ /* BB implement via Windows security descriptors eg
+ CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
+ -1, -1, local_nls);
+ in the meantime could set r/o dos attribute when
+ perms are eg: mode & 0222 == 0 */
}
}
- if (buf)
- kfree(buf);
- if (full_path)
- kfree(full_path);
+out:
+ kfree(buf);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
/* Try to reaquire byte range locks that were released when session */
/* to server was lost */
-static int cifs_relock_file(struct cifsFileInfo * cifsFile)
+static int cifs_relock_file(struct cifsFileInfo *cifsFile)
{
int rc = 0;
@@ -267,7 +315,8 @@ static int cifs_relock_file(struct cifsFileInfo * cifsFile)
return rc;
}
-static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
+static int cifs_reopen_file(struct inode *inode, struct file *file,
+ int can_flush)
{
int rc = -EACCES;
int xid, oplock;
@@ -276,78 +325,69 @@ static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flus
struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode;
char *full_path = NULL;
- int desiredAccess = 0x20197;
+ int desiredAccess;
int disposition = FILE_OPEN;
__u16 netfid;
- if(inode == NULL)
+ if (inode == NULL)
return -EBADF;
if (file->private_data) {
- pCifsFile = (struct cifsFileInfo *) file->private_data;
+ pCifsFile = (struct cifsFileInfo *)file->private_data;
} else
return -EBADF;
xid = GetXid();
down(&pCifsFile->fh_sem);
- if(pCifsFile->invalidHandle == FALSE) {
+ if (pCifsFile->invalidHandle == FALSE) {
up(&pCifsFile->fh_sem);
FreeXid(xid);
return 0;
}
- if(file->f_dentry == NULL) {
+ if (file->f_dentry == NULL) {
up(&pCifsFile->fh_sem);
- cFYI(1,("failed file reopen, no valid name if dentry freed"));
+ cFYI(1, ("failed file reopen, no valid name if dentry freed"));
FreeXid(xid);
return -EBADF;
}
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
/* can not grab rename sem here because various ops, including
-those that already have the rename sem can end up causing writepage
-to get called and if the server was down that means we end up here,
-and we can never tell if the caller already has the rename_sem */
+ those that already have the rename sem can end up causing writepage
+ to get called and if the server was down that means we end up here,
+ and we can never tell if the caller already has the rename_sem */
full_path = build_path_from_dentry(file->f_dentry);
- if(full_path == NULL) {
+ if (full_path == NULL) {
up(&pCifsFile->fh_sem);
FreeXid(xid);
return -ENOMEM;
}
- cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
- if ((file->f_flags & O_ACCMODE) == O_RDONLY)
- desiredAccess = GENERIC_READ;
- else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
- desiredAccess = GENERIC_WRITE;
- else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
- /* GENERIC_ALL is too much permission to request */
- /* can cause unnecessary access denied on create */
- /* desiredAccess = GENERIC_ALL; */
- desiredAccess = GENERIC_READ | GENERIC_WRITE;
- }
+ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
+ inode, file->f_flags,full_path));
+ desiredAccess = cifs_convert_flags(file->f_flags);
if (oplockEnabled)
oplock = REQ_OPLOCK;
else
oplock = FALSE;
-
/* Can not refresh inode by passing in file_info buf to be returned
- by SMBOpen and then calling get_inode_info with returned buf
- since file might have write behind data that needs to be flushed
- and server version of file size can be stale. If we
- knew for sure that inode was not dirty locally we could do this */
+ by SMBOpen and then calling get_inode_info with returned buf
+ since file might have write behind data that needs to be flushed
+ and server version of file size can be stale. If we knew for sure
+ that inode was not dirty locally we could do this */
-/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
- if(buf==0) {
+/* buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+ if (buf == 0) {
up(&pCifsFile->fh_sem);
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return -ENOMEM;
- }*/
+ } */
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
- CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
+ CREATE_NOT_DIR, &netfid, &oplock, NULL,
+ cifs_sb->local_nls);
if (rc) {
up(&pCifsFile->fh_sem);
cFYI(1, ("cifs_open returned 0x%x ", rc));
@@ -357,104 +397,103 @@ and we can never tell if the caller already has the rename_sem */
pCifsFile->invalidHandle = FALSE;
up(&pCifsFile->fh_sem);
pCifsInode = CIFS_I(inode);
- if(pCifsInode) {
- if(can_flush) {
+ if (pCifsInode) {
+ if (can_flush) {
filemap_fdatawrite(inode->i_mapping);
filemap_fdatawait(inode->i_mapping);
/* temporarily disable caching while we
- go to server to get inode info */
+ go to server to get inode info */
pCifsInode->clientCanCacheAll = FALSE;
pCifsInode->clientCanCacheRead = FALSE;
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&inode,
- full_path, inode->i_sb,xid);
+ full_path, inode->i_sb, xid);
else
rc = cifs_get_inode_info(&inode,
- full_path, NULL, inode->i_sb,xid);
+ full_path, NULL, inode->i_sb,
+ xid);
} /* else we are writing out data to server already
- and could deadlock if we tried to flush data, and
- since we do not know if we have data that would
- invalidate the current end of file on the server
- we can not go to the server to get the new
- inod info */
- if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
- pCifsInode->clientCanCacheAll = TRUE;
+ and could deadlock if we tried to flush data, and
+ since we do not know if we have data that would
+ invalidate the current end of file on the server
+ we can not go to the server to get the new inod
+ info */
+ if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
- cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
- } else if((oplock & 0xF) == OPLOCK_READ) {
+ cFYI(1, ("Exclusive Oplock granted on inode %p",
+ file->f_dentry->d_inode));
+ } else if ((oplock & 0xF) == OPLOCK_READ) {
pCifsInode->clientCanCacheRead = TRUE;
- pCifsInode->clientCanCacheAll = FALSE;
+ pCifsInode->clientCanCacheAll = FALSE;
} else {
pCifsInode->clientCanCacheRead = FALSE;
- pCifsInode->clientCanCacheAll = FALSE;
+ pCifsInode->clientCanCacheAll = FALSE;
}
cifs_relock_file(pCifsFile);
}
}
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
-int
-cifs_close(struct inode *inode, struct file *file)
+int cifs_close(struct inode *inode, struct file *file)
{
int rc = 0;
int xid;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
struct cifsFileInfo *pSMBFile =
- (struct cifsFileInfo *) file->private_data;
+ (struct cifsFileInfo *)file->private_data;
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
if (pSMBFile) {
- pSMBFile->closePend = TRUE;
+ pSMBFile->closePend = TRUE;
write_lock(&file->f_owner.lock);
- if(pTcon) {
+ if (pTcon) {
/* no sense reconnecting to close a file that is
- already closed */
+ already closed */
if (pTcon->tidStatus != CifsNeedReconnect) {
write_unlock(&file->f_owner.lock);
- rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
+ rc = CIFSSMBClose(xid, pTcon,
+ pSMBFile->netfid);
write_lock(&file->f_owner.lock);
}
}
list_del(&pSMBFile->flist);
list_del(&pSMBFile->tlist);
write_unlock(&file->f_owner.lock);
- if(pSMBFile->search_resume_name)
- kfree(pSMBFile->search_resume_name);
+ kfree(pSMBFile->search_resume_name);
kfree(file->private_data);
file->private_data = NULL;
} else
rc = -EBADF;
- if(list_empty(&(CIFS_I(inode)->openFileList))) {
- cFYI(1,("closing last open instance for inode %p",inode));
- /* if the file is not open we do not know if we can cache
- info on this inode, much less write behind and read ahead */
+ if (list_empty(&(CIFS_I(inode)->openFileList))) {
+ cFYI(1, ("closing last open instance for inode %p", inode));
+ /* if the file is not open we do not know if we can cache info
+ on this inode, much less write behind and read ahead */
CIFS_I(inode)->clientCanCacheRead = FALSE;
CIFS_I(inode)->clientCanCacheAll = FALSE;
}
- if((rc ==0) && CIFS_I(inode)->write_behind_rc)
+ if ((rc ==0) && CIFS_I(inode)->write_behind_rc)
rc = CIFS_I(inode)->write_behind_rc;
FreeXid(xid);
return rc;
}
-int
-cifs_closedir(struct inode *inode, struct file *file)
+int cifs_closedir(struct inode *inode, struct file *file)
{
int rc = 0;
int xid;
struct cifsFileInfo *pCFileStruct =
- (struct cifsFileInfo *) file->private_data;
- char * ptmp;
+ (struct cifsFileInfo *)file->private_data;
+ char *ptmp;
cFYI(1, ("Closedir inode = 0x%p with ", inode));
@@ -462,27 +501,28 @@ cifs_closedir(struct inode *inode, struct file *file)
if (pCFileStruct) {
struct cifsTconInfo *pTcon;
- struct cifs_sb_info * cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
cFYI(1, ("Freeing private data in close dir"));
- if(pCFileStruct->srch_inf.endOfSearch == FALSE) {
+ if (pCFileStruct->srch_inf.endOfSearch == FALSE) {
pCFileStruct->invalidHandle = TRUE;
rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
- cFYI(1,("Closing uncompleted readdir with rc %d",rc));
- /* not much we can do if it fails anywway, ignore rc */
+ cFYI(1, ("Closing uncompleted readdir with rc %d",
+ rc));
+ /* not much we can do if it fails anyway, ignore rc */
rc = 0;
}
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
- if(ptmp) {
- cFYI(1,("freeing smb buf in srch struct in closedir")); /* BB removeme BB */
+ if (ptmp) {
+ /* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir"));
pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
cifs_buf_release(ptmp);
}
ptmp = pCFileStruct->search_resume_name;
- if(ptmp) {
- cFYI(1,("freeing resume name in closedir")); /* BB removeme BB */
+ if (ptmp) {
+ /* BB removeme BB */ cFYI(1, ("freeing resume name in closedir"));
pCFileStruct->search_resume_name = NULL;
kfree(ptmp);
}
@@ -494,8 +534,7 @@ cifs_closedir(struct inode *inode, struct file *file)
return rc;
}
-int
-cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
+int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
{
int rc, xid;
__u32 lockType = LOCKING_ANDX_LARGE_FILES;
@@ -505,16 +544,15 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
int wait_flag = FALSE;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
- length = 1 + pfLock->fl_end - pfLock->fl_start;
+ length = 1 + pfLock->fl_end - pfLock->fl_start;
rc = -EACCES;
-
xid = GetXid();
- cFYI(1,
- ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
- cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
- pfLock->fl_end));
+ cFYI(1, ("Lock parm: 0x%x flockflags: "
+ "0x%x flocktype: 0x%x start: %lld end: %lld",
+ cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
+ pfLock->fl_end));
if (pfLock->fl_flags & FL_POSIX)
cFYI(1, ("Posix "));
@@ -525,11 +563,13 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
wait_flag = TRUE;
}
if (pfLock->fl_flags & FL_ACCESS)
- cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
+ cFYI(1, ("Process suspended by mandatory locking - "
+ "not implemented yet "));
if (pfLock->fl_flags & FL_LEASE)
cFYI(1, ("Lease on file - not implemented yet"));
- if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
- cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
+ if (pfLock->fl_flags &
+ (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
+ cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
if (pfLock->fl_type == F_WRLCK) {
cFYI(1, ("F_WRLCK "));
@@ -561,7 +601,7 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if (IS_GETLK(cmd)) {
rc = CIFSSMBLock(xid, pTcon,
- ((struct cifsFileInfo *) file->
+ ((struct cifsFileInfo *)file->
private_data)->netfid,
length,
pfLock->fl_start, 0, 1, lockType,
@@ -576,14 +616,15 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
0 /* wait flag */ );
pfLock->fl_type = F_UNLCK;
if (rc != 0)
- cERROR(1,
- ("Error unlocking previously locked range %d during test of lock ",
- rc));
+ cERROR(1, ("Error unlocking previously locked "
+ "range %d during test of lock ",
+ rc));
rc = 0;
} else {
/* if rc == ERR_SHARING_VIOLATION ? */
- rc = 0; /* do not change lock type to unlock since range in use */
+ rc = 0; /* do not change lock type to unlock
+ since range in use */
}
FreeXid(xid);
@@ -601,9 +642,8 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
return rc;
}
-ssize_t
-cifs_user_write(struct file * file, const char __user * write_data,
- size_t write_size, loff_t * poffset)
+ssize_t cifs_user_write(struct file *file, const char __user *write_data,
+ size_t write_size, loff_t *poffset)
{
int rc = 0;
unsigned int bytes_written = 0;
@@ -611,75 +651,76 @@ cifs_user_write(struct file * file, const char __user * write_data,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid, long_op;
- struct cifsFileInfo * open_file;
+ struct cifsFileInfo *open_file;
- if(file->f_dentry == NULL)
+ if (file->f_dentry == NULL)
return -EBADF;
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- if(cifs_sb == NULL) {
+ if (cifs_sb == NULL)
return -EBADF;
- }
+
pTcon = cifs_sb->tcon;
- /*cFYI(1,
+ /* cFYI(1,
(" write %d bytes to offset %lld of %s", write_size,
*poffset, file->f_dentry->d_name.name)); */
- if (file->private_data == NULL) {
+ if (file->private_data == NULL)
return -EBADF;
- } else {
+ else
open_file = (struct cifsFileInfo *) file->private_data;
- }
xid = GetXid();
- if(file->f_dentry->d_inode == NULL) {
+ if (file->f_dentry->d_inode == NULL) {
FreeXid(xid);
return -EBADF;
}
if (*poffset > file->f_dentry->d_inode->i_size)
- long_op = 2; /* writes past end of file can take a long time */
+ long_op = 2; /* writes past end of file can take a long time */
else
long_op = 1;
for (total_written = 0; write_size > total_written;
total_written += bytes_written) {
rc = -EAGAIN;
- while(rc == -EAGAIN) {
- if(file->private_data == NULL) {
+ while (rc == -EAGAIN) {
+ if (file->private_data == NULL) {
/* file has been closed on us */
FreeXid(xid);
/* if we have gotten here we have written some data
- and blocked, and the file has been freed on us
- while we blocked so return what we managed to write */
+ and blocked, and the file has been freed on us while
+ we blocked so return what we managed to write */
return total_written;
}
- if(open_file->closePend) {
+ if (open_file->closePend) {
FreeXid(xid);
- if(total_written)
+ if (total_written)
return total_written;
else
return -EBADF;
}
if (open_file->invalidHandle) {
- if((file->f_dentry == NULL) ||
- (file->f_dentry->d_inode == NULL)) {
+ if ((file->f_dentry == NULL) ||
+ (file->f_dentry->d_inode == NULL)) {
FreeXid(xid);
return total_written;
}
/* we could deadlock if we called
- filemap_fdatawait from here so tell
- reopen_file not to flush data to server now */
+ filemap_fdatawait from here so tell
+ reopen_file not to flush data to server
+ now */
rc = cifs_reopen_file(file->f_dentry->d_inode,
- file,FALSE);
- if(rc != 0)
+ file, FALSE);
+ if (rc != 0)
break;
}
rc = CIFSSMBWrite(xid, pTcon,
open_file->netfid,
- min_t(const int,cifs_sb->wsize,write_size - total_written),
+ min_t(const int, cifs_sb->wsize,
+ write_size - total_written),
*poffset, &bytes_written,
NULL, write_data + total_written, long_op);
}
@@ -692,11 +733,12 @@ cifs_user_write(struct file * file, const char __user * write_data,
}
} else
*poffset += bytes_written;
- long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
+ long_op = FALSE; /* subsequent writes fast -
+ 15 seconds is plenty */
}
#ifdef CONFIG_CIFS_STATS
- if(total_written > 0) {
+ if (total_written > 0) {
atomic_inc(&pTcon->num_writes);
spin_lock(&pTcon->stat_lock);
pTcon->bytes_written += total_written;
@@ -705,14 +747,15 @@ cifs_user_write(struct file * file, const char __user * write_data,
#endif
/* since the write may have blocked check these pointers again */
- if(file->f_dentry) {
- if(file->f_dentry->d_inode) {
+ if (file->f_dentry) {
+ if (file->f_dentry->d_inode) {
struct inode *inode = file->f_dentry->d_inode;
inode->i_ctime = inode->i_mtime =
current_fs_time(inode->i_sb);
if (total_written > 0) {
if (*poffset > file->f_dentry->d_inode->i_size)
- i_size_write(file->f_dentry->d_inode, *poffset);
+ i_size_write(file->f_dentry->d_inode,
+ *poffset);
}
mark_inode_dirty_sync(file->f_dentry->d_inode);
}
@@ -721,9 +764,8 @@ cifs_user_write(struct file * file, const char __user * write_data,
return total_written;
}
-static ssize_t
-cifs_write(struct file * file, const char *write_data,
- size_t write_size, loff_t * poffset)
+static ssize_t cifs_write(struct file *file, const char *write_data,
+ size_t write_size, loff_t *poffset)
{
int rc = 0;
unsigned int bytes_written = 0;
@@ -731,76 +773,78 @@ cifs_write(struct file * file, const char *write_data,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid, long_op;
- struct cifsFileInfo * open_file;
+ struct cifsFileInfo *open_file;
- if(file->f_dentry == NULL)
+ if (file->f_dentry == NULL)
return -EBADF;
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- if(cifs_sb == NULL) {
+ if (cifs_sb == NULL)
return -EBADF;
- }
+
pTcon = cifs_sb->tcon;
- /*cFYI(1,
+ /* cFYI(1,
(" write %d bytes to offset %lld of %s", write_size,
*poffset, file->f_dentry->d_name.name)); */
- if (file->private_data == NULL) {
+ if (file->private_data == NULL)
return -EBADF;
- } else {
- open_file = (struct cifsFileInfo *) file->private_data;
- }
+ else
+ open_file = (struct cifsFileInfo *)file->private_data;
xid = GetXid();
- if(file->f_dentry->d_inode == NULL) {
+ if (file->f_dentry->d_inode == NULL) {
FreeXid(xid);
return -EBADF;
}
if (*poffset > file->f_dentry->d_inode->i_size)
- long_op = 2; /* writes past end of file can take a long time */
+ long_op = 2; /* writes past end of file can take a long time */
else
long_op = 1;
for (total_written = 0; write_size > total_written;
total_written += bytes_written) {
rc = -EAGAIN;
- while(rc == -EAGAIN) {
- if(file->private_data == NULL) {
+ while (rc == -EAGAIN) {
+ if (file->private_data == NULL) {
/* file has been closed on us */
FreeXid(xid);
/* if we have gotten here we have written some data
- and blocked, and the file has been freed on us
- while we blocked so return what we managed to write */
+ and blocked, and the file has been freed on us
+ while we blocked so return what we managed to
+ write */
return total_written;
}
- if(open_file->closePend) {
+ if (open_file->closePend) {
FreeXid(xid);
- if(total_written)
+ if (total_written)
return total_written;
else
return -EBADF;
}
if (open_file->invalidHandle) {
- if((file->f_dentry == NULL) ||
+ if ((file->f_dentry == NULL) ||
(file->f_dentry->d_inode == NULL)) {
FreeXid(xid);
return total_written;
}
/* we could deadlock if we called
- filemap_fdatawait from here so tell
- reopen_file not to flush data to server now */
+ filemap_fdatawait from here so tell
+ reopen_file not to flush data to
+ server now */
rc = cifs_reopen_file(file->f_dentry->d_inode,
- file,FALSE);
- if(rc != 0)
+ file, FALSE);
+ if (rc != 0)
break;
}
rc = CIFSSMBWrite(xid, pTcon,
open_file->netfid,
- min_t(const int,cifs_sb->wsize,write_size - total_written),
- *poffset,&bytes_written,
+ min_t(const int, cifs_sb->wsize,
+ write_size - total_written),
+ *poffset, &bytes_written,
write_data + total_written, NULL, long_op);
}
if (rc || (bytes_written == 0)) {
@@ -812,11 +856,12 @@ cifs_write(struct file * file, const char *write_data,
}
} else
*poffset += bytes_written;
- long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
+ long_op = FALSE; /* subsequent writes fast -
+ 15 seconds is plenty */
}
#ifdef CONFIG_CIFS_STATS
- if(total_written > 0) {
+ if (total_written > 0) {
atomic_inc(&pTcon->num_writes);
spin_lock(&pTcon->stat_lock);
pTcon->bytes_written += total_written;
@@ -825,13 +870,14 @@ cifs_write(struct file * file, const char *write_data,
#endif
/* since the write may have blocked check these pointers again */
- if(file->f_dentry) {
- if(file->f_dentry->d_inode) {
- file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
- CURRENT_TIME;
+ if (file->f_dentry) {
+ if (file->f_dentry->d_inode) {
+ file->f_dentry->d_inode->i_ctime =
+ file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
if (total_written > 0) {
if (*poffset > file->f_dentry->d_inode->i_size)
- i_size_write(file->f_dentry->d_inode, *poffset);
+ i_size_write(file->f_dentry->d_inode,
+ *poffset);
}
mark_inode_dirty_sync(file->f_dentry->d_inode);
}
@@ -840,12 +886,11 @@ cifs_write(struct file * file, const char *write_data,
return total_written;
}
-static int
-cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
+static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
{
struct address_space *mapping = page->mapping;
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
- char * write_data;
+ char *write_data;
int rc = -EFAULT;
int bytes_written = 0;
struct cifs_sb_info *cifs_sb;
@@ -856,11 +901,8 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
struct list_head *tmp;
struct list_head *tmp1;
- if (!mapping) {
- return -EFAULT;
- } else if(!mapping->host) {
+ if (!mapping || !mapping->host)
return -EFAULT;
- }
inode = page->mapping->host;
cifs_sb = CIFS_SB(inode->i_sb);
@@ -870,64 +912,65 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
write_data = kmap(page);
write_data += from;
- if((to > PAGE_CACHE_SIZE) || (from > to)) {
+ if ((to > PAGE_CACHE_SIZE) || (from > to)) {
kunmap(page);
return -EIO;
}
/* racing with truncate? */
- if(offset > mapping->host->i_size) {
+ if (offset > mapping->host->i_size) {
kunmap(page);
return 0; /* don't care */
}
/* check to make sure that we are not extending the file */
- if(mapping->host->i_size - offset < (loff_t)to)
+ if (mapping->host->i_size - offset < (loff_t)to)
to = (unsigned)(mapping->host->i_size - offset);
-
cifsInode = CIFS_I(mapping->host);
read_lock(&GlobalSMBSeslock);
/* BB we should start at the end */
list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
- open_file = list_entry(tmp,struct cifsFileInfo, flist);
- if(open_file->closePend)
+ open_file = list_entry(tmp, struct cifsFileInfo, flist);
+ if (open_file->closePend)
continue;
/* We check if file is open for writing first */
- if((open_file->pfile) &&
+ if ((open_file->pfile) &&
((open_file->pfile->f_flags & O_RDWR) ||
(open_file->pfile->f_flags & O_WRONLY))) {
read_unlock(&GlobalSMBSeslock);
- bytes_written = cifs_write(open_file->pfile, write_data,
- to-from, &offset);
+ bytes_written = cifs_write(open_file->pfile,
+ write_data, to-from,
+ &offset);
read_lock(&GlobalSMBSeslock);
/* Does mm or vfs already set times? */
- inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
+ inode->i_atime =
+ inode->i_mtime = current_fs_time(inode->i_sb);
if ((bytes_written > 0) && (offset)) {
rc = 0;
- } else if(bytes_written < 0) {
- if(rc == -EBADF) {
- /* have seen a case in which
- kernel seemed to have closed/freed a file
- even with writes active so we might as well
- see if there are other file structs to try
- for the same inode before giving up */
+ } else if (bytes_written < 0) {
+ if (rc == -EBADF) {
+ /* have seen a case in which kernel seemed to
+ have closed/freed a file even with writes
+ active so we might as well see if there are
+ other file structs to try for the same
+ inode before giving up */
continue;
} else
rc = bytes_written;
}
- break; /* now that we found a valid file handle
- and tried to write to it we are done, no
- sense continuing to loop looking for another */
+ break; /* now that we found a valid file handle and
+ tried to write to it we are done, no sense
+ continuing to loop looking for another */
}
- if(tmp->next == NULL) {
- cFYI(1,("File instance %p removed",tmp));
+ if (tmp->next == NULL) {
+ cFYI(1, ("File instance %p removed", tmp));
break;
}
}
read_unlock(&GlobalSMBSeslock);
- if(open_file == NULL) {
- cFYI(1,("No writeable filehandles for inode"));
+ if (open_file == NULL) {
+ cFYI(1, ("No writeable filehandles for inode"));
rc = -EIO;
}
@@ -936,25 +979,24 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
}
#if 0
-static int
-cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
+static int cifs_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
{
int rc = -EFAULT;
int xid;
xid = GetXid();
- /* Find contiguous pages then iterate through repeating */
-/* call 16K write then Setpageuptodate or if LARGE_WRITE_X
-support then send larger writes via kevec so as to eliminate
-a memcpy */
+ /* Find contiguous pages then iterate through repeating
+ call 16K write then Setpageuptodate or if LARGE_WRITE_X
+ support then send larger writes via kevec so as to eliminate
+ a memcpy */
FreeXid(xid);
return rc;
}
#endif
-static int
-cifs_writepage(struct page* page, struct writeback_control *wbc)
+static int cifs_writepage(struct page* page, struct writeback_control *wbc)
{
int rc = -EFAULT;
int xid;
@@ -963,10 +1005,10 @@ cifs_writepage(struct page* page, struct writeback_control *wbc)
/* BB add check for wbc flags */
page_cache_get(page);
if (!PageUptodate(page)) {
- cFYI(1,("ppw - page not up to date"));
+ cFYI(1, ("ppw - page not up to date"));
}
- rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
+ rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
unlock_page(page);
page_cache_release(page);
@@ -974,66 +1016,67 @@ cifs_writepage(struct page* page, struct writeback_control *wbc)
return rc;
}
-static int
-cifs_commit_write(struct file *file, struct page *page, unsigned offset,
- unsigned to)
+static int cifs_commit_write(struct file *file, struct page *page,
+ unsigned offset, unsigned to)
{
int xid;
int rc = 0;
struct inode *inode = page->mapping->host;
loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
- char * page_data;
+ char *page_data;
xid = GetXid();
- cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
- if (position > inode->i_size){
+ cFYI(1, ("commit write for page %p up to position %lld for %d",
+ page, position, to));
+ if (position > inode->i_size) {
i_size_write(inode, position);
- /*if (file->private_data == NULL) {
+ /* if (file->private_data == NULL) {
rc = -EBADF;
} else {
open_file = (struct cifsFileInfo *)file->private_data;
cifs_sb = CIFS_SB(inode->i_sb);
rc = -EAGAIN;
- while(rc == -EAGAIN) {
- if((open_file->invalidHandle) &&
- (!open_file->closePend)) {
- rc = cifs_reopen_file(file->f_dentry->d_inode,file);
- if(rc != 0)
+ while (rc == -EAGAIN) {
+ if ((open_file->invalidHandle) &&
+ (!open_file->closePend)) {
+ rc = cifs_reopen_file(
+ file->f_dentry->d_inode, file);
+ if (rc != 0)
break;
}
- if(!open_file->closePend) {
- rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
- position, open_file->netfid,
- open_file->pid,FALSE);
+ if (!open_file->closePend) {
+ rc = CIFSSMBSetFileSize(xid,
+ cifs_sb->tcon, position,
+ open_file->netfid,
+ open_file->pid, FALSE);
} else {
rc = -EBADF;
break;
}
}
- cFYI(1,(" SetEOF (commit write) rc = %d",rc));
- }*/
+ cFYI(1, (" SetEOF (commit write) rc = %d", rc));
+ } */
}
if (!PageUptodate(page)) {
position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
/* can not rely on (or let) writepage write this data */
- if(to < offset) {
- cFYI(1,("Illegal offsets, can not copy from %d to %d",
- offset,to));
+ if (to < offset) {
+ cFYI(1, ("Illegal offsets, can not copy from %d to %d",
+ offset, to));
FreeXid(xid);
return rc;
}
- /* this is probably better than directly calling
- partialpage_write since in this function
- the file handle is known which we might as well
- leverage */
- /* BB check if anything else missing out of ppw */
- /* such as updating last write time */
+ /* this is probably better than directly calling
+ partialpage_write since in this function the file handle is
+ known which we might as well leverage */
+ /* BB check if anything else missing out of ppw
+ such as updating last write time */
page_data = kmap(page);
- rc = cifs_write(file, page_data+offset,to-offset,
- &position);
- if(rc > 0)
+ rc = cifs_write(file, page_data + offset, to-offset,
+ &position);
+ if (rc > 0)
rc = 0;
- /* else if rc < 0 should we set writebehind rc? */
+ /* else if (rc < 0) should we set writebehind rc? */
kunmap(page);
} else {
set_page_dirty(page);
@@ -1043,12 +1086,11 @@ cifs_commit_write(struct file *file, struct page *page, unsigned offset,
return rc;
}
-int
-cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
+int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
int xid;
int rc = 0;
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_dentry->d_inode;
xid = GetXid();
@@ -1056,14 +1098,13 @@ cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
dentry->d_name.name, datasync));
rc = filemap_fdatawrite(inode->i_mapping);
- if(rc == 0)
+ if (rc == 0)
CIFS_I(inode)->write_behind_rc = 0;
FreeXid(xid);
return rc;
}
-/* static int
-cifs_sync_page(struct page *page)
+/* static int cifs_sync_page(struct page *page)
{
struct address_space *mapping;
struct inode *inode;
@@ -1071,18 +1112,18 @@ cifs_sync_page(struct page *page)
unsigned int rpages = 0;
int rc = 0;
- cFYI(1,("sync page %p",page));
+ cFYI(1, ("sync page %p",page));
mapping = page->mapping;
if (!mapping)
return 0;
inode = mapping->host;
if (!inode)
- return 0;*/
+ return 0; */
/* fill in rpages then
- result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
+ result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
-/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
+/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
if (rc < 0)
return rc;
@@ -1092,35 +1133,32 @@ cifs_sync_page(struct page *page)
/*
* As file closes, flush all cached write data for this inode checking
* for write behind errors.
- *
*/
int cifs_flush(struct file *file)
{
struct inode * inode = file->f_dentry->d_inode;
int rc = 0;
- /* Rather than do the steps manually: */
- /* lock the inode for writing */
- /* loop through pages looking for write behind data (dirty pages) */
- /* coalesce into contiguous 16K (or smaller) chunks to write to server */
- /* send to server (prefer in parallel) */
- /* deal with writebehind errors */
- /* unlock inode for writing */
- /* filemapfdatawrite appears easier for the time being */
+ /* Rather than do the steps manually:
+ lock the inode for writing
+ loop through pages looking for write behind data (dirty pages)
+ coalesce into contiguous 16K (or smaller) chunks to write to server
+ send to server (prefer in parallel)
+ deal with writebehind errors
+ unlock inode for writing
+ filemapfdatawrite appears easier for the time being */
rc = filemap_fdatawrite(inode->i_mapping);
- if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
+ if (!rc) /* reset wb rc if we were able to write out dirty pages */
CIFS_I(inode)->write_behind_rc = 0;
- cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
+ cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
return rc;
}
-
-ssize_t
-cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
- loff_t * poffset)
+ssize_t cifs_user_read(struct file *file, char __user *read_data,
+ size_t read_size, loff_t *poffset)
{
int rc = -EACCES;
unsigned int bytes_read = 0;
@@ -1129,10 +1167,10 @@ cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid;
- struct cifsFileInfo * open_file;
- char * smb_read_data;
- char __user * current_offset;
- struct smb_com_read_rsp * pSMBr;
+ struct cifsFileInfo *open_file;
+ char *smb_read_data;
+ char __user *current_offset;
+ struct smb_com_read_rsp *pSMBr;
xid = GetXid();
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1144,19 +1182,22 @@ cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
}
open_file = (struct cifsFileInfo *)file->private_data;
- if((file->f_flags & O_ACCMODE) == O_WRONLY) {
- cFYI(1,("attempting read on write only file instance"));
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+ cFYI(1, ("attempting read on write only file instance"));
}
- for (total_read = 0,current_offset=read_data; read_size > total_read;
- total_read += bytes_read,current_offset+=bytes_read) {
- current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
+ for (total_read = 0, current_offset = read_data;
+ read_size > total_read;
+ total_read += bytes_read, current_offset += bytes_read) {
+ current_read_size = min_t(const int, read_size - total_read,
+ cifs_sb->rsize);
rc = -EAGAIN;
smb_read_data = NULL;
- while(rc == -EAGAIN) {
- if ((open_file->invalidHandle) && (!open_file->closePend)) {
+ while (rc == -EAGAIN) {
+ if ((open_file->invalidHandle) &&
+ (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,
- file,TRUE);
- if(rc != 0)
+ file, TRUE);
+ if (rc != 0)
break;
}
@@ -1166,13 +1207,15 @@ cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
&bytes_read, &smb_read_data);
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
- if(copy_to_user(current_offset,smb_read_data + 4/* RFC1001 hdr*/
- + le16_to_cpu(pSMBr->DataOffset), bytes_read)) {
+ if (copy_to_user(current_offset,
+ smb_read_data + 4 /* RFC1001 hdr */
+ + le16_to_cpu(pSMBr->DataOffset),
+ bytes_read)) {
rc = -EFAULT;
FreeXid(xid);
return rc;
}
- if(smb_read_data) {
+ if (smb_read_data) {
cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
@@ -1199,9 +1242,8 @@ cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
}
-static ssize_t
-cifs_read(struct file * file, char *read_data, size_t read_size,
- loff_t * poffset)
+static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
+ loff_t *poffset)
{
int rc = -EACCES;
unsigned int bytes_read = 0;
@@ -1210,8 +1252,8 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid;
- char * current_offset;
- struct cifsFileInfo * open_file;
+ char *current_offset;
+ struct cifsFileInfo *open_file;
xid = GetXid();
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1223,19 +1265,21 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
}
open_file = (struct cifsFileInfo *)file->private_data;
- if((file->f_flags & O_ACCMODE) == O_WRONLY) {
- cFYI(1,("attempting read on write only file instance"));
- }
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY)
+ cFYI(1, ("attempting read on write only file instance"));
- for (total_read = 0,current_offset=read_data; read_size > total_read;
- total_read += bytes_read,current_offset+=bytes_read) {
- current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
+ for (total_read = 0, current_offset = read_data;
+ read_size > total_read;
+ total_read += bytes_read, current_offset += bytes_read) {
+ current_read_size = min_t(const int, read_size - total_read,
+ cifs_sb->rsize);
rc = -EAGAIN;
- while(rc == -EAGAIN) {
- if ((open_file->invalidHandle) && (!open_file->closePend)) {
+ while (rc == -EAGAIN) {
+ if ((open_file->invalidHandle) &&
+ (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,
- file,TRUE);
- if(rc != 0)
+ file, TRUE);
+ if (rc != 0)
break;
}
@@ -1265,26 +1309,15 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
return total_read;
}
-int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
+int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct dentry * dentry = file->f_dentry;
- int rc, xid;
-
-#ifdef CIFS_EXPERIMENTAL /* BB fixme reenable when cifs_read_wrapper fixed */
- if(dentry->d_sb) {
- struct cifs_sb_info *cifs_sb;
- cifs_sb = CIFS_SB(sb);
- if(cifs_sb != NULL) {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
- return -ENODEV
- }
- }
-#endif /* CIFS_EXPERIMENTAL */
+ struct dentry *dentry = file->f_dentry;
+ int rc, xid;
xid = GetXid();
rc = cifs_revalidate(dentry);
if (rc) {
- cFYI(1,("Validation prior to mmap failed, error=%d", rc));
+ cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
FreeXid(xid);
return rc;
}
@@ -1295,37 +1328,39 @@ int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
static void cifs_copy_cache_pages(struct address_space *mapping,
- struct list_head *pages, int bytes_read,
- char *data,struct pagevec * plru_pvec)
+ struct list_head *pages, int bytes_read, char *data,
+ struct pagevec *plru_pvec)
{
struct page *page;
- char * target;
+ char *target;
while (bytes_read > 0) {
- if(list_empty(pages))
+ if (list_empty(pages))
break;
page = list_entry(pages->prev, struct page, lru);
list_del(&page->lru);
- if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
+ if (add_to_page_cache(page, mapping, page->index,
+ GFP_KERNEL)) {
page_cache_release(page);
- cFYI(1,("Add page cache failed"));
+ cFYI(1, ("Add page cache failed"));
continue;
}
target = kmap_atomic(page,KM_USER0);
- if(PAGE_CACHE_SIZE > bytes_read) {
- memcpy(target,data,bytes_read);
+ if (PAGE_CACHE_SIZE > bytes_read) {
+ memcpy(target, data, bytes_read);
/* zero the tail end of this partial page */
- memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
+ memset(target + bytes_read, 0,
+ PAGE_CACHE_SIZE - bytes_read);
bytes_read = 0;
} else {
- memcpy(target,data,PAGE_CACHE_SIZE);
+ memcpy(target, data, PAGE_CACHE_SIZE);
bytes_read -= PAGE_CACHE_SIZE;
}
- kunmap_atomic(target,KM_USER0);
+ kunmap_atomic(target, KM_USER0);
flush_dcache_page(page);
SetPageUptodate(page);
@@ -1337,23 +1372,21 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
return;
}
-
-static int
-cifs_readpages(struct file *file, struct address_space *mapping,
- struct list_head *page_list, unsigned num_pages)
+static int cifs_readpages(struct file *file, struct address_space *mapping,
+ struct list_head *page_list, unsigned num_pages)
{
int rc = -EACCES;
int xid;
loff_t offset;
- struct page * page;
+ struct page *page;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int bytes_read = 0;
unsigned int read_size,i;
- char * smb_read_data = NULL;
- struct smb_com_read_rsp * pSMBr;
+ char *smb_read_data = NULL;
+ struct smb_com_read_rsp *pSMBr;
struct pagevec lru_pvec;
- struct cifsFileInfo * open_file;
+ struct cifsFileInfo *open_file;
xid = GetXid();
if (file->private_data == NULL) {
@@ -1366,44 +1399,46 @@ cifs_readpages(struct file *file, struct address_space *mapping,
pagevec_init(&lru_pvec, 0);
- for(i = 0;i<num_pages;) {
+ for (i = 0; i < num_pages; ) {
unsigned contig_pages;
- struct page * tmp_page;
+ struct page *tmp_page;
unsigned long expected_index;
- if(list_empty(page_list)) {
+ if (list_empty(page_list))
break;
- }
+
page = list_entry(page_list->prev, struct page, lru);
offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
/* count adjacent pages that we will read into */
contig_pages = 0;
- expected_index = list_entry(page_list->prev,struct page,lru)->index;
+ expected_index =
+ list_entry(page_list->prev, struct page, lru)->index;
list_for_each_entry_reverse(tmp_page,page_list,lru) {
- if(tmp_page->index == expected_index) {
+ if (tmp_page->index == expected_index) {
contig_pages++;
expected_index++;
- } else {
+ } else
break;
- }
}
- if(contig_pages + i > num_pages) {
+ if (contig_pages + i > num_pages)
contig_pages = num_pages - i;
- }
- /* for reads over a certain size could initiate async read ahead */
+ /* for reads over a certain size could initiate async
+ read ahead */
read_size = contig_pages * PAGE_CACHE_SIZE;
/* Read size needs to be in multiples of one page */
- read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
+ read_size = min_t(const unsigned int, read_size,
+ cifs_sb->rsize & PAGE_CACHE_MASK);
rc = -EAGAIN;
- while(rc == -EAGAIN) {
- if ((open_file->invalidHandle) && (!open_file->closePend)) {
+ while (rc == -EAGAIN) {
+ if ((open_file->invalidHandle) &&
+ (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,
file, TRUE);
- if(rc != 0)
+ if (rc != 0)
break;
}
@@ -1412,18 +1447,19 @@ cifs_readpages(struct file *file, struct address_space *mapping,
read_size, offset,
&bytes_read, &smb_read_data);
/* BB need to check return code here */
- if(rc== -EAGAIN) {
- if(smb_read_data) {
+ if (rc== -EAGAIN) {
+ if (smb_read_data) {
cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
}
}
if ((rc < 0) || (smb_read_data == NULL)) {
- cFYI(1,("Read error in readpages: %d",rc));
+ cFYI(1, ("Read error in readpages: %d", rc));
/* clean up remaing pages off list */
while (!list_empty(page_list) && (i < num_pages)) {
- page = list_entry(page_list->prev, struct page, lru);
+ page = list_entry(page_list->prev, struct page,
+ lru);
list_del(&page->lru);
page_cache_release(page);
}
@@ -1441,31 +1477,40 @@ cifs_readpages(struct file *file, struct address_space *mapping,
pTcon->bytes_read += bytes_read;
spin_unlock(&pTcon->stat_lock);
#endif
- if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
+ if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
i++; /* account for partial page */
- /* server copy of file can have smaller size than client */
- /* BB do we need to verify this common case ? this case is ok -
- if we are at server EOF we will hit it on next read */
+ /* server copy of file can have smaller size
+ than client */
+ /* BB do we need to verify this common case ?
+ this case is ok - if we are at server EOF
+ we will hit it on next read */
- /* while(!list_empty(page_list) && (i < num_pages)) {
- page = list_entry(page_list->prev,struct page, list);
+ /* while (!list_empty(page_list) && (i < num_pages)) {
+ page = list_entry(page_list->prev,
+ struct page, list);
list_del(&page->list);
page_cache_release(page);
}
break; */
}
} else {
- cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
- /* BB turn off caching and do new lookup on file size at server? */
+ cFYI(1, ("No bytes read (%d) at offset %lld . "
+ "Cleaning remaining pages from readahead list",
+ bytes_read, offset));
+ /* BB turn off caching and do new lookup on
+ file size at server? */
while (!list_empty(page_list) && (i < num_pages)) {
- page = list_entry(page_list->prev, struct page, lru);
+ page = list_entry(page_list->prev, struct page,
+ lru);
list_del(&page->lru);
- page_cache_release(page); /* BB removeme - replace with zero of page? */
+
+ /* BB removeme - replace with zero of page? */
+ page_cache_release(page);
}
break;
}
- if(smb_read_data) {
+ if (smb_read_data) {
cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
@@ -1475,7 +1520,7 @@ cifs_readpages(struct file *file, struct address_space *mapping,
pagevec_lru_add(&lru_pvec);
/* need to free smb_read_data buf before exit */
- if(smb_read_data) {
+ if (smb_read_data) {
cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
@@ -1484,9 +1529,10 @@ cifs_readpages(struct file *file, struct address_space *mapping,
return rc;
}
-static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
+static int cifs_readpage_worker(struct file *file, struct page *page,
+ loff_t *poffset)
{
- char * read_data;
+ char *read_data;
int rc;
page_cache_get(page);
@@ -1497,16 +1543,15 @@ static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * p
if (rc < 0)
goto io_error;
- else {
- cFYI(1,("Bytes read %d ",rc));
- }
+ else
+ cFYI(1, ("Bytes read %d ",rc));
file->f_dentry->d_inode->i_atime =
current_fs_time(file->f_dentry->d_inode->i_sb);
- if(PAGE_CACHE_SIZE > rc) {
- memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
- }
+ if (PAGE_CACHE_SIZE > rc)
+ memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
+
flush_dcache_page(page);
SetPageUptodate(page);
rc = 0;
@@ -1517,8 +1562,7 @@ io_error:
return rc;
}
-static int
-cifs_readpage(struct file *file, struct page *page)
+static int cifs_readpage(struct file *file, struct page *page)
{
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
int rc = -EACCES;
@@ -1531,9 +1575,10 @@ cifs_readpage(struct file *file, struct page *page)
return -EBADF;
}
- cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
+ cFYI(1, ("readpage %p at offset %d 0x%x\n",
+ page, (int)offset, (int)offset));
- rc = cifs_readpage_worker(file,page,&offset);
+ rc = cifs_readpage_worker(file, page, &offset);
unlock_page(page);
@@ -1547,35 +1592,34 @@ cifs_readpage(struct file *file, struct page *page)
refreshing the inode only on increases in the file size
but this is tricky to do without racing with writebehind
page caching in the current Linux kernel design */
-
-int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
+int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
{
struct list_head *tmp;
struct list_head *tmp1;
struct cifsFileInfo *open_file = NULL;
int rc = TRUE;
- if(cifsInode == NULL)
+ if (cifsInode == NULL)
return rc;
read_lock(&GlobalSMBSeslock);
list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
- open_file = list_entry(tmp,struct cifsFileInfo, flist);
- if(open_file == NULL)
+ open_file = list_entry(tmp, struct cifsFileInfo, flist);
+ if (open_file == NULL)
break;
- if(open_file->closePend)
+ if (open_file->closePend)
continue;
/* We check if file is open for writing,
- BB we could supplement this with a check to see if file size
- changes have been flushed to server - ie inode metadata dirty */
- if((open_file->pfile) &&
- ((open_file->pfile->f_flags & O_RDWR) ||
- (open_file->pfile->f_flags & O_WRONLY))) {
- rc = FALSE;
- break;
+ BB we could supplement this with a check to see if file size
+ changes have been flushed to server - ie inode metadata dirty */
+ if ((open_file->pfile) &&
+ ((open_file->pfile->f_flags & O_RDWR) ||
+ (open_file->pfile->f_flags & O_WRONLY))) {
+ rc = FALSE;
+ break;
}
- if(tmp->next == NULL) {
- cFYI(1,("File instance %p removed",tmp));
+ if (tmp->next == NULL) {
+ cFYI(1, ("File instance %p removed", tmp));
break;
}
}
@@ -1585,11 +1629,11 @@ int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
static int cifs_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+ unsigned from, unsigned to)
{
int rc = 0;
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
- cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
+ cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
if (!PageUptodate(page)) {
/* if (to - from != PAGE_CACHE_SIZE) {
void *kaddr = kmap_atomic(page, KM_USER0);
@@ -1599,33 +1643,33 @@ static int cifs_prepare_write(struct file *file, struct page *page,
kunmap_atomic(kaddr, KM_USER0);
} */
/* If we are writing a full page it will be up to date,
- no need to read from the server */
- if((to==PAGE_CACHE_SIZE) && (from == 0))
+ no need to read from the server */
+ if ((to == PAGE_CACHE_SIZE) && (from == 0))
SetPageUptodate(page);
/* might as well read a page, it is fast enough */
- if((file->f_flags & O_ACCMODE) != O_WRONLY) {
- rc = cifs_readpage_worker(file,page,&offset);
+ if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
+ rc = cifs_readpage_worker(file, page, &offset);
} else {
- /* should we try using another
- file handle if there is one - how would we lock it
- to prevent close of that handle racing with this read? */
- /* In any case this will be written out by commit_write */
+ /* should we try using another file handle if there is one -
+ how would we lock it to prevent close of that handle
+ racing with this read?
+ In any case this will be written out by commit_write */
}
}
- /* BB should we pass any errors back? e.g. if we do not have read access to the file */
+ /* BB should we pass any errors back?
+ e.g. if we do not have read access to the file */
return 0;
}
-
struct address_space_operations cifs_addr_ops = {
.readpage = cifs_readpage,
.readpages = cifs_readpages,
.writepage = cifs_writepage,
- .prepare_write = cifs_prepare_write,
+ .prepare_write = cifs_prepare_write,
.commit_write = cifs_commit_write,
.set_page_dirty = __set_page_dirty_nobuffers,
- /* .sync_page = cifs_sync_page, */
- /*.direct_IO = */
+ /* .sync_page = cifs_sync_page, */
+ /* .direct_IO = */
};
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8ef40e473ef3d..d73b0aa86775e 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -30,10 +30,8 @@
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
-int
-cifs_get_inode_info_unix(struct inode **pinode,
- const unsigned char *search_path,
- struct super_block *sb,int xid)
+int cifs_get_inode_info_unix(struct inode **pinode,
+ const unsigned char *search_path, struct super_block *sb, int xid)
{
int rc = 0;
FILE_UNIX_BASIC_INFO findData;
@@ -44,23 +42,24 @@ cifs_get_inode_info_unix(struct inode **pinode,
pTcon = cifs_sb->tcon;
cFYI(1, (" Getting info on %s ", search_path));
- /* we could have done a find first instead but this returns more info */
+ /* could have done a find first instead but this returns more info */
rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
cifs_sb->local_nls);
- /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
+/* dump_mem("\nUnixQPathInfo return data", &findData,
+ sizeof(findData)); */
if (rc) {
if (rc == -EREMOTE) {
tmp_path =
- kmalloc(strnlen
- (pTcon->treeName,
- MAX_TREE_SIZE + 1) +
+ kmalloc(strnlen(pTcon->treeName,
+ MAX_TREE_SIZE + 1) +
strnlen(search_path, MAX_PATHCONF) + 1,
GFP_KERNEL);
if (tmp_path == NULL) {
return -ENOMEM;
}
- /* have to skip first of the double backslash of UNC name */
- strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
+ /* have to skip first of the double backslash of
+ UNC name */
+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
strncat(tmp_path, search_path, MAX_PATHCONF);
rc = connect_to_dfs_path(xid, pTcon->ses,
/* treename + */ tmp_path,
@@ -71,7 +70,6 @@ cifs_get_inode_info_unix(struct inode **pinode,
} else if (rc) {
return rc;
}
-
} else {
struct cifsInodeInfo *cifsInfo;
__u32 type = le32_to_cpu(findData.Type);
@@ -85,21 +83,22 @@ cifs_get_inode_info_unix(struct inode **pinode,
return -ENOMEM;
/* Is an i_ino of zero legal? */
/* Are there sanity checks we can use to ensure that
- the server is really filling in that field? */
+ the server is really filling in that field? */
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
- (*pinode)->i_ino =
+ (*pinode)->i_ino =
(unsigned long)findData.UniqueId;
} /* note ino incremented to unique num in new_inode */
insert_inode_hash(*pinode);
}
-
+
inode = *pinode;
cifsInfo = CIFS_I(inode);
cFYI(1, (" Old time %ld ", cifsInfo->time));
cifsInfo->time = jiffies;
cFYI(1, (" New time %ld ", cifsInfo->time));
- atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */
+ /* this is ok to set on every inode revalidate */
+ atomic_set(&cifsInfo->inUse,1);
inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
@@ -133,22 +132,19 @@ cifs_get_inode_info_unix(struct inode **pinode,
inode->i_nlink = le64_to_cpu(findData.Nlinks);
if(is_size_safe_to_change(cifsInfo)) {
- /* can not safely change the file size here if the
+ /* can not safely change the file size here if the
client is writing to it due to potential races */
i_size_write(inode, end_of_file);
-/* blksize needs to be multiple of two. So safer to default to blksize
- and blkbits set in superblock so 2**blkbits and blksize will match */
-/* inode->i_blksize =
- (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
- /* This seems incredibly stupid but it turns out that
- i_blocks is not related to (i_size / i_blksize), instead a
- size of 512 is required to be used for calculating num blocks */
-
+ /* blksize needs to be multiple of two. So safer to default to
+ blksize and blkbits set in superblock so 2**blkbits and blksize
+ will match rather than setting to:
+ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
-/* inode->i_blocks =
- (inode->i_blksize - 1 + num_of_bytes) >> inode->i_blkbits;*/
+ /* This seems incredibly stupid but it turns out that i_blocks
+ is not related to (i_size / i_blksize), instead 512 byte size
+ is required for calculating num blocks */
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation */
@@ -156,14 +152,17 @@ cifs_get_inode_info_unix(struct inode **pinode,
}
if (num_of_bytes < end_of_file)
- cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
+ cFYI(1, ("allocation size less than end of file "));
cFYI(1,
- ("Size %ld and blocks %ld ",
+ ("Size %ld and blocks %ld",
(unsigned long) inode->i_size, inode->i_blocks));
if (S_ISREG(inode->i_mode)) {
cFYI(1, (" File inode "));
inode->i_op = &cifs_file_inode_ops;
- inode->i_fop = &cifs_file_ops;
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ inode->i_fop = &cifs_file_direct_ops;
+ else
+ inode->i_fop = &cifs_file_ops;
inode->i_data.a_ops = &cifs_addr_ops;
} else if (S_ISDIR(inode->i_mode)) {
cFYI(1, (" Directory inode"));
@@ -172,7 +171,7 @@ cifs_get_inode_info_unix(struct inode **pinode,
} else if (S_ISLNK(inode->i_mode)) {
cFYI(1, (" Symbolic Link inode "));
inode->i_op = &cifs_symlink_inode_ops;
-/* tmp_inode->i_fop = *//* do not need to set to anything */
+ /* tmp_inode->i_fop = */ /* do not need to set to anything */
} else {
cFYI(1, (" Init special inode "));
init_special_inode(inode, inode->i_mode,
@@ -182,9 +181,9 @@ cifs_get_inode_info_unix(struct inode **pinode,
return rc;
}
-int
-cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
- FILE_ALL_INFO * pfindData, struct super_block *sb, int xid)
+int cifs_get_inode_info(struct inode **pinode,
+ const unsigned char *search_path, FILE_ALL_INFO *pfindData,
+ struct super_block *sb, int xid)
{
int rc = 0;
struct cifsTconInfo *pTcon;
@@ -198,18 +197,18 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
if((pfindData == NULL) && (*pinode != NULL)) {
if(CIFS_I(*pinode)->clientCanCacheRead) {
- cFYI(1,("No need to revalidate inode sizes on cached file "));
+ cFYI(1,("No need to revalidate cached inode sizes"));
return rc;
}
}
/* if file info not passed in then get it from server */
if(pfindData == NULL) {
- buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
+ buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if(buf == NULL)
return -ENOMEM;
pfindData = (FILE_ALL_INFO *)buf;
- /* could do find first instead but this returns more info */
+ /* could do find first instead but this returns more info */
rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
cifs_sb->local_nls);
}
@@ -223,8 +222,7 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
strnlen(search_path, MAX_PATHCONF) + 1,
GFP_KERNEL);
if (tmp_path == NULL) {
- if(buf)
- kfree(buf);
+ kfree(buf);
return -ENOMEM;
}
@@ -236,8 +234,7 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
kfree(tmp_path);
/* BB fix up inode etc. */
} else if (rc) {
- if(buf)
- kfree(buf);
+ kfree(buf);
return rc;
}
} else {
@@ -247,23 +244,38 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
/* get new inode */
if (*pinode == NULL) {
*pinode = new_inode(sb);
- if(*pinode == NULL)
+ if (*pinode == NULL)
return -ENOMEM;
- /* Is an i_ino of zero legal? */
- /* Are there sanity checks we can use to ensure that
- the server is really filling in that field? */
-
- /* We can not use the IndexNumber from either
- Windows or Samba as it is frequently set to zero */
- /* There may be higher info levels that work but
- Are there Windows server or network appliances
- for which IndexNumber field is not guaranteed unique? */
-
- /* if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
- (*pinode)->i_ino =
- (unsigned long)pfindData->IndexNumber;
- } */ /*NB: ino incremented to unique num in new_inode*/
-
+ /* Is an i_ino of zero legal? Can we use that to check
+ if the server supports returning inode numbers? Are
+ there other sanity checks we can use to ensure that
+ the server is really filling in that field? */
+
+ /* We can not use the IndexNumber field by default from
+ Windows or Samba (in ALL_INFO buf) but we can request
+ it explicitly. It may not be unique presumably if
+ the server has multiple devices mounted under one
+ share */
+
+ /* There may be higher info levels that work but are
+ there Windows server or network appliances for which
+ IndexNumber field is not guaranteed unique? */
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
+ int rc1 = 0;
+ __u64 inode_num;
+
+ rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
+ search_path, &inode_num,
+ cifs_sb->local_nls);
+ if(rc1) {
+ cFYI(1,("GetSrvInodeNum rc %d", rc1));
+ /* BB EOPNOSUPP disable SERVER_INUM? */
+ } else /* do we need cast or hash to ino? */
+ (*pinode)->i_ino = inode_num;
+ } /* else ino incremented to unique num in new_inode*/
+#endif /* CIFS_EXPERIMENTAL */
insert_inode_hash(*pinode);
}
inode = *pinode;
@@ -273,10 +285,10 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
cifsInfo->time = jiffies;
cFYI(1, (" New time %ld ", cifsInfo->time));
-/* blksize needs to be multiple of two. So safer to default to blksize
- and blkbits set in superblock so 2**blkbits and blksize will match */
-/* inode->i_blksize =
- (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
+ /* blksize needs to be multiple of two. So safer to default to
+ blksize and blkbits set in superblock so 2**blkbits and blksize
+ will match rather than setting to:
+ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
/* Linux can not store file creation time unfortunately so we ignore it */
inode->i_atime =
@@ -285,56 +297,60 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
- cFYI(0,
- (" Attributes came in as 0x%x ", attr));
+ cFYI(0, (" Attributes came in as 0x%x ", attr));
/* set default mode. will override for dirs below */
- if(atomic_read(&cifsInfo->inUse) == 0)
+ if (atomic_read(&cifsInfo->inUse) == 0)
/* new inode, can safely set these fields */
inode->i_mode = cifs_sb->mnt_file_mode;
/* if (attr & ATTR_REPARSE) */
-/* We no longer handle these as symlinks because we could not */
-/* follow them due to the absolute path with drive letter */
+ /* We no longer handle these as symlinks because we could not
+ follow them due to the absolute path with drive letter */
if (attr & ATTR_DIRECTORY) {
- /* override default perms since we do not do byte range locking on dirs */
+ /* override default perms since we do not do byte range locking
+ on dirs */
inode->i_mode = cifs_sb->mnt_dir_mode;
inode->i_mode |= S_IFDIR;
} else {
inode->i_mode |= S_IFREG;
- /* treat the dos attribute of read-only as read-only mode e.g. 555 */
- if(cifsInfo->cifsAttrs & ATTR_READONLY)
+ /* treat the dos attribute of read-only as read-only
+ mode e.g. 555 */
+ if (cifsInfo->cifsAttrs & ATTR_READONLY)
inode->i_mode &= ~(S_IWUGO);
- /* BB add code here - validate if device or weird share or device type? */
+ /* BB add code here -
+ validate if device or weird share or device type? */
}
- if(is_size_safe_to_change(cifsInfo)) {
- /* can not safely change the file size here if the
- client is writing to it due to potential races */
-
+ if (is_size_safe_to_change(cifsInfo)) {
+ /* can not safely change the file size here if the
+ client is writing to it due to potential races */
i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
- /* 512 bytes (2**9) is the fake blocksize that must be used */
- /* for this calculation */
- inode->i_blocks = (512 - 1 + le64_to_cpu(pfindData->AllocationSize))
- >> 9;
+ /* 512 bytes (2**9) is the fake blocksize that must be
+ used for this calculation */
+ inode->i_blocks = (512 - 1 + le64_to_cpu(
+ pfindData->AllocationSize)) >> 9;
}
inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
/* BB fill in uid and gid here? with help from winbind?
- or retrieve from NTFS stream extended attribute */
- if(atomic_read(&cifsInfo->inUse) == 0) {
+ or retrieve from NTFS stream extended attribute */
+ if (atomic_read(&cifsInfo->inUse) == 0) {
inode->i_uid = cifs_sb->mnt_uid;
inode->i_gid = cifs_sb->mnt_gid;
/* set so we do not keep refreshing these fields with
- bad data after user has changed them in memory */
+ bad data after user has changed them in memory */
atomic_set(&cifsInfo->inUse,1);
}
-
+
if (S_ISREG(inode->i_mode)) {
cFYI(1, (" File inode "));
inode->i_op = &cifs_file_inode_ops;
- inode->i_fop = &cifs_file_ops;
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ inode->i_fop = &cifs_file_direct_ops;
+ else
+ inode->i_fop = &cifs_file_ops;
inode->i_data.a_ops = &cifs_addr_ops;
} else if (S_ISDIR(inode->i_mode)) {
cFYI(1, (" Directory inode "));
@@ -348,14 +364,13 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
inode->i_rdev);
}
}
- if(buf)
- kfree(buf);
+ kfree(buf);
return rc;
}
-void
-cifs_read_inode(struct inode *inode)
-{ /* gets root inode */
+/* gets root inode */
+void cifs_read_inode(struct inode *inode)
+{
int xid;
struct cifs_sb_info *cifs_sb;
@@ -369,8 +384,7 @@ cifs_read_inode(struct inode *inode)
_FreeXid(xid);
}
-int
-cifs_unlink(struct inode *inode, struct dentry *direntry)
+int cifs_unlink(struct inode *inode, struct dentry *direntry)
{
int rc = 0;
int xid;
@@ -378,7 +392,7 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
struct cifsTconInfo *pTcon;
char *full_path = NULL;
struct cifsInodeInfo *cifsInode;
- FILE_BASIC_INFO * pinfo_buf;
+ FILE_BASIC_INFO *pinfo_buf;
cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
@@ -387,12 +401,12 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
-/* Unlink can be called from rename so we can not grab
- the sem here since we deadlock otherwise */
+ /* Unlink can be called from rename so we can not grab the sem here
+ since we deadlock otherwise */
/* down(&direntry->d_sb->s_vfs_rename_sem);*/
full_path = build_path_from_dentry(direntry);
/* up(&direntry->d_sb->s_vfs_rename_sem);*/
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
@@ -406,39 +420,76 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
int oplock = FALSE;
__u16 netfid;
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
- CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
- &netfid, &oplock, NULL, cifs_sb->local_nls);
- if(rc==0) {
- CIFSSMBRenameOpenFile(xid,pTcon,netfid,
- NULL, cifs_sb->local_nls);
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
+ CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
+ &netfid, &oplock, NULL, cifs_sb->local_nls);
+ if (rc==0) {
+ CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
+ cifs_sb->local_nls);
CIFSSMBClose(xid, pTcon, netfid);
direntry->d_inode->i_nlink--;
}
} else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */
- pinfo_buf = (FILE_BASIC_INFO *)kmalloc(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 = kmalloc(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);
- rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf,
- cifs_sb->local_nls);
+ if (!(pTcon->ses->flags & CIFS_SES_NT4))
+ rc = CIFSSMBSetTimes(xid, pTcon, full_path,
+ pinfo_buf,
+ cifs_sb->local_nls);
+ else
+ rc = -EOPNOTSUPP;
+
+ if (rc == -EOPNOTSUPP) {
+ int oplock = FALSE;
+ __u16 netfid;
+ /* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
+ full_path,
+ (__u16)ATTR_NORMAL,
+ cifs_sb->local_nls);
+ For some strange reason it seems that NT4 eats the
+ old setattr call without actually setting the
+ attributes so on to the third attempted workaround
+ */
+
+ /* BB could scan to see if we already have it open
+ and pass in pid of opener to function */
+ rc = CIFSSMBOpen(xid, pTcon, full_path,
+ FILE_OPEN, SYNCHRONIZE |
+ FILE_WRITE_ATTRIBUTES, 0,
+ &netfid, &oplock, NULL,
+ cifs_sb->local_nls);
+ if (rc==0) {
+ rc = CIFSSMBSetFileTimes(xid, pTcon,
+ pinfo_buf,
+ netfid);
+ CIFSSMBClose(xid, pTcon, netfid);
+ }
+ }
kfree(pinfo_buf);
}
- if(rc==0) {
- rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
+ if (rc==0) {
+ rc = CIFSSMBDelFile(xid, pTcon, full_path,
+ cifs_sb->local_nls);
if (!rc) {
direntry->d_inode->i_nlink--;
} else if (rc == -ETXTBSY) {
int oplock = FALSE;
__u16 netfid;
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
- CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
- &netfid, &oplock, NULL, cifs_sb->local_nls);
- if(rc==0) {
- CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls);
+ rc = CIFSSMBOpen(xid, pTcon, full_path,
+ FILE_OPEN, DELETE,
+ CREATE_NOT_DIR |
+ CREATE_DELETE_ON_CLOSE,
+ &netfid, &oplock, NULL,
+ cifs_sb->local_nls);
+ if (rc==0) {
+ CIFSSMBRenameOpenFile(xid, pTcon,
+ netfid, NULL,
+ cifs_sb->local_nls);
CIFSSMBClose(xid, pTcon, netfid);
direntry->d_inode->i_nlink--;
}
@@ -447,20 +498,19 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
}
}
cifsInode = CIFS_I(direntry->d_inode);
- cifsInode->time = 0; /* will force revalidate to get info when needed */
+ cifsInode->time = 0; /* will force revalidate to get info when
+ needed */
direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
- current_fs_time(inode->i_sb);
+ current_fs_time(inode->i_sb);
cifsInode = CIFS_I(inode);
cifsInode->time = 0; /* force revalidate of dir as well */
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
-int
-cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
+int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
{
int rc = 0;
int xid;
@@ -479,7 +529,7 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
down(&inode->i_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(direntry);
up(&inode->i_sb->s_vfs_rename_sem);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
@@ -494,40 +544,39 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb,xid);
else
- rc = cifs_get_inode_info(&newinode, full_path,NULL,
+ rc = cifs_get_inode_info(&newinode, full_path, NULL,
inode->i_sb,xid);
direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode);
- if(direntry->d_inode)
+ if (direntry->d_inode)
direntry->d_inode->i_nlink = 2;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
- (__u64)current->euid,
- (__u64)current->egid,
- 0 /* dev_t */,
- cifs_sb->local_nls);
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+ mode,
+ (__u64)current->euid,
+ (__u64)current->egid,
+ 0 /* dev_t */,
+ cifs_sb->local_nls);
} else {
- CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
- (__u64)-1,
- (__u64)-1,
- 0 /* dev_t */,
- cifs_sb->local_nls);
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+ mode, (__u64)-1,
+ (__u64)-1, 0 /* dev_t */,
+ cifs_sb->local_nls);
}
- else { /* BB to be implemented via Windows secrty descriptors*/
- /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
+ else {
+ /* BB to be implemented via Windows secrty descriptors
+ eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
+ -1, -1, local_nls); */
}
}
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
-
return rc;
}
-int
-cifs_rmdir(struct inode *inode, struct dentry *direntry)
+int cifs_rmdir(struct inode *inode, struct dentry *direntry)
{
int rc = 0;
int xid;
@@ -546,7 +595,7 @@ cifs_rmdir(struct inode *inode, struct dentry *direntry)
down(&inode->i_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(direntry);
up(&inode->i_sb->s_vfs_rename_sem);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
@@ -560,19 +609,18 @@ cifs_rmdir(struct inode *inode, struct dentry *direntry)
}
cifsInode = CIFS_I(direntry->d_inode);
- cifsInode->time = 0; /* force revalidate to go get info when needed */
+ cifsInode->time = 0; /* force revalidate to go get info when
+ needed */
direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
- current_fs_time(inode->i_sb);
+ current_fs_time(inode->i_sb);
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
-int
-cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
- struct inode *target_inode, struct dentry *target_direntry)
+int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
+ struct inode *target_inode, struct dentry *target_direntry)
{
char *fromName;
char *toName;
@@ -589,91 +637,90 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
pTcon = cifs_sb_source->tcon;
if (pTcon != cifs_sb_target->tcon) {
- FreeXid(xid);
- return -EXDEV; /* BB actually could be allowed if same server, but
- different share. Might eventually add support for this */
+ FreeXid(xid);
+ return -EXDEV; /* BB actually could be allowed if same server,
+ but different share.
+ Might eventually add support for this */
}
- /* we already have the rename sem so we do not need
- to grab it again here to protect the path integrity */
+ /* we already have the rename sem so we do not need to grab it again
+ here to protect the path integrity */
fromName = build_path_from_dentry(source_direntry);
toName = build_path_from_dentry(target_direntry);
- if((fromName == NULL) || (toName == NULL)) {
+ if ((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM;
goto cifs_rename_exit;
}
rc = CIFSSMBRename(xid, pTcon, fromName, toName,
cifs_sb_source->local_nls);
- if(rc == -EEXIST) {
- /* check if they are the same file
- because rename of hardlinked files is a noop */
- FILE_UNIX_BASIC_INFO * info_buf_source;
- FILE_UNIX_BASIC_INFO * info_buf_target;
-
- info_buf_source =
- kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
- if(info_buf_source != NULL) {
- info_buf_target = info_buf_source+1;
- rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
+ if (rc == -EEXIST) {
+ /* check if they are the same file because rename of hardlinked
+ files is a noop */
+ FILE_UNIX_BASIC_INFO *info_buf_source;
+ FILE_UNIX_BASIC_INFO *info_buf_target;
+
+ info_buf_source =
+ kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+ if (info_buf_source != NULL) {
+ info_buf_target = info_buf_source + 1;
+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
info_buf_source, cifs_sb_source->local_nls);
- if(rc == 0) {
- rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
+ if (rc == 0) {
+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
info_buf_target,
cifs_sb_target->local_nls);
}
- if((rc == 0) &&
- (info_buf_source->UniqueId ==
- info_buf_target->UniqueId)) {
- /* do not rename since the files are hardlinked
- which is a noop */
+ if ((rc == 0) &&
+ (info_buf_source->UniqueId ==
+ info_buf_target->UniqueId)) {
+ /* do not rename since the files are hardlinked which
+ is a noop */
} else {
/* we either can not tell the files are hardlinked
- (as with Windows servers) or files are not hardlinked
- so delete the target manually before renaming to
- follow POSIX rather than Windows semantics */
+ (as with Windows servers) or files are not
+ hardlinked so delete the target manually before
+ renaming to follow POSIX rather than Windows
+ semantics */
cifs_unlink(target_inode, target_direntry);
- rc = CIFSSMBRename(xid, pTcon, fromName, toName,
- cifs_sb_source->local_nls);
+ rc = CIFSSMBRename(xid, pTcon, fromName,
+ toName,
+ cifs_sb_source->local_nls);
}
kfree(info_buf_source);
} /* if we can not get memory just leave rc as EEXIST */
}
if (rc) {
- cFYI(1,("rename rc %d",rc)); /* BB removeme BB */
+ cFYI(1, ("rename rc %d", rc));
}
- if((rc == -EIO)||(rc == -EEXIST)) {
+ if ((rc == -EIO) || (rc == -EEXIST)) {
int oplock = FALSE;
__u16 netfid;
/* BB FIXME Is Generic Read correct for rename? */
/* if renaming directory - we should not say CREATE_NOT_DIR,
- need to test renaming open directory, also GENERIC_READ
- might not right be right access to request */
+ need to test renaming open directory, also GENERIC_READ
+ might not right be right access to request */
rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
- CREATE_NOT_DIR,
- &netfid, &oplock, NULL, cifs_sb_source->local_nls);
- if(rc==0) {
- CIFSSMBRenameOpenFile(xid,pTcon,netfid,
- toName, cifs_sb_source->local_nls);
+ CREATE_NOT_DIR, &netfid, &oplock, NULL,
+ cifs_sb_source->local_nls);
+ if (rc==0) {
+ CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
+ cifs_sb_source->local_nls);
CIFSSMBClose(xid, pTcon, netfid);
}
}
cifs_rename_exit:
- if (fromName)
- kfree(fromName);
- if (toName)
- kfree(toName);
-
+ kfree(fromName);
+ kfree(toName);
FreeXid(xid);
return rc;
}
-int
-cifs_revalidate(struct dentry *direntry)
+int cifs_revalidate(struct dentry *direntry)
{
int xid;
int rc = 0;
@@ -684,119 +731,120 @@ cifs_revalidate(struct dentry *direntry)
struct timespec local_mtime;
int invalidate_inode = FALSE;
- if(direntry->d_inode == NULL)
+ if (direntry->d_inode == NULL)
return -ENOENT;
cifsInode = CIFS_I(direntry->d_inode);
- if(cifsInode == NULL)
+ if (cifsInode == NULL)
return -ENOENT;
/* no sense revalidating inode info on file that no one can write */
- if(CIFS_I(direntry->d_inode)->clientCanCacheRead)
+ if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
return rc;
xid = GetXid();
cifs_sb = CIFS_SB(direntry->d_sb);
- /* can not safely grab the rename sem here if
- rename calls revalidate since that would deadlock */
+ /* can not safely grab the rename sem here if rename calls revalidate
+ since that would deadlock */
full_path = build_path_from_dentry(direntry);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
- cFYI(1,
- ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
- full_path, direntry->d_inode,
- direntry->d_inode->i_count.counter, direntry,
- direntry->d_time, jiffies));
+ cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
+ "jiffies %ld", full_path, direntry->d_inode,
+ direntry->d_inode->i_count.counter, direntry,
+ direntry->d_time, jiffies));
- if (cifsInode->time == 0){
+ if (cifsInode->time == 0) {
/* was set to zero previously to force revalidate */
- } else if (time_before(jiffies, cifsInode->time + HZ) && lookupCacheEnabled) {
- if((S_ISREG(direntry->d_inode->i_mode) == 0) ||
- (direntry->d_inode->i_nlink == 1)) {
- if (full_path)
- kfree(full_path);
+ } else if (time_before(jiffies, cifsInode->time + HZ) &&
+ lookupCacheEnabled) {
+ if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
+ (direntry->d_inode->i_nlink == 1)) {
+ kfree(full_path);
FreeXid(xid);
return rc;
} else {
- cFYI(1,("Have to revalidate file due to hardlinks"));
- }
+ cFYI(1, ("Have to revalidate file due to hardlinks"));
+ }
}
-
+
/* save mtime and size */
local_mtime = direntry->d_inode->i_mtime;
- local_size = direntry->d_inode->i_size;
+ local_size = direntry->d_inode->i_size;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
- direntry->d_sb,xid);
- if(rc) {
- cFYI(1,("error on getting revalidate info %d",rc));
-/* if(rc != -ENOENT)
- rc = 0; */ /* BB should we cache info on certain errors? */
+ direntry->d_sb,xid);
+ if (rc) {
+ cFYI(1, ("error on getting revalidate info %d", rc));
+/* if (rc != -ENOENT)
+ rc = 0; */ /* BB should we cache info on
+ certain errors? */
}
} else {
rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
- direntry->d_sb,xid);
- if(rc) {
- cFYI(1,("error on getting revalidate info %d",rc));
-/* if(rc != -ENOENT)
- rc = 0; */ /* BB should we cache info on certain errors? */
+ direntry->d_sb,xid);
+ if (rc) {
+ cFYI(1, ("error on getting revalidate info %d", rc));
+/* if (rc != -ENOENT)
+ rc = 0; */ /* BB should we cache info on
+ certain errors? */
}
}
/* should we remap certain errors, access denied?, to zero */
- /* if not oplocked, we invalidate inode pages if mtime
- or file size had changed on server */
+ /* if not oplocked, we invalidate inode pages if mtime or file size
+ had changed on server */
- if(timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
- (local_size == direntry->d_inode->i_size)) {
- cFYI(1,("cifs_revalidate - inode unchanged"));
+ if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
+ (local_size == direntry->d_inode->i_size)) {
+ cFYI(1, ("cifs_revalidate - inode unchanged"));
} else {
/* file may have changed on server */
- if(cifsInode->clientCanCacheRead) {
- /* no need to invalidate inode pages since we were
- the only ones who could have modified the file and
- the server copy is staler than ours */
+ if (cifsInode->clientCanCacheRead) {
+ /* no need to invalidate inode pages since we were the
+ only ones who could have modified the file and the
+ server copy is staler than ours */
} else {
invalidate_inode = TRUE;
}
}
- /* can not grab this sem since kernel filesys locking
- documentation indicates i_sem may be taken by the kernel
- on lookup and rename which could deadlock if we grab
- the i_sem here as well */
+ /* can not grab this sem since kernel filesys locking documentation
+ indicates i_sem may be taken by the kernel on lookup and rename
+ which could deadlock if we grab the i_sem here as well */
/* down(&direntry->d_inode->i_sem);*/
/* need to write out dirty pages here */
- if(direntry->d_inode->i_mapping) {
- /* do we need to lock inode until after invalidate completes below? */
+ if (direntry->d_inode->i_mapping) {
+ /* do we need to lock inode until after invalidate completes
+ below? */
filemap_fdatawrite(direntry->d_inode->i_mapping);
}
- if(invalidate_inode) {
- if(direntry->d_inode->i_mapping)
+ if (invalidate_inode) {
+ if (direntry->d_inode->i_mapping)
filemap_fdatawait(direntry->d_inode->i_mapping);
/* may eventually have to do this for open files too */
- if(list_empty(&(cifsInode->openFileList))) {
+ if (list_empty(&(cifsInode->openFileList))) {
/* Has changed on server - flush read ahead pages */
- cFYI(1,("Invalidating read ahead data on closed file"));
+ cFYI(1, ("Invalidating read ahead data on "
+ "closed file"));
invalidate_remote_inode(direntry->d_inode);
}
}
-/* up(&direntry->d_inode->i_sem);*/
+/* up(&direntry->d_inode->i_sem); */
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
-
return rc;
}
-int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
{
int err = cifs_revalidate(dentry);
if (!err)
@@ -807,7 +855,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
static int cifs_truncate_page(struct address_space *mapping, loff_t from)
{
pgoff_t index = from >> PAGE_CACHE_SHIFT;
- unsigned offset = from & (PAGE_CACHE_SIZE-1);
+ unsigned offset = from & (PAGE_CACHE_SIZE - 1);
struct page *page;
char *kaddr;
int rc = 0;
@@ -825,8 +873,7 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
return rc;
}
-int
-cifs_setattr(struct dentry *direntry, struct iattr *attrs)
+int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
{
int xid;
struct cifs_sb_info *cifs_sb;
@@ -841,20 +888,19 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
__u64 uid = 0xFFFFFFFFFFFFFFFFULL;
__u64 gid = 0xFFFFFFFFFFFFFFFFULL;
struct cifsInodeInfo *cifsInode;
- struct list_head * tmp;
+ struct list_head *tmp;
xid = GetXid();
- cFYI(1,
- (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
- direntry->d_name.name, attrs->ia_valid));
+ cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
+ direntry->d_name.name, attrs->ia_valid));
cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
pTcon = cifs_sb->tcon;
down(&direntry->d_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(direntry);
up(&direntry->d_sb->s_vfs_rename_sem);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
@@ -863,73 +909,84 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
/* BB check if we need to refresh inode from server now ? BB */
/* need to flush data before changing file size on server */
- filemap_fdatawrite(direntry->d_inode->i_mapping);
+ filemap_fdatawrite(direntry->d_inode->i_mapping);
filemap_fdatawait(direntry->d_inode->i_mapping);
if (attrs->ia_valid & ATTR_SIZE) {
- read_lock(&GlobalSMBSeslock);
- /* To avoid spurious oplock breaks from server, in the case
- of inodes that we already have open, avoid doing path
- based setting of file size if we can do it by handle.
- This keeps our caching token (oplock) and avoids
- timeouts when the local oplock break takes longer to flush
- writebehind data than the SMB timeout for the SetPathInfo
- request would allow */
- list_for_each(tmp, &cifsInode->openFileList) {
- open_file = list_entry(tmp,struct cifsFileInfo, flist);
+ read_lock(&GlobalSMBSeslock);
+ /* To avoid spurious oplock breaks from server, in the case of
+ inodes that we already have open, avoid doing path based
+ setting of file size if we can do it by handle.
+ This keeps our caching token (oplock) and avoids timeouts
+ when the local oplock break takes longer to flush
+ writebehind data than the SMB timeout for the SetPathInfo
+ request would allow */
+ list_for_each(tmp, &cifsInode->openFileList) {
+ open_file = list_entry(tmp, struct cifsFileInfo,
+ flist);
/* We check if file is open for writing first */
- if((open_file->pfile) &&
- ((open_file->pfile->f_flags & O_RDWR) ||
- (open_file->pfile->f_flags & O_WRONLY))) {
- if(open_file->invalidHandle == FALSE) {
- /* we found a valid, writeable network file
- handle to use to try to set the file size */
+ if ((open_file->pfile) &&
+ ((open_file->pfile->f_flags & O_RDWR) ||
+ (open_file->pfile->f_flags & O_WRONLY))) {
+ if (open_file->invalidHandle == FALSE) {
+ /* we found a valid, writeable network
+ file handle to use to try to set the
+ file size */
__u16 nfid = open_file->netfid;
__u32 npid = open_file->pid;
read_unlock(&GlobalSMBSeslock);
found = TRUE;
- rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
- nfid,npid,FALSE);
- cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc));
- /* Do not need reopen and retry on EAGAIN since we will
- retry by pathname below */
-
- break; /* now that we found one valid file handle no
- sense continuing to loop trying others */
+ rc = CIFSSMBSetFileSize(xid, pTcon,
+ attrs->ia_size, nfid, npid,
+ FALSE);
+ cFYI(1, ("SetFileSize by handle "
+ "(setattrs) rc = %d", rc));
+ /* Do not need reopen and retry on
+ EAGAIN since we will retry by
+ pathname below */
+
+ /* now that we found one valid file
+ handle no sense continuing to loop
+ trying others, so break here */
+ break;
}
}
}
- if(found == FALSE) {
+ if (found == FALSE)
read_unlock(&GlobalSMBSeslock);
- }
-
- if(rc != 0) {
- /* Set file size by pathname rather than by handle either
- because no valid, writeable file handle for it was found or
- because there was an error setting it by handle */
- rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
- cifs_sb->local_nls);
- cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc));
+ if (rc != 0) {
+ /* Set file size by pathname rather than by handle
+ either because no valid, writeable file handle for
+ it was found or because there was an error setting
+ it by handle */
+ rc = CIFSSMBSetEOF(xid, pTcon, full_path,
+ attrs->ia_size, FALSE,
+ cifs_sb->local_nls);
+ cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
}
-
- /* Server is ok setting allocation size implicitly - no need to call: */
- /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
+
+ /* Server is ok setting allocation size implicitly - no need
+ to call:
+ CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE,
+ cifs_sb->local_nls);
+ */
if (rc == 0) {
rc = vmtruncate(direntry->d_inode, attrs->ia_size);
- cifs_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
+ cifs_truncate_page(direntry->d_inode->i_mapping,
+ direntry->d_inode->i_size);
}
}
if (attrs->ia_valid & ATTR_UID) {
cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
uid = attrs->ia_uid;
- /* entry->uid = cpu_to_le16(attr->ia_uid); */
+ /* entry->uid = cpu_to_le16(attr->ia_uid); */
}
if (attrs->ia_valid & ATTR_GID) {
cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
gid = attrs->ia_gid;
- /* entry->gid = cpu_to_le16(attr->ia_gid); */
+ /* entry->gid = cpu_to_le16(attr->ia_gid); */
}
time_buf.Attributes = 0;
@@ -942,19 +999,23 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
&& (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
- 0 /* dev_t */, cifs_sb->local_nls);
+ 0 /* dev_t */, cifs_sb->local_nls);
else if (attrs->ia_valid & ATTR_MODE) {
- if((mode & S_IWUGO) == 0) /* not writeable */ {
- if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
- time_buf.Attributes =
- cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY);
- } else if((mode & S_IWUGO) == S_IWUGO) {
- if(cifsInode->cifsAttrs & ATTR_READONLY)
- time_buf.Attributes =
- cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY));
+ if ((mode & S_IWUGO) == 0) /* not writeable */ {
+ if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
+ time_buf.Attributes =
+ cpu_to_le32(cifsInode->cifsAttrs |
+ ATTR_READONLY);
+ } else if ((mode & S_IWUGO) == S_IWUGO) {
+ if (cifsInode->cifsAttrs & ATTR_READONLY)
+ time_buf.Attributes =
+ cpu_to_le32(cifsInode->cifsAttrs &
+ (~ATTR_READONLY));
}
- /* BB to be implemented - via Windows security descriptors or streams */
- /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/
+ /* BB to be implemented -
+ via Windows security descriptors or streams */
+ /* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
+ cifs_sb->local_nls); */
}
if (attrs->ia_valid & ATTR_ATIME) {
@@ -973,56 +1034,63 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
if (attrs->ia_valid & ATTR_CTIME) {
set_time = TRUE;
- cFYI(1, (" CIFS - CTIME changed ")); /* BB probably do not need */
+ cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */
time_buf.ChangeTime =
cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
} else
time_buf.ChangeTime = 0;
if (set_time || time_buf.Attributes) {
- /* BB what if setting one attribute fails
- (such as size) but time setting works */
+ /* BB what if setting one attribute fails (such as size) but
+ time setting works? */
time_buf.CreationTime = 0; /* do not change */
/* In the future we should experiment - try setting timestamps
- via Handle (SetFileInfo) instead of by path */
- rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
- cifs_sb->local_nls);
- if(rc == -EOPNOTSUPP) {
+ via Handle (SetFileInfo) instead of by path */
+ if (!(pTcon->ses->flags & CIFS_SES_NT4))
+ rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
+ cifs_sb->local_nls);
+ else
+ rc = -EOPNOTSUPP;
+
+ if (rc == -EOPNOTSUPP) {
int oplock = FALSE;
__u16 netfid;
- cFYI(1,("calling SetFileInfo since SetPathInfo for times not supported by this server"));
- /* BB we could scan to see if we already have it open */
- /* and pass in pid of opener to function */
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, FILE_WRITE_ATTRIBUTES,
- CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
- if(rc==0) {
- rc = CIFSSMBSetFileTimes(xid, pTcon,
- &time_buf, netfid);
+ cFYI(1, ("calling SetFileInfo since SetPathInfo for "
+ "times not supported by this server"));
+ /* BB we could scan to see if we already have it open
+ and pass in pid of opener to function */
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
+ SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
+ CREATE_NOT_DIR, &netfid, &oplock,
+ NULL, cifs_sb->local_nls);
+ if (rc==0) {
+ rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
+ netfid);
CIFSSMBClose(xid, pTcon, netfid);
} else {
/* BB For even older servers we could convert time_buf
- into old DOS style which uses two second granularity */
+ into old DOS style which uses two second
+ granularity */
/* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
- &time_buf, cifs_sb->local_nls); */
+ &time_buf, cifs_sb->local_nls); */
}
}
}
- /* do not need local check to inode_check_ok since the server does that */
+ /* do not need local check to inode_check_ok since the server does
+ that */
if (!rc)
rc = inode_setattr(direntry->d_inode, attrs);
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
-void
-cifs_delete_inode(struct inode *inode)
+void cifs_delete_inode(struct inode *inode)
{
cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
/* may have to add back in if and when safe distributed caching of
- directories added e.g. via FindNotify */
+ directories added e.g. via FindNotify */
}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 20aa4d8872e0d..7b38d3059a83d 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -353,10 +353,14 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
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)) {
- cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
- if (((unsigned int)length >= sizeof (struct smb_hdr) - 1)
- && (smb->Status.CifsError != 0))
+ if (((unsigned 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 */
+ } else {
+ cERROR(1, ("Length less than smb header size"));
+ }
}
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 5b15cee2ca2ab..6facb41117a3e 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -35,7 +35,7 @@
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
-#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
+#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 8a9baa8ada32f..f8bea395ec9e2 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -31,14 +31,13 @@
#include "cifs_fs_sb.h"
#include "cifsfs.h"
-
/* BB fixme - add debug wrappers around this function to disable it fixme BB */
-/* static void dump_cifs_file_struct(struct file * file, char * label)
+/* static void dump_cifs_file_struct(struct file *file, char *label)
{
struct cifsFileInfo * cf;
if(file) {
- cf = (struct cifsFileInfo *)file->private_data;
+ cf = file->private_data;
if(cf == NULL) {
cFYI(1,("empty cifs private file data"));
return;
@@ -59,7 +58,7 @@
/* Returns one if new inode created (which therefore needs to be hashed) */
/* Might check in the future if inode number changed so we can rehash inode */
static int construct_dentry(struct qstr *qstring, struct file *file,
- struct inode **ptmp_inode, struct dentry **pnew_dentry)
+ struct inode **ptmp_inode, struct dentry **pnew_dentry)
{
struct dentry *tmp_dentry;
struct cifs_sb_info *cifs_sb;
@@ -106,7 +105,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
}
static void fill_in_inode(struct inode *tmp_inode,
- FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
+ FILE_DIRECTORY_INFO *pfindData, int *pobject_type)
{
struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
@@ -127,17 +126,15 @@ static void fill_in_inode(struct inode *tmp_inode,
/* treat dos attribute of read-only as read-only mode bit e.g. 555? */
/* 2767 perms - indicate mandatory locking */
/* BB fill in uid and gid here? with help from winbind?
- or retrieve from NTFS stream extended attribute */
- if(atomic_read(&cifsInfo->inUse) == 0) {
+ or retrieve from NTFS stream extended attribute */
+ if (atomic_read(&cifsInfo->inUse) == 0) {
tmp_inode->i_uid = cifs_sb->mnt_uid;
tmp_inode->i_gid = cifs_sb->mnt_gid;
/* set default mode. will override for dirs below */
tmp_inode->i_mode = cifs_sb->mnt_file_mode;
}
- cFYI(0,
- ("CIFS FFIRST: Attributes came in as 0x%x",
- attr));
+ cFYI(0,("CIFS FFIRST: Attributes came in as 0x%x",attr));
if (attr & ATTR_DIRECTORY) {
*pobject_type = DT_DIR;
/* override default perms since we do not lock dirs */
@@ -148,23 +145,23 @@ static void fill_in_inode(struct inode *tmp_inode,
/* we no longer mark these because we could not follow them */
/* } else if (attr & ATTR_REPARSE) {
*pobject_type = DT_LNK;
- tmp_inode->i_mode |= S_IFLNK;*/
+ tmp_inode->i_mode |= S_IFLNK; */
} else {
*pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG;
- if(attr & ATTR_READONLY)
+ if (attr & ATTR_READONLY)
tmp_inode->i_mode &= ~(S_IWUGO);
- }/* could add code here - to validate if device or weird share type? */
+ } /* could add code here - to validate if device or weird share type? */
/* can not fill in nlink here as in qpathinfo version and Unx search */
- if(atomic_read(&cifsInfo->inUse) == 0) {
- atomic_set(&cifsInfo->inUse,1);
+ if (atomic_read(&cifsInfo->inUse) == 0) {
+ atomic_set(&cifsInfo->inUse, 1);
}
- if(is_size_safe_to_change(cifsInfo)) {
+ if (is_size_safe_to_change(cifsInfo)) {
/* can not safely change the file size here if the
client is writing to it due to potential races */
- i_size_write(tmp_inode,end_of_file);
+ i_size_write(tmp_inode, end_of_file);
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation, even though the reported blocksize is larger */
@@ -172,15 +169,18 @@ static void fill_in_inode(struct inode *tmp_inode,
}
if (allocation_size < end_of_file)
- cFYI(1, ("Possible sparse file: allocation size less than end of file "));
+ cFYI(1, ("May be sparse file, allocation less than file size"));
cFYI(1,
("File Size %ld and blocks %ld and blocksize %ld",
- (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
+ (unsigned long)tmp_inode->i_size, tmp_inode->i_blocks,
tmp_inode->i_blksize));
if (S_ISREG(tmp_inode->i_mode)) {
cFYI(1, (" File inode "));
tmp_inode->i_op = &cifs_file_inode_ops;
- tmp_inode->i_fop = &cifs_file_ops;
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ tmp_inode->i_fop = &cifs_file_direct_ops;
+ else
+ tmp_inode->i_fop = &cifs_file_ops;
tmp_inode->i_data.a_ops = &cifs_addr_ops;
} else if (S_ISDIR(tmp_inode->i_mode)) {
cFYI(1, (" Directory inode"));
@@ -197,9 +197,11 @@ static void fill_in_inode(struct inode *tmp_inode,
}
static void unix_fill_in_inode(struct inode *tmp_inode,
- FILE_UNIX_INFO * pfindData, int *pobject_type)
+ FILE_UNIX_INFO *pfindData, int *pobject_type)
{
struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+
__u32 type = le32_to_cpu(pfindData->Type);
__u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
__u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
@@ -245,8 +247,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
-
- if(is_size_safe_to_change(cifsInfo)) {
+ if (is_size_safe_to_change(cifsInfo)) {
/* can not safely change the file size here if the
client is writing to it due to potential races */
i_size_write(tmp_inode,end_of_file);
@@ -259,7 +260,10 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
if (S_ISREG(tmp_inode->i_mode)) {
cFYI(1, ("File inode"));
tmp_inode->i_op = &cifs_file_inode_ops;
- tmp_inode->i_fop = &cifs_file_ops;
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ tmp_inode->i_fop = &cifs_file_direct_ops;
+ else
+ tmp_inode->i_fop = &cifs_file_ops;
tmp_inode->i_data.a_ops = &cifs_addr_ops;
} else if (S_ISDIR(tmp_inode->i_mode)) {
cFYI(1, ("Directory inode"));
@@ -276,8 +280,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
}
}
-
-static int initiate_cifs_search(const int xid, struct file * file)
+static int initiate_cifs_search(const int xid, struct file *file)
{
int rc = 0;
char * full_path;
@@ -295,7 +298,7 @@ static int initiate_cifs_search(const int xid, struct file * file)
} else {
memset(file->private_data,0,sizeof(struct cifsFileInfo));
}
- cifsFile = (struct cifsFileInfo *)file->private_data;
+ cifsFile = file->private_data;
cifsFile->invalidHandle = TRUE;
cifsFile->srch_inf.endOfSearch = FALSE;
@@ -322,7 +325,7 @@ static int initiate_cifs_search(const int xid, struct file * file)
/* test for Unix extensions */
if (pTcon->ses->capabilities & CAP_UNIX) {
- cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
+ cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
} else /* not srvinos - BB fixme add check for backlevel? */ {
@@ -333,13 +336,12 @@ static int initiate_cifs_search(const int xid, struct file * file)
&cifsFile->netfid, &cifsFile->srch_inf);
if(rc == 0)
cifsFile->invalidHandle = FALSE;
- if(full_path)
- kfree(full_path);
+ kfree(full_path);
return rc;
}
/* return length of unicode string in bytes */
-static int cifs_unicode_bytelen(char * str)
+static int cifs_unicode_bytelen(char *str)
{
int len;
__le16 * ustr = (__le16 *)str;
@@ -352,7 +354,7 @@ static int cifs_unicode_bytelen(char * str)
return len << 1;
}
-static char * nxt_dir_entry(char * old_entry, char * end_of_smb)
+static char *nxt_dir_entry(char *old_entry, char *end_of_smb)
{
char * new_entry;
FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
@@ -372,7 +374,7 @@ static char * nxt_dir_entry(char * old_entry, char * end_of_smb)
#define UNICODE_DOT cpu_to_le16(0x2e)
/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
-static int cifs_entry_is_dot(char * current_entry, struct cifsFileInfo * cfile)
+static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
{
int rc = 0;
char * filename = NULL;
@@ -444,14 +446,14 @@ static int cifs_entry_is_dot(char * current_entry, struct cifsFileInfo * cfile)
assume that they are located in the findfirst return buffer.*/
/* We start counting in the buffer with entry 2 and increment for every
entry (do not increment for . or .. entry) */
-static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
- struct file * file, char ** ppCurrentEntry,int * num_to_ret)
+static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
+ struct file *file, char **ppCurrentEntry, int *num_to_ret)
{
int rc = 0;
int pos_in_buf = 0;
loff_t first_entry_in_buffer;
loff_t index_to_find = file->f_pos;
- struct cifsFileInfo * cifsFile = (struct cifsFileInfo *)file->private_data;
+ struct cifsFileInfo * cifsFile = file->private_data;
/* check if index in the buffer */
if((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL))
@@ -467,12 +469,10 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
cFYI(1,("search backing up - close and restart search"));
cifsFile->invalidHandle = TRUE;
CIFSFindClose(xid, pTcon, cifsFile->netfid);
- if(cifsFile->search_resume_name) {
- kfree(cifsFile->search_resume_name);
- cifsFile->search_resume_name = NULL;
- }
+ kfree(cifsFile->search_resume_name);
+ cifsFile->search_resume_name = NULL;
if(cifsFile->srch_inf.ntwrk_buf_start) {
- cFYI(1,("freeing SMB ff cache buf on search rewind"));
+ cFYI(1,("freeing SMB ff cache buf on search rewind"));
cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start);
}
rc = initiate_cifs_search(xid,file);
@@ -495,10 +495,11 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
int i;
char * current_entry;
char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
- smbCalcSize((struct smb_hdr *)cifsFile->srch_inf.ntwrk_buf_start);
+ smbCalcSize((struct smb_hdr *)
+ cifsFile->srch_inf.ntwrk_buf_start);
/* dump_cifs_file_struct(file,"found entry in fce "); */
- first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry -
- cifsFile->srch_inf.entries_in_buffer;
+ first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
+ - cifsFile->srch_inf.entries_in_buffer;
pos_in_buf = index_to_find - first_entry_in_buffer;
cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
current_entry = cifsFile->srch_inf.srch_entries_start;
@@ -517,7 +518,10 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
current_entry = nxt_dir_entry(current_entry,end_of_smb);
}
if((current_entry == NULL) && (i < pos_in_buf)) {
- cERROR(1,("reached end of buf searching for pos in buf %d index to find %lld rc %d",pos_in_buf,index_to_find,rc)); /* BB removeme BB */
+ /* BB fixme - check if we should flag this error */
+ cERROR(1,("reached end of buf searching for pos in buf"
+ " %d index to find %lld rc %d",
+ pos_in_buf,index_to_find,rc));
}
rc = 0;
*ppCurrentEntry = current_entry;
@@ -537,13 +541,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
}
/* inode num, inode type and filename returned */
-static int cifs_get_name_from_search_buf(struct qstr * pqst,char * current_entry,
- __u16 level,unsigned int unicode,struct nls_table * nlt,
- ino_t * pinum)
+static int cifs_get_name_from_search_buf(struct qstr *pqst,
+ char *current_entry, __u16 level, unsigned int unicode,
+ struct cifs_sb_info * cifs_sb, ino_t *pinum)
{
int rc = 0;
unsigned int len = 0;
char * filename;
+ struct nls_table * nlt = cifs_sb->local_nls;
*pinum = 0;
@@ -559,7 +564,8 @@ static int cifs_get_name_from_search_buf(struct qstr * pqst,char * current_entry
}
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB fixme */
- *pinum = pFindData->UniqueId;
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+ *pinum = pFindData->UniqueId;
} else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
FILE_DIRECTORY_INFO * pFindData =
(FILE_DIRECTORY_INFO *)current_entry;
@@ -598,10 +604,8 @@ static int cifs_get_name_from_search_buf(struct qstr * pqst,char * current_entry
return rc;
}
-
-static int
-cifs_filldir(char * pfindEntry, struct file *file,
- filldir_t filldir, void *direntry,char * scratch_buf)
+static int cifs_filldir(char *pfindEntry, struct file *file,
+ filldir_t filldir, void *direntry, char *scratch_buf)
{
int rc = 0;
struct qstr qstring;
@@ -631,7 +635,7 @@ cifs_filldir(char * pfindEntry, struct file *file,
qstring.name = scratch_buf;
rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
pCifsF->srch_inf.info_level,
- pCifsF->srch_inf.unicode,cifs_sb->local_nls,
+ pCifsF->srch_inf.unicode,cifs_sb,
&inum /* returned */);
if(rc)
@@ -665,7 +669,8 @@ cifs_filldir(char * pfindEntry, struct file *file,
return rc;
}
-static int cifs_save_resume_key(const char * current_entry,struct cifsFileInfo * cifsFile)
+static int cifs_save_resume_key(const char *current_entry,
+ struct cifsFileInfo *cifsFile)
{
int rc = 0;
unsigned int len = 0;
@@ -785,7 +790,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
FreeXid(xid);
return rc;
}
- cifsFile = (struct cifsFileInfo *) file->private_data;
+ cifsFile = file->private_data;
if (cifsFile->srch_inf.endOfSearch) {
if(cifsFile->srch_inf.emptyDir) {
cFYI(1, ("End of search, empty dir"));
@@ -796,11 +801,10 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
cifsFile->invalidHandle = TRUE;
CIFSFindClose(xid, pTcon, cifsFile->netfid);
}
- if(cifsFile->search_resume_name) {
- kfree(cifsFile->search_resume_name);
- cifsFile->search_resume_name = NULL;
- } */
-/* BB account for . and .. in f_pos */
+ kfree(cifsFile->search_resume_name);
+ cifsFile->search_resume_name = NULL; */
+
+ /* BB account for . and .. in f_pos as special case */
/* dump_cifs_file_struct(file, "rdir after default ");*/
rc = find_cifs_entry(xid,pTcon, file,
@@ -816,33 +820,43 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
}
cFYI(1,("loop through %d times filling dir for net buf %p",
num_to_fill,cifsFile->srch_inf.ntwrk_buf_start));
- end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
- smbCalcSize((struct smb_hdr *)cifsFile->srch_inf.ntwrk_buf_start);
+ end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
+ smbCalcSize((struct smb_hdr *)
+ cifsFile->srch_inf.ntwrk_buf_start);
tmp_buf = kmalloc(NAME_MAX+1,GFP_KERNEL);
for(i=0;(i<num_to_fill) && (rc == 0);i++) {
if(current_entry == NULL) {
- cERROR(1,("beyond end of smb with num to fill %d i %d",num_to_fill,i)); /* BB removeme BB */
+ /* evaluate whether this case is an error */
+ cERROR(1,("past end of SMB num to fill %d i %d",
+ num_to_fill, i));
break;
}
-/* if((!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) ||
- (cifsFile->srch_inf.info_level != something that supports server inodes)) {
+
+ /* BB FIXME - need to enable the below code BB */
+
+ /* if((!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) ||
+ (cifsFile->srch_inf.info_level !=
+ something that supports server inodes)) {
create dentry
create inode
- fill in inode new_inode (which makes number locally)
+ fill in inode new_inode (getting local i_ino)
}
- also create local inode for per reasons unless new mount parm says otherwise */
+ also create local inode for performance reasons (so we
+ have a cache of inode metadata) unless this new mount
+ parm says otherwise */
+
rc = cifs_filldir(current_entry, file,
filldir, direntry,tmp_buf);
file->f_pos++;
if(file->f_pos == cifsFile->srch_inf.index_of_last_entry) {
- cFYI(1,("last entry in buf at pos %lld %s",file->f_pos,tmp_buf)); /* BB removeme BB */
+ cFYI(1,("last entry in buf at pos %lld %s",
+ file->f_pos,tmp_buf)); /* BB removeme BB */
cifs_save_resume_key(current_entry,cifsFile);
break;
} else
current_entry = nxt_dir_entry(current_entry,end_of_smb);
}
- if(tmp_buf != NULL)
- kfree(tmp_buf);
+ kfree(tmp_buf);
break;
} /* end switch */
@@ -851,4 +865,3 @@ rddir2_exit:
FreeXid(xid);
return rc;
}
-
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 6d0e70efd3990..d6efb36cab2a7 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -315,7 +315,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
struct backing_dev_info *bdi = mapping->backing_dev_info;
long pages_skipped;
- if (bdi->memory_backed) {
+ if (!bdi_cap_writeback_dirty(bdi)) {
list_move(&inode->i_list, &sb->s_dirty);
if (sb == blockdev_superblock) {
/*
@@ -566,7 +566,7 @@ int write_inode_now(struct inode *inode, int sync)
.sync_mode = WB_SYNC_ALL,
};
- if (inode->i_mapping->backing_dev_info->memory_backed)
+ if (!mapping_cap_writeback_dirty(inode->i_mapping))
return 0;
might_sleep();
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index cfb9801f6ccff..a88ad29248511 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -806,15 +806,21 @@ int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
char *name;
int r = 0, w = 0, x = 0, err;
- if(desired & MAY_READ) r = 1;
- if(desired & MAY_WRITE) w = 1;
- if(desired & MAY_EXEC) x = 1;
+ if (desired & MAY_READ) r = 1;
+ if (desired & MAY_WRITE) w = 1;
+ if (desired & MAY_EXEC) x = 1;
name = inode_name(ino, 0);
- if(name == NULL) return(-ENOMEM);
- err = access_file(name, r, w, x);
+ if (name == NULL) return(-ENOMEM);
+
+ if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
+ S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
+ err = 0;
+ else
+ err = access_file(name, r, w, x);
kfree(name);
- if(!err) err = generic_permission(ino, desired, NULL);
- return(err);
+ if(!err)
+ err = generic_permission(ino, desired, NULL);
+ return err;
}
int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7a006cc6e1c24..2af3338f891bb 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -40,7 +40,7 @@ static struct inode_operations hugetlbfs_inode_operations;
static struct backing_dev_info hugetlbfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
int sysctl_hugetlb_shm_group;
diff --git a/fs/inode.c b/fs/inode.c
index ff654a2683312..90025a39a789f 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1098,15 +1098,16 @@ static inline void iput_final(struct inode *inode)
* @inode: inode to put
*
* Puts an inode, dropping its usage count. If the inode use count hits
- * zero the inode is also then freed and may be destroyed.
+ * zero, the inode is then freed and may also be destroyed.
+ *
+ * Consequently, iput() can sleep.
*/
void iput(struct inode *inode)
{
if (inode) {
struct super_operations *op = inode->i_sb->s_op;
- if (inode->i_state == I_CLEAR)
- BUG();
+ BUG_ON(inode->i_state == I_CLEAR);
if (op && op->put_inode)
op->put_inode(inode);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index cb094d03287cf..73f96acd5d378 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1472,8 +1472,8 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
if (cache->cred)
put_rpccred(cache->cred);
cache->cred = get_rpccred(set->cred);
- NFS_FLAGS(inode) &= ~NFS_INO_INVALID_ACCESS;
}
+ NFS_FLAGS(inode) &= ~NFS_INO_INVALID_ACCESS;
cache->jiffies = set->jiffies;
cache->mask = set->mask;
}
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 172393942ac0c..11ebf6c4aa54c 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -49,12 +49,16 @@
/* mode bit translations: */
-#define NFS4_READ_MODE (NFS4_ACE_READ_DATA | NFS4_ACE_READ_NAMED_ATTRS)
-#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_WRITE_NAMED_ATTRS | NFS4_ACE_APPEND_DATA)
+#define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
+#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
+/* We don't support these bits; insist they be neither allowed nor denied */
+#define NFS4_MASK_UNSUPP (NFS4_ACE_DELETE | NFS4_ACE_WRITE_OWNER \
+ | NFS4_ACE_READ_NAMED_ATTRS | NFS4_ACE_WRITE_NAMED_ATTRS)
+
/* flags used to simulate posix default ACLs */
#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
| NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
@@ -83,12 +87,15 @@ mask_from_posix(unsigned short perm, unsigned int flags)
static u32
deny_mask(u32 allow_mask, unsigned int flags)
{
- u32 ret = ~allow_mask & ~NFS4_ACE_DELETE;
+ u32 ret = ~allow_mask & ~NFS4_MASK_UNSUPP;
if (!(flags & NFS4_ACL_DIR))
ret &= ~NFS4_ACE_DELETE_CHILD;
return ret;
}
+/* XXX: modify functions to return NFS errors; they're only ever
+ * used by nfs code, after all.... */
+
static int
mode_from_nfs4(u32 perm, unsigned short *mode, unsigned int flags)
{
@@ -940,35 +947,8 @@ match_who(struct nfs4_ace *ace, uid_t owner, gid_t group, uid_t who)
}
}
-/* 0 = granted, -EACCES = denied; mask is an nfsv4 mask, not mode bits */
-int
-nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
- uid_t who, u32 mask)
-{
- struct nfs4_ace *ace;
- u32 allowed = 0;
-
- list_for_each_entry(ace, &acl->ace_head, l_ace) {
- if (!match_who(ace, group, owner, who))
- continue;
- switch (ace->type) {
- case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE:
- allowed |= ace->access_mask;
- if ((allowed & mask) == mask)
- return 0;
- break;
- case NFS4_ACE_ACCESS_DENIED_ACE_TYPE:
- if (ace->access_mask & mask)
- return -EACCES;
- break;
- }
- }
- return -EACCES;
-}
-
EXPORT_SYMBOL(nfs4_acl_new);
EXPORT_SYMBOL(nfs4_acl_free);
EXPORT_SYMBOL(nfs4_acl_add_ace);
EXPORT_SYMBOL(nfs4_acl_get_whotype);
EXPORT_SYMBOL(nfs4_acl_write_who);
-EXPORT_SYMBOL(nfs4_acl_permission);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 271c231e7ba44..c70de9c2af746 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -541,7 +541,7 @@ out:
atomic_set(&clp->cl_callback.cb_set, 0);
/* Success or failure, now we're either waiting for lease expiration
* or deleg_return. */
- nfs4_put_delegation(dp);
dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
+ nfs4_put_delegation(dp);
return;
}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 6146c284da0f1..e8158741e8b5c 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -197,30 +197,40 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
}
if (status)
goto out;
- if (open->op_claim_type == NFS4_OPEN_CLAIM_NULL) {
- /*
- * This block of code will (1) set CURRENT_FH to the file being opened,
- * creating it if necessary, (2) set open->op_cinfo,
- * (3) set open->op_truncate if the file is to be truncated
- * after opening, (4) do permission checking.
- */
- status = do_open_lookup(rqstp, current_fh, open);
- if (status)
+ switch (open->op_claim_type) {
+ case NFS4_OPEN_CLAIM_NULL:
+ /*
+ * (1) set CURRENT_FH to the file being opened,
+ * creating it if necessary, (2) set open->op_cinfo,
+ * (3) set open->op_truncate if the file is to be
+ * truncated after opening, (4) do permission checking.
+ */
+ status = do_open_lookup(rqstp, current_fh, open);
+ if (status)
+ goto out;
+ break;
+ case NFS4_OPEN_CLAIM_PREVIOUS:
+ /*
+ * The CURRENT_FH is already set to the file being
+ * opened. (1) set open->op_cinfo, (2) set
+ * open->op_truncate if the file is to be truncated
+ * after opening, (3) do permission checking.
+ */
+ status = do_open_fhandle(rqstp, current_fh, open);
+ if (status)
+ goto out;
+ break;
+ case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+ case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+ printk("NFSD: unsupported OPEN claim type %d\n",
+ open->op_claim_type);
+ status = nfserr_notsupp;
goto out;
- } else if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) {
- /*
- * The CURRENT_FH is already set to the file being opened. This
- * block of code will (1) set open->op_cinfo, (2) set
- * open->op_truncate if the file is to be truncated after opening,
- * (3) do permission checking.
- */
- status = do_open_fhandle(rqstp, current_fh, open);
- if (status)
+ default:
+ printk("NFSD: Invalid OPEN claim type %d\n",
+ open->op_claim_type);
+ status = nfserr_inval;
goto out;
- } else {
- printk("NFSD: unsupported OPEN claim type\n");
- status = nfserr_inval;
- goto out;
}
/*
* nfsd4_process_open2() does the actual opening of the file. If
@@ -573,8 +583,8 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
status = nfs_ok;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
nfs4_lock_state();
- if ((status = nfs4_preprocess_stateid_op(current_fh,
- &setattr->sa_stateid,
+ if ((status = nfs4_preprocess_stateid_op(current_fh,
+ &setattr->sa_stateid,
CHECK_FH | WR_STATE, NULL))) {
dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
goto out_unlock;
@@ -609,7 +619,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
return nfserr_inval;
nfs4_lock_state();
- if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
+ if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
CHECK_FH | WR_STATE, &filp))) {
dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
goto out;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 945328d7c3a2a..579f7fea79681 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -176,15 +176,11 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
}
}
-/* release_delegation:
- *
- * Remove the associated file_lock first, then remove the delegation.
+/* Remove the associated file_lock first, then remove the delegation.
* lease_modify() is called to remove the FS_LEASE file_lock from
* the i_flock list, eventually calling nfsd's lock_manager
* fl_release_callback.
- *
*/
-
static void
nfs4_close_delegation(struct nfs4_delegation *dp)
{
@@ -201,7 +197,7 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
/* Called under the state lock. */
static void
-release_delegation(struct nfs4_delegation *dp)
+unhash_delegation(struct nfs4_delegation *dp)
{
list_del_init(&dp->dl_del_perfile);
list_del_init(&dp->dl_del_perclnt);
@@ -345,7 +341,7 @@ expire_client(struct nfs4_client *clp)
while (!list_empty(&reaplist)) {
dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
list_del_init(&dp->dl_recall_lru);
- release_delegation(dp);
+ unhash_delegation(dp);
}
list_del(&clp->cl_idhash);
list_del(&clp->cl_strhash);
@@ -1123,7 +1119,8 @@ release_stateowner(struct nfs4_stateowner *sop)
}
static inline void
-init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open) {
+init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
+ struct nfs4_stateowner *sop = open->op_stateowner;
unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
INIT_LIST_HEAD(&stp->st_hash);
@@ -1529,20 +1526,19 @@ out:
}
static int
-nfs4_check_open(struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open, struct nfs4_stateid **stpp)
+nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
{
struct nfs4_stateid *local;
int status = nfserr_share_denied;
+ struct nfs4_stateowner *sop = open->op_stateowner;
list_for_each_entry(local, &fp->fi_perfile, st_perfile) {
- /* have we seen this open owner */
- if (local->st_stateowner == sop) {
- *stpp = local;
- continue;
- }
/* ignore lock owners */
if (local->st_stateowner->so_is_open_owner == 0)
continue;
+ /* remember if we have seen this open owner */
+ if (local->st_stateowner == sop)
+ *stpp = local;
/* check for conflicting share reservations */
if (!test_share(local, open))
goto out;
@@ -1575,6 +1571,21 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
return 0;
}
+static inline int
+nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
+ struct nfsd4_open *open)
+{
+ struct iattr iattr = {
+ .ia_valid = ATTR_SIZE,
+ .ia_size = 0,
+ };
+ if (!open->op_truncate)
+ return 0;
+ if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
+ return -EINVAL;
+ return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
+}
+
static int
nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
{
@@ -1587,29 +1598,22 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
share_access = ~share_access;
share_access &= open->op_share_access;
- /* update the struct file */
- if (share_access & NFS4_SHARE_ACCESS_WRITE) {
- status = get_write_access(inode);
- if (status)
- return nfserrno(status);
- if (open->op_truncate) {
- struct iattr iattr = {
- .ia_valid = ATTR_SIZE,
- .ia_size = 0,
- };
- status = nfsd_setattr(rqstp, cur_fh, &iattr, 0,
- (time_t)0);
- if (status) {
- put_write_access(inode);
- return status;
- }
- }
+ if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
+ return nfsd4_truncate(rqstp, cur_fh, open);
- /* remember the open */
- filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
- set_bit(open->op_share_access, &stp->st_access_bmap);
- set_bit(open->op_share_deny, &stp->st_deny_bmap);
+ status = get_write_access(inode);
+ if (status)
+ return nfserrno(status);
+ status = nfsd4_truncate(rqstp, cur_fh, open);
+ if (status) {
+ put_write_access(inode);
+ return status;
}
+ /* remember the open */
+ filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
+ set_bit(open->op_share_access, &stp->st_access_bmap);
+ set_bit(open->op_share_deny, &stp->st_deny_bmap);
+
return nfs_ok;
}
@@ -1694,7 +1698,6 @@ out:
int
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
- struct nfs4_stateowner *sop = open->op_stateowner;
struct nfs4_file *fp = NULL;
struct inode *ino = current_fh->fh_dentry->d_inode;
struct nfs4_stateid *stp = NULL;
@@ -1710,7 +1713,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
*/
fp = find_file(ino);
if (fp) {
- if ((status = nfs4_check_open(fp, sop, open, &stp)))
+ if ((status = nfs4_check_open(fp, open, &stp)))
goto out;
} else {
status = nfserr_resource;
@@ -1737,18 +1740,11 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
flags = MAY_READ;
if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags)))
goto out;
- init_stateid(stp, fp, sop, open);
- if (open->op_truncate) {
- struct iattr iattr = {
- .ia_valid = ATTR_SIZE,
- .ia_size = 0,
- };
- status = nfsd_setattr(rqstp, current_fh, &iattr, 0,
- (time_t)0);
- if (status) {
- release_stateid(stp, OPEN_STATE);
- goto out;
- }
+ init_stateid(stp, fp, open);
+ status = nfsd4_truncate(rqstp, current_fh, open);
+ if (status) {
+ release_stateid(stp, OPEN_STATE);
+ goto out;
}
}
memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
@@ -1859,7 +1855,7 @@ nfs4_laundromat(void)
list_for_each_safe(pos, next, &reaplist) {
dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
list_del_init(&dp->dl_recall_lru);
- release_delegation(dp);
+ unhash_delegation(dp);
}
test_val = NFSD_LEASE_TIME;
list_for_each_safe(pos, next, &close_lru) {
@@ -1929,7 +1925,8 @@ static inline int
access_permit_read(unsigned long access_bmap)
{
return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) ||
- test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
+ test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap) ||
+ test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap);
}
static inline int
@@ -2063,7 +2060,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
goto out;
renew_client(dp->dl_client);
if (flags & DELEG_RET)
- release_delegation(dp);
+ unhash_delegation(dp);
if (filpp)
*filpp = dp->dl_vfs_file;
}
@@ -3238,7 +3235,7 @@ __nfs4_state_shutdown(void)
list_for_each_safe(pos, next, &reaplist) {
dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
list_del_init(&dp->dl_recall_lru);
- release_delegation(dp);
+ unhash_delegation(dp);
}
release_all_files();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index f5e1833094dbc..36a058a112d57 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1331,7 +1331,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
if (bmval0 & FATTR4_WORD0_ACL) {
if (status == -EOPNOTSUPP)
bmval0 &= ~FATTR4_WORD0_ACL;
- else if (status != 0)
+ else if (status == -EINVAL) {
+ status = nfserr_attrnotsupp;
+ goto out;
+ } else if (status != 0)
goto out_nfserr;
}
}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 0fc725c3bd45c..e3e9d217236e4 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -393,7 +393,7 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
}
out:
kfree(buf);
- return (error);
+ return error;
}
int
@@ -417,7 +417,10 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
flags = NFS4_ACL_DIR;
error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
- if (error < 0)
+ if (error == -EINVAL) {
+ error = nfserr_attrnotsupp;
+ goto out;
+ } else if (error < 0)
goto out_nfserr;
if (pacl) {
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 97a7a8f30eb4e..0a88917605aee 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -45,7 +45,9 @@ static struct inode_operations ramfs_dir_inode_operations;
static struct backing_dev_info ramfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK |
+ BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
+ BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
};
struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 97dc6db0870ca..aff7b2dfa8eed 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -23,7 +23,7 @@ static struct address_space_operations sysfs_aops = {
static struct backing_dev_info sysfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
struct inode * sysfs_new_inode(mode_t mode)
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index 8ca8c0c922f53..2053cbacffc3d 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -19,6 +19,7 @@
* 18-11-2004 BJD Fixed definitions of GPE3, GPE4, GPE5 and GPE6
* 18-11-2004 BJD Added S3C2440 AC97 controls
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
+ * 28-Mar-2005 LCVR Fixed definition of GPB10
*/
@@ -212,9 +213,9 @@
#define S3C2410_GPB9_nXDACK0 (0x02 << 18)
#define S3C2410_GPB10 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 10)
-#define S3C2410_GPB10_INP (0x00 << 18)
-#define S3C2410_GPB10_OUTP (0x01 << 18)
-#define S3C2410_GPB10_nXDRE0 (0x02 << 18)
+#define S3C2410_GPB10_INP (0x00 << 20)
+#define S3C2410_GPB10_OUTP (0x01 << 20)
+#define S3C2410_GPB10_nXDRE0 (0x02 << 20)
/* Port C consits of 16 GPIO/Special function
*
diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
index dc96af6e9caab..2885972b0855c 100644
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -151,6 +151,7 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
#define atomic_inc_return(v) (atomic_add_return(1, v))
#define atomic_dec_return(v) (atomic_sub_return(1, v))
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)
diff --git a/include/asm-arm/ipc.h b/include/asm-arm/ipc.h
index 2bbbf6335d9c3..a46e3d9c2a3fc 100644
--- a/include/asm-arm/ipc.h
+++ b/include/asm-arm/ipc.h
@@ -1,29 +1 @@
-#ifndef __ASMARM_IPC_H
-#define __ASMARM_IPC_H
-
-/*
- * These are used to wrap system calls on ARM.
- *
- * See arch/arm/kernel/sys-arm.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-arm26/ipc.h b/include/asm-arm26/ipc.h
index c330504ba3f4c..a46e3d9c2a3fc 100644
--- a/include/asm-arm26/ipc.h
+++ b/include/asm-arm26/ipc.h
@@ -1,28 +1 @@
-#ifndef __ASMARM_IPC_H
-#define __ASMARM_IPC_H
-
-/*
- * These are used to wrap system calls on ARM.
- *
- * See arch/arm/kernel/sys-arm.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-cris/ipc.h b/include/asm-cris/ipc.h
index f086af6fa03ff..a46e3d9c2a3fc 100644
--- a/include/asm-cris/ipc.h
+++ b/include/asm-cris/ipc.h
@@ -1,35 +1 @@
-#ifndef __CRIS_IPC_H__
-#define __CRIS_IPC_H__
-
-/*
- * These are used to wrap system calls on CRIS.
- *
- * See arch/cris/kernel/sys_cris.c for ugly details..
- *
- * Same as x86 version.
- *
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-frv/ipc.h b/include/asm-frv/ipc.h
index 2f72065c63377..a46e3d9c2a3fc 100644
--- a/include/asm-frv/ipc.h
+++ b/include/asm-frv/ipc.h
@@ -1,33 +1 @@
-#ifndef __ASM_IPC_H__
-#define __ASM_IPC_H__
-
-/*
- * These are used to wrap system calls on FR-V
- *
- * See arch/frv/kernel/sys_frv.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
-
+#include <asm-generic/ipc.h>
diff --git a/include/asm-frv/tlbflush.h b/include/asm-frv/tlbflush.h
index c66aeb169208e..bc34626250846 100644
--- a/include/asm-frv/tlbflush.h
+++ b/include/asm-frv/tlbflush.h
@@ -58,7 +58,8 @@ do { \
#define __flush_tlb_global() flush_tlb_all()
#define flush_tlb() flush_tlb_all()
#define flush_tlb_kernel_range(start, end) flush_tlb_all()
-#define flush_tlb_pgtables(mm,start,end) asm volatile("movgs gr0,scr0 ! movgs gr0,scr1");
+#define flush_tlb_pgtables(mm,start,end) \
+ asm volatile("movgs %0,scr0 ! movgs %0,scr1" :: "r"(ULONG_MAX) : "memory");
#else
diff --git a/include/asm-generic/ipc.h b/include/asm-generic/ipc.h
new file mode 100644
index 0000000000000..a40407a165cec
--- /dev/null
+++ b/include/asm-generic/ipc.h
@@ -0,0 +1,31 @@
+#ifndef _ASM_GENERIC_IPC_H
+#define _ASM_GENERIC_IPC_H
+/*
+ * These are used to wrap system calls.
+ *
+ * See architecture code for ugly details..
+ */
+struct ipc_kludge {
+ struct msgbuf __user *msgp;
+ long msgtyp;
+};
+
+#define SEMOP 1
+#define SEMGET 2
+#define SEMCTL 3
+#define SEMTIMEDOP 4
+#define MSGSND 11
+#define MSGRCV 12
+#define MSGGET 13
+#define MSGCTL 14
+#define SHMAT 21
+#define SHMDT 22
+#define SHMGET 23
+#define SHMCTL 24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC 25
+
+#define IPCCALL(version,op) ((version)<<16 | (op))
+
+#endif /* _ASM_GENERIC_IPC_H */
diff --git a/include/asm-h8300/ipc.h b/include/asm-h8300/ipc.h
index 6219d8a90e552..a46e3d9c2a3fc 100644
--- a/include/asm-h8300/ipc.h
+++ b/include/asm-h8300/ipc.h
@@ -1,31 +1 @@
-#ifndef __H8300_IPC_H__
-#define __H8300_IPC_H__
-
-/*
- * These are used to wrap system calls on H8/300.
- *
- * See arch/h8300/kernel/sys_h8300.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index fb8cdcf41d4b5..11e67811a9901 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -4,6 +4,8 @@
#include <asm/ldt.h>
#include <asm/segment.h>
+#define CPU_16BIT_STACK_SIZE 1024
+
#ifndef __ASSEMBLY__
#include <linux/preempt.h>
@@ -15,6 +17,8 @@
extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
DECLARE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
+DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
+
struct Xgt_desc_struct {
unsigned short size;
unsigned long address __attribute__((packed));
diff --git a/include/asm-i386/ipc.h b/include/asm-i386/ipc.h
index 810a449f8a7e9..a46e3d9c2a3fc 100644
--- a/include/asm-i386/ipc.h
+++ b/include/asm-i386/ipc.h
@@ -1,32 +1 @@
-#ifndef __i386_IPC_H__
-#define __i386_IPC_H__
-
-/*
- * These are used to wrap system calls on x86.
- *
- * See arch/i386/kernel/sys_i386.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 8b28beda0e707..be258b0e5a5fb 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -146,6 +146,18 @@ static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx,
: "0" (op), "c"(0));
}
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+ int *edx)
+{
+ __asm__("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (op), "c" (count));
+}
+
/*
* CPUID functions returning a single datum
*/
diff --git a/include/asm-i386/seccomp.h b/include/asm-i386/seccomp.h
new file mode 100644
index 0000000000000..18da19e89bff2
--- /dev/null
+++ b/include/asm-i386/seccomp.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h>
+
+#ifdef TIF_32BIT
+#error "unexpected TIF_32BIT on i386"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-i386/segment.h b/include/asm-i386/segment.h
index abe3440a93ceb..bb5ff5b2c02ec 100644
--- a/include/asm-i386/segment.h
+++ b/include/asm-i386/segment.h
@@ -38,7 +38,7 @@
* 24 - APM BIOS support
* 25 - APM BIOS support
*
- * 26 - unused
+ * 26 - ESPFIX small SS
* 27 - unused
* 28 - unused
* 29 - unused
@@ -71,6 +71,9 @@
#define GDT_ENTRY_PNPBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 6)
#define GDT_ENTRY_APMBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 11)
+#define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE + 14)
+#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
+
#define GDT_ENTRY_DOUBLEFAULT_TSS 31
/*
diff --git a/include/asm-m32r/ipc.h b/include/asm-m32r/ipc.h
index 03aac6644b587..a46e3d9c2a3fc 100644
--- a/include/asm-m32r/ipc.h
+++ b/include/asm-m32r/ipc.h
@@ -1,35 +1 @@
-#ifndef __M32R_IPC_H__
-#define __M32R_IPC_H__
-
-/* orig : i386/ipc.h 2.6.0-test3 */
-
-/*
- * These are used to wrap system calls on x86.
- *
- * See arch/i386/kernel/sys_i386.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __M32R_IPC_H__ */
-
+#include <asm-generic/ipc.h>
diff --git a/include/asm-m32r/spinlock.h b/include/asm-m32r/spinlock.h
index ecf80b74d2c11..6608d8371c508 100644
--- a/include/asm-m32r/spinlock.h
+++ b/include/asm-m32r/spinlock.h
@@ -102,10 +102,8 @@ static inline void _raw_spin_lock(spinlock_t *lock)
unsigned long tmp0, tmp1;
#ifdef CONFIG_DEBUG_SPINLOCK
- __label__ here;
-here:
- if (lock->magic != SPINLOCK_MAGIC) {
- printk("pc: %p\n", &&here);
+ if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
+ printk("pc: %p\n", __builtin_return_address(0));
BUG();
}
#endif
diff --git a/include/asm-m68k/ipc.h b/include/asm-m68k/ipc.h
index 19e9cbe3f2661..a46e3d9c2a3fc 100644
--- a/include/asm-m68k/ipc.h
+++ b/include/asm-m68k/ipc.h
@@ -1,31 +1 @@
-#ifndef __m68k_IPC_H__
-#define __m68k_IPC_H__
-
-/*
- * These are used to wrap system calls on m68k.
- *
- * See arch/m68k/kernel/sys_m68k.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-m68knommu/ipc.h b/include/asm-m68knommu/ipc.h
index d66c4b2194006..a46e3d9c2a3fc 100644
--- a/include/asm-m68knommu/ipc.h
+++ b/include/asm-m68knommu/ipc.h
@@ -1 +1 @@
-#include <asm-m68k/ipc.h>
+#include <asm-generic/ipc.h>
diff --git a/include/asm-mips/ipc.h b/include/asm-mips/ipc.h
index 377bbd5ef62fc..a46e3d9c2a3fc 100644
--- a/include/asm-mips/ipc.h
+++ b/include/asm-mips/ipc.h
@@ -1,33 +1 @@
-#ifndef _ASM_IPC_H
-#define _ASM_IPC_H
-
-/*
- * These are used to wrap system calls on MIPS.
- *
- * See arch/mips/kernel/sysmips.c for ugly details..
- * FIXME: split up into ordinary syscalls ...
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* _ASM_IPC_H */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index 7dbda12a876d7..42fd1068cf2a4 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -86,7 +86,7 @@
*/
#define CPM_DATAONLY_BASE ((uint)128)
#define CPM_DP_NOSPACE ((uint)0x7fffffff)
-#ifdef CONFIG_8272
+#if defined(CONFIG_8272) || defined(CONFIG_MPC8555)
#define CPM_DATAONLY_SIZE ((uint)(8 * 1024) - CPM_DATAONLY_BASE)
#define CPM_FCC_SPECIAL_BASE ((uint)0x00009000)
#else
diff --git a/include/asm-ppc/ipc.h b/include/asm-ppc/ipc.h
index 512dfe962d8bb..a46e3d9c2a3fc 100644
--- a/include/asm-ppc/ipc.h
+++ b/include/asm-ppc/ipc.h
@@ -1,29 +1 @@
-#ifndef __PPC_IPC_H__
-#define __PPC_IPC_H__
-
-/*
- * These are used to wrap system calls on PowerPC.
- *
- * See arch/ppc/kernel/syscalls.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __PPC_IPC_H__ */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h
index 8e77baad0c4a4..06b86be61ed13 100644
--- a/include/asm-ppc/irq.h
+++ b/include/asm-ppc/irq.h
@@ -171,7 +171,7 @@ static __inline__ int irq_canonicalize(int irq)
#define NR_IRQS (NR_IPIC_INTS)
-#elif defined(CONFIG_CPM2) && defined(CONFIG_85xx)
+#elif defined(CONFIG_85xx)
/* Now include the board configuration specific associations.
*/
#include <asm/mpc85xx.h>
@@ -186,7 +186,7 @@ static __inline__ int irq_canonicalize(int irq)
#define NR_CPM_INTS 64
#define NR_EPIC_INTS 44
#ifndef NR_8259_INTS
-#define NR_8259_INTS 0
+#define NR_8259_INTS 0
#endif
#define NUM_8259_INTERRUPTS NR_8259_INTS
@@ -196,13 +196,59 @@ static __inline__ int irq_canonicalize(int irq)
#define NR_IRQS (NR_EPIC_INTS + NR_CPM_INTS + NR_8259_INTS)
-/* These values must be zero-based and map 1:1 with the EPIC configuration.
- * They are used throughout the 8560 I/O subsystem to generate
- * interrupt masks, flags, and other control patterns. This is why the
- * current kernel assumption of the 8259 as the base controller is such
- * a pain in the butt.
- */
+/* Internal IRQs on MPC85xx OpenPIC */
+
+#ifndef MPC85xx_OPENPIC_IRQ_OFFSET
+#ifdef CONFIG_CPM2
+#define MPC85xx_OPENPIC_IRQ_OFFSET (CPM_IRQ_OFFSET + NR_CPM_INTS)
+#else
+#define MPC85xx_OPENPIC_IRQ_OFFSET 0
+#endif
+#endif
+/* Not all of these exist on all MPC85xx implementations */
+#define MPC85xx_IRQ_L2CACHE ( 0 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_ECM ( 1 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DDR ( 2 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_LBIU ( 3 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA0 ( 4 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA1 ( 5 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA2 ( 6 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA3 ( 7 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PCI1 ( 8 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PCI2 ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_ERROR ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_BELL (10 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_TX (11 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_RX (12 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_TX (13 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_RX (14 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_ERROR (18 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_TX (19 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_RX (20 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_ERROR (24 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_FEC (25 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DUART (26 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_IIC1 (27 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PERFMON (28 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_SEC2 (29 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_CPM (30 + MPC85xx_OPENPIC_IRQ_OFFSET)
+
+/* The 12 external interrupt lines */
+#define MPC85xx_IRQ_EXT0 (32 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT1 (33 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT2 (34 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT3 (35 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT4 (36 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT5 (37 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT6 (38 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT7 (39 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT8 (40 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT9 (41 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT10 (42 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT11 (43 + MPC85xx_OPENPIC_IRQ_OFFSET)
+
+/* CPM related interrupts */
#define SIU_INT_ERROR ((uint)0x00+CPM_IRQ_OFFSET)
#define SIU_INT_I2C ((uint)0x01+CPM_IRQ_OFFSET)
#define SIU_INT_SPI ((uint)0x02+CPM_IRQ_OFFSET)
@@ -267,57 +313,62 @@ static __inline__ int irq_canonicalize(int irq)
* (Document errata updates have fixed this...make sure you have up to
* date processor documentation -- Dan).
*/
-#define NR_SIU_INTS 64
-
-#define SIU_INT_ERROR ((uint)0x00)
-#define SIU_INT_I2C ((uint)0x01)
-#define SIU_INT_SPI ((uint)0x02)
-#define SIU_INT_RISC ((uint)0x03)
-#define SIU_INT_SMC1 ((uint)0x04)
-#define SIU_INT_SMC2 ((uint)0x05)
-#define SIU_INT_IDMA1 ((uint)0x06)
-#define SIU_INT_IDMA2 ((uint)0x07)
-#define SIU_INT_IDMA3 ((uint)0x08)
-#define SIU_INT_IDMA4 ((uint)0x09)
-#define SIU_INT_SDMA ((uint)0x0a)
-#define SIU_INT_TIMER1 ((uint)0x0c)
-#define SIU_INT_TIMER2 ((uint)0x0d)
-#define SIU_INT_TIMER3 ((uint)0x0e)
-#define SIU_INT_TIMER4 ((uint)0x0f)
-#define SIU_INT_TMCNT ((uint)0x10)
-#define SIU_INT_PIT ((uint)0x11)
-#define SIU_INT_IRQ1 ((uint)0x13)
-#define SIU_INT_IRQ2 ((uint)0x14)
-#define SIU_INT_IRQ3 ((uint)0x15)
-#define SIU_INT_IRQ4 ((uint)0x16)
-#define SIU_INT_IRQ5 ((uint)0x17)
-#define SIU_INT_IRQ6 ((uint)0x18)
-#define SIU_INT_IRQ7 ((uint)0x19)
-#define SIU_INT_FCC1 ((uint)0x20)
-#define SIU_INT_FCC2 ((uint)0x21)
-#define SIU_INT_FCC3 ((uint)0x22)
-#define SIU_INT_MCC1 ((uint)0x24)
-#define SIU_INT_MCC2 ((uint)0x25)
-#define SIU_INT_SCC1 ((uint)0x28)
-#define SIU_INT_SCC2 ((uint)0x29)
-#define SIU_INT_SCC3 ((uint)0x2a)
-#define SIU_INT_SCC4 ((uint)0x2b)
-#define SIU_INT_PC15 ((uint)0x30)
-#define SIU_INT_PC14 ((uint)0x31)
-#define SIU_INT_PC13 ((uint)0x32)
-#define SIU_INT_PC12 ((uint)0x33)
-#define SIU_INT_PC11 ((uint)0x34)
-#define SIU_INT_PC10 ((uint)0x35)
-#define SIU_INT_PC9 ((uint)0x36)
-#define SIU_INT_PC8 ((uint)0x37)
-#define SIU_INT_PC7 ((uint)0x38)
-#define SIU_INT_PC6 ((uint)0x39)
-#define SIU_INT_PC5 ((uint)0x3a)
-#define SIU_INT_PC4 ((uint)0x3b)
-#define SIU_INT_PC3 ((uint)0x3c)
-#define SIU_INT_PC2 ((uint)0x3d)
-#define SIU_INT_PC1 ((uint)0x3e)
-#define SIU_INT_PC0 ((uint)0x3f)
+
+#ifndef CPM_IRQ_OFFSET
+#define CPM_IRQ_OFFSET 0
+#endif
+
+#define NR_CPM_INTS 64
+
+#define SIU_INT_ERROR ((uint)0x00 + CPM_IRQ_OFFSET)
+#define SIU_INT_I2C ((uint)0x01 + CPM_IRQ_OFFSET)
+#define SIU_INT_SPI ((uint)0x02 + CPM_IRQ_OFFSET)
+#define SIU_INT_RISC ((uint)0x03 + CPM_IRQ_OFFSET)
+#define SIU_INT_SMC1 ((uint)0x04 + CPM_IRQ_OFFSET)
+#define SIU_INT_SMC2 ((uint)0x05 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA1 ((uint)0x06 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA2 ((uint)0x07 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA3 ((uint)0x08 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA4 ((uint)0x09 + CPM_IRQ_OFFSET)
+#define SIU_INT_SDMA ((uint)0x0a + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER1 ((uint)0x0c + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER2 ((uint)0x0d + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER3 ((uint)0x0e + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER4 ((uint)0x0f + CPM_IRQ_OFFSET)
+#define SIU_INT_TMCNT ((uint)0x10 + CPM_IRQ_OFFSET)
+#define SIU_INT_PIT ((uint)0x11 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ2 ((uint)0x14 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ3 ((uint)0x15 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ4 ((uint)0x16 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ5 ((uint)0x17 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ6 ((uint)0x18 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ7 ((uint)0x19 + CPM_IRQ_OFFSET)
+#define SIU_INT_FCC1 ((uint)0x20 + CPM_IRQ_OFFSET)
+#define SIU_INT_FCC2 ((uint)0x21 + CPM_IRQ_OFFSET)
+#define SIU_INT_FCC3 ((uint)0x22 + CPM_IRQ_OFFSET)
+#define SIU_INT_MCC1 ((uint)0x24 + CPM_IRQ_OFFSET)
+#define SIU_INT_MCC2 ((uint)0x25 + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC1 ((uint)0x28 + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC2 ((uint)0x29 + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC3 ((uint)0x2a + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC4 ((uint)0x2b + CPM_IRQ_OFFSET)
+#define SIU_INT_PC15 ((uint)0x30 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC14 ((uint)0x31 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC13 ((uint)0x32 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC12 ((uint)0x33 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC11 ((uint)0x34 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC10 ((uint)0x35 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC9 ((uint)0x36 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC8 ((uint)0x37 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC7 ((uint)0x38 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC6 ((uint)0x39 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC5 ((uint)0x3a + CPM_IRQ_OFFSET)
+#define SIU_INT_PC4 ((uint)0x3b + CPM_IRQ_OFFSET)
+#define SIU_INT_PC3 ((uint)0x3c + CPM_IRQ_OFFSET)
+#define SIU_INT_PC2 ((uint)0x3d + CPM_IRQ_OFFSET)
+#define SIU_INT_PC1 ((uint)0x3e + CPM_IRQ_OFFSET)
+#define SIU_INT_PC0 ((uint)0x3f + CPM_IRQ_OFFSET)
#endif /* CONFIG_8260 */
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index edda15befa2de..e5f80c22fbfcf 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -10,7 +10,7 @@
* Originally written by Dale Farnsworth <dfarnsworth@mvista.com>
* for the 2.4 kernel.
*
- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 MontaVista, Software, Inc.
*
* This file is licensed under the terms of the GNU General Public License
@@ -26,53 +26,73 @@
#include <asm/types.h>
struct pt_regs;
-struct ocp_def;
#endif /* __ASSEMBLY__ */
/* ======================================================================== */
+/* PPC Sys devices definition */
+/* ======================================================================== */
+
+enum ppc_sys_devices {
+ MPC52xx_MSCAN1,
+ MPC52xx_MSCAN2,
+ MPC52xx_SPI,
+ MPC52xx_USB,
+ MPC52xx_BDLC,
+ MPC52xx_PSC1,
+ MPC52xx_PSC2,
+ MPC52xx_PSC3,
+ MPC52xx_PSC4,
+ MPC52xx_PSC5,
+ MPC52xx_PSC6,
+ MPC52xx_FEC,
+ MPC52xx_ATA,
+ MPC52xx_I2C1,
+ MPC52xx_I2C2,
+};
+
+
+/* ======================================================================== */
/* Main registers/struct addresses */
/* ======================================================================== */
-/* Theses are PHYSICAL addresses ! */
-/* TODO : There should be no static mapping, but it's not yet the case, so */
-/* we require a 1:1 mapping */
+/* MBAR position */
#define MPC52xx_MBAR 0xf0000000 /* Phys address */
-#define MPC52xx_MBAR_SIZE 0x00010000
#define MPC52xx_MBAR_VIRT 0xf0000000 /* Virt address */
+#define MPC52xx_MBAR_SIZE 0x00010000
-#define MPC52xx_MMAP_CTL (MPC52xx_MBAR + 0x0000)
-#define MPC52xx_SDRAM (MPC52xx_MBAR + 0x0100)
-#define MPC52xx_CDM (MPC52xx_MBAR + 0x0200)
-#define MPC52xx_SFTRST (MPC52xx_MBAR + 0x0220)
-#define MPC52xx_SFTRST_BIT 0x01000000
-#define MPC52xx_INTR (MPC52xx_MBAR + 0x0500)
-#define MPC52xx_GPTx(x) (MPC52xx_MBAR + 0x0600 + ((x)<<4))
-#define MPC52xx_RTC (MPC52xx_MBAR + 0x0800)
-#define MPC52xx_MSCAN1 (MPC52xx_MBAR + 0x0900)
-#define MPC52xx_MSCAN2 (MPC52xx_MBAR + 0x0980)
-#define MPC52xx_GPIO (MPC52xx_MBAR + 0x0b00)
-#define MPC52xx_GPIO_WKUP (MPC52xx_MBAR + 0x0c00)
-#define MPC52xx_PCI (MPC52xx_MBAR + 0x0d00)
-#define MPC52xx_USB_OHCI (MPC52xx_MBAR + 0x1000)
-#define MPC52xx_SDMA (MPC52xx_MBAR + 0x1200)
-#define MPC52xx_XLB (MPC52xx_MBAR + 0x1f00)
-#define MPC52xx_PSCx(x) (MPC52xx_MBAR + 0x2000 + ((x)<<9))
-#define MPC52xx_PSC1 (MPC52xx_MBAR + 0x2000)
-#define MPC52xx_PSC2 (MPC52xx_MBAR + 0x2200)
-#define MPC52xx_PSC3 (MPC52xx_MBAR + 0x2400)
-#define MPC52xx_PSC4 (MPC52xx_MBAR + 0x2600)
-#define MPC52xx_PSC5 (MPC52xx_MBAR + 0x2800)
-#define MPC52xx_PSC6 (MPC52xx_MBAR + 0x2C00)
-#define MPC52xx_FEC (MPC52xx_MBAR + 0x3000)
-#define MPC52xx_ATA (MPC52xx_MBAR + 0x3a00)
-#define MPC52xx_I2C1 (MPC52xx_MBAR + 0x3d00)
-#define MPC52xx_I2C_MICR (MPC52xx_MBAR + 0x3d20)
-#define MPC52xx_I2C2 (MPC52xx_MBAR + 0x3d40)
+#define MPC52xx_PA(x) ((phys_addr_t)(MPC52xx_MBAR + (x)))
+#define MPC52xx_VA(x) ((void __iomem *)(MPC52xx_MBAR_VIRT + (x)))
+
+/* Registers zone offset/size */
+#define MPC52xx_MMAP_CTL_OFFSET 0x0000
+#define MPC52xx_MMAP_CTL_SIZE 0x068
+#define MPC52xx_SDRAM_OFFSET 0x0100
+#define MPC52xx_SDRAM_SIZE 0x010
+#define MPC52xx_CDM_OFFSET 0x0200
+#define MPC52xx_CDM_SIZE 0x038
+#define MPC52xx_INTR_OFFSET 0x0500
+#define MPC52xx_INTR_SIZE 0x04c
+#define MPC52xx_GPTx_OFFSET(x) (0x0600 + ((x)<<4))
+#define MPC52xx_GPT_SIZE 0x010
+#define MPC52xx_RTC_OFFSET 0x0800
+#define MPC52xx_RTC_SIZE 0x024
+#define MPC52xx_GPIO_OFFSET 0x0b00
+#define MPC52xx_GPIO_SIZE 0x040
+#define MPC52xx_GPIO_WKUP_OFFSET 0x0c00
+#define MPC52xx_GPIO_WKUP_SIZE 0x028
+#define MPC52xx_PCI_OFFSET 0x0d00
+#define MPC52xx_PCI_SIZE 0x100
+#define MPC52xx_SDMA_OFFSET 0x1200
+#define MPC52xx_SDMA_SIZE 0x100
+#define MPC52xx_XLB_OFFSET 0x1f00
+#define MPC52xx_XLB_SIZE 0x100
+#define MPC52xx_PSCx_OFFSET(x) (((x)!=6)?(0x1e00+((x)<<9)):0x2c00)
+#define MPC52xx_PSC_SIZE 0x0a0
/* SRAM used for SDMA */
-#define MPC52xx_SRAM (MPC52xx_MBAR + 0x8000)
-#define MPC52xx_SRAM_SIZE (16*1024)
+#define MPC52xx_SRAM_OFFSET 0x8000
+#define MPC52xx_SRAM_SIZE 0x4000
/* ======================================================================== */
@@ -119,11 +139,12 @@ struct ocp_def;
#define MPC52xx_SPI_SPIF_IRQ (MPC52xx_PERP_IRQ_BASE + 14)
#define MPC52xx_I2C1_IRQ (MPC52xx_PERP_IRQ_BASE + 15)
#define MPC52xx_I2C2_IRQ (MPC52xx_PERP_IRQ_BASE + 16)
-#define MPC52xx_CAN1_IRQ (MPC52xx_PERP_IRQ_BASE + 17)
-#define MPC52xx_CAN2_IRQ (MPC52xx_PERP_IRQ_BASE + 18)
+#define MPC52xx_MSCAN1_IRQ (MPC52xx_PERP_IRQ_BASE + 17)
+#define MPC52xx_MSCAN2_IRQ (MPC52xx_PERP_IRQ_BASE + 18)
#define MPC52xx_IR_RX_IRQ (MPC52xx_PERP_IRQ_BASE + 19)
#define MPC52xx_IR_TX_IRQ (MPC52xx_PERP_IRQ_BASE + 20)
#define MPC52xx_XLB_ARB_IRQ (MPC52xx_PERP_IRQ_BASE + 21)
+#define MPC52xx_BDLC_IRQ (MPC52xx_PERP_IRQ_BASE + 22)
@@ -163,7 +184,7 @@ struct mpc52xx_mmap_ctl {
u32 cs6_start; /* MMAP_CTRL + 0x58 */
u32 cs6_stop; /* MMAP_CTRL + 0x5c */
u32 cs7_start; /* MMAP_CTRL + 0x60 */
- u32 cs7_stop; /* MMAP_CTRL + 0x60 */
+ u32 cs7_stop; /* MMAP_CTRL + 0x64 */
};
/* SDRAM control */
@@ -209,7 +230,7 @@ struct mpc52xx_sdma {
u16 tcr[16]; /* SDMA + 0x1c .. 0x3a */
- u8 ipr[32]; /* SDMA + 0x3c .. 5b */
+ u8 ipr[32]; /* SDMA + 0x3c .. 0x5b */
u32 cReqSelect; /* SDMA + 0x5c */
u32 task_size0; /* SDMA + 0x60 */
@@ -391,10 +412,20 @@ extern void mpc52xx_halt(void);
extern void mpc52xx_power_off(void);
extern void mpc52xx_progress(char *s, unsigned short hex);
extern void mpc52xx_calibrate_decr(void);
-extern void mpc52xx_add_board_devices(struct ocp_def board_ocp[]);
extern void mpc52xx_find_bridges(void);
+
+ /* Matching of PSC function */
+struct mpc52xx_psc_func {
+ int id;
+ char *func;
+};
+
+extern int mpc52xx_match_psc_function(int psc_idx, const char *func);
+extern struct mpc52xx_psc_func mpc52xx_psc_functions[];
+ /* This array is to be defined in platform file */
+
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
index 3f9e4237bf6f0..22713e331585a 100644
--- a/include/asm-ppc/mpc85xx.h
+++ b/include/asm-ppc/mpc85xx.h
@@ -52,55 +52,6 @@
*/
extern unsigned char __res[];
-/* Internal IRQs on MPC85xx OpenPIC */
-/* Not all of these exist on all MPC85xx implementations */
-
-#ifndef MPC85xx_OPENPIC_IRQ_OFFSET
-#define MPC85xx_OPENPIC_IRQ_OFFSET 64
-#endif
-
-/* The 32 internal sources */
-#define MPC85xx_IRQ_L2CACHE ( 0 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_ECM ( 1 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DDR ( 2 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_LBIU ( 3 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA0 ( 4 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA1 ( 5 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA2 ( 6 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA3 ( 7 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_PCI1 ( 8 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_PCI2 ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_ERROR ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_BELL (10 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_TX (11 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_RX (12 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC1_TX (13 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC1_RX (14 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC1_ERROR (18 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC2_TX (19 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC2_RX (20 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC2_ERROR (24 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_FEC (25 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DUART (26 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_IIC1 (27 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_PERFMON (28 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_SEC2 (29 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_CPM (30 + MPC85xx_OPENPIC_IRQ_OFFSET)
-
-/* The 12 external interrupt lines */
-#define MPC85xx_IRQ_EXT0 (32 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT1 (33 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT2 (34 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT3 (35 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT4 (36 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT5 (37 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT6 (38 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT7 (39 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT8 (40 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT9 (41 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT10 (42 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT11 (43 + MPC85xx_OPENPIC_IRQ_OFFSET)
-
/* Offset from CCSRBAR */
#define MPC85xx_CPM_OFFSET (0x80000)
#define MPC85xx_CPM_SIZE (0x40000)
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 293e47f1d99a5..24b991c427694 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -25,6 +25,8 @@
#include <asm/mpc83xx.h>
#elif defined(CONFIG_85xx)
#include <asm/mpc85xx.h>
+#elif defined(CONFIG_PPC_MPC52xx)
+#include <asm/mpc52xx.h>
#else
#error "need definition of ppc_sys_devices"
#endif
diff --git a/include/asm-ppc64/ipc.h b/include/asm-ppc64/ipc.h
index f91bf5b0d092e..a46e3d9c2a3fc 100644
--- a/include/asm-ppc64/ipc.h
+++ b/include/asm-ppc64/ipc.h
@@ -1,34 +1 @@
-#ifndef __PPC64_IPC_H__
-#define __PPC64_IPC_H__
-
-/*
- * These are used to wrap system calls on PowerPC.
- *
- * See arch/ppc64/kernel/syscalls.c for ugly details..
- *
- * 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.
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __PPC64_IPC_H__ */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h
index 3da661161cc52..a6cbca21ac1d7 100644
--- a/include/asm-ppc64/lmb.h
+++ b/include/asm-ppc64/lmb.h
@@ -51,6 +51,7 @@ extern unsigned long __init lmb_alloc_base(unsigned long, unsigned long,
extern unsigned long __init lmb_phys_mem_size(void);
extern unsigned long __init lmb_end_of_DRAM(void);
extern unsigned long __init lmb_abs_to_phys(unsigned long);
+extern void __init lmb_enforce_memory_limit(void);
extern void lmb_dump_all(void);
diff --git a/include/asm-ppc64/seccomp.h b/include/asm-ppc64/seccomp.h
new file mode 100644
index 0000000000000..c130c334bda1c
--- /dev/null
+++ b/include/asm-ppc64/seccomp.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h> /* already defines TIF_32BIT */
+
+#ifndef TIF_32BIT
+#error "unexpected TIF_32BIT on ppc64"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_read
+#define __NR_seccomp_write_32 __NR_write
+#define __NR_seccomp_exit_32 __NR_exit
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
index d4b978c26d710..037b5e06083c0 100644
--- a/include/asm-ppc64/thread_info.h
+++ b/include/asm-ppc64/thread_info.h
@@ -101,6 +101,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */
#define TIF_SINGLESTEP 9 /* singlestepping active */
#define TIF_MEMDIE 10
+#define TIF_SECCOMP 11 /* secure computing */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -113,7 +114,8 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
-#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
_TIF_NEED_RESCHED)
diff --git a/include/asm-s390/ipc.h b/include/asm-s390/ipc.h
index d6c041e9ca9aa..a46e3d9c2a3fc 100644
--- a/include/asm-s390/ipc.h
+++ b/include/asm-s390/ipc.h
@@ -1,40 +1 @@
-/*
- * include/asm-s390/ipc.h
- *
- * S390 version
- *
- * Derived from "include/asm-i386/ipc.h"
- */
-
-#ifndef __s390_IPC_H__
-#define __s390_IPC_H__
-
-/*
- * These are used to wrap system calls on S390.
- *
- * See arch/s390/kernel/sys_s390.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sh/ipc.h b/include/asm-sh/ipc.h
index 6ced9bec6abcd..a46e3d9c2a3fc 100644
--- a/include/asm-sh/ipc.h
+++ b/include/asm-sh/ipc.h
@@ -1,32 +1 @@
-#ifndef __ASM_SH_IPC_H
-#define __ASM_SH_IPC_H
-
-/*
- * These are used to wrap system calls on x86.
- *
- * See arch/i386/kernel/sys_i386.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __ASM_SH_IPC_H */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sh64/ipc.h b/include/asm-sh64/ipc.h
index d8d9389bd3ce7..a46e3d9c2a3fc 100644
--- a/include/asm-sh64/ipc.h
+++ b/include/asm-sh64/ipc.h
@@ -1,6 +1 @@
-#ifndef __ASM_SH64_IPC_H
-#define __ASM_SH64_IPC_H
-
-#include <asm-sh/ipc.h>
-
-#endif /* __ASM_SH64_IPC_H */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sparc/ipc.h b/include/asm-sparc/ipc.h
index 3064aaf8fa27c..a46e3d9c2a3fc 100644
--- a/include/asm-sparc/ipc.h
+++ b/include/asm-sparc/ipc.h
@@ -1,32 +1 @@
-#ifndef __SPARC_IPC_H__
-#define __SPARC_IPC_H__
-
-/*
- * These are used to wrap system calls on the sparc.
- *
- * See arch/sparc/kernel/sys_sparc.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sparc64/ipc.h b/include/asm-sparc64/ipc.h
index 39261d5523ef9..a46e3d9c2a3fc 100644
--- a/include/asm-sparc64/ipc.h
+++ b/include/asm-sparc64/ipc.h
@@ -1,33 +1 @@
-#ifndef __SPARC64_IPC_H__
-#define __SPARC64_IPC_H__
-
-/*
- * These are used to wrap system calls on the sparc.
- *
- * See arch/sparc64/kernel/sys_sparc32.c for ugly details..
- */
-struct ipc_kludge {
- u32 msgp;
- s32 msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-/* We don't need to maintain backward compatibility on 64bit, we've started fresh */
-#define IPCCALL(version,op) (op)
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-v850/ipc.h b/include/asm-v850/ipc.h
index 5656799cd4e85..a46e3d9c2a3fc 100644
--- a/include/asm-v850/ipc.h
+++ b/include/asm-v850/ipc.h
@@ -1,31 +1 @@
-#ifndef __V850_IPC_H__
-#define __V850_IPC_H__
-
-/*
- * These are used to wrap system calls on v850.
- *
- * See arch/v850/kernel/syscalls.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __V850_IPC_H__ */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-x86_64/ipc.h b/include/asm-x86_64/ipc.h
deleted file mode 100644
index 8736ba68c1183..0000000000000
--- a/include/asm-x86_64/ipc.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __x8664_IPC_H__
-#define __x8664_IPC_H__
-
-/* dummy */
-
-#endif
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
index 2aac15a1290fc..66f0be191ab4f 100644
--- a/include/asm-x86_64/msr.h
+++ b/include/asm-x86_64/msr.h
@@ -80,6 +80,18 @@ extern inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
: "0" (op));
}
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+ int *edx)
+{
+ __asm__("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (op), "c" (count));
+}
+
/*
* CPUID functions returning a single datum
*/
diff --git a/include/asm-x86_64/seccomp.h b/include/asm-x86_64/seccomp.h
new file mode 100644
index 0000000000000..553af65a2287a
--- /dev/null
+++ b/include/asm-x86_64/seccomp.h
@@ -0,0 +1,24 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h>
+
+#ifdef TIF_32BIT
+#error "unexpected TIF_32BIT on x86_64"
+#else
+#define TIF_32BIT TIF_IA32
+#endif
+
+#include <linux/unistd.h>
+#include <asm/ia32_unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_ia32_read
+#define __NR_seccomp_write_32 __NR_ia32_write
+#define __NR_seccomp_exit_32 __NR_ia32_exit
+#define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index f2a09f442d7dc..a8ea0164f3ab0 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -774,7 +774,7 @@ asmlinkage long sys_pipe(int *fildes);
asmlinkage long sys_ptrace(long request, long pid,
unsigned long addr, long data);
-asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs);
+asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs);
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on);
struct sigaction;
asmlinkage long sys_rt_sigaction(int sig,
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 3c369c6553e3e..f7a1390d67f5b 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -25,13 +25,39 @@ typedef int (congested_fn)(void *, int);
struct backing_dev_info {
unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */
unsigned long state; /* Always use atomic bitops on this */
- int memory_backed; /* Cannot clean pages with writepage */
+ unsigned int capabilities; /* Device capabilities */
congested_fn *congested_fn; /* Function pointer if device is md/dm */
void *congested_data; /* Pointer to aux data for congested func */
void (*unplug_io_fn)(struct backing_dev_info *, struct page *);
void *unplug_io_data;
};
+
+/*
+ * Flags in backing_dev_info::capability
+ * - The first two flags control whether dirty pages will contribute to the
+ * VM's accounting and whether writepages() should be called for dirty pages
+ * (something that would not, for example, be appropriate for ramfs)
+ * - These flags let !MMU mmap() govern direct device mapping vs immediate
+ * copying more easily for MAP_PRIVATE, especially for ROM filesystems
+ */
+#define BDI_CAP_NO_ACCT_DIRTY 0x00000001 /* Dirty pages shouldn't contribute to accounting */
+#define BDI_CAP_NO_WRITEBACK 0x00000002 /* Don't write pages back */
+#define BDI_CAP_MAP_COPY 0x00000004 /* Copy can be mapped (MAP_PRIVATE) */
+#define BDI_CAP_MAP_DIRECT 0x00000008 /* Can be mapped directly (MAP_SHARED) */
+#define BDI_CAP_READ_MAP 0x00000010 /* Can be mapped for reading */
+#define BDI_CAP_WRITE_MAP 0x00000020 /* Can be mapped for writing */
+#define BDI_CAP_EXEC_MAP 0x00000040 /* Can be mapped for execution */
+#define BDI_CAP_VMFLAGS \
+ (BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP)
+
+#if defined(VM_MAYREAD) && \
+ (BDI_CAP_READ_MAP != VM_MAYREAD || \
+ BDI_CAP_WRITE_MAP != VM_MAYWRITE || \
+ BDI_CAP_EXEC_MAP != VM_MAYEXEC)
+#error please change backing_dev_info::capabilities flags
+#endif
+
extern struct backing_dev_info default_backing_dev_info;
void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page);
@@ -62,4 +88,17 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi)
(1 << BDI_write_congested));
}
+#define bdi_cap_writeback_dirty(bdi) \
+ (!((bdi)->capabilities & BDI_CAP_NO_WRITEBACK))
+
+#define bdi_cap_account_dirty(bdi) \
+ (!((bdi)->capabilities & BDI_CAP_NO_ACCT_DIRTY))
+
+#define mapping_cap_writeback_dirty(mapping) \
+ bdi_cap_writeback_dirty((mapping)->backing_dev_info)
+
+#define mapping_cap_account_dirty(mapping) \
+ bdi_cap_account_dirty((mapping)->backing_dev_info)
+
+
#endif /* _LINUX_BACKING_DEV_H */
diff --git a/include/linux/console.h b/include/linux/console.h
index b9b183e986e5e..721371382ae5f 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -59,7 +59,6 @@ struct consw {
extern const struct consw *conswitchp;
extern const struct consw dummy_con; /* dummy console buffer */
-extern const struct consw fb_con; /* frame buffer based console */
extern const struct consw vga_con; /* VGA text console */
extern const struct consw newport_con; /* SGI Newport console */
extern const struct consw prom_con; /* SPARC PROM console */
diff --git a/include/linux/device.h b/include/linux/device.h
index a33424d41038c..cf470459fa691 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -110,7 +110,7 @@ struct device_driver {
int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
void (*shutdown) (struct device * dev);
- int (*suspend) (struct device * dev, u32 state, u32 level);
+ int (*suspend) (struct device * dev, pm_message_t state, u32 level);
int (*resume) (struct device * dev, u32 level);
};
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 9d1507c87cecc..b45d3e2d711a3 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -702,9 +702,7 @@ struct fb_tile_ops {
#define FBINFO_MISC_USEREVENT 0x10000 /* event request
from userspace */
-#define FBINFO_MISC_MODESWITCH 0x20000 /* mode switch */
-#define FBINFO_MISC_MODESWITCHLATE 0x40000 /* init hardware later */
-#define FBINFO_MISC_TILEBLITTING 0x80000 /* use tile blitting */
+#define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */
struct fb_info {
int node;
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 44da5ac8f88f9..aefedf04b9bb2 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -75,7 +75,7 @@ struct mmc_driver {
struct device_driver drv;
int (*probe)(struct mmc_card *);
void (*remove)(struct mmc_card *);
- int (*suspend)(struct mmc_card *, u32);
+ int (*suspend)(struct mmc_card *, pm_message_t);
int (*resume)(struct mmc_card *);
};
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index a5ae03ad495c4..a27d42d3e6522 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2159,6 +2159,8 @@
#define PCI_VENDOR_ID_S2IO 0x17d5
#define PCI_DEVICE_ID_S2IO_WIN 0x5731
#define PCI_DEVICE_ID_S2IO_UNI 0x5831
+#define PCI_DEVICE_ID_HERC_WIN 0x5732
+#define PCI_DEVICE_ID_HERC_UNI 0x5832
#define PCI_VENDOR_ID_INFINICON 0x1820
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index ee989b6ee22aa..3a2702bbb1d67 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -8,6 +8,7 @@
#define NR_SECCOMP_MODES 1
#include <linux/thread_info.h>
+#include <asm/seccomp.h>
typedef struct { int mode; } seccomp_t;
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index 29a1b14bb218b..c119ce7cbd22a 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -26,21 +26,23 @@ struct svc_cred {
struct svc_rqst; /* forward decl */
/* Authentication is done in the context of a domain.
- * For a server, a domain represents a group of clients using
+ *
+ * Currently, the nfs server uses the auth_domain to stand
+ * for the "client" listed in /etc/exports.
+ *
+ * More generally, a domain might represent a group of clients using
* a common mechanism for authentication and having a common mapping
* between local identity (uid) and network identity. All clients
* in a domain have similar general access rights. Each domain can
* contain multiple principals which will have different specific right
* based on normal Discretionary Access Control.
*
- * For a client, a domain represents a number of servers which all
- * use a common authentication mechanism and network identity name space.
- *
* A domain is created by an authentication flavour module based on name
* only. Userspace then fills in detail on demand.
*
- * The creation of a domain typically implies creation of one or
- * more caches for storing domain specific information.
+ * In the case of auth_unix and auth_null, the auth_domain is also
+ * associated with entries in another cache representing the mapping
+ * of ip addresses to the given client.
*/
struct auth_domain {
struct cache_head h;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 8d2687ae39ffd..c96728435935b 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -949,11 +949,11 @@ void *usb_buffer_alloc (struct usb_device *dev, size_t size,
void usb_buffer_free (struct usb_device *dev, size_t size,
void *addr, dma_addr_t dma);
-struct urb *usb_buffer_map (struct urb *urb);
#if 0
+struct urb *usb_buffer_map (struct urb *urb);
void usb_buffer_dmasync (struct urb *urb);
-#endif
void usb_buffer_unmap (struct urb *urb);
+#endif
struct scatterlist;
int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
diff --git a/include/linux/usb_cdc.h b/include/linux/usb_cdc.h
index 0b8d9a78a51a5..1b68c122279a8 100644
--- a/include/linux/usb_cdc.h
+++ b/include/linux/usb_cdc.h
@@ -6,8 +6,12 @@
* firmware based USB peripherals.
*/
-#define USB_CDC_SUBCLASS_ACM 2
-#define USB_CDC_SUBCLASS_ETHERNET 6
+#define USB_CDC_SUBCLASS_ACM 0x02
+#define USB_CDC_SUBCLASS_ETHERNET 0x06
+#define USB_CDC_SUBCLASS_WHCM 0x08
+#define USB_CDC_SUBCLASS_DMM 0x09
+#define USB_CDC_SUBCLASS_MDLM 0x0a
+#define USB_CDC_SUBCLASS_OBEX 0x0b
#define USB_CDC_PROTO_NONE 0
@@ -31,6 +35,11 @@
#define USB_CDC_UNION_TYPE 0x06 /* union_desc */
#define USB_CDC_COUNTRY_TYPE 0x07
#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */
+#define USB_CDC_WHCM_TYPE 0x11
+#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */
+#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */
+#define USB_CDC_DMM_TYPE 0x14
+#define USB_CDC_OBEX_TYPE 0x15
/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
struct usb_cdc_header_desc {
@@ -87,6 +96,27 @@ struct usb_cdc_ether_desc {
__u8 bNumberPowerFilters;
} __attribute__ ((packed));
+/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */
+struct usb_cdc_mdlm_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ __le16 bcdVersion;
+ __u8 bGUID[16];
+} __attribute__ ((packed));
+
+/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */
+struct usb_cdc_mdlm_detail_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ /* type is associated with mdlm_desc.bGUID */
+ __u8 bGuidDescriptorType;
+ __u8 bDetailData[];
+} __attribute__ ((packed));
+
/*-------------------------------------------------------------------------*/
/*
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 30c3e34316092..6d3413a567081 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -259,7 +259,7 @@ extern void pcmcia_unregister_socket(struct pcmcia_socket *socket);
extern struct class pcmcia_socket_class;
/* socket drivers are expected to use these callbacks in their .drv struct */
-extern int pcmcia_socket_dev_suspend(struct device *dev, u32 state);
+extern int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state);
extern int pcmcia_socket_dev_resume(struct device *dev);
#endif /* _LINUX_SS_H */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index d528aeb443ca2..07d974051b0c1 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -112,6 +112,7 @@ struct scsi_device {
unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
unsigned select_no_atn:1;
unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */
+ unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */
unsigned int device_blocked; /* Device returned QUEUE_FULL. */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 7b99edf388743..27f2c4e8943ac 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -590,6 +590,7 @@ static inline struct Scsi_Host *dev_to_shost(struct device *dev)
}
extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
+extern void scsi_flush_work(struct Scsi_Host *);
extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *);
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 7e96646b5cc5c..70ad16315a16f 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -212,9 +212,6 @@ struct fc_rport { /* aka fc_starget_attrs */
#define rport_to_shost(r) \
dev_to_shost(r->dev.parent)
-#define FC_SCSI_SCAN_DELAY (1 * HZ) /* 1 second delay */
-
-
/*
* FC SCSI Target Attributes
*
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index a841033c1c76c..2433e279e0712 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -356,6 +356,7 @@
#define AC97_SCAP_INDEP_SDIN (1<<6) /* independent SDIN */
#define AC97_SCAP_INV_EAPD (1<<7) /* inverted EAPD */
#define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */
+#define AC97_SCAP_NO_SPDIF (1<<9) /* don't build SPDIF controls */
/* ac97->flags */
#define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index b957763c32bb7..a4d149f34541e 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -582,6 +582,7 @@ enum sndrv_timer_slave_class {
/* global timers (device member) */
#define SNDRV_TIMER_GLOBAL_SYSTEM 0
#define SNDRV_TIMER_GLOBAL_RTC 1
+#define SNDRV_TIMER_GLOBAL_HPET 2
/* info flags */
#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h
index e8b8945863871..58c9ef3d18253 100644
--- a/include/sound/asoundef.h
+++ b/include/sound/asoundef.h
@@ -185,7 +185,7 @@
#define MIDI_CTL_LSB_GENERAL_PURPOSE4 0x33
#define MIDI_CTL_SUSTAIN 0x40
#define MIDI_CTL_PORTAMENTO 0x41
-#define MIDI_CTL_SUSTENUTO 0x42
+#define MIDI_CTL_SOSTENUTO 0x42
#define MIDI_CTL_SOFT_PEDAL 0x43
#define MIDI_CTL_LEGATO_FOOTSWITCH 0x44
#define MIDI_CTL_HOLD2 0x45
diff --git a/include/sound/core.h b/include/sound/core.h
index da8c781b81e17..9117c23e3a01b 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -490,4 +490,13 @@ static inline int snd_timestamp_null(struct timespec *tstamp)
#define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */
+/* for easier backward-porting */
+#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#ifndef gameport_set_dev_parent
+#define gameport_set_dev_parent(gp,xdev) ((gp)->dev.parent = (xdev))
+#define gameport_set_port_data(gp,r) ((gp)->port_data = (r))
+#define gameport_get_port_data(gp) (gp)->port_data
+#endif
+#endif
+
#endif /* __SOUND_CORE_H */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 89ff420adf3f3..43b6786abae52 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -280,6 +280,46 @@
#define AC97ADDRESS_READY 0x80 /* Read-only bit, reflects CODEC READY signal */
#define AC97ADDRESS_ADDRESS 0x7f /* Address of indexed AC97 register */
+/* Available on the Audigy 2 and Audigy 4 only. This is the P16V chip. */
+#define PTR2 0x20 /* Indexed register set pointer register */
+#define DATA2 0x24 /* Indexed register set data register */
+#define IPR2 0x28 /* P16V interrupt pending register */
+#define IPR2_PLAYBACK_CH_0_LOOP 0x00001000 /* Playback Channel 0 loop */
+#define IPR2_PLAYBACK_CH_0_HALF_LOOP 0x00000100 /* Playback Channel 0 half loop */
+#define IPR2_CAPTURE_CH_0_LOOP 0x00100000 /* Capture Channel 0 loop */
+#define IPR2_CAPTURE_CH_0_HALF_LOOP 0x00010000 /* Capture Channel 0 half loop */
+ /* 0x00000100 Playback. Only in once per period.
+ * 0x00110000 Capture. Int on half buffer.
+ */
+#define INTE2 0x2c /* P16V Interrupt enable register. */
+#define INTE2_PLAYBACK_CH_0_LOOP 0x00001000 /* Playback Channel 0 loop */
+#define INTE2_PLAYBACK_CH_0_HALF_LOOP 0x00000100 /* Playback Channel 0 half loop */
+#define INTE2_PLAYBACK_CH_1_LOOP 0x00002000 /* Playback Channel 1 loop */
+#define INTE2_PLAYBACK_CH_1_HALF_LOOP 0x00000200 /* Playback Channel 1 half loop */
+#define INTE2_PLAYBACK_CH_2_LOOP 0x00004000 /* Playback Channel 2 loop */
+#define INTE2_PLAYBACK_CH_2_HALF_LOOP 0x00000400 /* Playback Channel 2 half loop */
+#define INTE2_PLAYBACK_CH_3_LOOP 0x00008000 /* Playback Channel 3 loop */
+#define INTE2_PLAYBACK_CH_3_HALF_LOOP 0x00000800 /* Playback Channel 3 half loop */
+#define INTE2_CAPTURE_CH_0_LOOP 0x00100000 /* Capture Channel 0 loop */
+#define INTE2_CAPTURE_CH_0_HALF_LOOP 0x00010000 /* Caputre Channel 0 half loop */
+#define HCFG2 0x34 /* Defaults: 0, win2000 sets it to 00004201 */
+ /* 0x00000000 2-channel output. */
+ /* 0x00000200 8-channel output. */
+ /* 0x00000004 pauses stream/irq fail. */
+ /* Rest of bits no nothing to sound output */
+ /* bit 0: Enable P16V audio.
+ * bit 1: Lock P16V record memory cache.
+ * bit 2: Lock P16V playback memory cache.
+ * bit 3: Dummy record insert zero samples.
+ * bit 8: Record 8-channel in phase.
+ * bit 9: Playback 8-channel in phase.
+ * bit 11-12: Playback mixer attenuation: 0=0dB, 1=-6dB, 2=-12dB, 3=Mute.
+ * bit 13: Playback mixer enable.
+ * bit 14: Route SRC48 mixer output to fx engine.
+ * bit 15: Enable IEEE 1394 chip.
+ */
+#define IPR3 0x38 /* Cdif interrupt pending register */
+#define INTE3 0x3c /* Cdif interrupt enable register. */
/************************************************************************************************/
/* PCI function 1 registers, address = <val> + PCIBASE1 */
/************************************************************************************************/
@@ -995,6 +1035,23 @@ typedef struct {
void (*interrupt)(emu10k1_t *emu, unsigned int status);
} emu10k1_midi_t;
+typedef struct {
+ u32 vendor;
+ u32 device;
+ u32 subsystem;
+ unsigned char emu10k1_chip; /* Original SB Live. Not SB Live 24bit. */
+ unsigned char emu10k2_chip; /* Audigy 1 or Audigy 2. */
+ unsigned char ca0102_chip; /* Audigy 1 or Audigy 2. Not SB Audigy 2 Value. */
+ unsigned char ca0108_chip; /* Audigy 2 Value */
+ unsigned char ca0151_chip; /* P16V */
+ unsigned char spk71; /* Has 7.1 speakers */
+ unsigned char spdif_bug; /* Has Spdif phasing bug */
+ unsigned char ac97_chip; /* Has an AC97 chip */
+ unsigned char ecard; /* APS EEPROM */
+ char * driver;
+ char * name;
+} emu_chip_details_t;
+
struct _snd_emu10k1 {
int irq;
@@ -1004,6 +1061,7 @@ struct _snd_emu10k1 {
tos_link: 1, /* tos link detected */
rear_ac97: 1, /* rear channels are on AC'97 */
spk71:1; /* 7.1 configuration (Audigy 2 ZS) */
+ const emu_chip_details_t *card_capabilities; /* Contains profile of card capabilities */
unsigned int audigy; /* is Audigy? */
unsigned int revision; /* chip revision */
unsigned int serial; /* serial number */
@@ -1014,6 +1072,9 @@ struct _snd_emu10k1 {
int max_cache_pages; /* max memory size / PAGE_SIZE */
struct snd_dma_buffer silent_page; /* silent page */
struct snd_dma_buffer ptb_pages; /* page table pages */
+ struct snd_dma_device p16v_dma_dev;
+ struct snd_dma_buffer p16v_buffer;
+
snd_util_memhdr_t *memhdr; /* page allocation list */
emu10k1_memblk_t *reserved_page; /* reserved page */
@@ -1035,6 +1096,7 @@ struct _snd_emu10k1 {
snd_pcm_t *pcm;
snd_pcm_t *pcm_mic;
snd_pcm_t *pcm_efx;
+ snd_pcm_t *pcm_p16v;
spinlock_t synth_lock;
void *synth;
@@ -1046,6 +1108,8 @@ struct _snd_emu10k1 {
struct semaphore ptb_lock;
emu10k1_voice_t voices[NUM_G];
+ emu10k1_voice_t p16v_voices[4];
+ int p16v_device_offset;
emu10k1_pcm_mixer_t pcm_mixer[32];
emu10k1_pcm_mixer_t efx_pcm_mixer[NUM_EFX_PLAYBACK];
snd_kcontrol_t *ctl_send_routing;
@@ -1087,6 +1151,9 @@ int snd_emu10k1_create(snd_card_t * card,
int snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
int snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
int snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
+int snd_p16v_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
+int snd_p16v_free(emu10k1_t * emu);
+int snd_p16v_mixer(emu10k1_t * emu);
int snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
int snd_emu10k1_fx8010_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
int snd_emu10k1_mixer(emu10k1_t * emu);
@@ -1104,6 +1171,8 @@ int snd_emu10k1_fx8010_tram_setup(emu10k1_t *emu, u32 size);
/* I/O functions */
unsigned int snd_emu10k1_ptr_read(emu10k1_t * emu, unsigned int reg, unsigned int chn);
void snd_emu10k1_ptr_write(emu10k1_t *emu, unsigned int reg, unsigned int chn, unsigned int data);
+unsigned int snd_emu10k1_ptr20_read(emu10k1_t * emu, unsigned int reg, unsigned int chn);
+void snd_emu10k1_ptr20_write(emu10k1_t *emu, unsigned int reg, unsigned int chn, unsigned int data);
unsigned int snd_emu10k1_efx_read(emu10k1_t *emu, unsigned int pc);
void snd_emu10k1_intr_enable(emu10k1_t *emu, unsigned int intrenb);
void snd_emu10k1_intr_disable(emu10k1_t *emu, unsigned int intrenb);
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 92260e2d548ce..3f9db510dee33 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -79,9 +79,10 @@ struct _snd_rawmidi_runtime {
/* misc */
spinlock_t lock;
wait_queue_head_t sleep;
- /* event handler (room [output] or new bytes [input]) */
- struct tasklet_struct event_tasklet;
+ /* event handler (new bytes, input only) */
void (*event)(snd_rawmidi_substream_t *substream);
+ /* defers calls to event [input] or ops->trigger [output] */
+ struct tasklet_struct tasklet;
/* private data */
void *private_data;
void (*private_free)(snd_rawmidi_substream_t *substream);
diff --git a/include/sound/seq_midi_emul.h b/include/sound/seq_midi_emul.h
index 32158a6070116..e58ca45bc73b3 100644
--- a/include/sound/seq_midi_emul.h
+++ b/include/sound/seq_midi_emul.h
@@ -136,7 +136,7 @@ typedef struct snd_seq_midi_op {
#define gm_sustain control[MIDI_CTL_SUSTAIN]
#define gm_hold gm_sustain
#define gm_portamento control[MIDI_CTL_PORTAMENTO]
-#define gm_sustenuto control[MIDI_CTL_SUSTENUTO]
+#define gm_sostenuto control[MIDI_CTL_SOSTENUTO]
/*
* These macros give the complete value of the controls that consist
@@ -166,7 +166,7 @@ typedef struct snd_seq_midi_op {
#define SNDRV_MIDI_NOTE_OFF 0x00
#define SNDRV_MIDI_NOTE_ON 0x01
#define SNDRV_MIDI_NOTE_RELEASED 0x02
-#define SNDRV_MIDI_NOTE_SUSTENUTO 0x04
+#define SNDRV_MIDI_NOTE_SOSTENUTO 0x04
#define SNDRV_MIDI_PARAM_TYPE_REGISTERED 0
#define SNDRV_MIDI_PARAM_TYPE_NONREGISTERED 1
diff --git a/include/sound/version.h b/include/sound/version.h
index a4db7e75de4d3..98b4230778ed4 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated by configure. */
-#define CONFIG_SND_VERSION "1.0.8"
-#define CONFIG_SND_DATE " (Thu Jan 13 09:39:32 2005 UTC)"
+#define CONFIG_SND_VERSION "1.0.9rc2"
+#define CONFIG_SND_DATE " (Thu Mar 24 10:33:39 2005 UTC)"
diff --git a/include/video/s1d13xxxfb.h b/include/video/s1d13xxxfb.h
new file mode 100644
index 0000000000000..f06cc88607f51
--- /dev/null
+++ b/include/video/s1d13xxxfb.h
@@ -0,0 +1,166 @@
+/* drivers/video/s1d3xxxfb.h
+ *
+ * (c) 2004 Simtec Electronics
+ * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * Header file for Epson S1D13XXX driver code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef S1D13XXXFB_H
+#define S1D13XXXFB_H
+
+#define S1D_PALETTE_SIZE 256
+#define S1D_CHIP_REV 7 /* expected chip revision number for s1d13806 */
+#define S1D_FBID "S1D13806"
+#define S1D_DEVICENAME "s1d13806fb"
+
+/* register definitions (tested on s1d13896) */
+#define S1DREG_REV_CODE 0x0000 /* Revision Code Register */
+#define S1DREG_MISC 0x0001 /* Miscellaneous Register */
+#define S1DREG_GPIO_CNF0 0x0004 /* General IO Pins Configuration Register 0 */
+#define S1DREG_GPIO_CNF1 0x0005 /* General IO Pins Configuration Register 1 */
+#define S1DREG_GPIO_CTL0 0x0008 /* General IO Pins Control Register 0 */
+#define S1DREG_GPIO_CTL1 0x0009 /* General IO Pins Control Register 1 */
+#define S1DREG_CNF_STATUS 0x000C /* Configuration Status Readback Register */
+#define S1DREG_CLK_CNF 0x0010 /* Memory Clock Configuration Register */
+#define S1DREG_LCD_CLK_CNF 0x0014 /* LCD Pixel Clock Configuration Register */
+#define S1DREG_CRT_CLK_CNF 0x0018 /* CRT/TV Pixel Clock Configuration Register */
+#define S1DREG_MPLUG_CLK_CNF 0x001C /* MediaPlug Clock Configuration Register */
+#define S1DREG_CPU2MEM_WST_SEL 0x001E /* CPU To Memory Wait State Select Register */
+#define S1DREG_MEM_CNF 0x0020 /* Memory Configuration Register */
+#define S1DREG_SDRAM_REF_RATE 0x0021 /* SDRAM Refresh Rate Register */
+#define S1DREG_SDRAM_TC0 0x002A /* SDRAM Timing Control Register 0 */
+#define S1DREG_SDRAM_TC1 0x002B /* SDRAM Timing Control Register 1 */
+#define S1DREG_PANEL_TYPE 0x0030 /* Panel Type Register */
+#define S1DREG_MOD_RATE 0x0031 /* MOD Rate Register */
+#define S1DREG_LCD_DISP_HWIDTH 0x0032 /* LCD Horizontal Display Width Register: ((val)+1)*8)=pix/line */
+#define S1DREG_LCD_NDISP_HPER 0x0034 /* LCD Horizontal Non-Display Period Register: ((val)+1)*8)=NDpix/line */
+#define S1DREG_TFT_FPLINE_START 0x0035 /* TFT FPLINE Start Position Register */
+#define S1DREG_TFT_FPLINE_PWIDTH 0x0036 /* TFT FPLINE Pulse Width Register. */
+#define S1DREG_LCD_DISP_VHEIGHT0 0x0038 /* LCD Vertical Display Height Register 0 */
+#define S1DREG_LCD_DISP_VHEIGHT1 0x0039 /* LCD Vertical Display Height Register 1 */
+#define S1DREG_LCD_NDISP_VPER 0x003A /* LCD Vertical Non-Display Period Register: (val)+1=NDlines */
+#define S1DREG_TFT_FPFRAME_START 0x003B /* TFT FPFRAME Start Position Register */
+#define S1DREG_TFT_FPFRAME_PWIDTH 0x003C /* TFT FPFRAME Pulse Width Register */
+#define S1DREG_LCD_DISP_MODE 0x0040 /* LCD Display Mode Register */
+#define S1DREG_LCD_MISC 0x0041 /* LCD Miscellaneous Register */
+#define S1DREG_LCD_DISP_START0 0x0042 /* LCD Display Start Address Register 0 */
+#define S1DREG_LCD_DISP_START1 0x0043 /* LCD Display Start Address Register 1 */
+#define S1DREG_LCD_DISP_START2 0x0044 /* LCD Display Start Address Register 2 */
+#define S1DREG_LCD_MEM_OFF0 0x0046 /* LCD Memory Address Offset Register 0 */
+#define S1DREG_LCD_MEM_OFF1 0x0047 /* LCD Memory Address Offset Register 1 */
+#define S1DREG_LCD_PIX_PAN 0x0048 /* LCD Pixel Panning Register */
+#define S1DREG_LCD_DISP_FIFO_HTC 0x004A /* LCD Display FIFO High Threshold Control Register */
+#define S1DREG_LCD_DISP_FIFO_LTC 0x004B /* LCD Display FIFO Low Threshold Control Register */
+#define S1DREG_CRT_DISP_HWIDTH 0x0050 /* CRT/TV Horizontal Display Width Register: ((val)+1)*8)=pix/line */
+#define S1DREG_CRT_NDISP_HPER 0x0052 /* CRT/TV Horizontal Non-Display Period Register */
+#define S1DREG_CRT_HRTC_START 0x0053 /* CRT/TV HRTC Start Position Register */
+#define S1DREG_CRT_HRTC_PWIDTH 0x0054 /* CRT/TV HRTC Pulse Width Register */
+#define S1DREG_CRT_DISP_VHEIGHT0 0x0056 /* CRT/TV Vertical Display Height Register 0 */
+#define S1DREG_CRT_DISP_VHEIGHT1 0x0057 /* CRT/TV Vertical Display Height Register 1 */
+#define S1DREG_CRT_NDISP_VPER 0x0058 /* CRT/TV Vertical Non-Display Period Register */
+#define S1DREG_CRT_VRTC_START 0x0059 /* CRT/TV VRTC Start Position Register */
+#define S1DREG_CRT_VRTC_PWIDTH 0x005A /* CRT/TV VRTC Pulse Width Register */
+#define S1DREG_TV_OUT_CTL 0x005B /* TV Output Control Register */
+#define S1DREG_CRT_DISP_MODE 0x0060 /* CRT/TV Display Mode Register */
+#define S1DREG_CRT_DISP_START0 0x0062 /* CRT/TV Display Start Address Register 0 */
+#define S1DREG_CRT_DISP_START1 0x0063 /* CRT/TV Display Start Address Register 1 */
+#define S1DREG_CRT_DISP_START2 0x0064 /* CRT/TV Display Start Address Register 2 */
+#define S1DREG_CRT_MEM_OFF0 0x0066 /* CRT/TV Memory Address Offset Register 0 */
+#define S1DREG_CRT_MEM_OFF1 0x0067 /* CRT/TV Memory Address Offset Register 1 */
+#define S1DREG_CRT_PIX_PAN 0x0068 /* CRT/TV Pixel Panning Register */
+#define S1DREG_CRT_DISP_FIFO_HTC 0x006A /* CRT/TV Display FIFO High Threshold Control Register */
+#define S1DREG_CRT_DISP_FIFO_LTC 0x006B /* CRT/TV Display FIFO Low Threshold Control Register */
+#define S1DREG_LCD_CUR_CTL 0x0070 /* LCD Ink/Cursor Control Register */
+#define S1DREG_LCD_CUR_START 0x0071 /* LCD Ink/Cursor Start Address Register */
+#define S1DREG_LCD_CUR_XPOS0 0x0072 /* LCD Cursor X Position Register 0 */
+#define S1DREG_LCD_CUR_XPOS1 0x0073 /* LCD Cursor X Position Register 1 */
+#define S1DREG_LCD_CUR_YPOS0 0x0074 /* LCD Cursor Y Position Register 0 */
+#define S1DREG_LCD_CUR_YPOS1 0x0075 /* LCD Cursor Y Position Register 1 */
+#define S1DREG_LCD_CUR_BCTL0 0x0076 /* LCD Ink/Cursor Blue Color 0 Register */
+#define S1DREG_LCD_CUR_GCTL0 0x0077 /* LCD Ink/Cursor Green Color 0 Register */
+#define S1DREG_LCD_CUR_RCTL0 0x0078 /* LCD Ink/Cursor Red Color 0 Register */
+#define S1DREG_LCD_CUR_BCTL1 0x007A /* LCD Ink/Cursor Blue Color 1 Register */
+#define S1DREG_LCD_CUR_GCTL1 0x007B /* LCD Ink/Cursor Green Color 1 Register */
+#define S1DREG_LCD_CUR_RCTL1 0x007C /* LCD Ink/Cursor Red Color 1 Register */
+#define S1DREG_LCD_CUR_FIFO_HTC 0x007E /* LCD Ink/Cursor FIFO High Threshold Register */
+#define S1DREG_CRT_CUR_CTL 0x0080 /* CRT/TV Ink/Cursor Control Register */
+#define S1DREG_CRT_CUR_START 0x0081 /* CRT/TV Ink/Cursor Start Address Register */
+#define S1DREG_CRT_CUR_XPOS0 0x0082 /* CRT/TV Cursor X Position Register 0 */
+#define S1DREG_CRT_CUR_XPOS1 0x0083 /* CRT/TV Cursor X Position Register 1 */
+#define S1DREG_CRT_CUR_YPOS0 0x0084 /* CRT/TV Cursor Y Position Register 0 */
+#define S1DREG_CRT_CUR_YPOS1 0x0085 /* CRT/TV Cursor Y Position Register 1 */
+#define S1DREG_CRT_CUR_BCTL0 0x0086 /* CRT/TV Ink/Cursor Blue Color 0 Register */
+#define S1DREG_CRT_CUR_GCTL0 0x0087 /* CRT/TV Ink/Cursor Green Color 0 Register */
+#define S1DREG_CRT_CUR_RCTL0 0x0088 /* CRT/TV Ink/Cursor Red Color 0 Register */
+#define S1DREG_CRT_CUR_BCTL1 0x008A /* CRT/TV Ink/Cursor Blue Color 1 Register */
+#define S1DREG_CRT_CUR_GCTL1 0x008B /* CRT/TV Ink/Cursor Green Color 1 Register */
+#define S1DREG_CRT_CUR_RCTL1 0x008C /* CRT/TV Ink/Cursor Red Color 1 Register */
+#define S1DREG_CRT_CUR_FIFO_HTC 0x008E /* CRT/TV Ink/Cursor FIFO High Threshold Register */
+#define S1DREG_BBLT_CTL0 0x0100 /* BitBLT Control Register 0 */
+#define S1DREG_BBLT_CTL1 0x0101 /* BitBLT Control Register 1 */
+#define S1DREG_BBLT_CC_EXP 0x0102 /* BitBLT Code/Color Expansion Register */
+#define S1DREG_BBLT_OP 0x0103 /* BitBLT Operation Register */
+#define S1DREG_BBLT_SRC_START0 0x0104 /* BitBLT Source Start Address Register 0 */
+#define S1DREG_BBLT_SRC_START1 0x0105 /* BitBLT Source Start Address Register 1 */
+#define S1DREG_BBLT_SRC_START2 0x0106 /* BitBLT Source Start Address Register 2 */
+#define S1DREG_BBLT_DST_START0 0x0108 /* BitBLT Destination Start Address Register 0 */
+#define S1DREG_BBLT_DST_START1 0x0109 /* BitBLT Destination Start Address Register 1 */
+#define S1DREG_BBLT_DST_START2 0x010A /* BitBLT Destination Start Address Register 2 */
+#define S1DREG_BBLT_MEM_OFF0 0x010C /* BitBLT Memory Address Offset Register 0 */
+#define S1DREG_BBLT_MEM_OFF1 0x010D /* BitBLT Memory Address Offset Register 1 */
+#define S1DREG_BBLT_WIDTH0 0x0110 /* BitBLT Width Register 0 */
+#define S1DREG_BBLT_WIDTH1 0x0111 /* BitBLT Width Register 1 */
+#define S1DREG_BBLT_HEIGHT0 0x0112 /* BitBLT Height Register 0 */
+#define S1DREG_BBLT_HEIGHT1 0x0113 /* BitBLT Height Register 1 */
+#define S1DREG_BBLT_BGC0 0x0114 /* BitBLT Background Color Register 0 */
+#define S1DREG_BBLT_BGC1 0x0115 /* BitBLT Background Color Register 1 */
+#define S1DREG_BBLT_FGC0 0x0118 /* BitBLT Foreground Color Register 0 */
+#define S1DREG_BBLT_FGC1 0x0119 /* BitBLT Foreground Color Register 1 */
+#define S1DREG_LKUP_MODE 0x01E0 /* Look-Up Table Mode Register */
+#define S1DREG_LKUP_ADDR 0x01E2 /* Look-Up Table Address Register */
+#define S1DREG_LKUP_DATA 0x01E4 /* Look-Up Table Data Register */
+#define S1DREG_PS_CNF 0x01F0 /* Power Save Configuration Register */
+#define S1DREG_PS_STATUS 0x01F1 /* Power Save Status Register */
+#define S1DREG_CPU2MEM_WDOGT 0x01F4 /* CPU-to-Memory Access Watchdog Timer Register */
+#define S1DREG_COM_DISP_MODE 0x01FC /* Common Display Mode Register */
+
+#define S1DREG_DELAYOFF 0xFFFE
+#define S1DREG_DELAYON 0xFFFF
+
+/* Note: all above defines should go in separate header files
+ when implementing other S1D13xxx chip support. */
+
+struct s1d13xxxfb_regval {
+ u16 addr;
+ u8 value;
+};
+
+
+struct s1d13xxxfb_par {
+ void __iomem *regs;
+ unsigned char display;
+
+ unsigned int pseudo_palette[16];
+#ifdef CONFIG_PM
+ void *regs_save; /* pm saves all registers here */
+ void *disp_save; /* pm saves entire screen here */
+#endif
+};
+
+struct s1d13xxxfb_pdata {
+ const struct s1d13xxxfb_regval *initregs;
+ const unsigned int initregssize;
+ void (*platform_init_video)(void);
+#ifdef CONFIG_PM
+ int (*platform_suspend_video)(void);
+ int (*platform_resume_video)(void);
+#endif
+};
+
+#endif
+
diff --git a/include/video/trident.h b/include/video/trident.h
index abe7d67756de7..200be25516819 100644
--- a/include/video/trident.h
+++ b/include/video/trident.h
@@ -9,7 +9,7 @@
#define debug(f,a...)
#endif
-#define output(f, a...) printk("tridentfb: " f, ## a)
+#define output(f, a...) pr_info("tridentfb: " f, ## a)
#define Kb (1024)
#define Mb (Kb*Kb)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index cd942ce30b738..a6584d9099d32 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -193,7 +193,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry);
static struct backing_dev_info cpuset_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
static struct inode *cpuset_new_inode(mode_t mode)
@@ -1456,7 +1456,7 @@ void cpuset_init_current_mems_allowed(void)
* Do not call this routine if in_interrupt().
*/
-void cpuset_update_current_mems_allowed()
+void cpuset_update_current_mems_allowed(void)
{
struct cpuset *cs = current->cpuset;
diff --git a/kernel/printk.c b/kernel/printk.c
index 5d5754964bf40..1498689548d1e 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -54,7 +54,12 @@ int console_printk[4] = {
EXPORT_SYMBOL(console_printk);
+/*
+ * Low lever drivers may need that to know if they can schedule in
+ * their unblank() callback or not. So let's export it.
+ */
int oops_in_progress;
+EXPORT_SYMBOL(oops_in_progress);
/*
* console_sem protects the console_drivers list, and also
@@ -751,12 +756,15 @@ void console_unblank(void)
struct console *c;
/*
- * Try to get the console semaphore. If someone else owns it
- * we have to return without unblanking because console_unblank
- * may be called in interrupt context.
+ * console_unblank can no longer be called in interrupt context unless
+ * oops_in_progress is set to 1..
*/
- if (down_trylock(&console_sem) != 0)
- return;
+ if (oops_in_progress) {
+ if (down_trylock(&console_sem) != 0)
+ return;
+ } else
+ acquire_console_sem();
+
console_locked = 1;
console_may_schedule = 0;
for (c = console_drivers; c != NULL; c = c->next)
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index f0ae3c3c013eb..d00eded75d71f 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -465,6 +465,6 @@ void synchronize_kernel(void)
}
module_param(maxbatch, int, 0);
-EXPORT_SYMBOL(call_rcu);
-EXPORT_SYMBOL(call_rcu_bh);
-EXPORT_SYMBOL(synchronize_kernel);
+EXPORT_SYMBOL_GPL(call_rcu);
+EXPORT_SYMBOL_GPL(call_rcu_bh);
+EXPORT_SYMBOL_GPL(synchronize_kernel);
diff --git a/kernel/sched.c b/kernel/sched.c
index dff94ba6df386..f69c4a5361e3b 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -314,7 +314,6 @@ static inline void task_rq_unlock(runqueue_t *rq, unsigned long *flags)
static int show_schedstat(struct seq_file *seq, void *v)
{
int cpu;
- enum idle_type itype;
seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
seq_printf(seq, "timestamp %lu\n", jiffies);
@@ -340,6 +339,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
#ifdef CONFIG_SMP
/* domain-specific stats */
for_each_domain(cpu, sd) {
+ enum idle_type itype;
char mask_str[NR_CPUS];
cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index b6c5b35c737c0..c3391b6020e85 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -8,10 +8,6 @@
#include <linux/seccomp.h>
#include <linux/sched.h>
-#include <asm/unistd.h>
-#ifdef TIF_IA32
-#include <asm/ia32_unistd.h>
-#endif
/* #define SECCOMP_DEBUG 1 */
@@ -21,27 +17,13 @@
* to limit the stack allocations too.
*/
static int mode1_syscalls[] = {
- __NR_read, __NR_write, __NR_exit,
- /*
- * Allow either sigreturn or rt_sigreturn, newer archs
- * like x86-64 only defines __NR_rt_sigreturn.
- */
-#ifdef __NR_sigreturn
- __NR_sigreturn,
-#else
- __NR_rt_sigreturn,
-#endif
+ __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn,
0, /* null terminated */
};
-#ifdef TIF_IA32
-static int mode1_syscalls_32bit[] = {
- __NR_ia32_read, __NR_ia32_write, __NR_ia32_exit,
- /*
- * Allow either sigreturn or rt_sigreturn, newer archs
- * like x86-64 only defines __NR_rt_sigreturn.
- */
- __NR_ia32_sigreturn,
+#ifdef TIF_32BIT
+static int mode1_syscalls_32[] = {
+ __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
0, /* null terminated */
};
#endif
@@ -54,9 +36,9 @@ void __secure_computing(int this_syscall)
switch (mode) {
case 1:
syscall = mode1_syscalls;
-#ifdef TIF_IA32
- if (test_thread_flag(TIF_IA32))
- syscall = mode1_syscalls_32bit;
+#ifdef TIF_32BIT
+ if (test_thread_flag(TIF_32BIT))
+ syscall = mode1_syscalls_32;
#endif
do {
if (*syscall == this_syscall)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index bceee34aa9791..426a0cf7b11c6 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -108,7 +108,7 @@ config DEBUG_HIGHMEM
config DEBUG_BUGVERBOSE
bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
- depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || (X86 && !X86_64)
+ depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || (X86 && !X86_64) || FRV
default !EMBEDDED
help
Say Y here to make BUG() panics output the file name and line number
@@ -150,7 +150,7 @@ config DEBUG_FS
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
- depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU)
+ depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV)
help
If you say Y here the resulting kernel image will be slightly larger
and slower, but it will give very useful debugging information.
diff --git a/mm/filemap.c b/mm/filemap.c
index 553681db603d4..439b2bea8e342 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -172,7 +172,7 @@ static int __filemap_fdatawrite_range(struct address_space *mapping,
.end = end,
};
- if (mapping->backing_dev_info->memory_backed)
+ if (!mapping_cap_writeback_dirty(mapping))
return 0;
ret = do_writepages(mapping, &wbc);
@@ -269,7 +269,7 @@ int sync_page_range(struct inode *inode, struct address_space *mapping,
pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
int ret;
- if (mapping->backing_dev_info->memory_backed || !count)
+ if (!mapping_cap_writeback_dirty(mapping) || !count)
return 0;
ret = filemap_fdatawrite_range(mapping, pos, pos + count - 1);
if (ret == 0) {
@@ -295,7 +295,7 @@ int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
int ret;
- if (mapping->backing_dev_info->memory_backed || !count)
+ if (!mapping_cap_writeback_dirty(mapping) || !count)
return 0;
ret = filemap_fdatawrite_range(mapping, pos, pos + count - 1);
if (ret == 0)
diff --git a/mm/nommu.c b/mm/nommu.c
index a9cf49a0e0350..f613db39e8474 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -396,6 +396,7 @@ unsigned long do_mmap_pgoff(struct file *file,
unsigned int vm_flags;
void *result;
int ret, membacked;
+ unsigned long reqprot = prot;
/* do the simple checks first */
if (flags & MAP_FIXED || addr) {
@@ -506,7 +507,7 @@ unsigned long do_mmap_pgoff(struct file *file,
}
/* allow the security API to have its say */
- ret = security_file_mmap(file, prot, flags);
+ ret = security_file_mmap(file, reqprot, prot, flags);
if (ret)
return ret;
@@ -1063,3 +1064,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
return -ENOMEM;
}
+int in_gate_area_no_task(unsigned long addr)
+{
+ return 0;
+}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index ab35f448db18e..6ddd6a29c73b2 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -627,7 +627,7 @@ int __set_page_dirty_nobuffers(struct page *page)
mapping2 = page_mapping(page);
if (mapping2) { /* Race with truncate? */
BUG_ON(mapping2 != mapping);
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
inc_page_state(nr_dirty);
radix_tree_tag_set(&mapping->page_tree,
page_index(page), PAGECACHE_TAG_DIRTY);
@@ -713,7 +713,7 @@ int test_clear_page_dirty(struct page *page)
page_index(page),
PAGECACHE_TAG_DIRTY);
write_unlock_irqrestore(&mapping->tree_lock, flags);
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
dec_page_state(nr_dirty);
return 1;
}
@@ -744,7 +744,7 @@ int clear_page_dirty_for_io(struct page *page)
if (mapping) {
if (TestClearPageDirty(page)) {
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
dec_page_state(nr_dirty);
return 1;
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e87a9e1809f27..c73dbbc1cd8f5 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -780,6 +780,9 @@ __alloc_pages(unsigned int __nocast gfp_mask, unsigned int order,
/*
* Go through the zonelist again. Let __GFP_HIGH and allocations
* coming from realtime tasks to go deeper into reserves
+ *
+ * This is the last chance, in general, before the goto nopage.
+ * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc.
*/
for (i = 0; (z = zones[i]) != NULL; i++) {
if (!zone_watermark_ok(z, order, z->pages_min,
@@ -787,7 +790,7 @@ __alloc_pages(unsigned int __nocast gfp_mask, unsigned int order,
gfp_mask & __GFP_HIGH))
continue;
- if (!cpuset_zone_allowed(z))
+ if (wait && !cpuset_zone_allowed(z))
continue;
page = buffered_rmqueue(z, order, gfp_mask);
diff --git a/mm/readahead.c b/mm/readahead.c
index 8c4ac1267120f..b840e7c6ea740 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -23,6 +23,7 @@ EXPORT_SYMBOL(default_unplug_io_fn);
struct backing_dev_info default_backing_dev_info = {
.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
.state = 0,
+ .capabilities = BDI_CAP_MAP_COPY,
.unplug_io_fn = default_unplug_io_fn,
};
EXPORT_SYMBOL_GPL(default_backing_dev_info);
diff --git a/mm/shmem.c b/mm/shmem.c
index c1d60dd5579ef..61574b81d979f 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -184,8 +184,8 @@ static struct vm_operations_struct shmem_vm_ops;
static struct backing_dev_info shmem_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
- .unplug_io_fn = default_unplug_io_fn,
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+ .unplug_io_fn = default_unplug_io_fn,
};
static LIST_HEAD(shmem_swaplist);
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 994c262ae084d..a063a902ed034 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -29,7 +29,7 @@ static struct address_space_operations swap_aops = {
};
static struct backing_dev_info swap_backing_dev_info = {
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
.unplug_io_fn = swap_unplug_io_fn,
};
diff --git a/sound/core/control.c b/sound/core/control.c
index 576e35ed87593..f4ea6bff1dd3b 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -519,20 +519,25 @@ snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
unsigned int cmd, void __user *arg)
{
- snd_ctl_card_info_t info;
+ snd_ctl_card_info_t *info;
- memset(&info, 0, sizeof(info));
+ info = kcalloc(1, sizeof(*info), GFP_KERNEL);
+ if (! info)
+ return -ENOMEM;
down_read(&snd_ioctl_rwsem);
- info.card = card->number;
- strlcpy(info.id, card->id, sizeof(info.id));
- strlcpy(info.driver, card->driver, sizeof(info.driver));
- strlcpy(info.name, card->shortname, sizeof(info.name));
- strlcpy(info.longname, card->longname, sizeof(info.longname));
- strlcpy(info.mixername, card->mixername, sizeof(info.mixername));
- strlcpy(info.components, card->components, sizeof(info.components));
+ info->card = card->number;
+ strlcpy(info->id, card->id, sizeof(info->id));
+ strlcpy(info->driver, card->driver, sizeof(info->driver));
+ strlcpy(info->name, card->shortname, sizeof(info->name));
+ strlcpy(info->longname, card->longname, sizeof(info->longname));
+ strlcpy(info->mixername, card->mixername, sizeof(info->mixername));
+ strlcpy(info->components, card->components, sizeof(info->components));
up_read(&snd_ioctl_rwsem);
- if (copy_to_user(arg, &info, sizeof(snd_ctl_card_info_t)))
+ if (copy_to_user(arg, info, sizeof(snd_ctl_card_info_t))) {
+ kfree(info);
return -EFAULT;
+ }
+ kfree(info);
return 0;
}
diff --git a/sound/core/info.c b/sound/core/info.c
index de9879b3b3867..31faffe01cb0f 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -92,19 +92,18 @@ static int snd_info_version_done(void);
int snd_iprintf(snd_info_buffer_t * buffer, char *fmt,...)
{
va_list args;
- int res;
- char sbuffer[512];
+ int len, res;
if (buffer->stop || buffer->error)
return 0;
+ len = buffer->len - buffer->size;
va_start(args, fmt);
- res = vscnprintf(sbuffer, sizeof(sbuffer), fmt, args);
+ res = vsnprintf(buffer->curr, len, fmt, args);
va_end(args);
- if (buffer->size + res >= buffer->len) {
+ if (res >= len) {
buffer->stop = 1;
return 0;
}
- strcpy(buffer->curr, sbuffer);
buffer->curr += res;
buffer->size += res;
return res;
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 4ec82aad54fb7..1a81fe4df218b 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -40,7 +40,6 @@ int snd_task_name(struct task_struct *task, char *name, size_t size)
void snd_verbose_printk(const char *file, int line, const char *format, ...)
{
va_list args;
- char tmpbuf[512];
if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
char tmp[] = "<0>";
@@ -51,9 +50,8 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...)
printk("ALSA %s:%d: ", file, line);
}
va_start(args, format);
- vsnprintf(tmpbuf, sizeof(tmpbuf), format, args);
+ vprintk(format, args);
va_end(args);
- printk(tmpbuf);
}
#endif
@@ -61,7 +59,6 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...)
void snd_verbose_printd(const char *file, int line, const char *format, ...)
{
va_list args;
- char tmpbuf[512];
if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
char tmp[] = "<0>";
@@ -72,9 +69,8 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
printk(KERN_DEBUG "ALSA %s:%d: ", file, line);
}
va_start(args, format);
- vsnprintf(tmpbuf, sizeof(tmpbuf), format, args);
+ vprintk(format, args);
va_end(args);
- printk(tmpbuf);
}
#endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 877126ced65ae..98ed9a9f0da65 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -857,7 +857,7 @@ struct snd_mixer_oss_assign_table {
static int snd_mixer_oss_build_test(snd_mixer_oss_t *mixer, struct slot *slot, const char *name, int index, int item)
{
- snd_ctl_elem_info_t info;
+ snd_ctl_elem_info_t *info;
snd_kcontrol_t *kcontrol;
snd_card_t *card = mixer->card;
int err;
@@ -868,15 +868,22 @@ static int snd_mixer_oss_build_test(snd_mixer_oss_t *mixer, struct slot *slot, c
up_read(&card->controls_rwsem);
return 0;
}
- if ((err = kcontrol->info(kcontrol, &info)) < 0) {
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (! info) {
up_read(&card->controls_rwsem);
+ return -ENOMEM;
+ }
+ if ((err = kcontrol->info(kcontrol, info)) < 0) {
+ up_read(&card->controls_rwsem);
+ kfree(info);
return err;
}
slot->numid[item] = kcontrol->id.numid;
up_read(&card->controls_rwsem);
- if (info.count > slot->channels)
- slot->channels = info.count;
+ if (info->count > slot->channels)
+ slot->channels = info->count;
slot->present |= 1 << item;
+ kfree(info);
return 0;
}
@@ -961,10 +968,16 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os
return 0;
down_read(&mixer->card->controls_rwsem);
if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) {
- snd_ctl_elem_info_t uinfo;
+ snd_ctl_elem_info_t *uinfo;
- memset(&uinfo, 0, sizeof(uinfo));
- if (kctl->info(kctl, &uinfo)) {
+ uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
+ if (! uinfo) {
+ up_read(&mixer->card->controls_rwsem);
+ return -ENOMEM;
+ }
+
+ memset(uinfo, 0, sizeof(*uinfo));
+ if (kctl->info(kctl, uinfo)) {
up_read(&mixer->card->controls_rwsem);
return 0;
}
@@ -974,21 +987,22 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os
if (!strcmp(str, "Master Mono"))
strcpy(str, "Mix Mono");
slot.capture_item = 0;
- if (!strcmp(uinfo.value.enumerated.name, str)) {
+ if (!strcmp(uinfo->value.enumerated.name, str)) {
slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;
} else {
- for (slot.capture_item = 1; slot.capture_item < uinfo.value.enumerated.items; slot.capture_item++) {
- uinfo.value.enumerated.item = slot.capture_item;
- if (kctl->info(kctl, &uinfo)) {
+ for (slot.capture_item = 1; slot.capture_item < uinfo->value.enumerated.items; slot.capture_item++) {
+ uinfo->value.enumerated.item = slot.capture_item;
+ if (kctl->info(kctl, uinfo)) {
up_read(&mixer->card->controls_rwsem);
return 0;
}
- if (!strcmp(uinfo.value.enumerated.name, str)) {
+ if (!strcmp(uinfo->value.enumerated.name, str)) {
slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;
break;
}
}
}
+ kfree(uinfo);
}
up_read(&mixer->card->controls_rwsem);
if (slot.present != 0) {
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index b073ef48f02d9..1a805020f57a5 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2294,7 +2294,7 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
snd_info_buffer_t * buffer)
{
snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
- char line[256], str[32], task_name[32], *ptr;
+ char line[128], str[32], task_name[32], *ptr;
int idx1;
snd_pcm_oss_setup_t *setup, *setup1, template;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 9e4f76ab5f2a6..8d94325529a87 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -270,25 +270,35 @@ static const char *snd_pcm_oss_format_name(int format)
#ifdef CONFIG_PROC_FS
static void snd_pcm_proc_info_read(snd_pcm_substream_t *substream, snd_info_buffer_t *buffer)
{
- snd_pcm_info_t info;
+ snd_pcm_info_t *info;
int err;
+
snd_runtime_check(substream, return);
- err = snd_pcm_info(substream, &info);
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (! info) {
+ printk(KERN_DEBUG "snd_pcm_proc_info_read: cannot malloc\n");
+ return;
+ }
+
+ err = snd_pcm_info(substream, info);
if (err < 0) {
snd_iprintf(buffer, "error %d\n", err);
+ kfree(info);
return;
}
- snd_iprintf(buffer, "card: %d\n", info.card);
- snd_iprintf(buffer, "device: %d\n", info.device);
- snd_iprintf(buffer, "subdevice: %d\n", info.subdevice);
- snd_iprintf(buffer, "stream: %s\n", snd_pcm_stream_name(info.stream));
- snd_iprintf(buffer, "id: %s\n", info.id);
- snd_iprintf(buffer, "name: %s\n", info.name);
- snd_iprintf(buffer, "subname: %s\n", info.subname);
- snd_iprintf(buffer, "class: %d\n", info.dev_class);
- snd_iprintf(buffer, "subclass: %d\n", info.dev_subclass);
- snd_iprintf(buffer, "subdevices_count: %d\n", info.subdevices_count);
- snd_iprintf(buffer, "subdevices_avail: %d\n", info.subdevices_avail);
+ snd_iprintf(buffer, "card: %d\n", info->card);
+ snd_iprintf(buffer, "device: %d\n", info->device);
+ snd_iprintf(buffer, "subdevice: %d\n", info->subdevice);
+ snd_iprintf(buffer, "stream: %s\n", snd_pcm_stream_name(info->stream));
+ snd_iprintf(buffer, "id: %s\n", info->id);
+ snd_iprintf(buffer, "name: %s\n", info->name);
+ snd_iprintf(buffer, "subname: %s\n", info->subname);
+ snd_iprintf(buffer, "class: %d\n", info->dev_class);
+ snd_iprintf(buffer, "subclass: %d\n", info->dev_subclass);
+ snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count);
+ snd_iprintf(buffer, "subdevices_avail: %d\n", info->subdevices_avail);
+ kfree(info);
}
static void snd_pcm_stream_proc_info_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 0bee7c9c1fee2..cad9bbde99868 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -113,10 +113,18 @@ int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info)
int snd_pcm_info_user(snd_pcm_substream_t * substream, snd_pcm_info_t __user * _info)
{
- snd_pcm_info_t info;
- int err = snd_pcm_info(substream, &info);
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
+ snd_pcm_info_t *info;
+ int err;
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (! info)
+ return -ENOMEM;
+ err = snd_pcm_info(substream, info);
+ if (err >= 0) {
+ if (copy_to_user(_info, info, sizeof(*info)))
+ err = -EFAULT;
+ }
+ kfree(info);
return err;
}
@@ -1038,7 +1046,13 @@ static struct action_ops snd_pcm_action_suspend = {
*/
int snd_pcm_suspend(snd_pcm_substream_t *substream)
{
- return snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
+ int err;
+ unsigned long flags;
+
+ snd_pcm_stream_lock_irqsave(substream, flags);
+ err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+ return err;
}
/**
@@ -1057,11 +1071,8 @@ int snd_pcm_suspend_all(snd_pcm_t *pcm)
/* FIXME: the open/close code should lock this as well */
if (substream->runtime == NULL)
continue;
- snd_pcm_stream_lock(substream);
- if (substream->runtime->status->state != SNDRV_PCM_STATE_SUSPENDED)
- err = snd_pcm_suspend(substream);
- snd_pcm_stream_unlock(substream);
- if (err < 0)
+ err = snd_pcm_suspend(substream);
+ if (err < 0 && err != -EBUSY)
return err;
}
}
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 04f33178502bf..edba4118271c7 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -85,12 +85,18 @@ static inline int snd_rawmidi_ready_append(snd_rawmidi_substream_t * substream,
(!substream->append || runtime->avail >= count);
}
-static void snd_rawmidi_event_tasklet(unsigned long data)
+static void snd_rawmidi_input_event_tasklet(unsigned long data)
{
snd_rawmidi_substream_t *substream = (snd_rawmidi_substream_t *)data;
substream->runtime->event(substream);
}
+static void snd_rawmidi_output_trigger_tasklet(unsigned long data)
+{
+ snd_rawmidi_substream_t *substream = (snd_rawmidi_substream_t *)data;
+ substream->ops->trigger(substream, 1);
+}
+
static int snd_rawmidi_runtime_create(snd_rawmidi_substream_t * substream)
{
snd_rawmidi_runtime_t *runtime;
@@ -99,8 +105,14 @@ static int snd_rawmidi_runtime_create(snd_rawmidi_substream_t * substream)
return -ENOMEM;
spin_lock_init(&runtime->lock);
init_waitqueue_head(&runtime->sleep);
- tasklet_init(&runtime->event_tasklet, snd_rawmidi_event_tasklet,
- (unsigned long)substream);
+ if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)
+ tasklet_init(&runtime->tasklet,
+ snd_rawmidi_input_event_tasklet,
+ (unsigned long)substream);
+ else
+ tasklet_init(&runtime->tasklet,
+ snd_rawmidi_output_trigger_tasklet,
+ (unsigned long)substream);
runtime->event = NULL;
runtime->buffer_size = PAGE_SIZE;
runtime->avail_min = 1;
@@ -127,23 +139,34 @@ static int snd_rawmidi_runtime_free(snd_rawmidi_substream_t * substream)
return 0;
}
-static void snd_rawmidi_trigger(snd_rawmidi_substream_t * substream, int up)
+static inline void snd_rawmidi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+{
+ if (up) {
+ tasklet_hi_schedule(&substream->runtime->tasklet);
+ } else {
+ tasklet_kill(&substream->runtime->tasklet);
+ substream->ops->trigger(substream, 0);
+ }
+}
+
+static void snd_rawmidi_input_trigger(snd_rawmidi_substream_t * substream, int up)
{
substream->ops->trigger(substream, up);
if (!up && substream->runtime->event)
- tasklet_kill(&substream->runtime->event_tasklet);
+ tasklet_kill(&substream->runtime->tasklet);
}
int snd_rawmidi_drop_output(snd_rawmidi_substream_t * substream)
{
+ unsigned long flags;
snd_rawmidi_runtime_t *runtime = substream->runtime;
- snd_rawmidi_trigger(substream, 0);
+ snd_rawmidi_output_trigger(substream, 0);
runtime->drain = 0;
- /* interrupts are not enabled at this moment,
- so spinlock is not required */
+ spin_lock_irqsave(&runtime->lock, flags);
runtime->appl_ptr = runtime->hw_ptr = 0;
runtime->avail = runtime->buffer_size;
+ spin_unlock_irqrestore(&runtime->lock, flags);
return 0;
}
@@ -178,13 +201,15 @@ int snd_rawmidi_drain_output(snd_rawmidi_substream_t * substream)
int snd_rawmidi_drain_input(snd_rawmidi_substream_t * substream)
{
+ unsigned long flags;
snd_rawmidi_runtime_t *runtime = substream->runtime;
- snd_rawmidi_trigger(substream, 0);
+ snd_rawmidi_input_trigger(substream, 0);
runtime->drain = 0;
- /* interrupts aren't enabled at this moment, so spinlock isn't needed */
+ spin_lock_irqsave(&runtime->lock, flags);
runtime->appl_ptr = runtime->hw_ptr = 0;
runtime->avail = 0;
+ spin_unlock_irqrestore(&runtime->lock, flags);
return 0;
}
@@ -458,7 +483,7 @@ int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile)
substream = rfile->input;
rfile->input = NULL;
runtime = substream->runtime;
- snd_rawmidi_trigger(substream, 0);
+ snd_rawmidi_input_trigger(substream, 0);
substream->ops->close(substream);
if (runtime->private_free != NULL)
runtime->private_free(substream);
@@ -477,7 +502,7 @@ int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile)
snd_rawmidi_kernel_write(substream, &buf, 1);
}
if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS)
- snd_rawmidi_trigger(substream, 0);
+ snd_rawmidi_output_trigger(substream, 0);
substream->ops->close(substream);
if (runtime->private_free != NULL)
runtime->private_free(substream);
@@ -875,7 +900,7 @@ int snd_rawmidi_receive(snd_rawmidi_substream_t * substream, const unsigned char
}
if (result > 0) {
if (runtime->event)
- tasklet_hi_schedule(&runtime->event_tasklet);
+ tasklet_hi_schedule(&runtime->tasklet);
else if (snd_rawmidi_ready(substream))
wake_up(&runtime->sleep);
}
@@ -919,7 +944,7 @@ static long snd_rawmidi_kernel_read1(snd_rawmidi_substream_t *substream,
long snd_rawmidi_kernel_read(snd_rawmidi_substream_t *substream, unsigned char *buf, long count)
{
- snd_rawmidi_trigger(substream, 1);
+ snd_rawmidi_input_trigger(substream, 1);
return snd_rawmidi_kernel_read1(substream, buf, count, 1);
}
@@ -936,7 +961,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
if (substream == NULL)
return -EIO;
runtime = substream->runtime;
- snd_rawmidi_trigger(substream, 1);
+ snd_rawmidi_input_trigger(substream, 1);
result = 0;
while (count > 0) {
spin_lock_irq(&runtime->lock);
@@ -1072,11 +1097,8 @@ int snd_rawmidi_transmit_ack(snd_rawmidi_substream_t * substream, int count)
runtime->avail += count;
substream->bytes += count;
if (count > 0) {
- if (runtime->drain ||
- (runtime->event == NULL && snd_rawmidi_ready(substream)))
+ if (runtime->drain || snd_rawmidi_ready(substream))
wake_up(&runtime->sleep);
- if (runtime->event)
- tasklet_hi_schedule(&runtime->event_tasklet);
}
spin_unlock_irqrestore(&runtime->lock, flags);
return count;
@@ -1146,7 +1168,7 @@ static long snd_rawmidi_kernel_write1(snd_rawmidi_substream_t * substream, const
count1 = runtime->avail < runtime->buffer_size;
spin_unlock_irqrestore(&runtime->lock, flags);
if (count1)
- snd_rawmidi_trigger(substream, 1);
+ snd_rawmidi_output_trigger(substream, 1);
return result;
}
@@ -1231,7 +1253,7 @@ static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait)
rfile = file->private_data;
if (rfile->input != NULL) {
runtime = rfile->input->runtime;
- snd_rawmidi_trigger(rfile->input, 1);
+ snd_rawmidi_input_trigger(rfile->input, 1);
poll_wait(file, &runtime->sleep, wait);
}
if (rfile->output != NULL) {
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index 9f245c9994187..bac4b4f1a94ec 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -66,10 +66,17 @@ snd_seq_oss_create_client(void)
{
int rc;
snd_seq_client_callback_t callback;
- snd_seq_client_info_t info;
- snd_seq_port_info_t port;
+ snd_seq_client_info_t *info;
+ snd_seq_port_info_t *port;
snd_seq_port_callback_t port_callback;
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ port = kmalloc(sizeof(*port), GFP_KERNEL);
+ if (!info || !port) {
+ rc = -ENOMEM;
+ goto __error;
+ }
+
/* create ALSA client */
memset(&callback, 0, sizeof(callback));
@@ -79,38 +86,38 @@ snd_seq_oss_create_client(void)
rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS, &callback);
if (rc < 0)
- return rc;
+ goto __error;
system_client = rc;
debug_printk(("new client = %d\n", rc));
/* set client information */
- memset(&info, 0, sizeof(info));
- info.client = system_client;
- info.type = KERNEL_CLIENT;
- strcpy(info.name, "OSS sequencer");
+ memset(info, 0, sizeof(*info));
+ info->client = system_client;
+ info->type = KERNEL_CLIENT;
+ strcpy(info->name, "OSS sequencer");
- rc = call_ctl(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info);
+ rc = call_ctl(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info);
/* look up midi devices */
snd_seq_oss_midi_lookup_ports(system_client);
/* create annoucement receiver port */
- memset(&port, 0, sizeof(port));
- strcpy(port.name, "Receiver");
- port.addr.client = system_client;
- port.capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */
- port.type = 0;
+ memset(port, 0, sizeof(*port));
+ strcpy(port->name, "Receiver");
+ port->addr.client = system_client;
+ port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */
+ port->type = 0;
memset(&port_callback, 0, sizeof(port_callback));
/* don't set port_callback.owner here. otherwise the module counter
* is incremented and we can no longer release the module..
*/
port_callback.event_input = receive_announce;
- port.kernel = &port_callback;
+ port->kernel = &port_callback;
- call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port);
- if ((system_port = port.addr.port) >= 0) {
+ call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port);
+ if ((system_port = port->addr.port) >= 0) {
snd_seq_port_subscribe_t subs;
memset(&subs, 0, sizeof(subs));
@@ -120,9 +127,12 @@ snd_seq_oss_create_client(void)
subs.dest.port = system_port;
call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs);
}
+ rc = 0;
-
- return 0;
+ __error:
+ kfree(port);
+ kfree(info);
+ return rc;
}
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index 7120ad70dc034..9aece6c65dbc8 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -73,26 +73,27 @@ static int send_midi_event(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, seq_oss_m
int __init
snd_seq_oss_midi_lookup_ports(int client)
{
- snd_seq_system_info_t sysinfo;
- snd_seq_client_info_t clinfo;
- snd_seq_port_info_t pinfo;
- int rc;
-
- rc = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SYSTEM_INFO, &sysinfo);
- if (rc < 0)
- return rc;
-
- memset(&clinfo, 0, sizeof(clinfo));
- memset(&pinfo, 0, sizeof(pinfo));
- clinfo.client = -1;
- while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, &clinfo) == 0) {
- if (clinfo.client == client)
+ snd_seq_client_info_t *clinfo;
+ snd_seq_port_info_t *pinfo;
+
+ clinfo = kcalloc(1, sizeof(*clinfo), GFP_KERNEL);
+ pinfo = kcalloc(1, sizeof(*pinfo), GFP_KERNEL);
+ if (! clinfo || ! pinfo) {
+ kfree(clinfo);
+ kfree(pinfo);
+ return -ENOMEM;
+ }
+ clinfo->client = -1;
+ while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, clinfo) == 0) {
+ if (clinfo->client == client)
continue; /* ignore myself */
- pinfo.addr.client = clinfo.client;
- pinfo.addr.port = -1;
- while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, &pinfo) == 0)
- snd_seq_oss_midi_check_new_port(&pinfo);
+ pinfo->addr.client = clinfo->client;
+ pinfo->addr.port = -1;
+ while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, pinfo) == 0)
+ snd_seq_oss_midi_check_new_port(pinfo);
}
+ kfree(clinfo);
+ kfree(pinfo);
return 0;
}
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index a9957aeadc284..18247db45db65 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -289,8 +289,8 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
{
seq_midisynth_client_t *client;
seq_midisynth_t *msynth, *ms;
- snd_seq_port_info_t port;
- snd_rawmidi_info_t info;
+ snd_seq_port_info_t *port;
+ snd_rawmidi_info_t *info;
int newclient = 0;
unsigned int p, ports;
snd_seq_client_callback_t callbacks;
@@ -300,20 +300,25 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
unsigned int input_count = 0, output_count = 0;
snd_assert(card != NULL && device >= 0 && device < SNDRV_RAWMIDI_DEVICES, return -EINVAL);
- info.device = device;
- info.stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
- info.subdevice = 0;
- if (snd_rawmidi_info_select(card, &info) >= 0)
- output_count = info.subdevices_count;
- info.stream = SNDRV_RAWMIDI_STREAM_INPUT;
- if (snd_rawmidi_info_select(card, &info) >= 0) {
- input_count = info.subdevices_count;
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (! info)
+ return -ENOMEM;
+ info->device = device;
+ info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
+ info->subdevice = 0;
+ if (snd_rawmidi_info_select(card, info) >= 0)
+ output_count = info->subdevices_count;
+ info->stream = SNDRV_RAWMIDI_STREAM_INPUT;
+ if (snd_rawmidi_info_select(card, info) >= 0) {
+ input_count = info->subdevices_count;
}
ports = output_count;
if (ports < input_count)
ports = input_count;
- if (ports == 0)
+ if (ports == 0) {
+ kfree(info);
return -ENODEV;
+ }
if (ports > (256 / SNDRV_RAWMIDI_DEVICES))
ports = 256 / SNDRV_RAWMIDI_DEVICES;
@@ -324,6 +329,7 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
client = kcalloc(1, sizeof(*client), GFP_KERNEL);
if (client == NULL) {
up(&register_mutex);
+ kfree(info);
return -ENOMEM;
}
memset(&callbacks, 0, sizeof(callbacks));
@@ -333,14 +339,16 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
if (client->seq_client < 0) {
kfree(client);
up(&register_mutex);
+ kfree(info);
return -ENOMEM;
}
- set_client_name(client, card, &info);
+ set_client_name(client, card, info);
} else if (device == 0)
- set_client_name(client, card, &info); /* use the first device's name */
+ set_client_name(client, card, info); /* use the first device's name */
msynth = kcalloc(ports, sizeof(seq_midisynth_t), GFP_KERNEL);
- if (msynth == NULL)
+ port = kmalloc(sizeof(*port), GFP_KERNEL);
+ if (msynth == NULL || port == NULL)
goto __nomem;
for (p = 0; p < ports; p++) {
@@ -350,42 +358,42 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
goto __nomem;
/* declare port */
- memset(&port, 0, sizeof(port));
- port.addr.client = client->seq_client;
- port.addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p;
- port.flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
- memset(&info, 0, sizeof(info));
- info.device = device;
+ memset(port, 0, sizeof(*port));
+ port->addr.client = client->seq_client;
+ port->addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p;
+ port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
+ memset(info, 0, sizeof(*info));
+ info->device = device;
if (p < output_count)
- info.stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
+ info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
else
- info.stream = SNDRV_RAWMIDI_STREAM_INPUT;
- info.subdevice = p;
- if (snd_rawmidi_info_select(card, &info) >= 0)
- strcpy(port.name, info.subname);
- if (! port.name[0]) {
- if (info.name[0]) {
+ info->stream = SNDRV_RAWMIDI_STREAM_INPUT;
+ info->subdevice = p;
+ if (snd_rawmidi_info_select(card, info) >= 0)
+ strcpy(port->name, info->subname);
+ if (! port->name[0]) {
+ if (info->name[0]) {
if (ports > 1)
- snprintf(port.name, sizeof(port.name), "%s-%d", info.name, p);
+ snprintf(port->name, sizeof(port->name), "%s-%d", info->name, p);
else
- snprintf(port.name, sizeof(port.name), "%s", info.name);
+ snprintf(port->name, sizeof(port->name), "%s", info->name);
} else {
/* last resort */
if (ports > 1)
- sprintf(port.name, "MIDI %d-%d-%d", card->number, device, p);
+ sprintf(port->name, "MIDI %d-%d-%d", card->number, device, p);
else
- sprintf(port.name, "MIDI %d-%d", card->number, device);
+ sprintf(port->name, "MIDI %d-%d", card->number, device);
}
}
- if ((info.flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count)
- port.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
- if ((info.flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count)
- port.capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
- if ((port.capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) &&
- info.flags & SNDRV_RAWMIDI_INFO_DUPLEX)
- port.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
- port.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
- port.midi_channels = 16;
+ if ((info->flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count)
+ port->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
+ if ((info->flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count)
+ port->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
+ if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) &&
+ info->flags & SNDRV_RAWMIDI_INFO_DUPLEX)
+ port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
+ port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
+ port->midi_channels = 16;
memset(&pcallbacks, 0, sizeof(pcallbacks));
pcallbacks.owner = THIS_MODULE;
pcallbacks.private_data = ms;
@@ -394,11 +402,11 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
pcallbacks.use = midisynth_use;
pcallbacks.unuse = midisynth_unuse;
pcallbacks.event_input = event_process_midi;
- port.kernel = &pcallbacks;
- if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, &port)<0)
+ port->kernel = &pcallbacks;
+ if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0)
goto __nomem;
ms->seq_client = client->seq_client;
- ms->seq_port = port.addr.port;
+ ms->seq_port = port->addr.port;
}
client->ports_per_device[device] = ports;
client->ports[device] = msynth;
@@ -418,6 +426,8 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
snd_seq_delete_kernel_client(client->seq_client);
kfree(client);
}
+ kfree(info);
+ kfree(port);
up(&register_mutex);
return -ENOMEM;
}
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index 5b2e2ed977b7b..35fe8a7e34bf9 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -244,8 +244,8 @@ note_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan, int note, int
if (chan->gm_hold) {
/* Hold this note until pedal is turned off */
chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED;
- } else if (chan->note[note] & SNDRV_MIDI_NOTE_SUSTENUTO) {
- /* Mark this note as release; it will be turned off when sustenuto
+ } else if (chan->note[note] & SNDRV_MIDI_NOTE_SOSTENUTO) {
+ /* Mark this note as release; it will be turned off when sostenuto
* is turned off */
chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED;
} else {
@@ -287,18 +287,18 @@ do_control(snd_midi_op_t *ops, void *drv, snd_midi_channel_set_t *chset,
break;
case MIDI_CTL_PORTAMENTO:
break;
- case MIDI_CTL_SUSTENUTO:
+ case MIDI_CTL_SOSTENUTO:
if (value) {
/* Mark each note that is currently held down */
for (i = 0; i < 128; i++) {
if (chan->note[i] & SNDRV_MIDI_NOTE_ON)
- chan->note[i] |= SNDRV_MIDI_NOTE_SUSTENUTO;
+ chan->note[i] |= SNDRV_MIDI_NOTE_SOSTENUTO;
}
} else {
/* release all notes that were held */
for (i = 0; i < 128; i++) {
- if (chan->note[i] & SNDRV_MIDI_NOTE_SUSTENUTO) {
- chan->note[i] &= ~SNDRV_MIDI_NOTE_SUSTENUTO;
+ if (chan->note[i] & SNDRV_MIDI_NOTE_SOSTENUTO) {
+ chan->note[i] &= ~SNDRV_MIDI_NOTE_SOSTENUTO;
if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) {
chan->note[i] = SNDRV_MIDI_NOTE_OFF;
if (ops->note_off)
diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c
index ceecd72ee3751..e8f0a6683d50b 100644
--- a/sound/core/seq/seq_system.c
+++ b/sound/core/seq/seq_system.c
@@ -123,13 +123,19 @@ int __init snd_seq_system_client_init(void)
snd_seq_client_callback_t callbacks;
snd_seq_port_callback_t pcallbacks;
- snd_seq_client_info_t inf;
- snd_seq_port_info_t port;
+ snd_seq_client_info_t *inf;
+ snd_seq_port_info_t *port;
+
+ inf = kcalloc(1, sizeof(*inf), GFP_KERNEL);
+ port = kcalloc(1, sizeof(*port), GFP_KERNEL);
+ if (! inf || ! port) {
+ kfree(inf);
+ kfree(port);
+ return -ENOMEM;
+ }
memset(&callbacks, 0, sizeof(callbacks));
memset(&pcallbacks, 0, sizeof(pcallbacks));
- memset(&inf, 0, sizeof(inf));
- memset(&port, 0, sizeof(port));
pcallbacks.owner = THIS_MODULE;
pcallbacks.event_input = event_input_timer;
@@ -138,33 +144,35 @@ int __init snd_seq_system_client_init(void)
sysclient = snd_seq_create_kernel_client(NULL, 0, &callbacks);
/* set our name */
- inf.client = 0;
- inf.type = KERNEL_CLIENT;
- strcpy(inf.name, "System");
- snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &inf);
+ inf->client = 0;
+ inf->type = KERNEL_CLIENT;
+ strcpy(inf->name, "System");
+ snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, inf);
/* register timer */
- strcpy(port.name, "Timer");
- port.capability = SNDRV_SEQ_PORT_CAP_WRITE; /* accept queue control */
- port.capability |= SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast */
- port.kernel = &pcallbacks;
- port.type = 0;
- port.flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
- port.addr.client = sysclient;
- port.addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
- snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, &port);
+ strcpy(port->name, "Timer");
+ port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* accept queue control */
+ port->capability |= SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast */
+ port->kernel = &pcallbacks;
+ port->type = 0;
+ port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
+ port->addr.client = sysclient;
+ port->addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
+ snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port);
/* register announcement port */
- strcpy(port.name, "Announce");
- port.capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast only */
- port.kernel = NULL;
- port.type = 0;
- port.flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
- port.addr.client = sysclient;
- port.addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
- snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, &port);
- announce_port = port.addr.port;
-
+ strcpy(port->name, "Announce");
+ port->capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast only */
+ port->kernel = NULL;
+ port->type = 0;
+ port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
+ port->addr.client = sysclient;
+ port->addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
+ snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port);
+ announce_port = port->addr.port;
+
+ kfree(inf);
+ kfree(port);
return 0;
}
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 2785486292254..6b4e630ace541 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -354,39 +354,48 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
int client;
snd_seq_client_callback_t callbacks;
snd_seq_port_callback_t pcallbacks;
- snd_seq_client_info_t info;
- snd_seq_port_info_t pinfo;
+ snd_seq_client_info_t *info;
+ snd_seq_port_info_t *pinfo;
int err;
if (rdev->client >= 0)
return 0;
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ pinfo = kmalloc(sizeof(*pinfo), GFP_KERNEL);
+ if (! info || ! pinfo) {
+ err = -ENOMEM;
+ goto __error;
+ }
+
memset(&callbacks, 0, sizeof(callbacks));
callbacks.private_data = rdev;
callbacks.allow_input = 1;
callbacks.allow_output = 1;
client = snd_seq_create_kernel_client(rdev->card, rdev->device, &callbacks);
- if (client < 0)
- return client;
+ if (client < 0) {
+ err = client;
+ goto __error;
+ }
rdev->client = client;
/* set client name */
- memset(&info, 0, sizeof(info));
- info.client = client;
- info.type = KERNEL_CLIENT;
- sprintf(info.name, "%s %d-%d", rdev->rmidi->name, rdev->card->number, rdev->device);
+ memset(info, 0, sizeof(*info));
+ info->client = client;
+ info->type = KERNEL_CLIENT;
+ sprintf(info->name, "%s %d-%d", rdev->rmidi->name, rdev->card->number, rdev->device);
snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info);
/* create a port */
- memset(&pinfo, 0, sizeof(pinfo));
- pinfo.addr.client = client;
- sprintf(pinfo.name, "VirMIDI %d-%d", rdev->card->number, rdev->device);
+ memset(pinfo, 0, sizeof(*pinfo));
+ pinfo->addr.client = client;
+ sprintf(pinfo->name, "VirMIDI %d-%d", rdev->card->number, rdev->device);
/* set all capabilities */
- pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
- pinfo.capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
- pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
- pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
- pinfo.midi_channels = 16;
+ pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
+ pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
+ pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
+ pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
+ pinfo->midi_channels = 16;
memset(&pcallbacks, 0, sizeof(pcallbacks));
pcallbacks.owner = THIS_MODULE;
pcallbacks.private_data = rdev;
@@ -395,16 +404,21 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
pcallbacks.use = snd_virmidi_use;
pcallbacks.unuse = snd_virmidi_unuse;
pcallbacks.event_input = snd_virmidi_event_input;
- pinfo.kernel = &pcallbacks;
+ pinfo->kernel = &pcallbacks;
err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo);
if (err < 0) {
snd_seq_delete_kernel_client(client);
rdev->client = -1;
- return err;
+ goto __error;
}
- rdev->port = pinfo.addr.port;
- return 0; /* success */
+ rdev->port = pinfo->addr.port;
+ err = 0; /* success */
+
+ __error:
+ kfree(info);
+ kfree(pinfo);
+ return err;
}
diff --git a/sound/core/timer.c b/sound/core/timer.c
index fd5a7b276d9b4..fa762ca439be4 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -37,10 +37,12 @@
#include <linux/kerneld.h>
#endif
-#if !defined(CONFIG_SND_RTCTIMER) && !defined(CONFIG_SND_RTCTIMER_MODULE)
-#define DEFAULT_TIMER_LIMIT 1
-#else
+#if defined(CONFIG_SND_HPET) || defined(CONFIG_SND_HPET_MODULE)
+#define DEFAULT_TIMER_LIMIT 3
+#elif defined(CONFIG_SND_RTCTIMER) || defined(CONFIG_SND_RTCTIMER_MODULE)
#define DEFAULT_TIMER_LIMIT 2
+#else
+#define DEFAULT_TIMER_LIMIT 1
#endif
static int timer_limit = DEFAULT_TIMER_LIMIT;
@@ -1117,7 +1119,8 @@ static void snd_timer_user_append_to_tqueue(snd_timer_user_t *tu, snd_timer_trea
if (tu->qused >= tu->queue_size) {
tu->overrun++;
} else {
- memcpy(&tu->queue[tu->qtail++], tread, sizeof(*tread));
+ memcpy(&tu->tqueue[tu->qtail++], tread, sizeof(*tread));
+ tu->qtail %= tu->queue_size;
tu->qused++;
}
}
@@ -1140,6 +1143,8 @@ static void snd_timer_user_ccallback(snd_timer_instance_t *timeri,
spin_lock(&tu->qlock);
snd_timer_user_append_to_tqueue(tu, &r1);
spin_unlock(&tu->qlock);
+ kill_fasync(&tu->fasync, SIGIO, POLL_IN);
+ wake_up(&tu->qchange_sleep);
}
static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri,
@@ -1342,39 +1347,45 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid)
static int snd_timer_user_ginfo(struct file *file, snd_timer_ginfo_t __user *_ginfo)
{
- snd_timer_ginfo_t ginfo;
+ snd_timer_ginfo_t *ginfo;
snd_timer_id_t tid;
snd_timer_t *t;
struct list_head *p;
int err = 0;
- if (copy_from_user(&ginfo, _ginfo, sizeof(ginfo)))
+ ginfo = kmalloc(sizeof(*ginfo), GFP_KERNEL);
+ if (! ginfo)
+ return -ENOMEM;
+ if (copy_from_user(ginfo, _ginfo, sizeof(*ginfo))) {
+ kfree(ginfo);
return -EFAULT;
- tid = ginfo.tid;
- memset(&ginfo, 0, sizeof(ginfo));
- ginfo.tid = tid;
+ }
+ tid = ginfo->tid;
+ memset(ginfo, 0, sizeof(*ginfo));
+ ginfo->tid = tid;
down(&register_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
- ginfo.card = t->card ? t->card->number : -1;
+ ginfo->card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
- ginfo.flags |= SNDRV_TIMER_FLG_SLAVE;
- strlcpy(ginfo.id, t->id, sizeof(ginfo.id));
- strlcpy(ginfo.name, t->name, sizeof(ginfo.name));
- ginfo.resolution = t->hw.resolution;
+ ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
+ strlcpy(ginfo->id, t->id, sizeof(ginfo->id));
+ strlcpy(ginfo->name, t->name, sizeof(ginfo->name));
+ ginfo->resolution = t->hw.resolution;
if (t->hw.resolution_min > 0) {
- ginfo.resolution_min = t->hw.resolution_min;
- ginfo.resolution_max = t->hw.resolution_max;
+ ginfo->resolution_min = t->hw.resolution_min;
+ ginfo->resolution_max = t->hw.resolution_max;
}
list_for_each(p, &t->open_list_head) {
- ginfo.clients++;
+ ginfo->clients++;
}
} else {
err = -ENODEV;
}
up(&register_mutex);
- if (err >= 0 && copy_to_user(_ginfo, &ginfo, sizeof(ginfo)))
+ if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo)))
err = -EFAULT;
+ kfree(ginfo);
return err;
}
@@ -1488,23 +1499,28 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user *
static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info)
{
snd_timer_user_t *tu;
- snd_timer_info_t info;
+ snd_timer_info_t *info;
snd_timer_t *t;
+ int err = 0;
tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO);
t = tu->timeri->timer;
snd_assert(t != NULL, return -ENXIO);
- memset(&info, 0, sizeof(info));
- info.card = t->card ? t->card->number : -1;
+
+ info = kcalloc(1, sizeof(*info), GFP_KERNEL);
+ if (! info)
+ return -ENOMEM;
+ info->card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
- info.flags |= SNDRV_TIMER_FLG_SLAVE;
- strlcpy(info.id, t->id, sizeof(info.id));
- strlcpy(info.name, t->name, sizeof(info.name));
- info.resolution = t->hw.resolution;
- if (copy_to_user(_info, &info, sizeof(*_info)))
- return -EFAULT;
- return 0;
+ info->flags |= SNDRV_TIMER_FLG_SLAVE;
+ strlcpy(info->id, t->id, sizeof(info->id));
+ strlcpy(info->name, t->name, sizeof(info->name));
+ info->resolution = t->hw.resolution;
+ if (copy_to_user(_info, info, sizeof(*_info)))
+ err = -EFAULT;
+ kfree(info);
+ return err;
}
static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_params)
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 500c51b9a40e8..0f83c5241b6be 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -92,21 +92,19 @@ static void snd_mpu401_uart_clear_rx(mpu401_t *mpu)
static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
{
- unsigned long flags;
-
- spin_lock_irqsave(&mpu->input_lock, flags);
+ spin_lock(&mpu->input_lock);
if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
snd_mpu401_uart_input_read(mpu);
} else {
snd_mpu401_uart_clear_rx(mpu);
}
- spin_unlock_irqrestore(&mpu->input_lock, flags);
+ spin_unlock(&mpu->input_lock);
/* ok. for better Tx performance try do some output when input is done */
if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
- spin_lock_irqsave(&mpu->output_lock, flags);
+ spin_lock(&mpu->output_lock);
snd_mpu401_uart_output_write(mpu);
- spin_unlock_irqrestore(&mpu->output_lock, flags);
+ spin_unlock(&mpu->output_lock);
}
}
@@ -134,14 +132,13 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg
*/
static void snd_mpu401_uart_timer(unsigned long data)
{
- unsigned long flags;
mpu401_t *mpu = (mpu401_t *)data;
- spin_lock_irqsave(&mpu->timer_lock, flags);
+ spin_lock(&mpu->timer_lock);
/*mpu->mode |= MPU401_MODE_TIMER;*/
mpu->timer.expires = 1 + jiffies;
add_timer(&mpu->timer);
- spin_unlock_irqrestore(&mpu->timer_lock, flags);
+ spin_unlock(&mpu->timer_lock);
if (mpu->rmidi)
_snd_mpu401_uart_interrupt(mpu);
}
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 4cc76e21915cb..1280a57c49eb8 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -580,13 +580,12 @@ static void snd_mtpav_read_bytes(mtpav_t * mcrd)
static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs)
{
- unsigned long flags;
mtpav_t *mcard = dev_id;
//printk("irqh()\n");
- spin_lock_irqsave(&mcard->spinlock, flags);
+ spin_lock(&mcard->spinlock);
snd_mtpav_read_bytes(mcard);
- spin_unlock_irqrestore(&mcard->spinlock, flags);
+ spin_unlock(&mcard->spinlock);
return IRQ_HANDLED;
}
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index b2849983f348d..964b97e70c846 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -292,18 +292,17 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart)
*/
static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- unsigned long flags;
snd_uart16550_t *uart;
uart = (snd_uart16550_t *) dev_id;
- spin_lock_irqsave(&uart->open_lock, flags);
+ spin_lock(&uart->open_lock);
if (uart->filemode == SERIAL_MODE_NOT_OPENED) {
- spin_unlock_irqrestore(&uart->open_lock, flags);
+ spin_unlock(&uart->open_lock);
return IRQ_NONE;
}
inb(uart->base + UART_IIR); /* indicate to the UART that the interrupt has been serviced */
snd_uart16550_io_loop(uart);
- spin_unlock_irqrestore(&uart->open_lock, flags);
+ spin_unlock(&uart->open_lock);
return IRQ_HANDLED;
}
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index 8431a9dbd208f..f5e6018ea3f47 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -159,7 +159,7 @@ void snd_ak4114_reinit(ak4114_t *chip)
/* bring up statistics / event queing */
chip->init = 0;
INIT_WORK(&chip->work, ak4114_stats, chip);
- queue_delayed_work(chip->workqueue, &chip->work, 1);
+ queue_delayed_work(chip->workqueue, &chip->work, HZ / 10);
}
static unsigned int external_rate(unsigned char rcs1)
@@ -569,7 +569,7 @@ static void ak4114_stats(void *data)
if (chip->init)
return;
snd_ak4114_check_rate_and_errors(chip, 0);
- queue_delayed_work(chip->workqueue, &chip->work, 1);
+ queue_delayed_work(chip->workqueue, &chip->work, HZ / 10);
}
EXPORT_SYMBOL(snd_ak4114_create);
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 8f176b7129a88..db2b7274a9d6e 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -366,113 +366,121 @@ static int snd_akm4xxx_deemphasis_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
int snd_akm4xxx_build_controls(akm4xxx_t *ak)
{
unsigned int idx, num_emphs;
+ snd_kcontrol_t *ctl;
int err;
+ ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
+ if (! ctl)
+ return -ENOMEM;
+
for (idx = 0; idx < ak->num_dacs; ++idx) {
- snd_kcontrol_t ctl;
- memset(&ctl, 0, sizeof(ctl));
- strcpy(ctl.id.name, "DAC Volume");
- ctl.id.index = idx + ak->idx_offset * 2;
- ctl.id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- ctl.count = 1;
- ctl.info = snd_akm4xxx_volume_info;
- ctl.get = snd_akm4xxx_volume_get;
- ctl.put = snd_akm4xxx_volume_put;
+ memset(ctl, 0, sizeof(*ctl));
+ strcpy(ctl->id.name, "DAC Volume");
+ ctl->id.index = idx + ak->idx_offset * 2;
+ ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ ctl->count = 1;
+ ctl->info = snd_akm4xxx_volume_info;
+ ctl->get = snd_akm4xxx_volume_get;
+ ctl->put = snd_akm4xxx_volume_put;
switch (ak->type) {
case SND_AK4524:
- ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */
break;
case SND_AK4528:
- ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
break;
case SND_AK4529: {
int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; /* registers 2-7 and b,c */
- ctl.private_value = AK_COMPOSE(0, val, 0, 255) | AK_INVERT;
+ ctl->private_value = AK_COMPOSE(0, val, 0, 255) | AK_INVERT;
break;
}
case SND_AK4355:
- ctl.private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */
+ ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */
break;
case SND_AK4358:
if (idx >= 6)
- ctl.private_value = AK_COMPOSE(0, idx + 5, 0, 255); /* register 4-9, chip #0 only */
+ ctl->private_value = AK_COMPOSE(0, idx + 5, 0, 255); /* register 4-9, chip #0 only */
else
- ctl.private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */
+ ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */
break;
case SND_AK4381:
- ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); /* register 3 & 4 */
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); /* register 3 & 4 */
break;
default:
- return -EINVAL;
- }
- ctl.private_data = ak;
- if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
- return err;
+ err = -EINVAL;
+ goto __error;
+ }
+ ctl->private_data = ak;
+ if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
+ goto __error;
}
for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) {
- snd_kcontrol_t ctl;
- memset(&ctl, 0, sizeof(ctl));
- strcpy(ctl.id.name, "ADC Volume");
- ctl.id.index = idx + ak->idx_offset * 2;
- ctl.id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- ctl.count = 1;
- ctl.info = snd_akm4xxx_volume_info;
- ctl.get = snd_akm4xxx_volume_get;
- ctl.put = snd_akm4xxx_volume_put;
- ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
- ctl.private_data = ak;
- if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
- return err;
- memset(&ctl, 0, sizeof(ctl));
- strcpy(ctl.id.name, "IPGA Analog Capture Volume");
- ctl.id.index = idx + ak->idx_offset * 2;
- ctl.id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- ctl.count = 1;
- ctl.info = snd_akm4xxx_ipga_gain_info;
- ctl.get = snd_akm4xxx_ipga_gain_get;
- ctl.put = snd_akm4xxx_ipga_gain_put;
- ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); /* register 4 & 5 */
- ctl.private_data = ak;
- if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
- return err;
+ memset(ctl, 0, sizeof(*ctl));
+ strcpy(ctl->id.name, "ADC Volume");
+ ctl->id.index = idx + ak->idx_offset * 2;
+ ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ ctl->count = 1;
+ ctl->info = snd_akm4xxx_volume_info;
+ ctl->get = snd_akm4xxx_volume_get;
+ ctl->put = snd_akm4xxx_volume_put;
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
+ ctl->private_data = ak;
+ if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
+ goto __error;
+
+ memset(ctl, 0, sizeof(*ctl));
+ strcpy(ctl->id.name, "IPGA Analog Capture Volume");
+ ctl->id.index = idx + ak->idx_offset * 2;
+ ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ ctl->count = 1;
+ ctl->info = snd_akm4xxx_ipga_gain_info;
+ ctl->get = snd_akm4xxx_ipga_gain_get;
+ ctl->put = snd_akm4xxx_ipga_gain_put;
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); /* register 4 & 5 */
+ ctl->private_data = ak;
+ if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
+ goto __error;
}
if (ak->type == SND_AK4355 || ak->type == SND_AK4358)
num_emphs = 1;
else
num_emphs = ak->num_dacs / 2;
for (idx = 0; idx < num_emphs; idx++) {
- snd_kcontrol_t ctl;
- memset(&ctl, 0, sizeof(ctl));
- strcpy(ctl.id.name, "Deemphasis");
- ctl.id.index = idx + ak->idx_offset;
- ctl.id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- ctl.count = 1;
- ctl.info = snd_akm4xxx_deemphasis_info;
- ctl.get = snd_akm4xxx_deemphasis_get;
- ctl.put = snd_akm4xxx_deemphasis_put;
+ memset(ctl, 0, sizeof(*ctl));
+ strcpy(ctl->id.name, "Deemphasis");
+ ctl->id.index = idx + ak->idx_offset;
+ ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ ctl->count = 1;
+ ctl->info = snd_akm4xxx_deemphasis_info;
+ ctl->get = snd_akm4xxx_deemphasis_get;
+ ctl->put = snd_akm4xxx_deemphasis_put;
switch (ak->type) {
case SND_AK4524:
case SND_AK4528:
- ctl.private_value = AK_COMPOSE(idx, 3, 0, 0); /* register 3 */
+ ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); /* register 3 */
break;
case SND_AK4529: {
int shift = idx == 3 ? 6 : (2 - idx) * 2;
- ctl.private_value = AK_COMPOSE(0, 8, shift, 0); /* register 8 with shift */
+ ctl->private_value = AK_COMPOSE(0, 8, shift, 0); /* register 8 with shift */
break;
}
case SND_AK4355:
case SND_AK4358:
- ctl.private_value = AK_COMPOSE(idx, 3, 0, 0);
+ ctl->private_value = AK_COMPOSE(idx, 3, 0, 0);
break;
case SND_AK4381:
- ctl.private_value = AK_COMPOSE(idx, 1, 1, 0);
+ ctl->private_value = AK_COMPOSE(idx, 1, 1, 0);
break;
}
- ctl.private_data = ak;
- if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
- return err;
+ ctl->private_data = ak;
+ if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
+ goto __error;
}
- return 0;
+ err = 0;
+
+ __error:
+ kfree(ctl);
+ return err;
}
static int __init alsa_akm4xxx_module_init(void)
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index ffbe4bf4aa127..4a6be966bd9ff 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -3,6 +3,16 @@
menu "ISA devices"
depends on SND!=n && ISA
+config SND_AD1848_LIB
+ tristate
+ select SND_PCM
+ select SND_GENERIC_PM
+
+config SND_CS4231_LIB
+ tristate
+ select SND_PCM
+ select SND_GENERIC_PM
+
config SND_AD1816A
tristate "Analog Devices SoundPort AD1816A"
depends on SND && ISAPNP
@@ -19,8 +29,7 @@ config SND_AD1816A
config SND_AD1848
tristate "Generic AD1848/CS4248 driver"
depends on SND
- select SND_PCM
- select SND_GENERIC_PM
+ select SND_AD1848_LIB
help
Say Y here to include support for AD1848 (Analog Devices) or
CS4248 (Cirrus Logic - Crystal Semiconductors) chips.
@@ -35,8 +44,7 @@ config SND_CS4231
tristate "Generic Cirrus Logic CS4231 driver"
depends on SND
select SND_MPU401_UART
- select SND_PCM
- select SND_GENERIC_PM
+ select SND_CS4231_LIB
help
Say Y here to include support for CS4231 chips from Cirrus
Logic - Crystal Semiconductors.
@@ -49,8 +57,7 @@ config SND_CS4232
depends on SND
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
- select SND_GENERIC_PM
+ select SND_CS4231_LIB
help
Say Y here to include support for CS4232 chips from Cirrus
Logic - Crystal Semiconductors.
@@ -63,8 +70,7 @@ config SND_CS4236
depends on SND
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
- select SND_GENERIC_PM
+ select SND_CS4231_LIB
help
Say Y to include support for CS4235,CS4236,CS4237B,CS4238B,
CS4239 chips from Cirrus Logic - Crystal Semiconductors.
@@ -143,7 +149,7 @@ config SND_GUSMAX
tristate "Gravis UltraSound MAX"
depends on SND
select SND_RAWMIDI
- select SND_PCM
+ select SND_CS4231_LIB
select SND_GUS_SYNTH
help
Say Y here to include support for Gravis UltraSound MAX
@@ -156,7 +162,7 @@ config SND_INTERWAVE
tristate "AMD InterWave, Gravis UltraSound PnP"
depends on SND
select SND_RAWMIDI
- select SND_PCM
+ select SND_CS4231_LIB
select SND_GUS_SYNTH
help
Say Y here to include support for AMD InterWave based
@@ -170,7 +176,7 @@ config SND_INTERWAVE_STB
tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)"
depends on SND
select SND_RAWMIDI
- select SND_PCM
+ select SND_CS4231_LIB
select SND_GUS_SYNTH
help
Say Y here to include support for AMD InterWave based
@@ -186,7 +192,7 @@ config SND_OPTI92X_AD1848
select SND_OPL3_LIB
select SND_OPL4_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_AD1848_LIB
help
Say Y here to include support for soundcards based on Opti
82C92x or OTI-601 chips and using an AD1848 codec.
@@ -200,7 +206,7 @@ config SND_OPTI92X_CS4231
select SND_OPL3_LIB
select SND_OPL4_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for soundcards based on Opti
82C92x chips and using a CS4231 codec.
@@ -273,7 +279,7 @@ config SND_WAVEFRONT
depends on SND
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for Turtle Beach Maui, Tropez
and Tropez+ soundcards based on the Wavefront chip.
@@ -299,7 +305,7 @@ config SND_AZT2320
depends on SND && ISAPNP
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for soundcards based on the
Aztech Systems AZT2320 chip.
@@ -310,7 +316,7 @@ config SND_AZT2320
config SND_CMI8330
tristate "C-Media CMI8330"
depends on SND
- select SND_PCM
+ select SND_AD1848_LIB
help
Say Y here to include support for soundcards based on the
C-Media CMI8330 chip.
@@ -336,8 +342,7 @@ config SND_OPL3SA2
depends on SND
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
- select SND_GENERIC_PM
+ select SND_CS4231_LIB
help
Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3
chips.
@@ -348,7 +353,7 @@ config SND_OPL3SA2
config SND_SGALAXY
tristate "Aztech Sound Galaxy"
depends on SND
- select SND_PCM
+ select SND_AD1848_LIB
help
Say Y here to include support for Aztech Sound Galaxy
soundcards.
@@ -361,7 +366,7 @@ config SND_SSCAPE
depends on SND
select SND_HWDEP
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for Ensoniq SoundScape PnP
soundcards.
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
index c7ff304433e9f..66552e6013a4b 100644
--- a/sound/isa/gus/gus_synth.c
+++ b/sound/isa/gus/gus_synth.c
@@ -214,7 +214,7 @@ static int snd_gus_synth_new_device(snd_seq_device_t *dev)
snd_gus_card_t *gus;
int client, i;
snd_seq_client_callback_t callbacks;
- snd_seq_client_info_t cinfo;
+ snd_seq_client_info_t *cinfo;
snd_seq_port_subscribe_t sub;
snd_iwffff_ops_t *iwops;
snd_gf1_ops_t *gf1ops;
@@ -227,21 +227,28 @@ static int snd_gus_synth_new_device(snd_seq_device_t *dev)
init_MUTEX(&gus->register_mutex);
gus->gf1.seq_client = -1;
+ cinfo = kmalloc(sizeof(*cinfo), GFP_KERNEL);
+ if (! cinfo)
+ return -ENOMEM;
+
/* allocate new client */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.private_data = gus;
callbacks.allow_output = callbacks.allow_input = 1;
client = gus->gf1.seq_client =
snd_seq_create_kernel_client(gus->card, 1, &callbacks);
- if (client < 0)
+ if (client < 0) {
+ kfree(cinfo);
return client;
+ }
/* change name of client */
- memset(&cinfo, 0, sizeof(cinfo));
- cinfo.client = client;
- cinfo.type = KERNEL_CLIENT;
- sprintf(cinfo.name, gus->interwave ? "AMD InterWave" : "GF1");
- snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
+ memset(cinfo, 0, sizeof(*cinfo));
+ cinfo->client = client;
+ cinfo->type = KERNEL_CLIENT;
+ sprintf(cinfo->name, gus->interwave ? "AMD InterWave" : "GF1");
+ snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, cinfo);
+ kfree(cinfo);
for (i = 0; i < 4; i++)
snd_gus_synth_create_port(gus, i);
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index 9433d61fe5259..0c3c951009d85 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -1201,7 +1201,11 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header)
{
int i;
int num_samples;
- unsigned char msample_hdr[WF_MSAMPLE_BYTES];
+ unsigned char *msample_hdr;
+
+ msample_hdr = kmalloc(sizeof(WF_MSAMPLE_BYTES), GFP_KERNEL);
+ if (! msample_hdr)
+ return -ENOMEM;
munge_int32 (header->number, &msample_hdr[0], 2);
@@ -1234,11 +1238,13 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header)
(unsigned char *) (long) ((num_samples*2)+3),
msample_hdr)) {
snd_printk ("download of multisample failed.\n");
+ kfree(msample_hdr);
return -(EIO);
}
dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
+ kfree(msample_hdr);
return (0);
}
@@ -1356,78 +1362,103 @@ wavefront_find_free_patch (snd_wavefront_t *dev)
static int
wavefront_load_patch (snd_wavefront_t *dev, const char __user *addr)
-
{
- wavefront_patch_info header;
+ wavefront_patch_info *header;
+ int err;
- if (copy_from_user (&header, addr, sizeof(wavefront_patch_info) -
+ header = kmalloc(sizeof(*header), GFP_KERNEL);
+ if (! header)
+ return -ENOMEM;
+
+ if (copy_from_user (header, addr, sizeof(wavefront_patch_info) -
sizeof(wavefront_any))) {
snd_printk ("bad address for load patch.\n");
- return -(EFAULT);
+ err = -EFAULT;
+ goto __error;
}
DPRINT (WF_DEBUG_LOAD_PATCH, "download "
"Sample type: %d "
"Sample number: %d "
"Sample size: %d\n",
- header.subkey,
- header.number,
- header.size);
+ header->subkey,
+ header->number,
+ header->size);
- switch (header.subkey) {
+ switch (header->subkey) {
case WF_ST_SAMPLE: /* sample or sample_header, based on patch->size */
- if (copy_from_user (&header.hdr.s, header.hdrptr,
- sizeof (wavefront_sample)))
- return -EFAULT;
+ if (copy_from_user (&header->hdr.s, header->hdrptr,
+ sizeof (wavefront_sample))) {
+ err = -EFAULT;
+ break;
+ }
- return wavefront_send_sample (dev, &header, header.dataptr, 0);
+ err = wavefront_send_sample (dev, header, header->dataptr, 0);
+ break;
case WF_ST_MULTISAMPLE:
- if (copy_from_user (&header.hdr.s, header.hdrptr,
- sizeof (wavefront_multisample)))
- return -EFAULT;
-
- return wavefront_send_multisample (dev, &header);
+ if (copy_from_user (&header->hdr.s, header->hdrptr,
+ sizeof (wavefront_multisample))) {
+ err = -EFAULT;
+ break;
+ }
+ err = wavefront_send_multisample (dev, header);
+ break;
case WF_ST_ALIAS:
- if (copy_from_user (&header.hdr.a, header.hdrptr,
- sizeof (wavefront_alias)))
- return -EFAULT;
+ if (copy_from_user (&header->hdr.a, header->hdrptr,
+ sizeof (wavefront_alias))) {
+ err = -EFAULT;
+ break;
+ }
- return wavefront_send_alias (dev, &header);
+ err = wavefront_send_alias (dev, header);
+ break;
case WF_ST_DRUM:
- if (copy_from_user (&header.hdr.d, header.hdrptr,
- sizeof (wavefront_drum)))
- return -EFAULT;
+ if (copy_from_user (&header->hdr.d, header->hdrptr,
+ sizeof (wavefront_drum))) {
+ err = -EFAULT;
+ break;
+ }
- return wavefront_send_drum (dev, &header);
+ err = wavefront_send_drum (dev, header);
+ break;
case WF_ST_PATCH:
- if (copy_from_user (&header.hdr.p, header.hdrptr,
- sizeof (wavefront_patch)))
- return -EFAULT;
-
- return wavefront_send_patch (dev, &header);
+ if (copy_from_user (&header->hdr.p, header->hdrptr,
+ sizeof (wavefront_patch))) {
+ err = -EFAULT;
+ break;
+ }
+
+ err = wavefront_send_patch (dev, header);
+ break;
case WF_ST_PROGRAM:
- if (copy_from_user (&header.hdr.pr, header.hdrptr,
- sizeof (wavefront_program)))
- return -EFAULT;
+ if (copy_from_user (&header->hdr.pr, header->hdrptr,
+ sizeof (wavefront_program))) {
+ err = -EFAULT;
+ break;
+ }
- return wavefront_send_program (dev, &header);
+ err = wavefront_send_program (dev, header);
+ break;
default:
snd_printk ("unknown patch type %d.\n",
- header.subkey);
- return -(EINVAL);
+ header->subkey);
+ err = -EINVAL;
+ break;
}
- return 0;
+ __error:
+ kfree(header);
+ return err;
}
/***********************************************************************
@@ -1620,8 +1651,9 @@ snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file,
snd_card_t *card;
snd_wavefront_t *dev;
snd_wavefront_card_t *acard;
- wavefront_control wc;
+ wavefront_control *wc;
void __user *argp = (void __user *)arg;
+ int err;
card = (snd_card_t *) hw->card;
@@ -1640,14 +1672,19 @@ snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file,
break;
case WFCTL_WFCMD:
- if (copy_from_user (&wc, argp, sizeof (wc)))
- return -EFAULT;
- if (wavefront_synth_control (acard, &wc) < 0) {
- return -EIO;
- }
- if (copy_to_user (argp, &wc, sizeof (wc)))
- return -EFAULT;
- break;
+ wc = kmalloc(sizeof(*wc), GFP_KERNEL);
+ if (! wc)
+ return -ENOMEM;
+ if (copy_from_user (wc, argp, sizeof (*wc)))
+ err = -EFAULT;
+ else if (wavefront_synth_control (acard, wc) < 0)
+ err = -EIO;
+ else if (copy_to_user (argp, wc, sizeof (*wc)))
+ err = -EFAULT;
+ else
+ err = 0;
+ kfree(wc);
+ return err;
default:
return -EINVAL;
diff --git a/sound/oss/ali5455.c b/sound/oss/ali5455.c
index a48be23dabfc1..9c9e6c0410f26 100644
--- a/sound/oss/ali5455.c
+++ b/sound/oss/ali5455.c
@@ -3528,7 +3528,7 @@ static void __devexit ali_remove(struct pci_dev *pci_dev)
}
#ifdef CONFIG_PM
-static int ali_pm_suspend(struct pci_dev *dev, u32 pm_state)
+static int ali_pm_suspend(struct pci_dev *dev, pm_message_t pm_state)
{
struct ali_card *card = pci_get_drvdata(dev);
struct ali_state *state;
diff --git a/sound/oss/cs4281/cs4281_wrapper-24.c b/sound/oss/cs4281/cs4281_wrapper-24.c
index bd61a45983dd1..4559f02c99694 100644
--- a/sound/oss/cs4281/cs4281_wrapper-24.c
+++ b/sound/oss/cs4281/cs4281_wrapper-24.c
@@ -27,7 +27,7 @@
#include <linux/spinlock.h>
static int cs4281_resume_null(struct pci_dev *pcidev) { return 0; }
-static int cs4281_suspend_null(struct pci_dev *pcidev, u32 state) { return 0; }
+static int cs4281_suspend_null(struct pci_dev *pcidev, pm_message_t state) { return 0; }
#define free_dmabuf(state, dmabuf) \
pci_free_consistent(state->pcidev, \
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
index bc4941cb8b11f..8ce6b48f1881b 100644
--- a/sound/oss/cs46xx.c
+++ b/sound/oss/cs46xx.c
@@ -388,7 +388,7 @@ static int cs_hardware_init(struct cs_card *card);
static int cs46xx_powerup(struct cs_card *card, unsigned int type);
static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag);
static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state);
+static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
static int cs46xx_resume_tbl(struct pci_dev *pcidev);
#ifndef CS46XX_ACPI_SUPPORT
@@ -5774,7 +5774,7 @@ static int cs46xx_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
#endif
#if CS46XX_ACPI_SUPPORT
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state)
+static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state)
{
struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
CS_DBGOUT(CS_PM | CS_FUNCTION, 2,
diff --git a/sound/oss/cs46xxpm-24.h b/sound/oss/cs46xxpm-24.h
index 7402cb76e43a8..e220bd7240f14 100644
--- a/sound/oss/cs46xxpm-24.h
+++ b/sound/oss/cs46xxpm-24.h
@@ -36,7 +36,7 @@
* for now (12/22/00) only enable the pm_register PM support.
* allow these table entries to be null.
*/
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state);
+static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
static int cs46xx_resume_tbl(struct pci_dev *pcidev);
#define cs_pm_register(a, b, c) NULL
#define cs_pm_unregister_all(a)
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
index c5b130ae74d1d..6b3b9a99579db 100644
--- a/sound/oss/esssolo1.c
+++ b/sound/oss/esssolo1.c
@@ -2257,7 +2257,7 @@ static int setup_solo1(struct solo1_state *s)
}
static int
-solo1_suspend(struct pci_dev *pci_dev, u32 state) {
+solo1_suspend(struct pci_dev *pci_dev, pm_message_t state) {
struct solo1_state *s = (struct solo1_state*)pci_get_drvdata(pci_dev);
if (!s)
return 1;
diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
index a4b959ae9bbf5..7e9f667cf7a71 100644
--- a/sound/oss/i810_audio.c
+++ b/sound/oss/i810_audio.c
@@ -3470,7 +3470,7 @@ static void __devexit i810_remove(struct pci_dev *pci_dev)
}
#ifdef CONFIG_PM
-static int i810_pm_suspend(struct pci_dev *dev, u32 pm_state)
+static int i810_pm_suspend(struct pci_dev *dev, pm_message_t pm_state)
{
struct i810_card *card = pci_get_drvdata(dev);
struct i810_state *state;
diff --git a/sound/oss/maestro3.c b/sound/oss/maestro3.c
index 17d4f0792d382..f3dec70fcb9b2 100644
--- a/sound/oss/maestro3.c
+++ b/sound/oss/maestro3.c
@@ -375,7 +375,7 @@ static struct m3_card *devs;
* I'm not very good at laying out functions in a file :)
*/
static int m3_notifier(struct notifier_block *nb, unsigned long event, void *buf);
-static int m3_suspend(struct pci_dev *pci_dev, u32 state);
+static int m3_suspend(struct pci_dev *pci_dev, pm_message_t state);
static void check_suspend(struct m3_card *card);
static struct notifier_block m3_reboot_nb = {
@@ -2777,12 +2777,12 @@ static int m3_notifier(struct notifier_block *nb, unsigned long event, void *buf
for(card = devs; card != NULL; card = card->next) {
if(!card->in_suspend)
- m3_suspend(card->pcidev, 3); /* XXX legal? */
+ m3_suspend(card->pcidev, PMSG_SUSPEND); /* XXX legal? */
}
return 0;
}
-static int m3_suspend(struct pci_dev *pci_dev, u32 state)
+static int m3_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
unsigned long flags;
int i;
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index ddf39ed3ff629..47537f0a5b058 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -487,7 +487,7 @@ static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *ca
static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card);
static void ali_restore_regs(struct trident_card *card);
static void ali_save_regs(struct trident_card *card);
-static int trident_suspend(struct pci_dev *dev, u32 unused);
+static int trident_suspend(struct pci_dev *dev, pm_message_t unused);
static int trident_resume(struct pci_dev *dev);
static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel);
static int ali_setup_multi_channels(struct trident_card *card, int chan_nums);
@@ -3723,7 +3723,7 @@ ali_restore_regs(struct trident_card *card)
}
static int
-trident_suspend(struct pci_dev *dev, u32 unused)
+trident_suspend(struct pci_dev *dev, pm_message_t unused)
{
struct trident_card *card = pci_get_drvdata(dev);
diff --git a/sound/oss/ymfpci.c b/sound/oss/ymfpci.c
index 3bbe819ed3f72..05203ad523f7a 100644
--- a/sound/oss/ymfpci.c
+++ b/sound/oss/ymfpci.c
@@ -2074,7 +2074,7 @@ static /*const*/ struct file_operations ymf_mixer_fops = {
/*
*/
-static int ymf_suspend(struct pci_dev *pcidev, u32 unused)
+static int ymf_suspend(struct pci_dev *pcidev, pm_message_t unused)
{
struct ymf_unit *unit = pci_get_drvdata(pcidev);
unsigned long flags;
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index c2c9d0a5466c6..0b024ec1f7096 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -105,8 +105,8 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x41445374, 0xffffffff, "AD1981B", patch_ad1981b, NULL },
{ 0x41445375, 0xffffffff, "AD1985", patch_ad1985, NULL },
{ 0x41445378, 0xffffffff, "AD1986", patch_ad1985, NULL },
-{ 0x414c4300, 0xffffff00, "ALC100/100P", NULL, NULL },
-{ 0x414c4710, 0xfffffff0, "ALC200/200P", NULL, NULL },
+{ 0x414c4300, 0xffffff00, "ALC100,100P", NULL, NULL },
+{ 0x414c4710, 0xfffffff0, "ALC200,200P", NULL, NULL },
{ 0x414c4721, 0xffffffff, "ALC650D", NULL, NULL }, /* already patched */
{ 0x414c4722, 0xffffffff, "ALC650E", NULL, NULL }, /* already patched */
{ 0x414c4723, 0xffffffff, "ALC650F", NULL, NULL }, /* already patched */
@@ -145,11 +145,11 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x49434552, 0xffffffff, "VT1616i", patch_vt1616, NULL }, // VT1616 compatible (chipset integrated)
{ 0x49544520, 0xffffffff, "IT2226E", NULL, NULL },
{ 0x49544561, 0xffffffff, "IT2646E", patch_it2646, NULL },
-{ 0x4e534300, 0xffffffff, "LM4540/43/45/46/48", NULL, NULL }, // only guess --jk
+{ 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk
{ 0x4e534331, 0xffffffff, "LM4549", NULL, NULL },
{ 0x4e534350, 0xffffffff, "LM4550", NULL, NULL },
{ 0x50534304, 0xffffffff, "UCB1400", NULL, NULL },
-{ 0x53494c20, 0xffffffe0, "Si3036/8", NULL, mpatch_si3036 },
+{ 0x53494c20, 0xffffffe0, "Si3036,8", NULL, mpatch_si3036 },
{ 0x54524102, 0xffffffff, "TR28022", NULL, NULL },
{ 0x54524106, 0xffffffff, "TR28026", NULL, NULL },
{ 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028, NULL }, // added by xin jin [07/09/99]
@@ -158,26 +158,26 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF
{ 0x57454301, 0xffffffff, "W83971D", NULL, NULL },
{ 0x574d4c00, 0xffffffff, "WM9701A", NULL, NULL },
-{ 0x574d4C03, 0xffffffff, "WM9703/WM9707/WM9708/WM9717", patch_wolfson03, NULL},
-{ 0x574d4C04, 0xffffffff, "WM9704M/WM9704Q", patch_wolfson04, NULL},
-{ 0x574d4C05, 0xffffffff, "WM9705/WM9710", patch_wolfson05, NULL},
+{ 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL},
+{ 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q", patch_wolfson04, NULL},
+{ 0x574d4C05, 0xffffffff, "WM9705,WM9710", patch_wolfson05, NULL},
{ 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL},
-{ 0x574d4C12, 0xffffffff, "WM9711/WM9712", patch_wolfson11, NULL},
-{ 0x574d4c13, 0xffffffff, "WM9713/WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF},
+{ 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL},
+{ 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF},
{ 0x594d4800, 0xffffffff, "YMF743", NULL, NULL },
{ 0x594d4802, 0xffffffff, "YMF752", NULL, NULL },
{ 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL },
-{ 0x83847600, 0xffffffff, "STAC9700/83/84", patch_sigmatel_stac9700, NULL },
-{ 0x83847604, 0xffffffff, "STAC9701/3/4/5", NULL, NULL },
+{ 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL },
+{ 0x83847604, 0xffffffff, "STAC9701,3,4,5", NULL, NULL },
{ 0x83847605, 0xffffffff, "STAC9704", NULL, NULL },
-{ 0x83847608, 0xffffffff, "STAC9708/11", patch_sigmatel_stac9708, NULL },
-{ 0x83847609, 0xffffffff, "STAC9721/23", patch_sigmatel_stac9721, NULL },
+{ 0x83847608, 0xffffffff, "STAC9708,11", patch_sigmatel_stac9708, NULL },
+{ 0x83847609, 0xffffffff, "STAC9721,23", patch_sigmatel_stac9721, NULL },
{ 0x83847644, 0xffffffff, "STAC9744", patch_sigmatel_stac9744, NULL },
-{ 0x83847650, 0xffffffff, "STAC9750/51", NULL, NULL }, // patch?
-{ 0x83847652, 0xffffffff, "STAC9752/53", NULL, NULL }, // patch?
-{ 0x83847656, 0xffffffff, "STAC9756/57", patch_sigmatel_stac9756, NULL },
-{ 0x83847658, 0xffffffff, "STAC9758/59", patch_sigmatel_stac9758, NULL },
-{ 0x83847666, 0xffffffff, "STAC9766/67", NULL, NULL }, // patch?
+{ 0x83847650, 0xffffffff, "STAC9750,51", NULL, NULL }, // patch?
+{ 0x83847652, 0xffffffff, "STAC9752,53", NULL, NULL }, // patch?
+{ 0x83847656, 0xffffffff, "STAC9756,57", patch_sigmatel_stac9756, NULL },
+{ 0x83847658, 0xffffffff, "STAC9758,59", patch_sigmatel_stac9758, NULL },
+{ 0x83847666, 0xffffffff, "STAC9766,67", NULL, NULL }, // patch?
{ 0, 0, NULL, NULL, NULL }
};
@@ -1486,7 +1486,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build S/PDIF controls */
- if (ac97->ext_id & AC97_EI_SPDIF) {
+ if ((ac97->ext_id & AC97_EI_SPDIF) && !(ac97->scaps & AC97_SCAP_NO_SPDIF)) {
if (ac97->build_ops->build_spdif) {
if ((err = ac97->build_ops->build_spdif(ac97)) < 0)
return err;
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 65e6b2149d86d..13c34a5d8206d 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -1728,7 +1728,7 @@ static int alc655_iec958_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
- (unsigned short)ucontrol->value.enumerated.item[0],
+ (unsigned short)ucontrol->value.enumerated.item[0] << 12,
0);
}
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 37f3be18e6b18..f1a5f5723ee6b 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -601,9 +601,9 @@ static int __devinit snd_als4000_create_gameport(snd_card_als4000_t *acard, int
gameport_set_name(gp, "ALS4000 Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(acard->pci));
- gp->dev.parent = &acard->pci->dev;
+ gameport_set_dev_parent(gp, &acard->pci->dev);
gp->io = io_port;
- gp->port_data = r;
+ gameport_set_port_data(gp, r);
/* Enable legacy joystick port */
snd_als4000_set_addr(acard->gcr, 0, 0, 0, 1);
@@ -616,7 +616,7 @@ static int __devinit snd_als4000_create_gameport(snd_card_als4000_t *acard, int
static void snd_als4000_free_gameport(snd_card_als4000_t *acard)
{
if (acard->gameport) {
- struct resource *r = acard->gameport->port_data;
+ struct resource *r = gameport_get_port_data(acard->gameport);
gameport_unregister_port(acard->gameport);
acard->gameport = NULL;
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index a566571b255bf..6b04c0acc6f72 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -250,6 +250,7 @@ struct snd_atiixp_dma {
int running;
int pcm_open_flag;
int ac97_pcm_type; /* index # of ac97_pcm to access, -1 = not used */
+ unsigned int saved_curptr;
};
/*
@@ -1375,6 +1376,8 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock, const char
ac97.pci = chip->pci;
ac97.num = i;
ac97.scaps = AC97_SCAP_SKIP_MODEM;
+ if (! chip->spdif_over_aclink)
+ ac97.scaps |= AC97_SCAP_NO_SPDIF;
if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
chip->ac97[i] = NULL; /* to be sure */
snd_printdd("atiixp: codec %d not available for audio\n", i);
@@ -1404,8 +1407,12 @@ static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state)
int i;
for (i = 0; i < NUM_ATI_PCMDEVS; i++)
- if (chip->pcmdevs[i])
+ if (chip->pcmdevs[i]) {
+ atiixp_dma_t *dma = &chip->dmas[i];
+ if (dma->substream && dma->running)
+ dma->saved_curptr = readl(chip->remap_addr + dma->ops->dt_cur);
snd_pcm_suspend_all(chip->pcmdevs[i]);
+ }
for (i = 0; i < NUM_ATI_CODECS; i++)
if (chip->ac97[i])
snd_ac97_suspend(chip->ac97[i]);
@@ -1433,6 +1440,17 @@ static int snd_atiixp_resume(snd_card_t *card)
if (chip->ac97[i])
snd_ac97_resume(chip->ac97[i]);
+ for (i = 0; i < NUM_ATI_PCMDEVS; i++)
+ if (chip->pcmdevs[i]) {
+ atiixp_dma_t *dma = &chip->dmas[i];
+ if (dma->substream && dma->running) {
+ dma->ops->enable_dma(chip, 1);
+ writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN,
+ chip->remap_addr + dma->ops->llp_offset);
+ writel(dma->saved_curptr, chip->remap_addr + dma->ops->dt_cur);
+ }
+ }
+
return 0;
}
#endif /* CONFIG_PM */
diff --git a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c
index 0e1426e2c507e..a07d1deba3227 100644
--- a/sound/pci/au88x0/au88x0_game.c
+++ b/sound/pci/au88x0/au88x0_game.c
@@ -44,20 +44,20 @@
static unsigned char vortex_game_read(struct gameport *gameport)
{
- vortex_t *vortex = gameport->port_data;
+ vortex_t *vortex = gameport_get_port_data(gameport);
return hwread(vortex->mmio, VORTEX_GAME_LEGACY);
}
static void vortex_game_trigger(struct gameport *gameport)
{
- vortex_t *vortex = gameport->port_data;
+ vortex_t *vortex = gameport_get_port_data(gameport);
hwwrite(vortex->mmio, VORTEX_GAME_LEGACY, 0xff);
}
static int
vortex_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- vortex_t *vortex = gameport->port_data;
+ vortex_t *vortex = gameport_get_port_data(gameport);
int i;
*buttons = (~hwread(vortex->mmio, VORTEX_GAME_LEGACY) >> 4) & 0xf;
@@ -73,7 +73,7 @@ vortex_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
static int vortex_game_open(struct gameport *gameport, int mode)
{
- vortex_t *vortex = gameport->port_data;
+ vortex_t *vortex = gameport_get_port_data(gameport);
switch (mode) {
case GAMEPORT_MODE_COOKED:
@@ -106,14 +106,14 @@ static int __devinit vortex_gameport_register(vortex_t * vortex)
gameport_set_name(gp, "AU88x0 Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(vortex->pci_dev));
- gp->dev.parent = &vortex->pci_dev->dev;
+ gameport_set_dev_parent(gp, &vortex->pci_dev->dev);
gp->read = vortex_game_read;
gp->trigger = vortex_game_trigger;
gp->cooked_read = vortex_game_cooked_read;
gp->open = vortex_game_open;
- gp->port_data = vortex;
+ gameport_set_port_data(gp, vortex);
gp->fuzz = 64;
gameport_register_port(gp);
diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c
index 95ed26ead5c51..86e27d695c375 100644
--- a/sound/pci/au88x0/au88x0_mixer.c
+++ b/sound/pci/au88x0/au88x0_mixer.c
@@ -26,6 +26,7 @@ static int __devinit snd_vortex_mixer(vortex_t * vortex)
memset(&ac97, 0, sizeof(ac97));
// Intialize AC97 codec stuff.
ac97.private_data = vortex;
+ ac97.scaps = AC97_SCAP_NO_SPDIF;
err = snd_ac97_mixer(pbus, &ac97, &vortex->codec);
vortex->isquad = ((vortex->codec == NULL) ? 0 : (vortex->codec->ext_id&0x80));
return err;
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index f594b3f916cd9..b8ae534125c1e 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1245,9 +1245,9 @@ static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev)
gameport_set_name(gp, "AZF3328 Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
- gp->dev.parent = &chip->pci->dev;
+ gameport_set_dev_parent(gp, &chip->pci->dev);
gp->io = 0x200;
- gp->port_data = r;
+ gameport_set_port_data(gp, r);
snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) | LEGACY_JOY);
@@ -1260,7 +1260,7 @@ static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev)
static void snd_azf3328_free_joystick(azf3328_t *chip)
{
if (chip->gameport) {
- struct resource *r = chip->gameport->port_data;
+ struct resource *r = gameport_get_port_data(chip->gameport);
gameport_unregister_port(chip->gameport);
chip->gameport = NULL;
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 6571796faffb9..82533b45bc8cd 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -187,9 +187,9 @@ static snd_pcm_hardware_t snd_ca0106_playback_hw = {
.rate_max = 192000,
.channels_min = 2, //1,
.channels_max = 2, //6,
- .buffer_bytes_max = (32*1024),
+ .buffer_bytes_max = ((65536 - 64) * 8),
.period_bytes_min = 64,
- .period_bytes_max = (16*1024),
+ .period_bytes_max = (65536 - 64),
.periods_min = 2,
.periods_max = 8,
.fifo_size = 0,
@@ -206,9 +206,9 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = {
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
- .buffer_bytes_max = (32*1024),
+ .buffer_bytes_max = ((65536 - 64) * 8),
.period_bytes_min = 64,
- .period_bytes_max = (16*1024),
+ .period_bytes_max = (65536 - 64),
.periods_min = 2,
.periods_max = 2,
.fifo_size = 0,
@@ -513,6 +513,8 @@ static int snd_ca0106_pcm_prepare_playback(snd_pcm_substream_t *substream)
snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
+ /* FIXME test what 0 bytes does. */
+ snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0);
snd_ca0106_ptr_write(emu, 0x07, channel, 0x0);
snd_ca0106_ptr_write(emu, 0x08, channel, 0);
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index d69aadfd5d34e..113208fbde1bc 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2592,9 +2592,9 @@ static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev)
}
gameport_set_name(gp, "C-Media Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(cm->pci));
- gp->dev.parent = &cm->pci->dev;
+ gameport_set_dev_parent(gp, &cm->pci->dev);
gp->io = io_port;
- gp->port_data = r;
+ gameport_set_port_data(gp, r);
snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
@@ -2606,7 +2606,7 @@ static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev)
static void snd_cmipci_free_gameport(cmipci_t *cm)
{
if (cm->gameport) {
- struct resource *r = cm->gameport->port_data;
+ struct resource *r = gameport_get_port_data(cm->gameport);
gameport_unregister_port(cm->gameport);
cm->gameport = NULL;
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 5e3d35ba16ea2..d7e06b3caf973 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -697,11 +697,10 @@ static unsigned short snd_cs4281_ac97_read(ac97_t *ac97,
static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
{
- unsigned long flags;
cs4281_dma_t *dma = (cs4281_dma_t *)substream->runtime->private_data;
cs4281_t *chip = snd_pcm_substream_chip(substream);
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock(&chip->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
dma->valDCR |= BA0_DCR_MSK;
@@ -728,13 +727,13 @@ static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
dma->valFCR &= ~BA0_FCR_FEN;
break;
default:
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
return -EINVAL;
}
snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR);
snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR);
snd_cs4281_pokeBA0(chip, dma->regDCR, dma->valDCR);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
return 0;
}
@@ -1241,7 +1240,7 @@ static void __devinit snd_cs4281_proc_init(cs4281_t * chip)
static void snd_cs4281_gameport_trigger(struct gameport *gameport)
{
- cs4281_t *chip = gameport->port_data;
+ cs4281_t *chip = gameport_get_port_data(gameport);
snd_assert(chip, return);
snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff);
@@ -1249,7 +1248,7 @@ static void snd_cs4281_gameport_trigger(struct gameport *gameport)
static unsigned char snd_cs4281_gameport_read(struct gameport *gameport)
{
- cs4281_t *chip = gameport->port_data;
+ cs4281_t *chip = gameport_get_port_data(gameport);
snd_assert(chip, return 0);
return snd_cs4281_peekBA0(chip, BA0_JSPT);
@@ -1258,7 +1257,7 @@ static unsigned char snd_cs4281_gameport_read(struct gameport *gameport)
#ifdef COOKED_MODE
static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- cs4281_t *chip = gameport->port_data;
+ cs4281_t *chip = gameport_get_port_data(gameport);
unsigned js1, js2, jst;
snd_assert(chip, return 0);
@@ -1309,12 +1308,12 @@ static int __devinit snd_cs4281_create_gameport(cs4281_t *chip)
gameport_set_name(gp, "CS4281 Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
- gp->dev.parent = &chip->pci->dev;
+ gameport_set_dev_parent(gp, &chip->pci->dev);
gp->open = snd_cs4281_gameport_open;
gp->read = snd_cs4281_gameport_read;
gp->trigger = snd_cs4281_gameport_trigger;
gp->cooked_read = snd_cs4281_gameport_cooked_read;
- gp->port_data = chip;
+ gameport_set_port_data(gp, chip);
snd_cs4281_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
snd_cs4281_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
@@ -1332,8 +1331,8 @@ static void snd_cs4281_free_gameport(cs4281_t *chip)
}
}
#else
-static inline int snd_cs4281_gameport(cs4281_t *chip) { return -ENOSYS; }
-static inline void snd_cs4281_gameport_free(cs4281_t *chip) { }
+static inline int snd_cs4281_create_gameport(cs4281_t *chip) { return -ENOSYS; }
+static inline void snd_cs4281_free_gameport(cs4281_t *chip) { }
#endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */
@@ -1849,7 +1848,6 @@ static int __devinit snd_cs4281_midi(cs4281_t * chip, int device, snd_rawmidi_t
static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
cs4281_t *chip = dev_id;
- unsigned long flags;
unsigned int status, dma, val;
cs4281_dma_t *cdma;
@@ -1865,7 +1863,7 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
for (dma = 0; dma < 4; dma++)
if (status & BA0_HISR_DMA(dma)) {
cdma = &chip->dma[dma];
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock(&chip->reg_lock);
/* ack DMA IRQ */
val = snd_cs4281_peekBA0(chip, cdma->regHDSR);
/* workaround, sometimes CS4281 acknowledges */
@@ -1874,16 +1872,16 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
if ((val & BA0_HDSR_DHTC) && !(cdma->frag & 1)) {
cdma->frag--;
chip->spurious_dhtc_irq++;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
continue;
}
if ((val & BA0_HDSR_DTC) && (cdma->frag & 1)) {
cdma->frag--;
chip->spurious_dtc_irq++;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
continue;
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
snd_pcm_period_elapsed(cdma->substream);
}
}
@@ -1891,7 +1889,7 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
if ((status & BA0_HISR_MIDI) && chip->rmidi) {
unsigned char c;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock(&chip->reg_lock);
while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_RBE) == 0) {
c = snd_cs4281_peekBA0(chip, BA0_MIDRP);
if ((chip->midcr & BA0_MIDCR_RIE) == 0)
@@ -1908,7 +1906,7 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
}
snd_cs4281_pokeBA0(chip, BA0_MIDWP, c);
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
}
/* EOI to the PCI part... reenables interrupts */
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 320f2d5446f15..5f2ffb7efa061 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -765,9 +765,6 @@ static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t
static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
int cmd)
{
-#ifndef CONFIG_SND_CS46XX_NEW_DSP
- unsigned long flags;
-#endif
cs46xx_t *chip = snd_pcm_substream_chip(substream);
/*snd_pcm_runtime_t *runtime = substream->runtime;*/
int result = 0;
@@ -792,7 +789,7 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
if (substream->runtime->periods != CS46XX_FRAGS)
snd_cs46xx_playback_transfer(substream);
#else
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock(&chip->reg_lock);
if (substream->runtime->periods != CS46XX_FRAGS)
snd_cs46xx_playback_transfer(substream);
{ unsigned int tmp;
@@ -800,7 +797,7 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
tmp &= 0x0000ffff;
snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
#endif
break;
case SNDRV_PCM_TRIGGER_STOP:
@@ -813,13 +810,13 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
if (!cpcm->pcm_channel->unlinked)
cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
#else
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock(&chip->reg_lock);
{ unsigned int tmp;
tmp = snd_cs46xx_peek(chip, BA1_PCTL);
tmp &= 0x0000ffff;
snd_cs46xx_poke(chip, BA1_PCTL, tmp);
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
#endif
break;
default:
@@ -833,12 +830,11 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
static int snd_cs46xx_capture_trigger(snd_pcm_substream_t * substream,
int cmd)
{
- unsigned long flags;
cs46xx_t *chip = snd_pcm_substream_chip(substream);
unsigned int tmp;
int result = 0;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock(&chip->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
@@ -856,7 +852,7 @@ static int snd_cs46xx_capture_trigger(snd_pcm_substream_t * substream,
result = -EINVAL;
break;
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
return result;
}
@@ -1153,7 +1149,6 @@ static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- unsigned long flags;
cs46xx_t *chip = dev_id;
u32 status1;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -1217,7 +1212,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
if ((status1 & HISR_MIDI) && chip->rmidi) {
unsigned char c;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock(&chip->reg_lock);
while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) {
c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
if ((chip->midcr & MIDCR_RIE) == 0)
@@ -1234,7 +1229,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
}
snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c);
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
}
/*
* EOI to the PCI part....reenables interrupts
@@ -2695,7 +2690,7 @@ int __devinit snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmi
static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
{
- cs46xx_t *chip = gameport->port_data;
+ cs46xx_t *chip = gameport_get_port_data(gameport);
snd_assert(chip, return);
snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF);
@@ -2703,7 +2698,7 @@ static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
{
- cs46xx_t *chip = gameport->port_data;
+ cs46xx_t *chip = gameport_get_port_data(gameport);
snd_assert(chip, return 0);
return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
@@ -2711,7 +2706,7 @@ static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- cs46xx_t *chip = gameport->port_data;
+ cs46xx_t *chip = gameport_get_port_data(gameport);
unsigned js1, js2, jst;
snd_assert(chip, return 0);
@@ -2757,8 +2752,8 @@ int __devinit snd_cs46xx_gameport(cs46xx_t *chip)
gameport_set_name(gp, "CS46xx Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
- gp->dev.parent = &chip->pci->dev;
- gp->port_data = chip;
+ gameport_set_dev_parent(gp, &chip->pci->dev);
+ gameport_set_port_data(gp, chip);
gp->open = snd_cs46xx_gameport_open;
gp->read = snd_cs46xx_gameport_read;
diff --git a/sound/pci/emu10k1/Makefile b/sound/pci/emu10k1/Makefile
index 460504e49b5ad..e521c38cef455 100644
--- a/sound/pci/emu10k1/Makefile
+++ b/sound/pci/emu10k1/Makefile
@@ -5,7 +5,7 @@
snd-emu10k1-objs := emu10k1.o emu10k1_main.o \
irq.o memory.o voice.o emumpu401.o emupcm.o io.o \
- emuproc.o emumixer.o emufx.o timer.o
+ emuproc.o emumixer.o emufx.o timer.o p16v.o
snd-emu10k1-synth-objs := emu10k1_synth.o emu10k1_callback.o emu10k1_patch.o
snd-emu10k1x-objs := emu10k1x.o
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index dce58a3223785..6446afe19d80c 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -138,7 +138,15 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0) {
snd_card_free(card);
return err;
- }
+ }
+ /* This stores the periods table. */
+ if (emu->audigy && emu->revision == 4) { /* P16V */
+ if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &emu->p16v_buffer) < 0) {
+ snd_p16v_free(emu);
+ return -ENOMEM;
+ }
+ }
+
if ((err = snd_emu10k1_mixer(emu)) < 0) {
snd_card_free(card);
return err;
@@ -152,8 +160,13 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0) {
snd_card_free(card);
return err;
- }
-
+ }
+ if (emu->audigy && emu->revision == 4) { /* P16V */
+ if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ }
if (emu->audigy) {
if ((err = snd_emu10k1_audigy_midi(emu)) < 0) {
snd_card_free(card);
@@ -185,23 +198,11 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
}
#endif
- if (emu->audigy && (emu->serial == 0x10011102) ) {
- strcpy(card->driver, "Audigy2");
- strcpy(card->shortname, "Sound Blaster Audigy2_Value");
- } else if (emu->audigy && (emu->revision == 4) ) {
- strcpy(card->driver, "Audigy2");
- strcpy(card->shortname, "Sound Blaster Audigy2");
- } else if (emu->audigy) {
- strcpy(card->driver, "Audigy");
- strcpy(card->shortname, "Sound Blaster Audigy");
- } else if (emu->APS) {
- strcpy(card->driver, "E-mu APS");
- strcpy(card->shortname, "E-mu APS");
- } else {
- strcpy(card->driver, "EMU10K1");
- strcpy(card->shortname, "Sound Blaster Live!");
- }
- sprintf(card->longname, "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", card->shortname, emu->revision, emu->serial, emu->port, emu->irq);
+ strcpy(card->driver, emu->card_capabilities->driver);
+ strcpy(card->shortname, emu->card_capabilities->name);
+ snprintf(card->longname, sizeof(card->longname),
+ "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i",
+ card->shortname, emu->revision, emu->serial, emu->port, emu->irq);
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 6956b106f333a..c3c96f9f2c7fe 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -39,6 +39,7 @@
#include <sound/core.h>
#include <sound/emu10k1.h>
+#include "p16v.h"
#if 0
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Creative Labs, Inc.");
@@ -178,14 +179,17 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
tmp &= 0xfffff1ff;
tmp |= (0x2<<9);
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
-
+
/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
- outl(0x600000, emu->port + 0x20);
- outl(0x14, emu->port + 0x24);
-
+ snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14);
/* Setup SRCMulti Input Audio Enable */
- outl(0x6E0000, emu->port + 0x20);
- outl(0xFF00FF00, emu->port + 0x24);
+ /* Use 0xFFFFFFFF to enable P16V sounds. */
+ snd_emu10k1_ptr20_write(emu, SRCMULTI_ENABLE, 0, 0xFFFFFFFF);
+
+ /* Enabled Phased (8-channel) P16V playback */
+ outl(0x0201, emu->port + HCFG2);
+ /* Set playback routing. */
+ snd_emu10k1_ptr_write(emu, CAPTURE_P16V_SOURCE, 0, 78e4);
}
if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */
/* Hacks for Alice3 to work independent of haP16V driver */
@@ -596,6 +600,8 @@ static int snd_emu10k1_free(emu10k1_t *emu)
if (emu->port)
pci_release_regions(emu->pci);
pci_disable_device(emu->pci);
+ if (emu->audigy && emu->revision == 4) /* P16V */
+ snd_p16v_free(emu);
kfree(emu);
return 0;
}
@@ -606,6 +612,85 @@ static int snd_emu10k1_dev_free(snd_device_t *device)
return snd_emu10k1_free(emu);
}
+/* vendor, device, subsystem, emu10k1_chip, emu10k2_chip, ca0102_chip, ca0108_chip, ca0151_chip, spk71, spdif_bug, ac97_chip, ecard, driver, name */
+
+static emu_chip_details_t emu_chip_details[] = {
+ /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
+ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
+ .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]",
+ .emu10k2_chip = 1,
+ .ca0108_chip = 1,
+ .spk71 = 1} ,
+ {.vendor = 0x1102, .device = 0x0008,
+ .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
+ .emu10k2_chip = 1,
+ .ca0108_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
+ .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
+ .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102,
+ .driver = "Audigy2", .name = "Audigy 2 ZS [2001]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102,
+ .driver = "Audigy2", .name = "Audigy 2 [SB0240]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
+ .driver = "Audigy2", .name = "Audigy 2 EX [1005]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spdif_bug = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
+ .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004,
+ .driver = "Audigy", .name = "Audigy 1 or 2 [Unknown]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .spdif_bug = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
+ .driver = "EMU10K1", .name = "E-mu APS [4001]",
+ .emu10k1_chip = 1,
+ .ecard = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
+ .driver = "EMU10K1", .name = "SB Live 5.1",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0002,
+ .driver = "EMU10K1", .name = "SB Live [Unknown]",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1} ,
+ { } /* terminator */
+};
+
int __devinit snd_emu10k1_create(snd_card_t * card,
struct pci_dev * pci,
unsigned short extin_mask,
@@ -617,15 +702,14 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu10k1_t *emu;
int err;
int is_audigy;
+ unsigned char revision;
+ const emu_chip_details_t *c;
static snd_device_ops_t ops = {
.dev_free = snd_emu10k1_dev_free,
};
*remu = NULL;
- // is_audigy = (int)pci->driver_data;
- is_audigy = (pci->device == 0x0004) || ( (pci->device == 0x0008) );
-
/* enable PCI device */
if ((err = pci_enable_device(pci)) < 0)
return err;
@@ -635,15 +719,6 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
pci_disable_device(pci);
return -ENOMEM;
}
- /* set the DMA transfer mask */
- emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
- if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
- pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
- snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask);
- kfree(emu);
- pci_disable_device(pci);
- return -ENXIO;
- }
emu->card = card;
spin_lock_init(&emu->reg_lock);
spin_lock_init(&emu->emu_lock);
@@ -658,8 +733,43 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu->irq = -1;
emu->synth = NULL;
emu->get_synth_voice = NULL;
+ /* read revision & serial */
+ pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
+ emu->revision = revision;
+ pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
+ pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
+ emu->card_type = EMU10K1_CARD_CREATIVE;
+ snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
- emu->audigy = is_audigy;
+ for (c = emu_chip_details; c->vendor; c++) {
+ if (c->vendor == pci->vendor && c->device == pci->device) {
+ if (c->subsystem == emu->serial) break;
+ if (c->subsystem == 0) break;
+ }
+ }
+ if (c->vendor == 0) {
+ snd_printk(KERN_ERR "emu10k1: Card not recognised\n");
+ kfree(emu);
+ pci_disable_device(pci);
+ return -ENOENT;
+ }
+ emu->card_capabilities = c;
+ if (c->subsystem != 0)
+ snd_printdd("Sound card name=%s\n", c->name);
+ else
+ snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial);
+
+ is_audigy = emu->audigy = c->emu10k2_chip;
+
+ /* set the DMA transfer mask */
+ emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
+ if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
+ pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
+ snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask);
+ kfree(emu);
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
if (is_audigy)
emu->gpr_base = A_FXGPREGBASE;
else
@@ -705,30 +815,15 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu->memhdr->block_extra_size = sizeof(emu10k1_memblk_t) - sizeof(snd_util_memblk_t);
pci_set_master(pci);
- /* read revision & serial */
- pci_read_config_byte(pci, PCI_REVISION_ID, (char *)&emu->revision);
- pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
- pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
- emu->card_type = EMU10K1_CARD_CREATIVE;
- if (emu->serial == 0x40011102) {
+
+ if (c->ecard) {
emu->card_type = EMU10K1_CARD_EMUAPS;
emu->APS = 1;
- emu->no_ac97 = 1; /* APS has no AC97 chip */
- }
- else if (emu->revision == 4 && emu->serial == 0x10051102) {
- /* Audigy 2 EX has apparently no effective AC97 controls
- * (for both input and output), so we skip the AC97 detections
- */
- snd_printdd(KERN_INFO "Audigy2 EX is detected. skipping ac97.\n");
- emu->no_ac97 = 1;
- }
-
- if (emu->revision == 4 && (emu->model == 0x2001 || emu->model == 0x2002)) {
- /* Audigy 2 ZS */
- snd_printdd(KERN_INFO "Audigy2 ZS is detected. setting 7.1 mode.\n");
- emu->spk71 = 1;
}
+ if (! c->ac97_chip)
+ emu->no_ac97 = 1;
+ emu->spk71 = c->spk71;
emu->fx8010.fxbus_mask = 0x303f;
if (extin_mask == 0)
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 0c64e24e1bc17..27dfd8ddddf48 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -749,6 +749,7 @@ static int snd_emu10k1x_ac97(emu10k1x_t *chip)
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
+ ac97.scaps = AC97_SCAP_NO_SPDIF;
return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
}
@@ -1265,7 +1266,6 @@ static void mpu401_clear_rx(emu10k1x_t *emu, emu10k1x_midi_t *mpu)
static void do_emu10k1x_midi_interrupt(emu10k1x_t *emu, emu10k1x_midi_t *midi, unsigned int status)
{
- unsigned long flags;
unsigned char byte;
if (midi->rmidi == NULL) {
@@ -1285,7 +1285,7 @@ static void do_emu10k1x_midi_interrupt(emu10k1x_t *emu, emu10k1x_midi_t *midi, u
}
spin_unlock(&midi->input_lock);
- spin_lock_irqsave(&midi->output_lock, flags);
+ spin_lock(&midi->output_lock);
if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) {
if (midi->substream_output &&
snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
@@ -1294,7 +1294,7 @@ static void do_emu10k1x_midi_interrupt(emu10k1x_t *emu, emu10k1x_midi_t *midi, u
snd_emu10k1x_intr_disable(emu, midi->tx_enable);
}
}
- spin_unlock_irqrestore(&midi->output_lock, flags);
+ spin_unlock(&midi->output_lock);
}
static void snd_emu10k1x_midi_interrupt(emu10k1x_t *emu, unsigned int status)
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 92329bc039512..b9fa2e887fee3 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -634,7 +634,8 @@ static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *ic
snd_ctl_elem_id_t __user *_id;
snd_ctl_elem_id_t id;
emu10k1_fx8010_control_gpr_t __user *_gctl;
- emu10k1_fx8010_control_gpr_t gctl;
+ emu10k1_fx8010_control_gpr_t *gctl;
+ int err;
for (i = 0, _id = icode->gpr_del_controls;
i < icode->gpr_del_control_count; i++, _id++) {
@@ -643,29 +644,42 @@ static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *ic
if (snd_emu10k1_look_for_ctl(emu, &id) == NULL)
return -ENOENT;
}
+ gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
+ if (! gctl)
+ return -ENOMEM;
+ err = 0;
for (i = 0, _gctl = icode->gpr_add_controls;
i < icode->gpr_add_control_count; i++, _gctl++) {
- if (copy_from_user(&gctl, _gctl, sizeof(gctl)))
- return -EFAULT;
- if (snd_emu10k1_look_for_ctl(emu, &gctl.id))
+ if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
+ err = -EFAULT;
+ goto __error;
+ }
+ if (snd_emu10k1_look_for_ctl(emu, &gctl->id))
continue;
down_read(&emu->card->controls_rwsem);
- if (snd_ctl_find_id(emu->card, &gctl.id) != NULL) {
+ if (snd_ctl_find_id(emu->card, &gctl->id) != NULL) {
up_read(&emu->card->controls_rwsem);
- return -EEXIST;
+ err = -EEXIST;
+ goto __error;
}
up_read(&emu->card->controls_rwsem);
- if (gctl.id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
- gctl.id.iface != SNDRV_CTL_ELEM_IFACE_PCM)
- return -EINVAL;
+ if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
+ gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
+ err = -EINVAL;
+ goto __error;
+ }
}
for (i = 0, _gctl = icode->gpr_list_controls;
i < icode->gpr_list_control_count; i++, _gctl++) {
/* FIXME: we need to check the WRITE access */
- if (copy_from_user(&gctl, _gctl, sizeof(gctl)))
- return -EFAULT;
+ if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
+ err = -EFAULT;
+ goto __error;
+ }
}
- return 0;
+ __error:
+ kfree(gctl);
+ return err;
}
static void snd_emu10k1_ctl_private_free(snd_kcontrol_t *kctl)
@@ -682,52 +696,59 @@ static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode
{
unsigned int i, j;
emu10k1_fx8010_control_gpr_t __user *_gctl;
- emu10k1_fx8010_control_gpr_t gctl;
- snd_emu10k1_fx8010_ctl_t *ctl, nctl;
+ emu10k1_fx8010_control_gpr_t *gctl;
+ snd_emu10k1_fx8010_ctl_t *ctl, *nctl;
snd_kcontrol_new_t knew;
snd_kcontrol_t *kctl;
snd_ctl_elem_value_t *val;
int err = 0;
val = (snd_ctl_elem_value_t *)kmalloc(sizeof(*val), GFP_KERNEL);
- if (!val)
- return -ENOMEM;
+ gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
+ nctl = kmalloc(sizeof(*nctl), GFP_KERNEL);
+ if (!val || !gctl || !nctl) {
+ err = -ENOMEM;
+ goto __error;
+ }
+
for (i = 0, _gctl = icode->gpr_add_controls;
i < icode->gpr_add_control_count; i++, _gctl++) {
- if (copy_from_user(&gctl, _gctl, sizeof(gctl))) {
+ if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
err = -EFAULT;
goto __error;
}
- snd_runtime_check(gctl.id.iface == SNDRV_CTL_ELEM_IFACE_MIXER ||
- gctl.id.iface == SNDRV_CTL_ELEM_IFACE_PCM, err = -EINVAL; goto __error);
- snd_runtime_check(gctl.id.name[0] != '\0', err = -EINVAL; goto __error);
- ctl = snd_emu10k1_look_for_ctl(emu, &gctl.id);
+ snd_runtime_check(gctl->id.iface == SNDRV_CTL_ELEM_IFACE_MIXER ||
+ gctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM, err = -EINVAL; goto __error);
+ snd_runtime_check(gctl->id.name[0] != '\0', err = -EINVAL; goto __error);
+ ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id);
memset(&knew, 0, sizeof(knew));
- knew.iface = gctl.id.iface;
- knew.name = gctl.id.name;
- knew.index = gctl.id.index;
- knew.device = gctl.id.device;
- knew.subdevice = gctl.id.subdevice;
+ knew.iface = gctl->id.iface;
+ knew.name = gctl->id.name;
+ knew.index = gctl->id.index;
+ knew.device = gctl->id.device;
+ knew.subdevice = gctl->id.subdevice;
knew.info = snd_emu10k1_gpr_ctl_info;
knew.get = snd_emu10k1_gpr_ctl_get;
knew.put = snd_emu10k1_gpr_ctl_put;
- memset(&nctl, 0, sizeof(nctl));
- nctl.vcount = gctl.vcount;
- nctl.count = gctl.count;
+ memset(nctl, 0, sizeof(*nctl));
+ nctl->vcount = gctl->vcount;
+ nctl->count = gctl->count;
for (j = 0; j < 32; j++) {
- nctl.gpr[j] = gctl.gpr[j];
- nctl.value[j] = ~gctl.value[j]; /* inverted, we want to write new value in gpr_ctl_put() */
- val->value.integer.value[j] = gctl.value[j];
+ nctl->gpr[j] = gctl->gpr[j];
+ nctl->value[j] = ~gctl->value[j]; /* inverted, we want to write new value in gpr_ctl_put() */
+ val->value.integer.value[j] = gctl->value[j];
}
- nctl.min = gctl.min;
- nctl.max = gctl.max;
- nctl.translation = gctl.translation;
+ nctl->min = gctl->min;
+ nctl->max = gctl->max;
+ nctl->translation = gctl->translation;
if (ctl == NULL) {
ctl = (snd_emu10k1_fx8010_ctl_t *)kmalloc(sizeof(*ctl), GFP_KERNEL);
- if (ctl == NULL)
- continue;
+ if (ctl == NULL) {
+ err = -ENOMEM;
+ goto __error;
+ }
knew.private_value = (unsigned long)ctl;
- memcpy(ctl, &nctl, sizeof(nctl));
+ *ctl = *nctl;
if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) {
kfree(ctl);
goto __error;
@@ -737,15 +758,17 @@ static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode
list_add_tail(&ctl->list, &emu->fx8010.gpr_ctl);
} else {
/* overwrite */
- nctl.list = ctl->list;
- nctl.kcontrol = ctl->kcontrol;
- memcpy(ctl, &nctl, sizeof(nctl));
+ nctl->list = ctl->list;
+ nctl->kcontrol = ctl->kcontrol;
+ *ctl = *nctl;
snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id);
}
snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val);
}
__error:
+ kfree(nctl);
+ kfree(gctl);
kfree(val);
return err;
}
@@ -774,40 +797,47 @@ static int snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icod
{
unsigned int i = 0, j;
unsigned int total = 0;
- emu10k1_fx8010_control_gpr_t gctl;
+ emu10k1_fx8010_control_gpr_t *gctl;
emu10k1_fx8010_control_gpr_t __user *_gctl;
snd_emu10k1_fx8010_ctl_t *ctl;
snd_ctl_elem_id_t *id;
struct list_head *list;
+ gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
+ if (! gctl)
+ return -ENOMEM;
+
_gctl = icode->gpr_list_controls;
list_for_each(list, &emu->fx8010.gpr_ctl) {
ctl = emu10k1_gpr_ctl(list);
total++;
if (_gctl && i < icode->gpr_list_control_count) {
- memset(&gctl, 0, sizeof(gctl));
+ memset(gctl, 0, sizeof(*gctl));
id = &ctl->kcontrol->id;
- gctl.id.iface = id->iface;
- strlcpy(gctl.id.name, id->name, sizeof(gctl.id.name));
- gctl.id.index = id->index;
- gctl.id.device = id->device;
- gctl.id.subdevice = id->subdevice;
- gctl.vcount = ctl->vcount;
- gctl.count = ctl->count;
+ gctl->id.iface = id->iface;
+ strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name));
+ gctl->id.index = id->index;
+ gctl->id.device = id->device;
+ gctl->id.subdevice = id->subdevice;
+ gctl->vcount = ctl->vcount;
+ gctl->count = ctl->count;
for (j = 0; j < 32; j++) {
- gctl.gpr[j] = ctl->gpr[j];
- gctl.value[j] = ctl->value[j];
+ gctl->gpr[j] = ctl->gpr[j];
+ gctl->value[j] = ctl->value[j];
}
- gctl.min = ctl->min;
- gctl.max = ctl->max;
- gctl.translation = ctl->translation;
- if (copy_to_user(_gctl, &gctl, sizeof(gctl)))
+ gctl->min = ctl->min;
+ gctl->max = ctl->max;
+ gctl->translation = ctl->translation;
+ if (copy_to_user(_gctl, gctl, sizeof(*gctl))) {
+ kfree(gctl);
return -EFAULT;
+ }
_gctl++;
i++;
}
}
icode->gpr_list_control_total = total;
+ kfree(gctl);
return 0;
}
@@ -1339,6 +1369,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
/* IEC958 Optical Raw Playback Switch */
+ gpr_map[gpr++] = 0;
gpr_map[gpr++] = 0x1008;
gpr_map[gpr++] = 0xffff0000;
for (z = 0; z < 2; z++) {
@@ -1349,7 +1380,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_SWITCH(icode, &ptr, tmp + 0, tmp + 2, gpr + z);
A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
- A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
+ if ((z==1) && (emu->card_capabilities->spdif_bug)) {
+ /* Due to a SPDIF output bug on some Audigy cards, this code delays the Right channel by 1 sample */
+ snd_printk("Installing spdif_bug patch: %s\n", emu->card_capabilities->name);
+ A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000);
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
+ } else {
+ A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
+ }
}
snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "IEC958 Optical Raw Playback Switch", gpr, 0);
gpr += 2;
@@ -2092,7 +2130,7 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
memset(info, 0, sizeof(info));
info->card = emu->card_type;
info->internal_tram_size = emu->fx8010.itram_size;
- info->external_tram_size = emu->fx8010.etram_pages.bytes;
+ info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
fxbus = fxbuses;
extin = emu->audigy ? audigy_ins : creative_ins;
extout = emu->audigy ? audigy_outs : creative_outs;
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index a57a82c9fbfa1..044663d31aa77 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -3,6 +3,7 @@
* Takashi Iwai <tiwai@suse.de>
* Creative Labs, Inc.
* Routines for control of EMU10K1 chips / mixer routines
+ * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
*
* BUGS:
* --
@@ -481,9 +482,13 @@ static int snd_emu10k1_efx_send_routing_put(snd_kcontrol_t * kcontrol,
change = 1;
}
}
- if (change && mix->epcm->voices[ch])
- update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
- &mix->send_routing[0][0]);
+
+ if (change && mix->epcm) {
+ if (mix->epcm->voices[ch]) {
+ update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
+ &mix->send_routing[0][0]);
+ }
+ }
spin_unlock_irqrestore(&emu->reg_lock, flags);
return change;
}
@@ -543,9 +548,12 @@ static int snd_emu10k1_efx_send_volume_put(snd_kcontrol_t * kcontrol,
change = 1;
}
}
- if (change && mix->epcm->voices[ch])
- update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
- &mix->send_volume[0][0]);
+ if (change && mix->epcm) {
+ if (mix->epcm->voices[ch]) {
+ update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
+ &mix->send_volume[0][0]);
+ }
+ }
spin_unlock_irqrestore(&emu->reg_lock, flags);
return change;
}
@@ -599,8 +607,11 @@ static int snd_emu10k1_efx_attn_put(snd_kcontrol_t * kcontrol,
mix->attn[0] = val;
change = 1;
}
- if (change && mix->epcm->voices[ch])
- snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
+ if (change && mix->epcm) {
+ if (mix->epcm->voices[ch]) {
+ snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
+ }
+ }
spin_unlock_irqrestore(&emu->reg_lock, flags);
return change;
}
@@ -795,6 +806,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = emu;
ac97.private_free = snd_emu10k1_mixer_free_ac97;
+ ac97.scaps = AC97_SCAP_NO_SPDIF;
if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0)
return err;
if (emu->audigy) {
@@ -912,11 +924,6 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
- if ((kctl = ctl_find(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT))) != NULL) {
- /* already defined by ac97, remove it */
- /* FIXME: or do we need both controls? */
- remove_ctl(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT));
- }
if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
@@ -939,6 +946,10 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
if ((err = snd_ctl_add(card, kctl)))
return err;
}
-
+ if (emu->audigy && emu->revision == 4) { /* P16V */
+ if ((err = snd_p16v_mixer(emu)))
+ return err;
+ }
+
return 0;
}
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c
index c54d0fc7ed90f..eb57458a96654 100644
--- a/sound/pci/emu10k1/emumpu401.c
+++ b/sound/pci/emu10k1/emumpu401.c
@@ -73,7 +73,6 @@ static void mpu401_clear_rx(emu10k1_t *emu, emu10k1_midi_t *mpu)
static void do_emu10k1_midi_interrupt(emu10k1_t *emu, emu10k1_midi_t *midi, unsigned int status)
{
- unsigned long flags;
unsigned char byte;
if (midi->rmidi == NULL) {
@@ -93,7 +92,7 @@ static void do_emu10k1_midi_interrupt(emu10k1_t *emu, emu10k1_midi_t *midi, unsi
}
spin_unlock(&midi->input_lock);
- spin_lock_irqsave(&midi->output_lock, flags);
+ spin_lock(&midi->output_lock);
if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) {
if (midi->substream_output &&
snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
@@ -102,7 +101,7 @@ static void do_emu10k1_midi_interrupt(emu10k1_t *emu, emu10k1_midi_t *midi, unsi
snd_emu10k1_intr_disable(emu, midi->tx_enable);
}
}
- spin_unlock_irqrestore(&midi->output_lock, flags);
+ spin_unlock(&midi->output_lock);
}
static void snd_emu10k1_midi_interrupt(emu10k1_t *emu, unsigned int status)
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 2f0815903f2c7..d1c2a02c486bc 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -2,6 +2,7 @@
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
* Creative Labs, Inc.
* Routines for control of EMU10K1 chips / PCM routines
+ * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
*
* BUGS:
* --
@@ -109,14 +110,17 @@ static int snd_emu10k1_pcm_channel_alloc(emu10k1_pcm_t * epcm, int voices)
snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]);
epcm->voices[1] = NULL;
}
- if (voices == 1 && epcm->voices[0] != NULL)
- return 0; /* already allocated */
- if (voices == 2 && epcm->voices[0] != NULL && epcm->voices[1] != NULL)
- return 0;
- if (voices > 1) {
- if (epcm->voices[0] != NULL && epcm->voices[1] == NULL) {
- snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]);
- epcm->voices[0] = NULL;
+ for (i = 0; i < voices; i++) {
+ if (epcm->voices[i] == NULL)
+ break;
+ }
+ if (i == voices)
+ return 0; /* already allocated */
+
+ for (i = 0; i < ARRAY_SIZE(epcm->voices); i++) {
+ if (epcm->voices[i]) {
+ snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
+ epcm->voices[i] = NULL;
}
}
err = snd_emu10k1_voice_alloc(epcm->emu,
@@ -271,11 +275,11 @@ static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu,
int master, int extra,
emu10k1_voice_t *evoice,
unsigned int start_addr,
- unsigned int end_addr)
+ unsigned int end_addr,
+ emu10k1_pcm_mixer_t *mix)
{
snd_pcm_substream_t *substream = evoice->epcm->substream;
snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_mixer_t *mix;
unsigned int silent_page, tmp;
int voice, stereo, w_16;
unsigned char attn, send_amount[8];
@@ -285,11 +289,6 @@ static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu,
unsigned int ccis;
voice = evoice->number;
- if (evoice->epcm->type == PLAYBACK_EFX)
- mix = &emu->efx_pcm_mixer[voice - evoice->epcm->voices[0]->number];
- else
- mix = &emu->pcm_mixer[substream->number];
-
stereo = runtime->channels == 2;
w_16 = snd_pcm_format_width(runtime->format) == 16;
@@ -493,14 +492,16 @@ static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream)
}
end_addr += start_addr;
snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
- start_addr, end_addr);
+ start_addr, end_addr, NULL);
start_addr = epcm->start_addr;
end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream);
snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0],
- start_addr, end_addr);
+ start_addr, end_addr,
+ &emu->pcm_mixer[substream->number]);
if (epcm->voices[1])
snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[1],
- start_addr, end_addr);
+ start_addr, end_addr,
+ &emu->pcm_mixer[substream->number]);
return 0;
}
@@ -522,16 +523,18 @@ static int snd_emu10k1_efx_playback_prepare(snd_pcm_substream_t * substream)
channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK;
snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
- start_addr, start_addr + (channel_size / 2));
+ start_addr, start_addr + (channel_size / 2), NULL);
/* only difference with the master voice is we use it for the pointer */
snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0],
- start_addr, start_addr + channel_size);
+ start_addr, start_addr + channel_size,
+ &emu->efx_pcm_mixer[0]);
start_addr += channel_size;
for (i = 1; i < NUM_EFX_PLAYBACK; i++) {
snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[i],
- start_addr, start_addr+channel_size);
+ start_addr, start_addr + channel_size,
+ &emu->efx_pcm_mixer[i]);
start_addr += channel_size;
}
@@ -650,12 +653,13 @@ static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, int extra, emu
}
}
-static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra)
+static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t *evoice,
+ int master, int extra,
+ emu10k1_pcm_mixer_t *mix)
{
snd_pcm_substream_t *substream;
snd_pcm_runtime_t *runtime;
- emu10k1_pcm_mixer_t *mix;
- unsigned int attn;
+ unsigned int attn, vattn;
unsigned int voice, tmp;
if (evoice == NULL) /* skip second voice for mono */
@@ -664,15 +668,12 @@ static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t *
runtime = substream->runtime;
voice = evoice->number;
- mix = evoice->epcm->type == PLAYBACK_EFX
- ? &emu->efx_pcm_mixer[voice - evoice->epcm->voices[0]->number]
- : &emu->pcm_mixer[substream->number];
-
attn = extra ? 0 : 0x00ff;
tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0;
+ vattn = mix != NULL ? (mix->attn[tmp] << 16) : 0;
snd_emu10k1_ptr_write(emu, IFATN, voice, attn);
- snd_emu10k1_ptr_write(emu, VTFT, voice, (mix->attn[tmp] << 16) | 0xffff);
- snd_emu10k1_ptr_write(emu, CVCF, voice, (mix->attn[tmp] << 16) | 0xffff);
+ snd_emu10k1_ptr_write(emu, VTFT, voice, vattn | 0xffff);
+ snd_emu10k1_ptr_write(emu, CVCF, voice, vattn | 0xffff);
snd_emu10k1_ptr_write(emu, DCYSUSV, voice, 0x7f7f);
snd_emu10k1_voice_clear_loop_stop(emu, voice);
}
@@ -721,7 +722,9 @@ static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
emu10k1_pcm_t *epcm = runtime->private_data;
+ emu10k1_pcm_mixer_t *mix;
int result = 0;
+
// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
spin_lock(&emu->reg_lock);
switch (cmd) {
@@ -730,9 +733,10 @@ static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[0]);
/* follow thru */
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0);
- snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0);
- snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1);
+ mix = &emu->pcm_mixer[substream->number];
+ snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix);
+ snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix);
+ snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL);
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1, 0);
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0, 0);
snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
@@ -847,7 +851,7 @@ static int snd_emu10k1_efx_playback_trigger(snd_pcm_substream_t * substream,
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
emu10k1_pcm_t *epcm = runtime->private_data;
- int i = 0;
+ int i;
int result = 0;
spin_lock(&emu->reg_lock);
@@ -861,16 +865,16 @@ static int snd_emu10k1_efx_playback_trigger(snd_pcm_substream_t * substream,
/* follow thru */
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, 0);
- snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1);
- for (i = 1; i < NUM_EFX_PLAYBACK; i++) {
- snd_emu10k1_playback_prepare_voice(emu, epcm->voices[i], 0, 0);
- }
+ snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL);
+ snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, 0,
+ &emu->efx_pcm_mixer[0]);
+ for (i = 1; i < NUM_EFX_PLAYBACK; i++)
+ snd_emu10k1_playback_prepare_voice(emu, epcm->voices[i], 0, 0,
+ &emu->efx_pcm_mixer[i]);
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 0, 0);
snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
- for (i = 1; i < NUM_EFX_PLAYBACK; i++) {
+ for (i = 1; i < NUM_EFX_PLAYBACK; i++)
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i], 0, 0);
- }
epcm->running = 1;
break;
case SNDRV_PCM_TRIGGER_STOP:
@@ -1273,7 +1277,7 @@ int __devinit snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strcpy(pcm->name, "EMU10K1");
+ strcpy(pcm->name, "ADC Capture/Standard PCM Playback");
emu->pcm = pcm;
for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
@@ -1308,7 +1312,7 @@ int __devinit snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rp
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strcpy(pcm->name, "EMU10K1 multichannel EFX");
+ strcpy(pcm->name, "Multichannel Playback");
emu->pcm = pcm;
for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
@@ -1357,7 +1361,7 @@ int __devinit snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_mic_ops);
pcm->info_flags = 0;
- strcpy(pcm->name, "EMU10K1 MIC");
+ strcpy(pcm->name, "Mic Capture");
emu->pcm_mic = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
@@ -1695,7 +1699,7 @@ int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
pcm->info_flags = 0;
- strcpy(pcm->name, "EMU10K1 EFX");
+ strcpy(pcm->name, "Multichannel Capture/PT Playback");
emu->pcm_efx = pcm;
if (rpcm)
*rpcm = pcm;
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index 69dcc2a2f311f..d990d5eb45a81 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -184,7 +184,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "Card : %s\n",
emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative"));
snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size);
- snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes);
+ snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2);
snd_iprintf(buffer, "\n");
snd_iprintf(buffer, "Effect Send Routing :\n");
for (idx = 0; idx < NUM_G; idx++) {
@@ -413,7 +413,7 @@ static void snd_ptr_write(emu10k1_t *emu,
static void snd_emu_proc_ptr_reg_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer, int iobase, int offset, int length)
+ snd_info_buffer_t * buffer, int iobase, int offset, int length, int voices)
{
emu10k1_t *emu = entry->private_data;
unsigned long value;
@@ -425,7 +425,7 @@ static void snd_emu_proc_ptr_reg_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "Registers 0x%x\n", iobase);
for(i = offset; i < offset+length; i++) {
snd_iprintf(buffer, "%02X: ",i);
- for (j = 0; j < 64; j++) {
+ for (j = 0; j < voices; j++) {
if(iobase == 0)
value = snd_ptr_read(emu, 0, i, j);
else
@@ -466,25 +466,25 @@ static void snd_emu_proc_ptr_reg_write20(snd_info_entry_t *entry,
static void snd_emu_proc_ptr_reg_read00a(snd_info_entry_t *entry,
snd_info_buffer_t * buffer)
{
- snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0, 0x40);
+ snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0, 0x40, 64);
}
static void snd_emu_proc_ptr_reg_read00b(snd_info_entry_t *entry,
snd_info_buffer_t * buffer)
{
- snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0x40, 0x40);
+ snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0x40, 0x40, 64);
}
static void snd_emu_proc_ptr_reg_read20a(snd_info_entry_t *entry,
snd_info_buffer_t * buffer)
{
- snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0, 0x40);
+ snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0, 0x40, 4);
}
static void snd_emu_proc_ptr_reg_read20b(snd_info_entry_t *entry,
snd_info_buffer_t * buffer)
{
- snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x40, 0x40);
+ snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x40, 0x40, 4);
}
#endif
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index b97fec10f51e8..b9d3ae0dcab7a 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -91,6 +91,38 @@ void snd_emu10k1_ptr_write(emu10k1_t *emu, unsigned int reg, unsigned int chn, u
}
}
+unsigned int snd_emu10k1_ptr20_read(emu10k1_t * emu,
+ unsigned int reg,
+ unsigned int chn)
+{
+ unsigned long flags;
+ unsigned int regptr, val;
+
+ regptr = (reg << 16) | chn;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ outl(regptr, emu->port + 0x20 + PTR);
+ val = inl(emu->port + 0x20 + DATA);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+ return val;
+}
+
+void snd_emu10k1_ptr20_write(emu10k1_t *emu,
+ unsigned int reg,
+ unsigned int chn,
+ unsigned int data)
+{
+ unsigned int regptr;
+ unsigned long flags;
+
+ regptr = (reg << 16) | chn;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ outl(regptr, emu->port + 0x20 + PTR);
+ outl(data, emu->port + 0x20 + DATA);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
void snd_emu10k1_intr_enable(emu10k1_t *emu, unsigned int intrenb)
{
unsigned long flags;
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index f271d482517af..b81a7cafff39e 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -33,7 +33,7 @@
irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
emu10k1_t *emu = dev_id;
- unsigned int status, orig_status;
+ unsigned int status, status2, orig_status, orig_status2;
int handled = 0;
while ((status = inl(emu->port + IPR)) != 0) {
@@ -149,7 +149,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
if (status) {
unsigned int bits;
- snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
+ //snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
//make sure any interrupts we don't handle are disabled:
bits = INTE_FXDSPENABLE |
INTE_PCIERRORENABLE |
@@ -170,5 +170,20 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
outl(orig_status, emu->port + IPR); /* ack all */
}
+ if (emu->audigy && emu->revision == 4) { /* P16V */
+ while ((status2 = inl(emu->port + IPR2)) != 0) {
+ u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */
+ emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]);
+ orig_status2 = status2;
+ if(status2 & mask) {
+ if(pvoice->use) {
+ snd_pcm_period_elapsed(pvoice->epcm->substream);
+ } else {
+ snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
+ }
+ }
+ outl(orig_status2, emu->port + IPR2); /* ack all */
+ }
+ }
return IRQ_RETVAL(handled);
}
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
new file mode 100644
index 0000000000000..d03cb2fefc9e2
--- /dev/null
+++ b/sound/pci/emu10k1/p16v.c
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
+ * Driver p16v chips
+ * Version: 0.22
+ *
+ * FEATURES currently supported:
+ * Output fixed at S32_LE, 2 channel to hw:0,0
+ * Rates: 44.1, 48, 96, 192.
+ *
+ * Changelog:
+ * 0.8
+ * Use separate card based buffer for periods table.
+ * 0.9
+ * Use 2 channel output streams instead of 8 channel.
+ * (8 channel output streams might be good for ASIO type output)
+ * Corrected speaker output, so Front -> Front etc.
+ * 0.10
+ * Fixed missed interrupts.
+ * 0.11
+ * Add Sound card model number and names.
+ * Add Analog volume controls.
+ * 0.12
+ * Corrected playback interrupts. Now interrupt per period, instead of half period.
+ * 0.13
+ * Use single trigger for multichannel.
+ * 0.14
+ * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo.
+ * 0.15
+ * Force buffer_size / period_size == INTEGER.
+ * 0.16
+ * Update p16v.c to work with changed alsa api.
+ * 0.17
+ * Update p16v.c to work with changed alsa api. Removed boot_devs.
+ * 0.18
+ * Merging with snd-emu10k1 driver.
+ * 0.19
+ * One stereo channel at 24bit now works.
+ * 0.20
+ * Added better register defines.
+ * 0.21
+ * Integrated with snd-emu10k1 driver.
+ * 0.22
+ * Removed #if 0 ... #endif
+ *
+ *
+ * BUGS:
+ * Some stability problems when unloading the snd-p16v kernel module.
+ * --
+ *
+ * TODO:
+ * SPDIF out.
+ * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz.
+ * Currently capture fixed at 48000Hz.
+ *
+ * --
+ * GENERAL INFO:
+ * Model: SB0240
+ * P16V Chip: CA0151-DBS
+ * Audigy 2 Chip: CA0102-IAT
+ * AC97 Codec: STAC 9721
+ * ADC: Philips 1361T (Stereo 24bit)
+ * DAC: CS4382-K (8-channel, 24bit, 192Khz)
+ *
+ * This code was initally based on code from ALSA's emu10k1x.c which is:
+ * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/info.h>
+#include <sound/emu10k1.h>
+#include "p16v.h"
+
+#define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
+#define PCM_FRONT_CHANNEL 0
+#define PCM_REAR_CHANNEL 1
+#define PCM_CENTER_LFE_CHANNEL 2
+#define PCM_UNKNOWN_CHANNEL 3
+#define CONTROL_FRONT_CHANNEL 0
+#define CONTROL_REAR_CHANNEL 3
+#define CONTROL_CENTER_LFE_CHANNEL 1
+#define CONTROL_UNKNOWN_CHANNEL 2
+
+/* Card IDs:
+ * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2002 -> Audigy2 ZS 7.1 Model:SB0350
+ * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1007 -> Audigy2 6.1 Model:SB0240
+ * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1002 -> Audigy2 Platinum Model:SB msb0240230009266
+ * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2007 -> Audigy4 Pro Model:SB0380 M1SB0380472001901E
+ *
+ */
+
+ /* hardware definition */
+static snd_pcm_hardware_t snd_p16v_playback_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
+ .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 ,
+ .rate_min = 48000,
+ .rate_max = 192000,
+ .channels_min = 8,
+ .channels_max = 8,
+ .buffer_bytes_max = (32*1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (16*1024),
+ .periods_min = 2,
+ .periods_max = 8,
+ .fifo_size = 0,
+};
+
+static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime)
+{
+ snd_pcm_t *epcm = runtime->private_data;
+
+ if (epcm) {
+ //snd_printk("epcm free: %p\n", epcm);
+ kfree(epcm);
+ }
+}
+
+/* open_playback callback */
+static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, int channel_id)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ emu10k1_voice_t *channel = &(emu->p16v_voices[channel_id]);
+ emu10k1_pcm_t *epcm;
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int err;
+
+ epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ //snd_printk("epcm kcalloc: %p\n", epcm);
+
+ if (epcm == NULL)
+ return -ENOMEM;
+ epcm->emu = emu;
+ epcm->substream = substream;
+ //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id);
+
+ runtime->private_data = epcm;
+ runtime->private_free = snd_p16v_pcm_free_substream;
+
+ runtime->hw = snd_p16v_playback_hw;
+
+ channel->emu = emu;
+ channel->number = channel_id;
+
+ channel->use=1;
+ //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use);
+ //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
+ //channel->interrupt = snd_p16v_pcm_channel_interrupt;
+ channel->epcm=epcm;
+ if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+ return err;
+
+ return 0;
+}
+
+/* close callback */
+static int snd_p16v_pcm_close_playback(snd_pcm_substream_t *substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ //snd_pcm_runtime_t *runtime = substream->runtime;
+ //emu10k1_pcm_t *epcm = runtime->private_data;
+ emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
+/* FIXME: maybe zero others */
+ return 0;
+}
+
+static int snd_p16v_pcm_open_playback_front(snd_pcm_substream_t *substream)
+{
+ return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
+}
+
+/* hw_params callback */
+static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ int result;
+ //snd_printk("hw_params alloc: substream=%p\n", substream);
+ result = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ //snd_printk("hw_params alloc: result=%d\n", result);
+ //dump_stack();
+ return result;
+}
+
+/* hw_free callback */
+static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream)
+{
+ int result;
+ //snd_printk("hw_params free: substream=%p\n", substream);
+ result = snd_pcm_lib_free_pages(substream);
+ //snd_printk("hw_params free: result=%d\n", result);
+ //dump_stack();
+ return result;
+}
+
+/* prepare playback callback */
+static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ //emu10k1_pcm_t *epcm = runtime->private_data;
+ int channel = substream->pcm->device - emu->p16v_device_offset;
+ u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
+ u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
+ int i;
+ u32 tmp;
+
+ //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
+ //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
+ //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->p16v_buffer.addr, emu->p16v_buffer.area, emu->p16v_buffer.bytes);
+ tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
+ switch (runtime->rate) {
+ case 44100:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x8000); /* FIXME: This will change the capture rate as well! */
+ break;
+ case 48000:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x0000); /* FIXME: This will change the capture rate as well! */
+ break;
+ case 96000:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x4000); /* FIXME: This will change the capture rate as well! */
+ break;
+ case 192000:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x2000); /* FIXME: This will change the capture rate as well! */
+ break;
+ default:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, 0x0000); /* FIXME: This will change the capture rate as well! */
+ break;
+ }
+ /* FIXME: Check emu->buffer.size before actually writing to it. */
+ for(i=0; i < runtime->periods; i++) {
+ table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
+ table_base[(i*2)+1]=period_size_bytes<<16;
+ }
+
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel));
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
+ snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
+ snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);
+
+ return 0;
+}
+
+static void snd_p16v_intr_enable(emu10k1_t *emu, unsigned int intrenb)
+{
+ unsigned long flags;
+ unsigned int enable;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ enable = inl(emu->port + INTE2) | intrenb;
+ outl(enable, emu->port + INTE2);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
+static void snd_p16v_intr_disable(emu10k1_t *emu, unsigned int intrenb)
+{
+ unsigned long flags;
+ unsigned int disable;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ disable = inl(emu->port + INTE2) & (~intrenb);
+ outl(disable, emu->port + INTE2);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
+/* trigger_playback callback */
+static int snd_p16v_pcm_trigger_playback(snd_pcm_substream_t *substream,
+ int cmd)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime;
+ emu10k1_pcm_t *epcm;
+ int channel;
+ int result = 0;
+ struct list_head *pos;
+ snd_pcm_substream_t *s;
+ u32 basic = 0;
+ u32 inte = 0;
+ int running=0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ running=1;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ default:
+ running=0;
+ break;
+ }
+ snd_pcm_group_for_each(pos, substream) {
+ s = snd_pcm_group_substream_entry(pos);
+ runtime = s->runtime;
+ epcm = runtime->private_data;
+ channel = substream->pcm->device-emu->p16v_device_offset;
+ //snd_printk("p16v channel=%d\n",channel);
+ epcm->running = running;
+ basic |= (0x1<<channel);
+ inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel);
+ snd_pcm_trigger_done(s, substream);
+ }
+ //snd_printk("basic=0x%x, inte=0x%x\n",basic, inte);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ snd_p16v_intr_enable(emu, inte);
+ snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)| (basic));
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
+ snd_p16v_intr_disable(emu, inte);
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+ return result;
+}
+
+/* pointer_playback callback */
+static snd_pcm_uframes_t
+snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ emu10k1_pcm_t *epcm = runtime->private_data;
+ snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
+ int channel = substream->pcm->device - emu->p16v_device_offset;
+ if (!epcm->running)
+ return 0;
+
+ ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
+ ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
+ ptr4 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
+ if (ptr3 != ptr4) ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
+ ptr2 = bytes_to_frames(runtime, ptr1);
+ ptr2+= (ptr4 >> 3) * runtime->period_size;
+ ptr=ptr2;
+ if (ptr >= runtime->buffer_size)
+ ptr -= runtime->buffer_size;
+
+ return ptr;
+}
+
+/* operators */
+static snd_pcm_ops_t snd_p16v_playback_front_ops = {
+ .open = snd_p16v_pcm_open_playback_front,
+ .close = snd_p16v_pcm_close_playback,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_p16v_pcm_hw_params_playback,
+ .hw_free = snd_p16v_pcm_hw_free_playback,
+ .prepare = snd_p16v_pcm_prepare_playback,
+ .trigger = snd_p16v_pcm_trigger_playback,
+ .pointer = snd_p16v_pcm_pointer_playback,
+};
+
+int snd_p16v_free(emu10k1_t *chip)
+{
+ // release the data
+ if (chip->p16v_buffer.area) {
+ snd_dma_free_pages(&chip->p16v_buffer);
+ //snd_printk("period lables free: %p\n", &chip->p16v_buffer);
+ }
+ return 0;
+}
+
+static void snd_p16v_pcm_free(snd_pcm_t *pcm)
+{
+ emu10k1_t *emu = pcm->private_data;
+ //snd_printk("snd_p16v_pcm_free pcm: called\n");
+ snd_pcm_lib_preallocate_free_for_all(pcm);
+ emu->pcm = NULL;
+}
+
+int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
+{
+ snd_pcm_t *pcm;
+ snd_pcm_substream_t *substream;
+ int err;
+ int capture=0;
+
+ //snd_printk("snd_p16v_pcm called. device=%d\n", device);
+ emu->p16v_device_offset = device;
+ if (rpcm)
+ *rpcm = NULL;
+ //if (device == 0) capture=1;
+ if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0)
+ return err;
+
+ pcm->private_data = emu;
+ pcm->private_free = snd_p16v_pcm_free;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
+
+ pcm->info_flags = 0;
+ pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
+ strcpy(pcm->name, "p16v");
+ emu->pcm = pcm;
+
+ for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ substream;
+ substream = substream->next) {
+ if ((err = snd_pcm_lib_preallocate_pages(substream,
+ SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
+ return err;
+ //snd_printk("preallocate playback substream: err=%d\n", err);
+ }
+
+ for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+ substream;
+ substream = substream->next) {
+ if ((err = snd_pcm_lib_preallocate_pages(substream,
+ SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024)) < 0)
+ return err;
+ //snd_printk("preallocate capture substream: err=%d\n", err);
+ }
+
+ if (rpcm)
+ *rpcm = pcm;
+
+ return 0;
+}
+
+static int snd_p16v_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 255;
+ return 0;
+}
+
+static int snd_p16v_volume_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol, int reg, int high_low)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ u32 value;
+
+ value = snd_emu10k1_ptr20_read(emu, reg, high_low);
+ if (high_low == 1) {
+ ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
+ ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
+ } else {
+ ucontrol->value.integer.value[0] = 0xff - ((value >> 8) & 0xff); /* Left */
+ ucontrol->value.integer.value[1] = 0xff - ((value >> 0) & 0xff); /* Right */
+ }
+ return 0;
+}
+
+static int snd_p16v_volume_get_spdif_front(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 0;
+ int reg = PLAYBACK_VOLUME_MIXER7;
+ return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_get_spdif_center_lfe(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 1;
+ int reg = PLAYBACK_VOLUME_MIXER7;
+ return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
+}
+static int snd_p16v_volume_get_spdif_unknown(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 0;
+ int reg = PLAYBACK_VOLUME_MIXER8;
+ return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
+}
+static int snd_p16v_volume_get_spdif_rear(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 1;
+ int reg = PLAYBACK_VOLUME_MIXER8;
+ return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_get_analog_front(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 0;
+ int reg = PLAYBACK_VOLUME_MIXER9;
+ return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_get_analog_center_lfe(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 1;
+ int reg = PLAYBACK_VOLUME_MIXER9;
+ return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
+}
+static int snd_p16v_volume_get_analog_rear(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 1;
+ int reg = PLAYBACK_VOLUME_MIXER10;
+ return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_get_analog_unknown(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 0;
+ int reg = PLAYBACK_VOLUME_MIXER10;
+ return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol, int reg, int high_low)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ u32 value;
+ value = snd_emu10k1_ptr20_read(emu, reg, 0);
+ //value = value & 0xffff;
+ if (high_low == 1) {
+ value &= 0xffff;
+ value = value | ((0xff - ucontrol->value.integer.value[0]) << 24) | ((0xff - ucontrol->value.integer.value[1]) << 16);
+ } else {
+ value &= 0xffff0000;
+ value = value | ((0xff - ucontrol->value.integer.value[0]) << 8) | ((0xff - ucontrol->value.integer.value[1]) );
+ }
+ snd_emu10k1_ptr20_write(emu, reg, 0, value);
+ return 1;
+}
+
+static int snd_p16v_volume_put_spdif_front(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 0;
+ int reg = PLAYBACK_VOLUME_MIXER7;
+ return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_put_spdif_center_lfe(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 1;
+ int reg = PLAYBACK_VOLUME_MIXER7;
+ return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_put_spdif_unknown(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 0;
+ int reg = PLAYBACK_VOLUME_MIXER8;
+ return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_put_spdif_rear(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 1;
+ int reg = PLAYBACK_VOLUME_MIXER8;
+ return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_put_analog_front(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 0;
+ int reg = PLAYBACK_VOLUME_MIXER9;
+ return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_put_analog_center_lfe(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 1;
+ int reg = PLAYBACK_VOLUME_MIXER9;
+ return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_put_analog_rear(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 1;
+ int reg = PLAYBACK_VOLUME_MIXER10;
+ return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
+}
+
+static int snd_p16v_volume_put_analog_unknown(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ int high_low = 0;
+ int reg = PLAYBACK_VOLUME_MIXER10;
+ return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
+}
+
+static snd_kcontrol_new_t snd_p16v_volume_control_analog_front =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD Analog Front Volume",
+ .info = snd_p16v_volume_info,
+ .get = snd_p16v_volume_get_analog_front,
+ .put = snd_p16v_volume_put_analog_front
+};
+
+static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD Analog Center/LFE Volume",
+ .info = snd_p16v_volume_info,
+ .get = snd_p16v_volume_get_analog_center_lfe,
+ .put = snd_p16v_volume_put_analog_center_lfe
+};
+
+static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD Analog Unknown Volume",
+ .info = snd_p16v_volume_info,
+ .get = snd_p16v_volume_get_analog_unknown,
+ .put = snd_p16v_volume_put_analog_unknown
+};
+
+static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD Analog Rear Volume",
+ .info = snd_p16v_volume_info,
+ .get = snd_p16v_volume_get_analog_rear,
+ .put = snd_p16v_volume_put_analog_rear
+};
+
+static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD SPDIF Front Volume",
+ .info = snd_p16v_volume_info,
+ .get = snd_p16v_volume_get_spdif_front,
+ .put = snd_p16v_volume_put_spdif_front
+};
+
+static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD SPDIF Center/LFE Volume",
+ .info = snd_p16v_volume_info,
+ .get = snd_p16v_volume_get_spdif_center_lfe,
+ .put = snd_p16v_volume_put_spdif_center_lfe
+};
+
+static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD SPDIF Unknown Volume",
+ .info = snd_p16v_volume_info,
+ .get = snd_p16v_volume_get_spdif_unknown,
+ .put = snd_p16v_volume_put_spdif_unknown
+};
+
+static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD SPDIF Rear Volume",
+ .info = snd_p16v_volume_info,
+ .get = snd_p16v_volume_get_spdif_rear,
+ .put = snd_p16v_volume_put_spdif_rear
+};
+
+int snd_p16v_mixer(emu10k1_t *emu)
+{
+ int err;
+ snd_kcontrol_t *kctl;
+ snd_card_t *card = emu->card;
+ if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_front, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_rear, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_center_lfe, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_unknown, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_front, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_rear, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_center_lfe, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_unknown, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ return 0;
+}
+
diff --git a/sound/pci/emu10k1/p16v.h b/sound/pci/emu10k1/p16v.h
new file mode 100644
index 0000000000000..1532149403360
--- /dev/null
+++ b/sound/pci/emu10k1/p16v.h
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
+ * Driver p16v chips
+ * Version: 0.21
+ *
+ * FEATURES currently supported:
+ * Output fixed at S32_LE, 2 channel to hw:0,0
+ * Rates: 44.1, 48, 96, 192.
+ *
+ * Changelog:
+ * 0.8
+ * Use separate card based buffer for periods table.
+ * 0.9
+ * Use 2 channel output streams instead of 8 channel.
+ * (8 channel output streams might be good for ASIO type output)
+ * Corrected speaker output, so Front -> Front etc.
+ * 0.10
+ * Fixed missed interrupts.
+ * 0.11
+ * Add Sound card model number and names.
+ * Add Analog volume controls.
+ * 0.12
+ * Corrected playback interrupts. Now interrupt per period, instead of half period.
+ * 0.13
+ * Use single trigger for multichannel.
+ * 0.14
+ * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo.
+ * 0.15
+ * Force buffer_size / period_size == INTEGER.
+ * 0.16
+ * Update p16v.c to work with changed alsa api.
+ * 0.17
+ * Update p16v.c to work with changed alsa api. Removed boot_devs.
+ * 0.18
+ * Merging with snd-emu10k1 driver.
+ * 0.19
+ * One stereo channel at 24bit now works.
+ * 0.20
+ * Added better register defines.
+ * 0.21
+ * Split from p16v.c
+ *
+ *
+ * BUGS:
+ * Some stability problems when unloading the snd-p16v kernel module.
+ * --
+ *
+ * TODO:
+ * SPDIF out.
+ * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz.
+ * Currently capture fixed at 48000Hz.
+ *
+ * --
+ * GENERAL INFO:
+ * Model: SB0240
+ * P16V Chip: CA0151-DBS
+ * Audigy 2 Chip: CA0102-IAT
+ * AC97 Codec: STAC 9721
+ * ADC: Philips 1361T (Stereo 24bit)
+ * DAC: CS4382-K (8-channel, 24bit, 192Khz)
+ *
+ * This code was initally based on code from ALSA's emu10k1x.c which is:
+ * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/********************************************************************************************************/
+/* Audigy2 P16V pointer-offset register set, accessed through the PTR2 and DATA2 registers */
+/********************************************************************************************************/
+
+/* The sample rate of the SPDIF outputs is set by modifying a register in the EMU10K2 PTR register A_SPDIF_SAMPLERATE.
+ * The sample rate is also controlled by the same registers that control the rate of the EMU10K2 sample rate converters.
+ */
+
+/* Initally all registers from 0x00 to 0x3f have zero contents. */
+#define PLAYBACK_LIST_ADDR 0x00 /* Base DMA address of a list of pointers to each period/size */
+ /* One list entry: 4 bytes for DMA address,
+ * 4 bytes for period_size << 16.
+ * One list entry is 8 bytes long.
+ * One list entry for each period in the buffer.
+ */
+#define PLAYBACK_LIST_SIZE 0x01 /* Size of list in bytes << 16. E.g. 8 periods -> 0x00380000 */
+#define PLAYBACK_LIST_PTR 0x02 /* Pointer to the current period being played */
+#define PLAYBACK_UNKNOWN3 0x03 /* Not used */
+#define PLAYBACK_DMA_ADDR 0x04 /* Playback DMA addresss */
+#define PLAYBACK_PERIOD_SIZE 0x05 /* Playback period size. win2000 uses 0x04000000 */
+#define PLAYBACK_POINTER 0x06 /* Playback period pointer. Used with PLAYBACK_LIST_PTR to determine buffer position currently in DAC */
+#define PLAYBACK_FIFO_END_ADDRESS 0x07 /* Playback FIFO end address */
+#define PLAYBACK_FIFO_POINTER 0x08 /* Playback FIFO pointer and number of valid sound samples in cache */
+#define PLAYBACK_UNKNOWN9 0x09 /* Not used */
+#define CAPTURE_DMA_ADDR 0x10 /* Capture DMA address */
+#define CAPTURE_BUFFER_SIZE 0x11 /* Capture buffer size */
+#define CAPTURE_POINTER 0x12 /* Capture buffer pointer. Sample currently in ADC */
+#define CAPTURE_FIFO_POINTER 0x13 /* Capture FIFO pointer and number of valid sound samples in cache */
+#define CAPTURE_P16V_VOLUME1 0x14 /* Low: Capture volume 0xXXXX3030 */
+#define CAPTURE_P16V_VOLUME2 0x15 /* High:Has no effect on capture volume */
+#define CAPTURE_P16V_SOURCE 0x16 /* P16V source select. Set to 0x0700E4E5 for AC97 CAPTURE */
+ /* [0:1] Capture input 0 channel select. 0 = Capture output 0.
+ * 1 = Capture output 1.
+ * 2 = Capture output 2.
+ * 3 = Capture output 3.
+ * [3:2] Capture input 1 channel select. 0 = Capture output 0.
+ * 1 = Capture output 1.
+ * 2 = Capture output 2.
+ * 3 = Capture output 3.
+ * [5:4] Capture input 2 channel select. 0 = Capture output 0.
+ * 1 = Capture output 1.
+ * 2 = Capture output 2.
+ * 3 = Capture output 3.
+ * [7:6] Capture input 3 channel select. 0 = Capture output 0.
+ * 1 = Capture output 1.
+ * 2 = Capture output 2.
+ * 3 = Capture output 3.
+ * [9:8] Playback input 0 channel select. 0 = Play output 0.
+ * 1 = Play output 1.
+ * 2 = Play output 2.
+ * 3 = Play output 3.
+ * [11:10] Playback input 1 channel select. 0 = Play output 0.
+ * 1 = Play output 1.
+ * 2 = Play output 2.
+ * 3 = Play output 3.
+ * [13:12] Playback input 2 channel select. 0 = Play output 0.
+ * 1 = Play output 1.
+ * 2 = Play output 2.
+ * 3 = Play output 3.
+ * [15:14] Playback input 3 channel select. 0 = Play output 0.
+ * 1 = Play output 1.
+ * 2 = Play output 2.
+ * 3 = Play output 3.
+ * [19:16] Playback mixer output enable. 1 bit per channel.
+ * [23:20] Capture mixer output enable. 1 bit per channel.
+ * [26:24] FX engine channel capture 0 = 0x60-0x67.
+ * 1 = 0x68-0x6f.
+ * 2 = 0x70-0x77.
+ * 3 = 0x78-0x7f.
+ * 4 = 0x80-0x87.
+ * 5 = 0x88-0x8f.
+ * 6 = 0x90-0x97.
+ * 7 = 0x98-0x9f.
+ * [31:27] Not used.
+ */
+
+ /* 0x1 = capture on.
+ * 0x100 = capture off.
+ * 0x200 = capture off.
+ * 0x1000 = capture off.
+ */
+#define CAPTURE_RATE_STATUS 0x17 /* Capture sample rate. Read only */
+ /* [15:0] Not used.
+ * [18:16] Channel 0 Detected sample rate. 0 - 44.1khz
+ * 1 - 48 khz
+ * 2 - 96 khz
+ * 3 - 192 khz
+ * 7 - undefined rate.
+ * [19] Channel 0. 1 - Valid, 0 - Not Valid.
+ * [22:20] Channel 1 Detected sample rate.
+ * [23] Channel 1. 1 - Valid, 0 - Not Valid.
+ * [26:24] Channel 2 Detected sample rate.
+ * [27] Channel 2. 1 - Valid, 0 - Not Valid.
+ * [30:28] Channel 3 Detected sample rate.
+ * [31] Channel 3. 1 - Valid, 0 - Not Valid.
+ */
+/* 0x18 - 0x1f unused */
+#define PLAYBACK_LAST_SAMPLE 0x20 /* The sample currently being played. Read only */
+/* 0x21 - 0x3f unused */
+#define BASIC_INTERRUPT 0x40 /* Used by both playback and capture interrupt handler */
+ /* Playback (0x1<<channel_id) Don't touch high 16bits. */
+ /* Capture (0x100<<channel_id). not tested */
+ /* Start Playback [3:0] (one bit per channel)
+ * Start Capture [11:8] (one bit per channel)
+ * Record source select for channel 0 [18:16]
+ * Record source select for channel 1 [22:20]
+ * Record source select for channel 2 [26:24]
+ * Record source select for channel 3 [30:28]
+ * 0 - SPDIF channel.
+ * 1 - I2S channel.
+ * 2 - SRC48 channel.
+ * 3 - SRCMulti_SPDIF channel.
+ * 4 - SRCMulti_I2S channel.
+ * 5 - SPDIF channel.
+ * 6 - fxengine capture.
+ * 7 - AC97 capture.
+ */
+ /* Default 41110000.
+ * Writing 0xffffffff hangs the PC.
+ * Writing 0xffff0000 -> 77770000 so it must be some sort of route.
+ * bit 0x1 starts DMA playback on channel_id 0
+ */
+/* 0x41,42 take values from 0 - 0xffffffff, but have no effect on playback */
+/* 0x43,0x48 do not remember settings */
+/* 0x41-45 unused */
+#define WATERMARK 0x46 /* Test bit to indicate cache level usage */
+ /* Values it can have while playing on channel 0.
+ * 0000f000, 0000f004, 0000f008, 0000f00c.
+ * Readonly.
+ */
+/* 0x47-0x4f unused */
+/* 0x50-0x5f Capture cache data */
+#define SRCSel 0x60 /* SRCSel. Default 0x4. Bypass P16V 0x14 */
+ /* [0] 0 = 10K2 audio, 1 = SRC48 mixer output.
+ * [2] 0 = 10K2 audio, 1 = SRCMulti SPDIF mixer output.
+ * [4] 0 = 10K2 audio, 1 = SRCMulti I2S mixer output.
+ */
+ /* SRC48 converts samples rates 44.1, 48, 96, 192 to 48 khz. */
+ /* SRCMulti converts 48khz samples rates to 44.1, 48, 96, 192 to 48. */
+ /* SRC48 and SRCMULTI sample rate select and output select. */
+ /* 0xffffffff -> 0xC0000015
+ * 0xXXXXXXX4 = Enable Front Left/Right
+ * Enable PCMs
+ */
+
+/* 0x61 -> 0x6c are Volume controls */
+#define PLAYBACK_VOLUME_MIXER1 0x61 /* SRC48 Low to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER2 0x62 /* SRC48 High to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER3 0x63 /* SRCMULTI SPDIF Low to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER4 0x64 /* SRCMULTI SPDIF High to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER5 0x65 /* SRCMULTI I2S Low to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER6 0x66 /* SRCMULTI I2S High to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER7 0x67 /* P16V Low to SRCMULTI SPDIF mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER8 0x68 /* P16V High to SRCMULTI SPDIF mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER9 0x69 /* P16V Low to SRCMULTI I2S mixer input volume control. */
+ /* 0xXXXX3030 = PCM0 Volume (Front).
+ * 0x3030XXXX = PCM1 Volume (Center)
+ */
+#define PLAYBACK_VOLUME_MIXER10 0x6a /* P16V High to SRCMULTI I2S mixer input volume control. */
+ /* 0x3030XXXX = PCM3 Volume (Rear). */
+#define PLAYBACK_VOLUME_MIXER11 0x6b /* E10K2 Low to SRC48 mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER12 0x6c /* E10K2 High to SRC48 mixer input volume control. */
+
+#define SRC48_ENABLE 0x6d /* SRC48 input audio enable */
+ /* SRC48 converts samples rates 44.1, 48, 96, 192 to 48 khz. */
+ /* [23:16] The corresponding P16V channel to SRC48 enabled if == 1.
+ * [31:24] The corresponding E10K2 channel to SRC48 enabled.
+ */
+#define SRCMULTI_ENABLE 0x6e /* SRCMulti input audio enable. Default 0xffffffff */
+ /* SRCMulti converts 48khz samples rates to 44.1, 48, 96, 192 to 48. */
+ /* [7:0] The corresponding P16V channel to SRCMulti_I2S enabled if == 1.
+ * [15:8] The corresponding E10K2 channel to SRCMulti I2S enabled.
+ * [23:16] The corresponding P16V channel to SRCMulti SPDIF enabled.
+ * [31:24] The corresponding E10K2 channel to SRCMulti SPDIF enabled.
+ */
+ /* Bypass P16V 0xff00ff00
+ * Bitmap. 0 = Off, 1 = On.
+ * P16V playback outputs:
+ * 0xXXXXXXX1 = PCM0 Left. (Front)
+ * 0xXXXXXXX2 = PCM0 Right.
+ * 0xXXXXXXX4 = PCM1 Left. (Center/LFE)
+ * 0xXXXXXXX8 = PCM1 Right.
+ * 0xXXXXXX1X = PCM2 Left. (Unknown)
+ * 0xXXXXXX2X = PCM2 Right.
+ * 0xXXXXXX4X = PCM3 Left. (Rear)
+ * 0xXXXXXX8X = PCM3 Right.
+ */
+#define AUDIO_OUT_ENABLE 0x6f /* Default: 000100FF */
+ /* [3:0] Does something, but not documented. Probably capture enable.
+ * [7:4] Playback channels enable. not documented.
+ * [16] AC97 output enable if == 1
+ * [30] 0 = SRCMulti_I2S input from fxengine 0x68-0x6f.
+ * 1 = SRCMulti_I2S input from SRC48 output.
+ * [31] 0 = SRCMulti_SPDIF input from fxengine 0x60-0x67.
+ * 1 = SRCMulti_SPDIF input from SRC48 output.
+ */
+ /* 0xffffffff -> C00100FF */
+ /* 0 -> Not playback sound, irq still running */
+ /* 0xXXXXXX10 = PCM0 Left/Right On. (Front)
+ * 0xXXXXXX20 = PCM1 Left/Right On. (Center/LFE)
+ * 0xXXXXXX40 = PCM2 Left/Right On. (Unknown)
+ * 0xXXXXXX80 = PCM3 Left/Right On. (Rear)
+ */
+#define PLAYBACK_SPDIF_SELECT 0x70 /* Default: 12030F00 */
+ /* 0xffffffff -> 3FF30FFF */
+ /* 0x00000001 pauses stream/irq fail. */
+ /* All other bits do not effect playback */
+#define PLAYBACK_SPDIF_SRC_SELECT 0x71 /* Default: 0000E4E4 */
+ /* 0xffffffff -> F33FFFFF */
+ /* All bits do not effect playback */
+#define PLAYBACK_SPDIF_USER_DATA0 0x72 /* SPDIF out user data 0 */
+#define PLAYBACK_SPDIF_USER_DATA1 0x73 /* SPDIF out user data 1 */
+/* 0x74-0x75 unknown */
+#define CAPTURE_SPDIF_CONTROL 0x76 /* SPDIF in control setting */
+#define CAPTURE_SPDIF_STATUS 0x77 /* SPDIF in status */
+#define CAPURE_SPDIF_USER_DATA0 0x78 /* SPDIF in user data 0 */
+#define CAPURE_SPDIF_USER_DATA1 0x79 /* SPDIF in user data 1 */
+#define CAPURE_SPDIF_USER_DATA2 0x7a /* SPDIF in user data 2 */
+
diff --git a/sound/pci/emu10k1/timer.c b/sound/pci/emu10k1/timer.c
index c9c421a647436..d2e364607c1dc 100644
--- a/sound/pci/emu10k1/timer.c
+++ b/sound/pci/emu10k1/timer.c
@@ -1,10 +1,8 @@
/*
* Copyright (c) by Lee Revell <rlrevell@joe-job.com>
- *
+ * Clemens Ladisch <clemens@ladisch.de>
* Routines for control of EMU10K1 chips
*
- * Copied from similar code by Clemens Ladisch in the ymfpci driver
- *
* BUGS:
* --
*
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
index e4704b3de87db..d251d3440eecc 100644
--- a/sound/pci/emu10k1/voice.c
+++ b/sound/pci/emu10k1/voice.c
@@ -62,15 +62,13 @@ static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, em
continue;
}
- /* make sure the block of voices does not cross the 32 voice boundary */
- //if (((i % 32) + number) > 32)
- // continue;
-
skip = 0;
for (k = 0; k < number; k++) {
voice = &emu->voices[(i+k) % NUM_G];
- if (voice->use)
+ if (voice->use) {
skip = 1;
+ break;
+ }
}
if (!skip) {
// printk("allocated voice %d\n", i);
@@ -81,12 +79,8 @@ static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, em
}
}
- if (first_voice == last_voice) {
- printk("BUG (or not enough voices), number %d, next free %d!\n",
- number,
- emu->next_free_voice);
+ if (first_voice == last_voice)
return -ENOMEM;
- }
for (i=0; i < number; i++) {
voice = &emu->voices[(first_voice + i) % NUM_G];
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index fe0410469a0a7..f910399db5c39 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -754,8 +754,6 @@ static void snd_es1371_dac2_rate(ensoniq_t * ensoniq, unsigned int rate)
static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
{
- unsigned long flags;
-
ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -775,13 +773,13 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
} else if (s == ensoniq->capture_substream)
return -EINVAL;
}
- spin_lock_irqsave(&ensoniq->reg_lock, flags);
+ spin_lock(&ensoniq->reg_lock);
if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)
ensoniq->sctrl |= what;
else
ensoniq->sctrl &= ~what;
outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
- spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+ spin_unlock(&ensoniq->reg_lock);
break;
}
case SNDRV_PCM_TRIGGER_START:
@@ -803,13 +801,13 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
snd_pcm_trigger_done(s, substream);
}
}
- spin_lock_irqsave(&ensoniq->reg_lock, flags);
+ spin_lock(&ensoniq->reg_lock);
if (cmd == SNDRV_PCM_TRIGGER_START)
ensoniq->ctrl |= what;
else
ensoniq->ctrl &= ~what;
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
- spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+ spin_unlock(&ensoniq->reg_lock);
break;
}
default:
@@ -958,11 +956,10 @@ static int snd_ensoniq_capture_prepare(snd_pcm_substream_t * substream)
static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(snd_pcm_substream_t * substream)
{
- unsigned long flags;
ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
size_t ptr;
- spin_lock_irqsave(&ensoniq->reg_lock, flags);
+ spin_lock(&ensoniq->reg_lock);
if (inl(ES_REG(ensoniq, CONTROL)) & ES_DAC1_EN) {
outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, DAC1_SIZE)));
@@ -970,17 +967,16 @@ static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(snd_pcm_substream_t * sub
} else {
ptr = 0;
}
- spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+ spin_unlock(&ensoniq->reg_lock);
return ptr;
}
static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(snd_pcm_substream_t * substream)
{
- unsigned long flags;
ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
size_t ptr;
- spin_lock_irqsave(&ensoniq->reg_lock, flags);
+ spin_lock(&ensoniq->reg_lock);
if (inl(ES_REG(ensoniq, CONTROL)) & ES_DAC2_EN) {
outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, DAC2_SIZE)));
@@ -988,17 +984,16 @@ static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(snd_pcm_substream_t * sub
} else {
ptr = 0;
}
- spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+ spin_unlock(&ensoniq->reg_lock);
return ptr;
}
static snd_pcm_uframes_t snd_ensoniq_capture_pointer(snd_pcm_substream_t * substream)
{
- unsigned long flags;
ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
size_t ptr;
- spin_lock_irqsave(&ensoniq->reg_lock, flags);
+ spin_lock(&ensoniq->reg_lock);
if (inl(ES_REG(ensoniq, CONTROL)) & ES_ADC_EN) {
outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, ADC_SIZE)));
@@ -1006,7 +1001,7 @@ static snd_pcm_uframes_t snd_ensoniq_capture_pointer(snd_pcm_substream_t * subst
} else {
ptr = 0;
}
- spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+ spin_unlock(&ensoniq->reg_lock);
return ptr;
}
@@ -1802,7 +1797,7 @@ static int __devinit snd_ensoniq_create_gameport(ensoniq_t *ensoniq, int dev)
gameport_set_name(gp, "ES137x");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(ensoniq->pci));
- gp->dev.parent = &ensoniq->pci->dev;
+ gameport_set_dev_parent(gp, &ensoniq->pci->dev);
gp->io = io_port;
ensoniq->ctrl |= ES_JYSTK_EN;
@@ -2088,14 +2083,13 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq)
{
- unsigned long flags;
snd_rawmidi_t * rmidi = ensoniq->rmidi;
unsigned char status, mask, byte;
if (rmidi == NULL)
return;
/* do Rx at first */
- spin_lock_irqsave(&ensoniq->reg_lock, flags);
+ spin_lock(&ensoniq->reg_lock);
mask = ensoniq->uartm & ES_MODE_INPUT ? ES_RXRDY : 0;
while (mask) {
status = inb(ES_REG(ensoniq, UART_STATUS));
@@ -2104,10 +2098,10 @@ static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq)
byte = inb(ES_REG(ensoniq, UART_DATA));
snd_rawmidi_receive(ensoniq->midi_input, &byte, 1);
}
- spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+ spin_unlock(&ensoniq->reg_lock);
/* do Tx at second */
- spin_lock_irqsave(&ensoniq->reg_lock, flags);
+ spin_lock(&ensoniq->reg_lock);
mask = ensoniq->uartm & ES_MODE_OUTPUT ? ES_TXRDY : 0;
while (mask) {
status = inb(ES_REG(ensoniq, UART_STATUS));
@@ -2121,7 +2115,7 @@ static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq)
outb(byte, ES_REG(ensoniq, UART_DATA));
}
}
- spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+ spin_unlock(&ensoniq->reg_lock);
}
static int snd_ensoniq_midi_input_open(snd_rawmidi_substream_t * substream)
@@ -2288,7 +2282,6 @@ static int __devinit snd_ensoniq_midi(ensoniq_t * ensoniq, int device, snd_rawmi
static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- unsigned long flags;
ensoniq_t *ensoniq = dev_id;
unsigned int status, sctrl;
@@ -2299,7 +2292,7 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs
if (!(status & ES_INTR))
return IRQ_NONE;
- spin_lock_irqsave(&ensoniq->reg_lock, flags);
+ spin_lock(&ensoniq->reg_lock);
sctrl = ensoniq->sctrl;
if (status & ES_DAC1)
sctrl &= ~ES_P1_INT_EN;
@@ -2309,7 +2302,7 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs
sctrl &= ~ES_R1_INT_EN;
outl(sctrl, ES_REG(ensoniq, SERIAL));
outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
- spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+ spin_unlock(&ensoniq->reg_lock);
if (status & ES_UART)
snd_ensoniq_midi_interrupt(ensoniq);
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 5ee27ac7df616..b4ca8adf393c6 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1435,7 +1435,7 @@ static int __devinit snd_es1938_create_gameport(es1938_t *chip)
gameport_set_name(gp, "ES1938");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
- gp->dev.parent = &chip->pci->dev;
+ gameport_set_dev_parent(gp, &chip->pci->dev);
gp->io = chip->game_port;
gameport_register_port(gp);
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 2cc087f3f418b..faf63ff19c42a 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -586,6 +586,7 @@ struct snd_es1968 {
spinlock_t reg_lock;
spinlock_t ac97_lock;
struct tasklet_struct hwvol_tq;
+ unsigned int in_suspend;
/* Maestro Stuff */
u16 maestro_map[32];
@@ -1937,6 +1938,9 @@ static void es1968_update_hw_volume(unsigned long private_data)
outb(0x88, chip->io_port + 0x1e);
outb(0x88, chip->io_port + 0x1f);
+ if (chip->in_suspend)
+ return;
+
if (! chip->master_switch || ! chip->master_volume)
return;
@@ -2410,6 +2414,7 @@ static int es1968_suspend(snd_card_t *card, pm_message_t state)
if (! chip->do_pm)
return 0;
+ chip->in_suspend = 1;
snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
snd_es1968_bob_stop(chip);
@@ -2421,6 +2426,7 @@ static int es1968_suspend(snd_card_t *card, pm_message_t state)
static int es1968_resume(snd_card_t *card)
{
es1968_t *chip = card->pm_private_data;
+ struct list_head *p;
if (! chip->do_pm)
return 0;
@@ -2441,10 +2447,23 @@ static int es1968_resume(snd_card_t *card)
/* restore ac97 state */
snd_ac97_resume(chip->ac97);
+ list_for_each(p, &chip->substream_list) {
+ esschan_t *es = list_entry(p, esschan_t, list);
+ switch (es->mode) {
+ case ESM_MODE_PLAY:
+ snd_es1968_playback_setup(chip, es, es->substream->runtime);
+ break;
+ case ESM_MODE_CAPTURE:
+ snd_es1968_capture_setup(chip, es, es->substream->runtime);
+ break;
+ }
+ }
+
/* start timer again */
if (chip->bobclient)
snd_es1968_bob_start(chip);
+ chip->in_suspend = 0;
return 0;
}
#endif /* CONFIG_PM */
@@ -2477,8 +2496,9 @@ static int __devinit snd_es1968_create_gameport(es1968_t *chip, int dev)
gameport_set_name(gp, "ES1968 Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
- gp->dev.parent = &chip->pci->dev;
+ gameport_set_dev_parent(gp, &chip->pci->dev);
gp->io = JOYSTICK_ADDR;
+ gameport_set_port_data(gp, r);
gameport_register_port(gp);
@@ -2488,7 +2508,7 @@ static int __devinit snd_es1968_create_gameport(es1968_t *chip, int dev)
static void snd_es1968_free_gameport(es1968_t *chip)
{
if (chip->gameport) {
- struct resource *r = chip->gameport->port_data;
+ struct resource *r = gameport_get_port_data(chip->gameport);
gameport_unregister_port(chip->gameport);
chip->gameport = NULL;
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 99f45314262a9..570a59d33b419 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,5 +1,5 @@
snd-hda-intel-objs := hda_intel.o
-snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o
+snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o
ifdef CONFIG_PROC_FS
snd-hda-codec-objs += hda_proc.o
endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index ccd8fd9eba511..9ed117ac0c090 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -49,6 +49,7 @@ struct hda_vendor_id {
/* codec vendor labels */
static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x10ec, "Realtek" },
+ { 0x13f6, "C-Media" },
{ 0x434d, "C-Media" },
{} /* terminator */
};
@@ -610,6 +611,8 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
if (! info)
return 0;
if (! (info->status & INFO_AMP_CAPS)) {
+ if (!(snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_AMP_OVRD))
+ nid = codec->afg;
info->amp_caps = snd_hda_param_read(codec, nid, direction == HDA_OUTPUT ?
AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
info->status |= INFO_AMP_CAPS;
@@ -954,6 +957,9 @@ static int snd_hda_spdif_out_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
if (change || codec->in_resume) {
codec->spdif_ctls = val;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT |
+ AC_AMP_SET_OUTPUT | ((val & 1) ? 0 : 0x80));
}
up(&codec->spdif_mutex);
return change;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 7cd7dd0885537..69f7b6c4cf83a 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -617,6 +617,7 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
char name[32];
int err;
int created = 0;
+ snd_kcontrol_new_t knew;
if (type)
sprintf(name, "%s %s Switch", type, dir_sfx);
@@ -624,16 +625,14 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
sprintf(name, "%s Switch", dir_sfx);
if ((node->wid_caps & AC_WCAP_IN_AMP) &&
(node->amp_in_caps & AC_AMPCAP_MUTE)) {
- snd_kcontrol_new_t knew =
- HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT);
+ knew = (snd_kcontrol_new_t)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
created = 1;
} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
(node->amp_out_caps & AC_AMPCAP_MUTE)) {
- snd_kcontrol_new_t knew =
- HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT);
+ knew = (snd_kcontrol_new_t)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
@@ -646,16 +645,14 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
sprintf(name, "%s Volume", dir_sfx);
if ((node->wid_caps & AC_WCAP_IN_AMP) &&
(node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) {
- snd_kcontrol_new_t knew =
- HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT);
+ knew = (snd_kcontrol_new_t)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
created = 1;
} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
(node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) {
- snd_kcontrol_new_t knew =
- HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT);
+ knew = (snd_kcontrol_new_t)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index 66c39ce37a812..cf6abce42bc9e 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -6,9 +6,12 @@
extern struct hda_codec_preset snd_hda_preset_realtek[];
/* C-Media codecs */
extern struct hda_codec_preset snd_hda_preset_cmedia[];
+/* Analog Devices codecs */
+extern struct hda_codec_preset snd_hda_preset_analog[];
static const struct hda_codec_preset *hda_preset_tables[] = {
snd_hda_preset_realtek,
snd_hda_preset_cmedia,
+ snd_hda_preset_analog,
NULL
};
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
new file mode 100644
index 0000000000000..75d23849f71ac
--- /dev/null
+++ b/sound/pci/hda/patch_analog.c
@@ -0,0 +1,445 @@
+/*
+ * HD audio interface patch for AD1986A
+ *
+ * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+struct ad1986a_spec {
+ struct semaphore amp_mutex; /* PCM volume/mute control mutex */
+ struct hda_multi_out multiout; /* playback */
+ unsigned int cur_mux; /* capture source */
+ struct hda_pcm pcm_rec[2]; /* PCM information */
+};
+
+#define AD1986A_SPDIF_OUT 0x02
+#define AD1986A_FRONT_DAC 0x03
+#define AD1986A_SURR_DAC 0x04
+#define AD1986A_CLFE_DAC 0x05
+#define AD1986A_ADC 0x06
+
+static hda_nid_t ad1986a_dac_nids[3] = {
+ AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
+};
+
+static struct hda_input_mux ad1986a_capture_source = {
+ .num_items = 7,
+ .items = {
+ { "Mic", 0x0 },
+ { "CD", 0x1 },
+ { "Aux", 0x3 },
+ { "Line", 0x4 },
+ { "Mix", 0x5 },
+ { "Mono", 0x6 },
+ { "Phone", 0x7 },
+ },
+};
+
+/*
+ * PCM control
+ *
+ * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
+ */
+
+#define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info
+
+static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *ad = codec->spec;
+
+ down(&ad->amp_mutex);
+ snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
+ up(&ad->amp_mutex);
+ return 0;
+}
+
+static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *ad = codec->spec;
+ int i, change = 0;
+
+ down(&ad->amp_mutex);
+ for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
+ change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
+ }
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
+ up(&ad->amp_mutex);
+ return change;
+}
+
+#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_volume_info
+
+static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *ad = codec->spec;
+
+ down(&ad->amp_mutex);
+ snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
+ up(&ad->amp_mutex);
+ return 0;
+}
+
+static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *ad = codec->spec;
+ int i, change = 0;
+
+ down(&ad->amp_mutex);
+ for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
+ change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+ }
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
+ up(&ad->amp_mutex);
+ return change;
+}
+
+/*
+ * input MUX handling
+ */
+static int ad1986a_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ return snd_hda_input_mux_info(&ad1986a_capture_source, uinfo);
+}
+
+static int ad1986a_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *spec = codec->spec;
+
+ ucontrol->value.enumerated.item[0] = spec->cur_mux;
+ return 0;
+}
+
+static int ad1986a_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *spec = codec->spec;
+
+ return snd_hda_input_mux_put(codec, &ad1986a_capture_source, ucontrol,
+ AD1986A_ADC, &spec->cur_mux);
+}
+
+/*
+ * mixers
+ */
+static snd_kcontrol_new_t ad1986a_mixers[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Volume",
+ .info = ad1986a_pcm_amp_vol_info,
+ .get = ad1986a_pcm_amp_vol_get,
+ .put = ad1986a_pcm_amp_vol_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Switch",
+ .info = ad1986a_pcm_amp_sw_info,
+ .get = ad1986a_pcm_amp_sw_get,
+ .put = ad1986a_pcm_amp_sw_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
+ },
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = ad1986a_mux_enum_info,
+ .get = ad1986a_mux_enum_get,
+ .put = ad1986a_mux_enum_put,
+ },
+ HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
+ { } /* end */
+};
+
+/*
+ * initialization verbs
+ */
+static struct hda_verb ad1986a_init_verbs[] = {
+ /* Front, Surround, CLFE DAC; mute as default */
+ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* Downmix - off */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* HP, Line-Out, Surround, CLFE selectors */
+ {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
+ {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
+ {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
+ {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Mono selector */
+ {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Mic selector: Mic 1/2 pin */
+ {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Line-in selector: Line-in */
+ {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Mic 1/2 swap */
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Record selector: mic */
+ {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
+ {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* PC beep */
+ {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ { } /* end */
+};
+
+
+static int ad1986a_init(struct hda_codec *codec)
+{
+ snd_hda_sequence_write(codec, ad1986a_init_verbs);
+ return 0;
+}
+
+static int ad1986a_build_controls(struct hda_codec *codec)
+{
+ int err;
+
+ err = snd_hda_add_new_ctls(codec, ad1986a_mixers);
+ if (err < 0)
+ return err;
+ err = snd_hda_create_spdif_out_ctls(codec, AD1986A_SPDIF_OUT);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+/*
+ * Analog playback callbacks
+ */
+static int ad1986a_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int ad1986a_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+ format, substream);
+}
+
+static int ad1986a_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int ad1986a_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int ad1986a_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+static int ad1986a_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
+{
+ snd_hda_codec_setup_stream(codec, AD1986A_ADC, stream_tag, 0, format);
+ return 0;
+}
+
+static int ad1986a_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ snd_hda_codec_setup_stream(codec, AD1986A_ADC, 0, 0, 0);
+ return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream ad1986a_pcm_analog_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 6,
+ .nid = AD1986A_FRONT_DAC, /* NID to query formats and rates */
+ .ops = {
+ .open = ad1986a_playback_pcm_open,
+ .prepare = ad1986a_playback_pcm_prepare,
+ .cleanup = ad1986a_playback_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream ad1986a_pcm_analog_capture = {
+ .substreams = 2,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = AD1986A_ADC, /* NID to query formats and rates */
+ .ops = {
+ .prepare = ad1986a_capture_pcm_prepare,
+ .cleanup = ad1986a_capture_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream ad1986a_pcm_digital_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = AD1986A_SPDIF_OUT,
+ .ops = {
+ .open = ad1986a_dig_playback_pcm_open,
+ .close = ad1986a_dig_playback_pcm_close
+ },
+};
+
+static int ad1986a_build_pcms(struct hda_codec *codec)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
+
+ codec->num_pcms = 2;
+ codec->pcm_info = info;
+
+ info->name = "AD1986A Analog";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_analog_playback;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1986a_pcm_analog_capture;
+ info++;
+
+ info->name = "AD1986A Digital";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_digital_playback;
+
+ return 0;
+}
+
+static void ad1986a_free(struct hda_codec *codec)
+{
+ kfree(codec->spec);
+}
+
+#ifdef CONFIG_PM
+static int ad1986a_resume(struct hda_codec *codec)
+{
+ ad1986a_init(codec);
+ snd_hda_resume_ctls(codec, ad1986a_mixers);
+ snd_hda_resume_spdif_out(codec);
+ return 0;
+}
+#endif
+
+static struct hda_codec_ops ad1986a_patch_ops = {
+ .build_controls = ad1986a_build_controls,
+ .build_pcms = ad1986a_build_pcms,
+ .init = ad1986a_init,
+ .free = ad1986a_free,
+#ifdef CONFIG_PM
+ .resume = ad1986a_resume,
+#endif
+};
+
+static int patch_ad1986a(struct hda_codec *codec)
+{
+ struct ad1986a_spec *spec;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ init_MUTEX(&spec->amp_mutex);
+ codec->spec = spec;
+
+ spec->multiout.max_channels = 6;
+ spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
+ spec->multiout.dac_nids = ad1986a_dac_nids;
+ spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
+
+ codec->patch_ops = ad1986a_patch_ops;
+
+ return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_analog[] = {
+ { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
+ {} /* terminator */
+};
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 6e0ae05c85c96..b7cc8e4bffb7f 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -112,9 +112,9 @@ static struct hda_verb cmi9880_ch2_init[] = {
/* 3-stack / 6 channel */
static struct hda_verb cmi9880_ch6_init[] = {
- /* set line-in PIN for input */
+ /* set line-in PIN for output */
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* set mic PIN for input, also enable vref */
+ /* set mic PIN for output */
{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
/* route front PCM (DAC1) to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
@@ -123,9 +123,9 @@ static struct hda_verb cmi9880_ch6_init[] = {
/* 3-stack+front / 8 channel */
static struct hda_verb cmi9880_ch8_init[] = {
- /* set line-in PIN for input */
+ /* set line-in PIN for output */
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* set mic PIN for input, also enable vref */
+ /* set mic PIN for output */
{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
/* route rear-surround PCM (DAC4) to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
@@ -565,7 +565,7 @@ static int patch_cmi9880(struct hda_codec *codec)
spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl);
if (spec->board_config < 0) {
snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
- spec->board_config = CMI_MINIMAL;
+ spec->board_config = CMI_FULL_DIG; /* try everything */
}
switch (spec->board_config) {
@@ -615,6 +615,7 @@ static int patch_cmi9880(struct hda_codec *codec)
* patch entries
*/
struct hda_codec_preset snd_hda_preset_cmedia[] = {
+ { .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 },
{ .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 },
{} /* terminator */
};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 6495a0babd0e0..17c5062423aee 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1133,6 +1133,8 @@ snd_kcontrol_new_t alc260_base_mixer[] = {
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
{
@@ -1162,6 +1164,8 @@ static struct hda_verb alc260_init_verbs[] = {
{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
/* enable HP */
{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* enable Mono */
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
/* unmute amp left and right */
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
/* set connection select to line in (default select for this ADC) */
@@ -1174,6 +1178,10 @@ static struct hda_verb alc260_init_verbs[] = {
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
/* mute pin widget amp left and right (no gain on this amp) */
{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* unmute Mono mixer amp left and right (volume = 0) */
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
/* mute LINE-2 out */
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
@@ -1190,6 +1198,9 @@ static struct hda_verb alc260_init_verbs[] = {
/* Unmute Headphone out path */
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Mono out path */
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
{ }
};
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index dd9047c50e609..65bb0f47af2c1 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1062,7 +1062,7 @@ static int snd_mixart_free(mixart_mgr_t *mgr)
free_irq(mgr->irq, (void *)mgr);
/* reset board if some firmware was loaded */
- if(mgr->hwdep->dsp_loaded) {
+ if(mgr->dsp_loaded) {
snd_mixart_reset_board(mgr);
snd_printdd("reset miXart !\n");
}
@@ -1203,7 +1203,7 @@ static void snd_mixart_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx);
/* stats available when embedded OS is running */
- if (chip->mgr->hwdep->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) {
+ if (chip->mgr->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) {
snd_iprintf(buffer, "- hardware -\n");
switch (chip->mgr->board_type ) {
case MIXART_DAUGHTER_TYPE_NONE : snd_iprintf(buffer, "\tmiXart8 (no daughter board)\n\n"); break;
@@ -1381,7 +1381,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
}
}
- /* init firmware status (mgr->hwdep->dsp_loaded reset in hwdep_new) */
+ /* init firmware status (mgr->dsp_loaded reset in hwdep_new) */
mgr->board_type = MIXART_DAUGHTER_TYPE_NONE;
/* create array of streaminfo */
diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h
index 4cde2638bd4e9..f87152f94c0e9 100644
--- a/sound/pci/mixart/mixart.h
+++ b/sound/pci/mixart/mixart.h
@@ -112,7 +112,7 @@ struct snd_mixart_mgr {
struct semaphore setup_mutex; /* mutex used in hw_params, open and close */
/* hardware interface */
- snd_hwdep_t *hwdep;
+ unsigned int dsp_loaded; /* bit flags of loaded dsp indices */
unsigned int board_type; /* read from embedded once elf file is loaded, 250 = miXart8, 251 = with AES, 252 = with Cobranet */
struct snd_dma_buffer flowinfo;
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index 0da472b7dc722..edd1599fe45e7 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -142,26 +142,35 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
u32 k;
int err;
mixart_msg_t request;
- mixart_enum_connector_resp_t connector;
- mixart_audio_info_req_t audio_info_req;
- mixart_audio_info_resp_t audio_info;
+ mixart_enum_connector_resp_t *connector;
+ mixart_audio_info_req_t *audio_info_req;
+ mixart_audio_info_resp_t *audio_info;
+
+ connector = kmalloc(sizeof(*connector), GFP_KERNEL);
+ audio_info_req = kmalloc(sizeof(*audio_info_req), GFP_KERNEL);
+ audio_info = kmalloc(sizeof(*audio_info), GFP_KERNEL);
+ if (! connector || ! audio_info_req || ! audio_info) {
+ err = -ENOMEM;
+ goto __error;
+ }
- audio_info_req.line_max_level = MIXART_FLOAT_P_22_0_TO_HEX;
- audio_info_req.micro_max_level = MIXART_FLOAT_M_20_0_TO_HEX;
- audio_info_req.cd_max_level = MIXART_FLOAT____0_0_TO_HEX;
+ audio_info_req->line_max_level = MIXART_FLOAT_P_22_0_TO_HEX;
+ audio_info_req->micro_max_level = MIXART_FLOAT_M_20_0_TO_HEX;
+ audio_info_req->cd_max_level = MIXART_FLOAT____0_0_TO_HEX;
request.message_id = MSG_SYSTEM_ENUM_PLAY_CONNECTOR;
request.uid = (mixart_uid_t){0,0}; /* board num = 0 */
request.data = NULL;
request.size = 0;
- err = snd_mixart_send_msg(mgr, &request, sizeof(connector), &connector);
- if((err < 0) || (connector.error_code) || (connector.uid_count > MIXART_MAX_PHYS_CONNECTORS)) {
+ err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector);
+ if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) {
snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PLAY_CONNECTOR\n");
- return -EINVAL;
+ err = -EINVAL;
+ goto __error;
}
- for(k=0; k < connector.uid_count; k++) {
+ for(k=0; k < connector->uid_count; k++) {
mixart_pipe_t* pipe;
if(k < MIXART_FIRST_DIG_AUDIO_ID) {
@@ -170,25 +179,25 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_out_dig;
}
if(k & 1) {
- pipe->uid_right_connector = connector.uid[k]; /* odd */
+ pipe->uid_right_connector = connector->uid[k]; /* odd */
} else {
- pipe->uid_left_connector = connector.uid[k]; /* even */
+ pipe->uid_left_connector = connector->uid[k]; /* even */
}
- /* snd_printk(KERN_DEBUG "playback connector[%d].object_id = %x\n", k, connector.uid[k].object_id); */
+ /* snd_printk(KERN_DEBUG "playback connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */
/* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */
request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO;
- request.uid = connector.uid[k];
- request.data = &audio_info_req;
- request.size = sizeof(audio_info_req);
+ request.uid = connector->uid[k];
+ request.data = audio_info_req;
+ request.size = sizeof(*audio_info_req);
- err = snd_mixart_send_msg(mgr, &request, sizeof(audio_info), &audio_info);
+ err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info);
if( err < 0 ) {
snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n");
- return err;
+ goto __error;
}
- /*snd_printk(KERN_DEBUG "play analog_info.analog_level_present = %x\n", audio_info.info.analog_info.analog_level_present);*/
+ /*snd_printk(KERN_DEBUG "play analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/
}
request.message_id = MSG_SYSTEM_ENUM_RECORD_CONNECTOR;
@@ -196,13 +205,14 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
request.data = NULL;
request.size = 0;
- err = snd_mixart_send_msg(mgr, &request, sizeof(connector), &connector);
- if((err < 0) || (connector.error_code) || (connector.uid_count > MIXART_MAX_PHYS_CONNECTORS)) {
+ err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector);
+ if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) {
snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_RECORD_CONNECTOR\n");
- return -EINVAL;
+ err = -EINVAL;
+ goto __error;
}
- for(k=0; k < connector.uid_count; k++) {
+ for(k=0; k < connector->uid_count; k++) {
mixart_pipe_t* pipe;
if(k < MIXART_FIRST_DIG_AUDIO_ID) {
@@ -211,28 +221,34 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_in_dig;
}
if(k & 1) {
- pipe->uid_right_connector = connector.uid[k]; /* odd */
+ pipe->uid_right_connector = connector->uid[k]; /* odd */
} else {
- pipe->uid_left_connector = connector.uid[k]; /* even */
+ pipe->uid_left_connector = connector->uid[k]; /* even */
}
- /* snd_printk(KERN_DEBUG "capture connector[%d].object_id = %x\n", k, connector.uid[k].object_id); */
+ /* snd_printk(KERN_DEBUG "capture connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */
/* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */
request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO;
- request.uid = connector.uid[k];
- request.data = &audio_info_req;
- request.size = sizeof(audio_info_req);
+ request.uid = connector->uid[k];
+ request.data = audio_info_req;
+ request.size = sizeof(*audio_info_req);
- err = snd_mixart_send_msg(mgr, &request, sizeof(audio_info), &audio_info);
+ err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info);
if( err < 0 ) {
snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n");
- return err;
+ goto __error;
}
- /*snd_printk(KERN_DEBUG "rec analog_info.analog_level_present = %x\n", audio_info.info.analog_info.analog_level_present);*/
+ /*snd_printk(KERN_DEBUG "rec analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/
}
+ err = 0;
- return 0;
+ __error:
+ kfree(connector);
+ kfree(audio_info_req);
+ kfree(audio_info);
+
+ return err;
}
static int mixart_enum_physio(mixart_mgr_t *mgr)
@@ -546,6 +562,7 @@ int snd_mixart_setup_firmware(mixart_mgr_t *mgr)
release_firmware(fw_entry);
if (err < 0)
return err;
+ mgr->dsp_loaded |= 1 << i;
}
return 0;
}
@@ -573,7 +590,7 @@ static int mixart_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info
strcpy(info->id, "miXart");
info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX;
- if (mgr->hwdep->dsp_loaded & (1 << MIXART_MOTHERBOARD_ELF_INDEX))
+ if (mgr->dsp_loaded & (1 << MIXART_MOTHERBOARD_ELF_INDEX))
info->chip_ready = 1;
info->version = MIXART_DRIVER_VERSION;
@@ -599,6 +616,9 @@ static int mixart_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
}
err = mixart_dsp_load(mgr, dsp->index, &fw);
vfree(fw.data);
+ if (err < 0)
+ return err;
+ mgr->dsp_loaded |= 1 << dsp->index;
return err;
}
@@ -619,8 +639,7 @@ int snd_mixart_setup_firmware(mixart_mgr_t *mgr)
hw->ops.dsp_load = mixart_hwdep_dsp_load;
hw->exclusive = 1;
sprintf(hw->name, SND_MIXART_HWDEP_ID);
- mgr->hwdep = hw;
- mgr->hwdep->dsp_loaded = 0;
+ mgr->dsp_loaded = 0;
return snd_card_register(mgr->chip[0]->card);
}
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index a5ed64c368b87..b96acd5a57dbd 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1183,15 +1183,14 @@ static int snd_rme32_playback_fd_ack(snd_pcm_substream_t *substream)
{
rme32_t *rme32 = snd_pcm_substream_chip(substream);
snd_pcm_indirect_t *rec, *cprec;
- unsigned long flags;
rec = &rme32->playback_pcm;
cprec = &rme32->capture_pcm;
- spin_lock_irqsave(&rme32->lock, flags);
+ spin_lock(&rme32->lock);
rec->hw_queue_size = RME32_BUFFER_SIZE;
if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE))
rec->hw_queue_size -= cprec->hw_ready;
- spin_unlock_irqrestore(&rme32->lock, flags);
+ spin_unlock(&rme32->lock);
snd_pcm_indirect_playback_transfer(substream, rec,
snd_rme32_pb_trans_copy);
return 0;
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index cb0b8fbe18f8d..12efbf0fab549 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3905,7 +3905,6 @@ static int snd_hdsp_ioctl(snd_pcm_substream_t *substream,
static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
{
- unsigned long flags;
hdsp_t *hdsp = snd_pcm_substream_chip(substream);
snd_pcm_substream_t *other;
int running;
@@ -3925,7 +3924,7 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
return -EIO;
}
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock(&hdsp->lock);
running = hdsp->running;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -3936,7 +3935,7 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
break;
default:
snd_BUG();
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock(&hdsp->lock);
return -EINVAL;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -3978,7 +3977,7 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
else if (hdsp->running && !running)
hdsp_stop_audio(hdsp);
hdsp->running = running;
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock(&hdsp->lock);
return 0;
}
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 9348385341a19..cfd2c5fd6ddf5 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1183,7 +1183,7 @@ static int __devinit snd_sonicvibes_create_gameport(sonicvibes_t *sonic)
gameport_set_name(gp, "SonicVibes Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(sonic->pci));
- gp->dev.parent = &sonic->pci->dev;
+ gameport_set_dev_parent(gp, &sonic->pci->dev);
gp->io = sonic->game_port;
gameport_register_port(gp);
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 5a722bf017cc6..ccd5ca2ba16f5 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -3112,7 +3112,7 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
static unsigned char snd_trident_gameport_read(struct gameport *gameport)
{
- trident_t *chip = gameport->port_data;
+ trident_t *chip = gameport_get_port_data(gameport);
snd_assert(chip, return 0);
return inb(TRID_REG(chip, GAMEPORT_LEGACY));
@@ -3120,7 +3120,7 @@ static unsigned char snd_trident_gameport_read(struct gameport *gameport)
static void snd_trident_gameport_trigger(struct gameport *gameport)
{
- trident_t *chip = gameport->port_data;
+ trident_t *chip = gameport_get_port_data(gameport);
snd_assert(chip, return);
outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
@@ -3128,7 +3128,7 @@ static void snd_trident_gameport_trigger(struct gameport *gameport)
static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- trident_t *chip = gameport->port_data;
+ trident_t *chip = gameport_get_port_data(gameport);
int i;
snd_assert(chip, return 0);
@@ -3145,7 +3145,7 @@ static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes
static int snd_trident_gameport_open(struct gameport *gameport, int mode)
{
- trident_t *chip = gameport->port_data;
+ trident_t *chip = gameport_get_port_data(gameport);
snd_assert(chip, return 0);
@@ -3175,9 +3175,9 @@ int __devinit snd_trident_create_gameport(trident_t *chip)
gameport_set_name(gp, "Trident 4DWave");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
- gp->dev.parent = &chip->pci->dev;
+ gameport_set_dev_parent(gp, &chip->pci->dev);
- gp->port_data = chip;
+ gameport_set_port_data(gp, chip);
gp->fuzz = 64;
gp->read = snd_trident_gameport_read;
gp->trigger = snd_trident_gameport_trigger;
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index bd1cdea6e1607..f1ce808501da5 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -1660,9 +1660,9 @@ static int __devinit snd_via686_create_gameport(via82xx_t *chip, int dev, unsign
gameport_set_name(gp, "VIA686 Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
- gp->dev.parent = &chip->pci->dev;
+ gameport_set_dev_parent(gp, &chip->pci->dev);
gp->io = JOYSTICK_ADDR;
- gp->port_data = r;
+ gameport_set_port_data(gp, r);
/* Enable legacy joystick port */
*legacy |= VIA_FUNC_ENABLE_GAME;
@@ -1676,7 +1676,7 @@ static int __devinit snd_via686_create_gameport(via82xx_t *chip, int dev, unsign
static void snd_via686_free_gameport(via82xx_t *chip)
{
if (chip->gameport) {
- struct resource *r = chip->gameport->port_data;
+ struct resource *r = gameport_get_port_data(chip->gameport);
gameport_unregister_port(chip->gameport);
chip->gameport = NULL;
@@ -1838,14 +1838,10 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
{
- ac97_t ac97;
unsigned int val;
int max_count;
unsigned char pval;
- memset(&ac97, 0, sizeof(ac97));
- ac97.private_data = chip;
-
#if 0 /* broken on K7M? */
if (chip->chip_type == TYPE_VIA686)
/* disable all legacy ports */
@@ -1897,11 +1893,6 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
snd_printk("AC'97 codec is not ready [0x%x]\n", val);
- /* and then reset codec.. */
- snd_via82xx_codec_ready(chip, 0);
- snd_via82xx_codec_write(&ac97, AC97_RESET, 0x0000);
- snd_via82xx_codec_read(&ac97, 0);
-
#if 0 /* FIXME: we don't support the second codec yet so skip the detection now.. */
snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |
VIA_REG_AC97_SECONDARY_VALID |
@@ -2168,6 +2159,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
{ .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
{ .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
+ { .vendor = 0x1462, .device = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
{ .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
{ .vendor = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
{ .vendor = 0x147b, .device = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 64304bf42ef1b..ea5c6f6401593 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -940,14 +940,10 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
{
- ac97_t ac97;
unsigned int val;
int max_count;
unsigned char pval;
- memset(&ac97, 0, sizeof(ac97));
- ac97.private_data = chip;
-
pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval);
if((pval & VIA_MC97_CTRL_INIT) != VIA_MC97_CTRL_INIT) {
pci_write_config_byte(chip->pci, 0x44, pval|VIA_MC97_CTRL_INIT);
@@ -996,13 +992,6 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
snd_printk("AC'97 codec is not ready [0x%x]\n", val);
- /* and then reset codec.. */
-#if 0 /* do we need it? when? */
- snd_via82xx_codec_ready(chip, 0);
- snd_via82xx_codec_write(&ac97, AC97_RESET, 0x0000);
- snd_via82xx_codec_read(&ac97, 0);
-#endif
-
snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |
VIA_REG_AC97_SECONDARY_VALID |
(VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT));
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 8a8338ca8864a..9f3ef22df08dd 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -138,8 +138,9 @@ static int __devinit snd_ymfpci_create_gameport(ymfpci_t *chip, int dev,
gameport_set_name(gp, "Yamaha YMF Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
- gp->dev.parent = &chip->pci->dev;
+ gameport_set_dev_parent(gp, &chip->pci->dev);
gp->io = io_port;
+ gameport_set_port_data(gp, r);
if (chip->pci->device >= 0x0010) /* YMF 744/754 */
pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port);
@@ -155,7 +156,7 @@ static int __devinit snd_ymfpci_create_gameport(ymfpci_t *chip, int dev,
void snd_ymfpci_free_gameport(ymfpci_t *chip)
{
if (chip->gameport) {
- struct resource *r = chip->gameport->port_data;
+ struct resource *r = gameport_get_port_data(chip->gameport);
gameport_unregister_port(chip->gameport);
chip->gameport = NULL;
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index bae45fe2f2de4..f72c81cc99527 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -272,12 +272,17 @@ static void pdacf_config(dev_link_t *link)
client_handle_t handle = link->handle;
pdacf_t *pdacf = link->priv;
tuple_t tuple;
- cisparse_t parse;
+ cisparse_t *parse = NULL;
config_info_t conf;
u_short buf[32];
int last_fn, last_ret;
snd_printdd(KERN_DEBUG "pdacf_config called\n");
+ parse = kmalloc(sizeof(*parse), GFP_KERNEL);
+ if (! parse) {
+ snd_printk(KERN_ERR "pdacf_config: cannot allocate\n");
+ return;
+ }
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *)buf;
@@ -286,9 +291,10 @@ static void pdacf_config(dev_link_t *link)
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));
- link->conf.ConfigBase = parse.config.base;
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &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;
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 963fdc986c453..84b0bbddbd226 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1141,7 +1141,7 @@ static int init_usb_pitch(struct usb_device *dev, int iface,
data[0] = 1;
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
+ PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
dev->devnum, iface, ep);
return err;
@@ -1167,14 +1167,14 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
data[2] = rate >> 16;
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+ SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n",
dev->devnum, iface, fmt->altsetting, rate, ep);
return err;
}
if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+ SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n",
dev->devnum, iface, fmt->altsetting, ep);
return 0; /* some devices don't support reading */
@@ -1606,62 +1606,65 @@ static int hw_rule_format(snd_pcm_hw_params_t *params,
return changed;
}
+#define MAX_MASK 64
+
/*
* check whether the registered audio formats need special hw-constraints
*/
static int check_hw_params_convention(snd_usb_substream_t *subs)
{
int i;
- u32 channels[64];
- u32 rates[64];
+ u32 *channels;
+ u32 *rates;
u32 cmaster, rmaster;
u32 rate_min = 0, rate_max = 0;
struct list_head *p;
+ int err = 1;
- memset(channels, 0, sizeof(channels));
- memset(rates, 0, sizeof(rates));
+ channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
+ rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
list_for_each(p, &subs->fmt_list) {
struct audioformat *f;
f = list_entry(p, struct audioformat, list);
/* unconventional channels? */
if (f->channels > 32)
- return 1;
+ goto __out;
/* continuous rate min/max matches? */
if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) {
if (rate_min && f->rate_min != rate_min)
- return 1;
+ goto __out;
if (rate_max && f->rate_max != rate_max)
- return 1;
+ goto __out;
rate_min = f->rate_min;
rate_max = f->rate_max;
}
/* combination of continuous rates and fixed rates? */
if (rates[f->format] & SNDRV_PCM_RATE_CONTINUOUS) {
if (f->rates != rates[f->format])
- return 1;
+ goto __out;
}
if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) {
if (rates[f->format] && rates[f->format] != f->rates)
- return 1;
+ goto __out;
}
channels[f->format] |= (1 << f->channels);
rates[f->format] |= f->rates;
}
/* check whether channels and rates match for all formats */
cmaster = rmaster = 0;
- for (i = 0; i < 64; i++) {
+ for (i = 0; i < MAX_MASK; i++) {
if (cmaster != channels[i] && cmaster && channels[i])
- return 1;
+ goto __out;
if (rmaster != rates[i] && rmaster && rates[i])
- return 1;
+ goto __out;
if (channels[i])
cmaster = channels[i];
if (rates[i])
rmaster = rates[i];
}
/* check whether channels match for all distinct rates */
- memset(channels, 0, sizeof(channels));
+ memset(channels, 0, MAX_MASK * sizeof(u32));
list_for_each(p, &subs->fmt_list) {
struct audioformat *f;
f = list_entry(p, struct audioformat, list);
@@ -1675,11 +1678,16 @@ static int check_hw_params_convention(snd_usb_substream_t *subs)
cmaster = 0;
for (i = 0; i < 32; i++) {
if (cmaster != channels[i] && cmaster && channels[i])
- return 1;
+ goto __out;
if (channels[i])
cmaster = channels[i];
}
- return 0;
+ err = 0;
+
+ __out:
+ kfree(channels);
+ kfree(rates);
+ return err;
}
@@ -2936,7 +2944,7 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
snd_printdd("sending Extigy boot sequence...\n");
/* Send message to force it to reconnect with full interface. */
err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev,0),
- 0x10, 0x43, 0x0001, 0x000a, NULL, 0, HZ);
+ 0x10, 0x43, 0x0001, 0x000a, NULL, 0, 1000);
if (err < 0) snd_printdd("error sending boot message: %d\n", err);
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&dev->descriptor, sizeof(dev->descriptor));
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index aa4693617bf72..5d32857ff9554 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -287,7 +287,7 @@ static int send_bulk_static_data(snd_usb_midi_out_endpoint_t* ep,
memcpy(buf, data, len);
dump_urb("sending", buf, len);
err = usb_bulk_msg(ep->umidi->chip->dev, ep->urb->pipe, buf, len,
- NULL, HZ / 4);
+ NULL, 250);
kfree(buf);
return err;
}