Merge branch 'classmate' into release
authorLen Brown <len.brown@intel.com>
Thu, 24 Dec 2009 06:17:31 +0000 (01:17 -0500)
committerLen Brown <len.brown@intel.com>
Thu, 24 Dec 2009 06:17:31 +0000 (01:17 -0500)
449 files changed:
Documentation/ABI/testing/sysfs-bus-usb
Documentation/driver-model/driver.txt
Documentation/filesystems/sysfs.txt
Documentation/power/runtime_pm.txt
Documentation/powerpc/dts-bindings/fsl/mpic.txt [new file with mode: 0644]
Documentation/sound/alsa/HD-Audio-Models.txt
Documentation/stable_kernel_rules.txt
Documentation/trace/events-kmem.txt
Documentation/usb/power-management.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/include/asm/bug.h
arch/alpha/include/asm/perf_event.h [new file with mode: 0644]
arch/alpha/include/asm/unistd.h
arch/alpha/kernel/systbls.S
arch/ia64/include/asm/acpi.h
arch/ia64/kernel/Makefile
arch/ia64/kernel/acpi-processor.c [deleted file]
arch/powerpc/boot/dts/katmai.dts
arch/powerpc/boot/dts/mpc8315erdb.dts
arch/powerpc/boot/dts/mpc8349emitx.dts
arch/powerpc/boot/dts/warp.dts
arch/powerpc/boot/ugecon.c
arch/powerpc/configs/g5_defconfig
arch/powerpc/configs/iseries_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/ppc64e_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/include/asm/bug.h
arch/powerpc/include/asm/gpio.h
arch/powerpc/kernel/align.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/mmu_context_nohash.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/platforms/83xx/suspend.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/embedded6xx/flipper-pic.c
arch/powerpc/platforms/embedded6xx/hlwd-pic.c
arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
arch/powerpc/platforms/iseries/mf.c
arch/powerpc/platforms/iseries/viopath.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/cmm.c
arch/powerpc/platforms/pseries/dlpar.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/sysdev/cpm2_pic.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/mpc8xxx_gpio.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/mpic_msi.c
arch/powerpc/sysdev/mpic_u3msi.c
arch/s390/crypto/aes_s390.c
arch/s390/hypfs/hypfs_diag.c
arch/s390/hypfs/hypfs_vm.c
arch/s390/include/asm/unistd.h
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/ipl.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/traps.c
arch/x86/Kconfig
arch/x86/include/asm/acpi.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/hw_irq.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/msr.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/stacktrace.h
arch/x86/kernel/acpi/Makefile
arch/x86/kernel/acpi/processor.c [deleted file]
arch/x86/kernel/apic/apic_flat_64.c
arch/x86/kernel/apic/bigsmp_32.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/x2apic_cluster.c
arch/x86/kernel/apic/x2apic_phys.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpuid.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/dumpstack.h
arch/x86/kernel/dumpstack_32.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/e820.c
arch/x86/kernel/microcode_core.c
arch/x86/kernel/msr.c
arch/x86/kernel/stacktrace.c
arch/x86/kernel/tsc.c
arch/x86/kernel/uv_irq.c
arch/x86/lib/Makefile
arch/x86/lib/msr-smp.c [new file with mode: 0644]
arch/x86/lib/msr.c
arch/x86/mm/srat_32.c
arch/x86/mm/srat_64.c
arch/x86/oprofile/backtrace.c
arch/x86/tools/chkobjdump.awk
arch/x86/tools/gen-insn-attr-x86.awk
drivers/acpi/Makefile
drivers/acpi/blacklist.c
drivers/acpi/bus.c
drivers/acpi/ec.c
drivers/acpi/internal.h
drivers/acpi/processor_core.c
drivers/acpi/processor_pdc.c [new file with mode: 0644]
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/pata_bf54x.c
drivers/ata/pata_cmd64x.c
drivers/ata/pata_hpt3x2n.c
drivers/ata/pata_octeon_cf.c
drivers/ata/sata_mv.c
drivers/base/bus.c
drivers/base/core.c
drivers/base/devtmpfs.c
drivers/base/driver.c
drivers/base/memory.c
drivers/base/platform.c
drivers/base/power/main.c
drivers/base/power/runtime.c
drivers/bluetooth/btusb.c
drivers/char/nozomi.c
drivers/char/sonypi.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_ioc32.c
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/i2c/ch7006_drv.c
drivers/gpu/drm/i2c/ch7006_mode.c
drivers/gpu/drm/i810/i810_dma.c
drivers/gpu/drm/i810/i810_drv.c
drivers/gpu/drm/i830/i830_dma.c
drivers/gpu/drm/i830/i830_drv.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_ioc32.c
drivers/gpu/drm/mga/mga_drv.c
drivers/gpu/drm/mga/mga_ioc32.c
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bios.h
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_grctx.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nouveau_grctx.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/nouveau_ioc32.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv04_crtc.c
drivers/gpu/drm/nouveau/nv04_dac.c
drivers/gpu/drm/nouveau/nv04_dfp.c
drivers/gpu/drm/nouveau/nv04_display.c
drivers/gpu/drm/nouveau/nv04_graph.c
drivers/gpu/drm/nouveau/nv10_graph.c
drivers/gpu/drm/nouveau/nv17_tv.c
drivers/gpu/drm/nouveau/nv40_graph.c
drivers/gpu/drm/nouveau/nv40_grctx.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nv50_crtc.c
drivers/gpu/drm/nouveau/nv50_cursor.c
drivers/gpu/drm/nouveau/nv50_dac.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_fifo.c
drivers/gpu/drm/nouveau/nv50_graph.c
drivers/gpu/drm/nouveau/nv50_sor.c
drivers/gpu/drm/r128/r128_drv.c
drivers/gpu/drm/r128/r128_ioc32.c
drivers/gpu/drm/radeon/atom.c
drivers/gpu/drm/radeon/atom.h
drivers/gpu/drm/radeon/atombios.h
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r100_track.h
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r300_cmdbuf.c
drivers/gpu/drm/radeon/r300_reg.h
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_clocks.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_ioc32.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_test.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/savage/savage_drv.c
drivers/gpu/drm/sis/sis_drv.c
drivers/gpu/drm/tdfx/tdfx_drv.c
drivers/gpu/drm/via/via_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/infiniband/hw/cxgb3/cxio_hal.h
drivers/infiniband/hw/cxgb3/cxio_resource.c
drivers/isdn/mISDN/l1oip_core.c
drivers/media/video/cx23885/cx23888-ir.c
drivers/media/video/meye.c
drivers/media/video/meye.h
drivers/net/bnx2.c
drivers/net/can/at91_can.c
drivers/net/davinci_emac.c
drivers/net/e100.c
drivers/net/e1000e/82571.c
drivers/net/gianfar.c
drivers/net/gianfar.h
drivers/net/netxen/netxen_nic_main.c
drivers/net/phy/broadcom.c
drivers/net/wireless/libertas/cmd.c
drivers/net/wireless/libertas/dev.h
drivers/net/wireless/libertas/main.c
drivers/platform/x86/fujitsu-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/s390/block/dasd_alias.c
drivers/s390/block/dasd_diag.c
drivers/s390/char/fs3270.c
drivers/s390/char/tape_34xx.c
drivers/s390/char/tape_3590.c
drivers/s390/char/tape_block.c
drivers/s390/char/tape_char.c
drivers/s390/char/tape_class.c
drivers/s390/char/tape_core.c
drivers/s390/char/tape_proc.c
drivers/s390/char/tape_std.c
drivers/s390/cio/ccwreq.c
drivers/s390/cio/device.c
drivers/s390/cio/device_pgid.c
drivers/s390/cio/fcx.c
drivers/s390/cio/io_sch.h
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_perf.c
drivers/s390/cio/qdio_perf.h
drivers/s390/cio/qdio_setup.c
drivers/scsi/libiscsi.c
drivers/scsi/libiscsi_tcp.c
drivers/scsi/libsrp.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/batman-adv/Kconfig
drivers/staging/batman-adv/send.c
drivers/staging/comedi/comedi.h
drivers/staging/comedi/drivers/jr3_pci.c
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/dst/Kconfig [deleted file]
drivers/staging/dst/Makefile [deleted file]
drivers/staging/dst/crypto.c [deleted file]
drivers/staging/dst/dcore.c [deleted file]
drivers/staging/dst/export.c [deleted file]
drivers/staging/dst/state.c [deleted file]
drivers/staging/dst/thread_pool.c [deleted file]
drivers/staging/dst/trans.c [deleted file]
drivers/staging/panel/Kconfig
drivers/staging/panel/panel.c
drivers/staging/pohmelfs/dir.c
drivers/staging/ramzswap/TODO
drivers/staging/ramzswap/ramzswap_drv.c
drivers/staging/rtl8187se/ieee80211/ieee80211.h
drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
drivers/staging/rtl8187se/r8180_core.c
drivers/staging/rtl8187se/r8180_wx.c
drivers/staging/rtl8192e/ieee80211.h
drivers/staging/rtl8192e/ieee80211/ieee80211.h
drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
drivers/staging/rtl8192e/r8192E_core.c
drivers/staging/rtl8192su/ieee80211/ieee80211.h
drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c
drivers/staging/rtl8192su/r8192U_core.c
drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
drivers/staging/sm7xx/Kconfig [new file with mode: 0644]
drivers/staging/sm7xx/Makefile [new file with mode: 0644]
drivers/staging/sm7xx/TODO [new file with mode: 0644]
drivers/staging/sm7xx/smtc2d.c [new file with mode: 0644]
drivers/staging/sm7xx/smtc2d.h [new file with mode: 0644]
drivers/staging/sm7xx/smtcfb.c [new file with mode: 0644]
drivers/staging/sm7xx/smtcfb.h [new file with mode: 0644]
drivers/staging/vt6655/Kconfig
drivers/staging/vt6656/Kconfig
drivers/staging/wlan-ng/prism2fw.c
drivers/usb/Makefile
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/sysfs.c
drivers/usb/core/usb.c
drivers/usb/early/ehci-dbgp.c
drivers/usb/gadget/audio.c
drivers/usb/gadget/f_audio.c
drivers/usb/gadget/u_audio.c
drivers/usb/gadget/u_audio.h
drivers/usb/host/fhci-sched.c
drivers/usb/host/fhci-tds.c
drivers/usb/host/fhci.h
drivers/usb/misc/appledisplay.c
drivers/usb/misc/emi62.c
drivers/usb/musb/blackfin.c
drivers/usb/musb/blackfin.h
drivers/usb/musb/cppi_dma.c
drivers/usb/musb/davinci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_gadget_ep0.c
drivers/usb/otg/isp1301_omap.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/ftdi_sio_ids.h [new file with mode: 0644]
drivers/usb/serial/generic.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/usb-serial.c
drivers/watchdog/Kconfig
drivers/watchdog/geodewdt.c
fs/anon_inodes.c
fs/compat_ioctl.c
fs/eventfd.c
fs/eventpoll.c
fs/ext3/inode.c
fs/ext3/namei.c
fs/ext3/resize.c
fs/ext3/super.c
fs/ext4/ext4.h
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/file_table.c
fs/internal.h
fs/jbd/journal.c
fs/jbd2/journal.c
fs/jfs/super.c
fs/namei.c
fs/nfsd/nfsfh.c
fs/ocfs2/alloc.c
fs/ocfs2/alloc.h
fs/ocfs2/namei.c
fs/ocfs2/refcounttree.c
fs/open.c
fs/proc/array.c
fs/quota/dquot.c
fs/quota/quota_v2.c
fs/signalfd.c
fs/stat.c
fs/super.c
fs/sysfs/bin.c
fs/timerfd.c
include/acpi/processor.h
include/drm/drmP.h
include/linux/decompress/mm.h
include/linux/device.h
include/linux/dst.h [deleted file]
include/linux/elf.h
include/linux/ext3_fs_sb.h
include/linux/ext3_jbd.h
include/linux/fs.h
include/linux/kfifo.h
include/linux/memory.h
include/linux/mm.h
include/linux/namei.h
include/linux/perf_counter.h [deleted file]
include/linux/quota.h
include/linux/rcutiny.h
include/linux/rcutree.h
include/linux/sched.h
include/linux/sysfs.h
include/linux/usb/serial.h
include/scsi/libiscsi.h
include/scsi/libiscsi_tcp.h
include/scsi/libsrp.h
init/initramfs.c
init/main.c
kernel/audit_tree.c
kernel/auditsc.c
kernel/cpu.c
kernel/kfifo.c
kernel/kthread.c
kernel/perf_event.c
kernel/resource.c
kernel/sched.c
kernel/sched_clock.c
kernel/sched_fair.c
kernel/sched_rt.c
kernel/signal.c
kernel/sys.c
kernel/time.c
kernel/time/clockevents.c
kernel/time/timekeeping.c
kernel/timer.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_sysprof.c
lib/decompress_bunzip2.c
lib/string.c
mm/page_alloc.c
net/bluetooth/hidp/core.c
net/bluetooth/l2cap.c
net/dccp/probe.c
net/ipv6/reassembly.c
net/ipv6/route.c
security/tomoyo/file.c
sound/arm/aaci.c
sound/arm/aaci.h
sound/core/Kconfig
sound/core/pcm_lib.c
sound/core/pcm_timer.c
sound/isa/msnd/msnd_midi.c
sound/isa/sb/emu8000.c
sound/mips/sgio2audio.c
sound/oss/pss.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/stac9766.c
sound/soc/codecs/wm8974.c
sound/soc/codecs/wm9712.c
sound/soc/imx/mx27vis_wm8974.c
sound/soc/sh/fsi.c
sound/usb/usbaudio.c
tools/perf/Makefile
tools/perf/builtin-probe.c
tools/perf/builtin-report.c
tools/perf/util/event.h
tools/perf/util/probe-event.c
tools/perf/util/probe-finder.h
virt/kvm/kvm_main.c

index deb6b48..a07c0f3 100644 (file)
@@ -21,25 +21,27 @@ Contact:    Alan Stern <stern@rowland.harvard.edu>
 Description:
                Each USB device directory will contain a file named
                power/level.  This file holds a power-level setting for
-               the device, one of "on", "auto", or "suspend".
+               the device, either "on" or "auto".
 
                "on" means that the device is not allowed to autosuspend,
                although normal suspends for system sleep will still
                be honored.  "auto" means the device will autosuspend
                and autoresume in the usual manner, according to the
-               capabilities of its driver.  "suspend" means the device
-               is forced into a suspended state and it will not autoresume
-               in response to I/O requests.  However remote-wakeup requests
-               from the device may still be enabled (the remote-wakeup
-               setting is controlled separately by the power/wakeup
-               attribute).
+               capabilities of its driver.
 
                During normal use, devices should be left in the "auto"
-               level.  The other levels are meant for administrative uses.
+               level.  The "on" level is meant for administrative uses.
                If you want to suspend a device immediately but leave it
                free to wake up in response to I/O requests, you should
                write "0" to power/autosuspend.
 
+               Device not capable of proper suspend and resume should be
+               left in the "on" level.  Although the USB spec requires
+               devices to support suspend/resume, many of them do not.
+               In fact so many don't that by default, the USB core
+               initializes all non-hub devices in the "on" level.  Some
+               drivers may change this setting when they are bound.
+
 What:          /sys/bus/usb/devices/.../power/persist
 Date:          May 2007
 KernelVersion: 2.6.23
index 60120fb..d2cd6fb 100644 (file)
@@ -226,5 +226,5 @@ struct driver_attribute driver_attr_debug;
 This can then be used to add and remove the attribute from the
 driver's directory using:
 
-int driver_create_file(struct device_driver *, struct driver_attribute *);
-void driver_remove_file(struct device_driver *, struct driver_attribute *);
+int driver_create_file(struct device_driver *, const struct driver_attribute *);
+void driver_remove_file(struct device_driver *, const struct driver_attribute *);
index b245d52..931c806 100644 (file)
@@ -91,8 +91,8 @@ struct device_attribute {
                         const char *buf, size_t count);
 };
 
-int device_create_file(struct device *, struct device_attribute *);
-void device_remove_file(struct device *, struct device_attribute *);
+int device_create_file(struct device *, const struct device_attribute *);
+void device_remove_file(struct device *, const struct device_attribute *);
 
 It also defines this helper for defining device attributes: 
 
@@ -316,8 +316,8 @@ DEVICE_ATTR(_name, _mode, _show, _store);
 
 Creation/Removal:
 
-int device_create_file(struct device *device, struct device_attribute * attr);
-void device_remove_file(struct device * dev, struct device_attribute * attr);
+int device_create_file(struct device *dev, const struct device_attribute * attr);
+void device_remove_file(struct device *dev, const struct device_attribute * attr);
 
 
 - bus drivers (include/linux/device.h)
@@ -358,7 +358,7 @@ DRIVER_ATTR(_name, _mode, _show, _store)
 
 Creation/Removal:
 
-int driver_create_file(struct device_driver *, struct driver_attribute *);
-void driver_remove_file(struct device_driver *, struct driver_attribute *);
+int driver_create_file(struct device_driver *, const struct driver_attribute *);
+void driver_remove_file(struct device_driver *, const struct driver_attribute *);
 
 
index 4a3109b..356fd86 100644 (file)
@@ -42,80 +42,81 @@ struct dev_pm_ops {
        ...
 };
 
-The ->runtime_suspend() callback is executed by the PM core for the bus type of
-the device being suspended.  The bus type's callback is then _entirely_
-_responsible_ for handling the device as appropriate, which may, but need not
-include executing the device driver's own ->runtime_suspend() callback (from the
+The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are
+executed by the PM core for either the bus type, or device type (if the bus
+type's callback is not defined), or device class (if the bus type's and device
+type's callbacks are not defined) of given device.  The bus type, device type
+and device class callbacks are referred to as subsystem-level callbacks in what
+follows.
+
+The subsystem-level suspend callback is _entirely_ _responsible_ for handling
+the suspend of the device as appropriate, which may, but need not include
+executing the device driver's own ->runtime_suspend() callback (from the
 PM core's point of view it is not necessary to implement a ->runtime_suspend()
-callback in a device driver as long as the bus type's ->runtime_suspend() knows
-what to do to handle the device).
+callback in a device driver as long as the subsystem-level suspend callback
+knows what to do to handle the device).
 
-  * Once the bus type's ->runtime_suspend() callback has completed successfully
+  * Once the subsystem-level suspend callback has completed successfully
     for given device, the PM core regards the device as suspended, which need
     not mean that the device has been put into a low power state.  It is
     supposed to mean, however, that the device will not process data and will
-    not communicate with the CPU(s) and RAM until its bus type's
-    ->runtime_resume() callback is executed for it.  The run-time PM status of
-    a device after successful execution of its bus type's ->runtime_suspend()
-    callback is 'suspended'.
-
-  * If the bus type's ->runtime_suspend() callback returns -EBUSY or -EAGAIN,
-    the device's run-time PM status is supposed to be 'active', which means that
-    the device _must_ be fully operational afterwards.
-
-  * If the bus type's ->runtime_suspend() callback returns an error code
-    different from -EBUSY or -EAGAIN, the PM core regards this as a fatal
-    error and will refuse to run the helper functions described in Section 4
-    for the device, until the status of it is directly set either to 'active'
-    or to 'suspended' (the PM core provides special helper functions for this
-    purpose).
-
-In particular, if the driver requires remote wakeup capability for proper
-functioning and device_run_wake() returns 'false' for the device, then
-->runtime_suspend() should return -EBUSY.  On the other hand, if
-device_run_wake() returns 'true' for the device and the device is put
-into a low power state during the execution of its bus type's
-->runtime_suspend(), it is expected that remote wake-up (i.e. hardware mechanism
-allowing the device to request a change of its power state, such as PCI PME)
-will be enabled for the device.  Generally, remote wake-up should be enabled
-for all input devices put into a low power state at run time.
-
-The ->runtime_resume() callback is executed by the PM core for the bus type of
-the device being woken up.  The bus type's callback is then _entirely_
-_responsible_ for handling the device as appropriate, which may, but need not
-include executing the device driver's own ->runtime_resume() callback (from the
-PM core's point of view it is not necessary to implement a ->runtime_resume()
-callback in a device driver as long as the bus type's ->runtime_resume() knows
-what to do to handle the device).
-
-  * Once the bus type's ->runtime_resume() callback has completed successfully,
-    the PM core regards the device as fully operational, which means that the
-    device _must_ be able to complete I/O operations as needed.  The run-time
-    PM status of the device is then 'active'.
-
-  * If the bus type's ->runtime_resume() callback returns an error code, the PM
-    core regards this as a fatal error and will refuse to run the helper
-    functions described in Section 4 for the device, until its status is
-    directly set either to 'active' or to 'suspended' (the PM core provides
-    special helper functions for this purpose).
-
-The ->runtime_idle() callback is executed by the PM core for the bus type of
-given device whenever the device appears to be idle, which is indicated to the
-PM core by two counters, the device's usage counter and the counter of 'active'
-children of the device.
+    not communicate with the CPU(s) and RAM until the subsystem-level resume
+    callback is executed for it.  The run-time PM status of a device after
+    successful execution of the subsystem-level suspend callback is 'suspended'.
+
+  * If the subsystem-level suspend callback returns -EBUSY or -EAGAIN,
+    the device's run-time PM status is 'active', which means that the device
+    _must_ be fully operational afterwards.
+
+  * If the subsystem-level suspend callback returns an error code different
+    from -EBUSY or -EAGAIN, the PM core regards this as a fatal error and will
+    refuse to run the helper functions described in Section 4 for the device,
+    until the status of it is directly set either to 'active', or to 'suspended'
+    (the PM core provides special helper functions for this purpose).
+
+In particular, if the driver requires remote wake-up capability (i.e. hardware
+mechanism allowing the device to request a change of its power state, such as
+PCI PME) for proper functioning and device_run_wake() returns 'false' for the
+device, then ->runtime_suspend() should return -EBUSY.  On the other hand, if
+device_run_wake() returns 'true' for the device and the device is put into a low
+power state during the execution of the subsystem-level suspend callback, it is
+expected that remote wake-up will be enabled for the device.  Generally, remote
+wake-up should be enabled for all input devices put into a low power state at
+run time.
+
+The subsystem-level resume callback is _entirely_ _responsible_ for handling the
+resume of the device as appropriate, which may, but need not include executing
+the device driver's own ->runtime_resume() callback (from the PM core's point of
+view it is not necessary to implement a ->runtime_resume() callback in a device
+driver as long as the subsystem-level resume callback knows what to do to handle
+the device).
+
+  * Once the subsystem-level resume callback has completed successfully, the PM
+    core regards the device as fully operational, which means that the device
+    _must_ be able to complete I/O operations as needed.  The run-time PM status
+    of the device is then 'active'.
+
+  * If the subsystem-level resume callback returns an error code, the PM core
+    regards this as a fatal error and will refuse to run the helper functions
+    described in Section 4 for the device, until its status is directly set
+    either to 'active' or to 'suspended' (the PM core provides special helper
+    functions for this purpose).
+
+The subsystem-level idle callback is executed by the PM core whenever the device
+appears to be idle, which is indicated to the PM core by two counters, the
+device's usage counter and the counter of 'active' children of the device.
 
   * If any of these counters is decreased using a helper function provided by
     the PM core and it turns out to be equal to zero, the other counter is
     checked.  If that counter also is equal to zero, the PM core executes the
-    device bus type's ->runtime_idle() callback (with the device as an
-    argument).
+    subsystem-level idle callback with the device as an argument.
 
-The action performed by a bus type's ->runtime_idle() callback is totally
-dependent on the bus type in question, but the expected and recommended action
-is to check if the device can be suspended (i.e. if all of the conditions
-necessary for suspending the device are satisfied) and to queue up a suspend
-request for the device in that case.  The value returned by this callback is
-ignored by the PM core.
+The action performed by a subsystem-level idle callback is totally dependent on
+the subsystem in question, but the expected and recommended action is to check
+if the device can be suspended (i.e. if all of the conditions necessary for
+suspending the device are satisfied) and to queue up a suspend request for the
+device in that case.  The value returned by this callback is ignored by the PM
+core.
 
 The helper functions provided by the PM core, described in Section 4, guarantee
 that the following constraints are met with respect to the bus type's run-time
@@ -238,41 +239,41 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       removing the device from device hierarchy
 
   int pm_runtime_idle(struct device *dev);
-    - execute ->runtime_idle() for the device's bus type; returns 0 on success
-      or error code on failure, where -EINPROGRESS means that ->runtime_idle()
-      is already being executed
+    - execute the subsystem-level idle callback for the device; returns 0 on
+      success or error code on failure, where -EINPROGRESS means that
+      ->runtime_idle() is already being executed
 
   int pm_runtime_suspend(struct device *dev);
-    - execute ->runtime_suspend() for the device's bus type; returns 0 on
+    - execute the subsystem-level suspend callback for the device; returns 0 on
       success, 1 if the device's run-time PM status was already 'suspended', or
       error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt
       to suspend the device again in future
 
   int pm_runtime_resume(struct device *dev);
-    - execute ->runtime_resume() for the device's bus type; returns 0 on
+    - execute the subsystem-leve resume callback for the device; returns 0 on
       success, 1 if the device's run-time PM status was already 'active' or
       error code on failure, where -EAGAIN means it may be safe to attempt to
       resume the device again in future, but 'power.runtime_error' should be
       checked additionally
 
   int pm_request_idle(struct device *dev);
-    - submit a request to execute ->runtime_idle() for the device's bus type
-      (the request is represented by a work item in pm_wq); returns 0 on success
-      or error code if the request has not been queued up
+    - submit a request to execute the subsystem-level idle callback for the
+      device (the request is represented by a work item in pm_wq); returns 0 on
+      success or error code if the request has not been queued up
 
   int pm_schedule_suspend(struct device *dev, unsigned int delay);
-    - schedule the execution of ->runtime_suspend() for the device's bus type
-      in future, where 'delay' is the time to wait before queuing up a suspend
-      work item in pm_wq, in milliseconds (if 'delay' is zero, the work item is
-      queued up immediately); returns 0 on success, 1 if the device's PM
+    - schedule the execution of the subsystem-level suspend callback for the
+      device in future, where 'delay' is the time to wait before queuing up a
+      suspend work item in pm_wq, in milliseconds (if 'delay' is zero, the work
+      item is queued up immediately); returns 0 on success, 1 if the device's PM
       run-time status was already 'suspended', or error code if the request
       hasn't been scheduled (or queued up if 'delay' is 0); if the execution of
       ->runtime_suspend() is already scheduled and not yet expired, the new
       value of 'delay' will be used as the time to wait
 
   int pm_request_resume(struct device *dev);
-    - submit a request to execute ->runtime_resume() for the device's bus type
-      (the request is represented by a work item in pm_wq); returns 0 on
+    - submit a request to execute the subsystem-level resume callback for the
+      device (the request is represented by a work item in pm_wq); returns 0 on
       success, 1 if the device's run-time PM status was already 'active', or
       error code if the request hasn't been queued up
 
@@ -303,12 +304,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       run-time PM callbacks described in Section 2
 
   int pm_runtime_disable(struct device *dev);
-    - prevent the run-time PM helper functions from running the device bus
-      type's run-time PM callbacks, make sure that all of the pending run-time
-      PM operations on the device are either completed or canceled; returns
-      1 if there was a resume request pending and it was necessary to execute
-      ->runtime_resume() for the device's bus type to satisfy that request,
-      otherwise 0 is returned
+    - prevent the run-time PM helper functions from running subsystem-level
+      run-time PM callbacks for the device, make sure that all of the pending
+      run-time PM operations on the device are either completed or canceled;
+      returns 1 if there was a resume request pending and it was necessary to
+      execute the subsystem-level resume callback for the device to satisfy that
+      request, otherwise 0 is returned
 
   void pm_suspend_ignore_children(struct device *dev, bool enable);
     - set/unset the power.ignore_children flag of the device
@@ -378,5 +379,55 @@ pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
 they will fail returning -EAGAIN, because the device's usage counter is
 incremented by the core before executing ->probe() and ->remove().  Still, it
 may be desirable to suspend the device as soon as ->probe() or ->remove() has
-finished, so the PM core uses pm_runtime_idle_sync() to invoke the device bus
-type's ->runtime_idle() callback at that time.
+finished, so the PM core uses pm_runtime_idle_sync() to invoke the
+subsystem-level idle callback for the device at that time.
+
+6. Run-time PM and System Sleep
+
+Run-time PM and system sleep (i.e., system suspend and hibernation, also known
+as suspend-to-RAM and suspend-to-disk) interact with each other in a couple of
+ways.  If a device is active when a system sleep starts, everything is
+straightforward.  But what should happen if the device is already suspended?
+
+The device may have different wake-up settings for run-time PM and system sleep.
+For example, remote wake-up may be enabled for run-time suspend but disallowed
+for system sleep (device_may_wakeup(dev) returns 'false').  When this happens,
+the subsystem-level system suspend callback is responsible for changing the
+device's wake-up setting (it may leave that to the device driver's system
+suspend routine).  It may be necessary to resume the device and suspend it again
+in order to do so.  The same is true if the driver uses different power levels
+or other settings for run-time suspend and system sleep.
+
+During system resume, devices generally should be brought back to full power,
+even if they were suspended before the system sleep began.  There are several
+reasons for this, including:
+
+  * The device might need to switch power levels, wake-up settings, etc.
+
+  * Remote wake-up events might have been lost by the firmware.
+
+  * The device's children may need the device to be at full power in order
+    to resume themselves.
+
+  * The driver's idea of the device state may not agree with the device's
+    physical state.  This can happen during resume from hibernation.
+
+  * The device might need to be reset.
+
+  * Even though the device was suspended, if its usage counter was > 0 then most
+    likely it would need a run-time resume in the near future anyway.
+
+  * Always going back to full power is simplest.
+
+If the device was suspended before the sleep began, then its run-time PM status
+will have to be updated to reflect the actual post-system sleep status.  The way
+to do this is:
+
+       pm_runtime_disable(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+
+The PM core always increments the run-time usage counter before calling the
+->prepare() callback and decrements it after calling the ->complete() callback.
+Hence disabling run-time PM temporarily like this will not cause any run-time
+suspend callbacks to be lost.
diff --git a/Documentation/powerpc/dts-bindings/fsl/mpic.txt b/Documentation/powerpc/dts-bindings/fsl/mpic.txt
new file mode 100644 (file)
index 0000000..71e39cf
--- /dev/null
@@ -0,0 +1,42 @@
+* OpenPIC and its interrupt numbers on Freescale's e500/e600 cores
+
+The OpenPIC specification does not specify which interrupt source has to
+become which interrupt number. This is up to the software implementation
+of the interrupt controller. The only requirement is that every
+interrupt source has to have an unique interrupt number / vector number.
+To accomplish this the current implementation assigns the number zero to
+the first source, the number one to the second source and so on until
+all interrupt sources have their unique number.
+Usually the assigned vector number equals the interrupt number mentioned
+in the documentation for a given core / CPU. This is however not true
+for the e500 cores (MPC85XX CPUs) where the documentation distinguishes
+between internal and external interrupt sources and starts counting at
+zero for both of them.
+
+So what to write for external interrupt source X or internal interrupt
+source Y into the device tree? Here is an example:
+
+The memory map for the interrupt controller in the MPC8544[0] shows,
+that the first interrupt source starts at 0x5_0000 (PIC Register Address
+Map-Interrupt Source Configuration Registers). This source becomes the
+number zero therefore:
+ External interrupt 0 = interrupt number 0
+ External interrupt 1 = interrupt number 1
+ External interrupt 2 = interrupt number 2
+ ...
+Every interrupt number allocates 0x20 bytes register space. So to get
+its number it is sufficient to shift the lower 16bits to right by five.
+So for the external interrupt 10 we have:
+  0x0140 >> 5 = 10
+
+After the external sources, the internal sources follow. The in core I2C
+controller on the MPC8544 for instance has the internal source number
+27. Oo obtain its interrupt number we take the lower 16bits of its memory
+address (0x5_0560) and shift it right:
+ 0x0560 >> 5 = 43
+
+Therefore the I2C device node for the MPC8544 CPU has to have the
+interrupt number 43 specified in the device tree.
+
+[0] MPC8544E PowerQUICCTM III, Integrated Host Processor Family Reference Manual
+    MPC8544ERM Rev. 1 10/2007
index e93afff..e72cee9 100644 (file)
@@ -403,4 +403,5 @@ STAC9872
 Cirrus Logic CS4206/4207
 ========================
   mbp55                MacBook Pro 5,5
+  imac27       IMac 27 Inch
   auto         BIOS setup (default)
index a452227..5effa5b 100644 (file)
@@ -26,13 +26,33 @@ Procedure for submitting patches to the -stable tree:
 
  - Send the patch, after verifying that it follows the above rules, to
    stable@kernel.org.
+ - To have the patch automatically included in the stable tree, add the
+   the tag
+     Cc: stable@kernel.org
+   in the sign-off area. Once the patch is merged it will be applied to
+   the stable tree without anything else needing to be done by the author
+   or subsystem maintainer.
+ - If the patch requires other patches as prerequisites which can be
+   cherry-picked than this can be specified in the following format in
+   the sign-off area:
+
+     Cc: <stable@kernel.org> # .32.x: a1f84a3: sched: Check for idle
+     Cc: <stable@kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
+     Cc: <stable@kernel.org> # .32.x: fd21073: sched: Fix affinity logic
+     Cc: <stable@kernel.org> # .32.x
+    Signed-off-by: Ingo Molnar <mingo@elte.hu>
+
+   The tag sequence has the meaning of:
+     git cherry-pick a1f84a3
+     git cherry-pick 1b9508f
+     git cherry-pick fd21073
+     git cherry-pick <this commit>
+
  - The sender will receive an ACK when the patch has been accepted into the
    queue, or a NAK if the patch is rejected.  This response might take a few
    days, according to the developer's schedules.
  - If accepted, the patch will be added to the -stable queue, for review by
    other developers and by the relevant subsystem maintainer.
- - If the stable@kernel.org address is added to a patch, when it goes into
-   Linus's tree it will automatically be emailed to the stable team.
  - Security patches should not be sent to this alias, but instead to the
    documented security@kernel.org address.
 
index 6ef2a86..aa82ee4 100644 (file)
@@ -1,7 +1,7 @@
                        Subsystem Trace Points: kmem
 
-The tracing system kmem captures events related to object and page allocation
-within the kernel. Broadly speaking there are four major subheadings.
+The kmem tracing system captures events related to object and page allocation
+within the kernel. Broadly speaking there are five major subheadings.
 
   o Slab allocation of small objects of unknown type (kmalloc)
   o Slab allocation of small objects of known type
@@ -9,7 +9,7 @@ within the kernel. Broadly speaking there are four major subheadings.
   o Per-CPU Allocator Activity
   o External Fragmentation
 
-This document will describe what each of the tracepoints are and why they
+This document describes what each of the tracepoints is and why they
 might be useful.
 
 1. Slab allocation of small objects of unknown type
@@ -34,7 +34,7 @@ kmem_cache_free               call_site=%lx ptr=%p
 These events are similar in usage to the kmalloc-related events except that
 it is likely easier to pin the event down to a specific cache. At the time
 of writing, no information is available on what slab is being allocated from,
-but the call_site can usually be used to extrapolate that information
+but the call_site can usually be used to extrapolate that information.
 
 3. Page allocation
 ==================
@@ -80,9 +80,9 @@ event indicating whether it is for a percpu_refill or not.
 When the per-CPU list is too full, a number of pages are freed, each one
 which triggers a mm_page_pcpu_drain event.
 
-The individual nature of the events are so that pages can be tracked
+The individual nature of the events is so that pages can be tracked
 between allocation and freeing. A number of drain or refill pages that occur
-consecutively imply the zone->lock being taken once. Large amounts of PCP
+consecutively imply the zone->lock being taken once. Large amounts of per-CPU
 refills and drains could imply an imbalance between CPUs where too much work
 is being concentrated in one place. It could also indicate that the per-CPU
 lists should be a larger size. Finally, large amounts of refills on one CPU
@@ -102,6 +102,6 @@ is important.
 
 Large numbers of this event implies that memory is fragmenting and
 high-order allocations will start failing at some time in the future. One
-means of reducing the occurange of this event is to increase the size of
+means of reducing the occurrence of this event is to increase the size of
 min_free_kbytes in increments of 3*pageblock_size*nr_online_nodes where
 pageblock_size is usually the size of the default hugepage size.
index c7c1dc2..3bf6818 100644 (file)
@@ -71,12 +71,10 @@ being accessed through sysfs, then it definitely is idle.
        Forms of dynamic PM
        -------------------
 
-Dynamic suspends can occur in two ways: manual and automatic.
-"Manual" means that the user has told the kernel to suspend a device,
-whereas "automatic" means that the kernel has decided all by itself to
-suspend a device.  Automatic suspend is called "autosuspend" for
-short.  In general, a device won't be autosuspended unless it has been
-idle for some minimum period of time, the so-called idle-delay time.
+Dynamic suspends occur when the kernel decides to suspend an idle
+device.  This is called "autosuspend" for short.  In general, a device
+won't be autosuspended unless it has been idle for some minimum period
+of time, the so-called idle-delay time.
 
 Of course, nothing the kernel does on its own initiative should
 prevent the computer or its devices from working properly.  If a
@@ -96,10 +94,11 @@ idle.
 We can categorize power management events in two broad classes:
 external and internal.  External events are those triggered by some
 agent outside the USB stack: system suspend/resume (triggered by
-userspace), manual dynamic suspend/resume (also triggered by
-userspace), and remote wakeup (triggered by the device).  Internal
-events are those triggered within the USB stack: autosuspend and
-autoresume.
+userspace), manual dynamic resume (also triggered by userspace), and
+remote wakeup (triggered by the device).  Internal events are those
+triggered within the USB stack: autosuspend and autoresume.  Note that
+all dynamic suspend events are internal; external agents are not
+allowed to issue dynamic suspends.
 
 
        The user interface for dynamic PM
@@ -145,9 +144,9 @@ relevant attribute files are: wakeup, level, and autosuspend.
                number of seconds the device should remain idle before
                the kernel will autosuspend it (the idle-delay time).
                The default is 2.  0 means to autosuspend as soon as
-               the device becomes idle, and -1 means never to
-               autosuspend.  You can write a number to the file to
-               change the autosuspend idle-delay time.
+               the device becomes idle, and negative values mean
+               never to autosuspend.  You can write a number to the
+               file to change the autosuspend idle-delay time.
 
 Writing "-1" to power/autosuspend and writing "on" to power/level do
 essentially the same thing -- they both prevent the device from being
@@ -377,9 +376,9 @@ the device hasn't been idle for long enough, a delayed workqueue
 routine is automatically set up to carry out the operation when the
 autosuspend idle-delay has expired.
 
-Autoresume attempts also can fail.  This will happen if power/level is
-set to "suspend" or if the device doesn't manage to resume properly.
-Unlike autosuspend, there's no delay for an autoresume.
+Autoresume attempts also can fail, although failure would mean that
+the device is no longer present or operating properly.  Unlike
+autosuspend, there's no delay for an autoresume.
 
 
        Other parts of the driver interface
@@ -527,13 +526,3 @@ succeed, it may still remain active and thus cause the system to
 resume as soon as the system suspend is complete.  Or the remote
 wakeup may fail and get lost.  Which outcome occurs depends on timing
 and on the hardware and firmware design.
-
-More interestingly, a device might undergo a manual resume or
-autoresume during system suspend.  With current kernels this shouldn't
-happen, because manual resumes must be initiated by userspace and
-autoresumes happen in response to I/O requests, but all user processes
-and I/O should be quiescent during a system suspend -- thanks to the
-freezer.  However there are plans to do away with the freezer, which
-would mean these things would become possible.  If and when this comes
-about, the USB core will carefully arrange matters so that either type
-of resume will block until the entire system has resumed.
index 9ddfc97..cf3f412 100644 (file)
@@ -1402,6 +1402,8 @@ L:        linux-usb@vger.kernel.org
 S:     Supported
 F:     Documentation/usb/WUSB-Design-overview.txt
 F:     Documentation/usb/wusb-cbaf
+F:     drivers/usb/host/hwa-hc.c
+F:     drivers/usb/host/whci/
 F:     drivers/usb/wusbcore/
 F:     include/linux/usb/wusb*
 
@@ -3683,7 +3685,7 @@ F:        include/linux/isicom.h
 MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
 M:     Felipe Balbi <felipe.balbi@nokia.com>
 L:     linux-usb@vger.kernel.org
-T:     git git://gitorious.org/musb/mainline.git
+T:     git git://gitorious.org/usb/usb.git
 S:     Maintained
 F:     drivers/usb/musb/
 
@@ -5436,7 +5438,10 @@ ULTRA-WIDEBAND (UWB) SUBSYSTEM:
 M:     David Vrabel <david.vrabel@csr.com>
 L:     linux-usb@vger.kernel.org
 S:     Supported
-F:     drivers/uwb/*
+F:     drivers/uwb/
+X:     drivers/uwb/wlp/
+X:     drivers/uwb/i1480/i1480u-wlp/
+X:     drivers/uwb/i1480/i1480-wlp.h
 F:     include/linux/uwb.h
 F:     include/linux/uwb/
 
@@ -5949,9 +5954,12 @@ W:       http://linuxwimax.org
 
 WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM
 M:     David Vrabel <david.vrabel@csr.com>
+L:     netdev@vger.kernel.org
 S:     Maintained
 F:     include/linux/wlp.h
 F:     drivers/uwb/wlp/
+F:     drivers/uwb/i1480/i1480u-wlp/
+F:     drivers/uwb/i1480/i1480-wlp.h
 
 WISTRON LAPTOP BUTTON DRIVER
 M:     Miloslav Trmac <mitr@volny.cz>
index 0ac5812..e6b06cb 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,13 @@ NAME = Man-Eating Seals of Antiquity
 # o  print "Entering directory ...";
 MAKEFLAGS += -rR --no-print-directory
 
+# Avoid funny character set dependencies
+unexport LC_ALL
+LC_CTYPE=C
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_CTYPE LC_COLLATE LC_NUMERIC
+
 # We are using a recursive build, so we need to do a little thinking
 # to get the ordering right.
 #
index d828758..9d055b4 100644 (file)
@@ -135,9 +135,7 @@ config HAVE_DEFAULT_NO_SPIN_MUTEXES
 
 config HAVE_HW_BREAKPOINT
        bool
-       depends on HAVE_PERF_EVENTS
-       select ANON_INODES
-       select PERF_EVENTS
+       depends on PERF_EVENTS
 
 config HAVE_USER_RETURN_NOTIFIER
        bool
index 4434481..bd7261e 100644 (file)
@@ -9,6 +9,7 @@ config ALPHA
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_SYSCALL_WRAPPERS
+       select HAVE_PERF_EVENTS
        help
          The Alpha is a 64-bit general-purpose processor designed and
          marketed by the Digital Equipment Corporation of blessed memory,
index 1720c8a..f091682 100644 (file)
@@ -13,7 +13,8 @@
                "call_pal %0  # bugchk\n\t"                             \
                ".long %1\n\t.8byte %2"                                 \
                : : "i"(PAL_bugchk), "i"(__LINE__), "i"(__FILE__));     \
-       for ( ; ; ); } while (0)
+       unreachable();                                                  \
+  } while (0)
 
 #define HAVE_ARCH_BUG
 #endif
diff --git a/arch/alpha/include/asm/perf_event.h b/arch/alpha/include/asm/perf_event.h
new file mode 100644 (file)
index 0000000..3bef852
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __ASM_ALPHA_PERF_EVENT_H
+#define __ASM_ALPHA_PERF_EVENT_H
+
+/* Alpha only supports software events through this interface. */
+static inline void set_perf_event_pending(void) { }
+
+#define PERF_EVENT_INDEX_OFFSET 0
+
+#endif /* __ASM_ALPHA_PERF_EVENT_H */
index 7f23665..804e531 100644 (file)
 #define __IGNORE_pause
 #define __IGNORE_time
 #define __IGNORE_utime
+#define __IGNORE_umount2
 
 /*
  * Linux-specific system calls begin at 300
 #define __NR_timerfd                   477
 #define __NR_eventfd                   478
 #define __NR_recvmmsg                  479
+#define __NR_fallocate                 480
+#define __NR_timerfd_create            481
+#define __NR_timerfd_settime           482
+#define __NR_timerfd_gettime           483
+#define __NR_signalfd4                 484
+#define __NR_eventfd2                  485
+#define __NR_epoll_create1             486
+#define __NR_dup3                      487
+#define __NR_pipe2                     488
+#define __NR_inotify_init1             489
+#define __NR_preadv                    490
+#define __NR_pwritev                   491
+#define __NR_rt_tgsigqueueinfo         492
+#define __NR_perf_event_open           493
 
 #ifdef __KERNEL__
 
-#define NR_SYSCALLS                    480
+#define NR_SYSCALLS                    494
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index cda6b8b..09acb78 100644 (file)
@@ -495,9 +495,23 @@ sys_call_table:
        .quad sys_epoll_pwait
        .quad sys_utimensat                     /* 475 */
        .quad sys_signalfd
-       .quad sys_ni_syscall
+       .quad sys_ni_syscall                    /* sys_timerfd */
        .quad sys_eventfd
        .quad sys_recvmmsg
+       .quad sys_fallocate                             /* 480 */
+       .quad sys_timerfd_create
+       .quad sys_timerfd_settime
+       .quad sys_timerfd_gettime
+       .quad sys_signalfd4
+       .quad sys_eventfd2                              /* 485 */
+       .quad sys_epoll_create1
+       .quad sys_dup3
+       .quad sys_pipe2
+       .quad sys_inotify_init1
+       .quad sys_preadv                                /* 490 */
+       .quad sys_pwritev
+       .quad sys_rt_tgsigqueueinfo
+       .quad sys_perf_event_open
 
        .size sys_call_table, . - sys_call_table
        .type sys_call_table, @object
index 91df968..7ae5889 100644 (file)
@@ -132,6 +132,12 @@ extern int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS];
 extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
 #endif
 
+static inline bool arch_has_acpi_pdc(void) { return true; }
+static inline void arch_acpi_set_pdc_bits(u32 *buf)
+{
+       buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
+}
+
 #define acpi_unlazy_tlb(x)
 
 #ifdef CONFIG_ACPI_NUMA
index 2a75e93..e123634 100644 (file)
@@ -18,10 +18,6 @@ obj-$(CONFIG_IA64_GENERIC)   += acpi-ext.o
 obj-$(CONFIG_IA64_HP_ZX1)      += acpi-ext.o
 obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o
 
-ifneq ($(CONFIG_ACPI_PROCESSOR),)
-obj-y                          += acpi-processor.o
-endif
-
 obj-$(CONFIG_IA64_PALINFO)     += palinfo.o
 obj-$(CONFIG_IOSAPIC)          += iosapic.o
 obj-$(CONFIG_MODULES)          += module.o
diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c
deleted file mode 100644 (file)
index dbda7bd..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * arch/ia64/kernel/acpi-processor.c
- *
- * Copyright (C) 2005 Intel Corporation
- *     Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- *     - Added _PDC for platforms with Intel CPUs
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-
-#include <acpi/processor.h>
-#include <asm/acpi.h>
-
-static void init_intel_pdc(struct acpi_processor *pr)
-{
-       struct acpi_object_list *obj_list;
-       union acpi_object *obj;
-       u32 *buf;
-
-       /* allocate and initialize pdc. It will be used later. */
-       obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
-       if (!obj_list) {
-               printk(KERN_ERR "Memory allocation error\n");
-               return;
-       }
-
-       obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-       if (!obj) {
-               printk(KERN_ERR "Memory allocation error\n");
-               kfree(obj_list);
-               return;
-       }
-
-       buf = kmalloc(12, GFP_KERNEL);
-       if (!buf) {
-               printk(KERN_ERR "Memory allocation error\n");
-               kfree(obj);
-               kfree(obj_list);
-               return;
-       }
-
-       buf[0] = ACPI_PDC_REVISION_ID;
-       buf[1] = 1;
-       buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
-       /*
-        * The default of PDC_SMP_T_SWCOORD bit is set for IA64 cpu so
-        * that OSPM is capable of native ACPI throttling software
-        * coordination using BIOS supplied _TSD info.
-        */
-       buf[2] |= ACPI_PDC_SMP_T_SWCOORD;
-
-       obj->type = ACPI_TYPE_BUFFER;
-       obj->buffer.length = 12;
-       obj->buffer.pointer = (u8 *) buf;
-       obj_list->count = 1;
-       obj_list->pointer = obj;
-       pr->pdc = obj_list;
-
-       return;
-}
-
-/* Initialize _PDC data based on the CPU vendor */
-void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
-{
-       pr->pdc = NULL;
-       init_intel_pdc(pr);
-       return;
-}
-
-EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
-
-void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr)
-{
-       if (pr->pdc) {
-               kfree(pr->pdc->pointer->buffer.pointer);
-               kfree(pr->pdc->pointer);
-               kfree(pr->pdc);
-               pr->pdc = NULL;
-       }
-}
-
-EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc);
index 51eb6ed..8f345de 100644 (file)
                dcr-reg = <0x00c 0x002>;
        };
 
+       MQ0: mq {
+               compatible = "ibm,mq-440spe";
+               dcr-reg = <0x040 0x020>;
+       };
+
        plb {
                compatible = "ibm,plb-440spe", "ibm,plb-440gp", "ibm,plb4";
                #address-cells = <2>;
                #size-cells = <1>;
                /*        addr-child     addr-parent    size */
-               ranges = <0x4 0xe0000000 0x4 0xe0000000 0x20000000
+               ranges = <0x4 0x00100000 0x4 0x00100000 0x00001000
+                         0x4 0x00200000 0x4 0x00200000 0x00000400
+                         0x4 0xe0000000 0x4 0xe0000000 0x20000000
                          0xc 0x00000000 0xc 0x00000000 0x20000000
                          0xd 0x00000000 0xd 0x00000000 0x80000000
                          0xd 0x80000000 0xd 0x80000000 0x80000000
                                0x0 0x0 0x0 0x3 &UIC3 0xa 0x4 /* swizzled int C */
                                0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>;
                };
+
+               I2O: i2o@400100000 {
+                       compatible = "ibm,i2o-440spe";
+                       reg = <0x00000004 0x00100000 0x100>;
+                       dcr-reg = <0x060 0x020>;
+               };
+
+               DMA0: dma0@400100100 {
+                       compatible = "ibm,dma-440spe";
+                       cell-index = <0>;
+                       reg = <0x00000004 0x00100100 0x100>;
+                       dcr-reg = <0x060 0x020>;
+                       interrupt-parent = <&DMA0>;
+                       interrupts = <0 1>;
+                       #interrupt-cells = <1>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <
+                               0 &UIC0 0x14 4
+                               1 &UIC1 0x16 4>;
+               };
+
+               DMA1: dma1@400100200 {
+                       compatible = "ibm,dma-440spe";
+                       cell-index = <1>;
+                       reg = <0x00000004 0x00100200 0x100>;
+                       dcr-reg = <0x060 0x020>;
+                       interrupt-parent = <&DMA1>;
+                       interrupts = <0 1>;
+                       #interrupt-cells = <1>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <
+                               0 &UIC0 0x16 4
+                               1 &UIC1 0x16 4>;
+               };
+
+               xor-accel@400200000 {
+                       compatible = "amcc,xor-accelerator";
+                       reg = <0x00000004 0x00200000 0x400>;
+                       interrupt-parent = <&UIC1>;
+                       interrupts = <0x1f 4>;
+               };
        };
 
        chosen {
index 32e10f5..8a3a4f3 100644 (file)
                        interrupt-parent = <&ipic>;
                        tbi-handle = <&tbi0>;
                        phy-handle = < &phy0 >;
+                       fsl,magic-packet;
 
                        mdio@520 {
                                #address-cells = <1>;
                        interrupt-parent = <&ipic>;
                        tbi-handle = <&tbi1>;
                        phy-handle = < &phy1 >;
+                       fsl,magic-packet;
 
                        mdio@520 {
                                #address-cells = <1>;
                        interrupt-parent = <&ipic>;
                };
 
+               gtm1: timer@500 {
+                       compatible = "fsl,mpc8315-gtm", "fsl,gtm";
+                       reg = <0x500 0x100>;
+                       interrupts = <90 8 78 8 84 8 72 8>;
+                       interrupt-parent = <&ipic>;
+                       clock-frequency = <133333333>;
+               };
+
+               timer@600 {
+                       compatible = "fsl,mpc8315-gtm", "fsl,gtm";
+                       reg = <0x600 0x100>;
+                       interrupts = <91 8 79 8 85 8 73 8>;
+                       interrupt-parent = <&ipic>;
+                       clock-frequency = <133333333>;
+               };
+
                /* IPIC
                 * interrupts cell = <intr #, sense>
                 * sense values match linux IORESOURCE_IRQ_* defines:
                                      0x59 0x8>;
                        interrupt-parent = < &ipic >;
                };
+
+               pmc: power@b00 {
+                       compatible = "fsl,mpc8315-pmc", "fsl,mpc8313-pmc",
+                                    "fsl,mpc8349-pmc";
+                       reg = <0xb00 0x100 0xa00 0x100>;
+                       interrupts = <80 8>;
+                       interrupt-parent = <&ipic>;
+                       fsl,mpc8313-wakeup-timer = <&gtm1>;
+               };
        };
 
        pci0: pci@e0008500 {
index feeeb7f..b53d1df 100644 (file)
                        reg = <0x200 0x100>;
                };
 
+               gpio1: gpio-controller@c00 {
+                       #gpio-cells = <2>;
+                       compatible = "fsl,mpc8349-gpio";
+                       reg = <0xc00 0x100>;
+                       interrupts = <74 0x8>;
+                       interrupt-parent = <&ipic>;
+                       gpio-controller;
+               };
+
+               gpio2: gpio-controller@d00 {
+                       #gpio-cells = <2>;
+                       compatible = "fsl,mpc8349-gpio";
+                       reg = <0xd00 0x100>;
+                       interrupts = <75 0x8>;
+                       interrupt-parent = <&ipic>;
+                       gpio-controller;
+               };
+
                i2c@3000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        interrupts = <14 0x8>;
                        interrupt-parent = <&ipic>;
                        dfsrr;
+
+                       eeprom: at24@50 {
+                               compatible = "st-micro,24c256";
+                               reg = <0x50>;
+                       };
+
                };
 
                i2c@3100 {
                                interrupt-parent = <&ipic>;
                        };
 
+                       pcf1: iexp@38 {
+                               #gpio-cells = <2>;
+                               compatible = "ti,pcf8574a";
+                               reg = <0x38>;
+                               gpio-controller;
+                       };
+
+                       pcf2: iexp@39 {
+                               #gpio-cells = <2>;
+                               compatible = "ti,pcf8574a";
+                               reg = <0x39>;
+                               gpio-controller;
+                       };
+
+                       spd: at24@51 {
+                               compatible = "at24,spd";
+                               reg = <0x51>;
+                       };
+
                        mcu_pio: mcu@a {
                                #gpio-cells = <2>;
                                compatible = "fsl,mc9s08qg8-mpc8349emitx",
                        reg = <0x700 0x100>;
                        device_type = "ipic";
                };
+
+               gpio-leds {
+                       compatible = "gpio-leds";
+
+                       green {
+                               label = "Green";
+                               gpios = <&pcf1 0 1>;
+                               linux,default-trigger = "heartbeat";
+                       };
+
+                       yellow {
+                               label = "Yellow";
+                               gpios = <&pcf1 1 1>;
+                               /* linux,default-trigger = "heartbeat"; */
+                               default-state = "on";
+                       };
+               };
+
        };
 
        pci0: pci@e0008500 {
                compatible = "fsl,mpc8349e-localbus",
                             "fsl,pq2pro-localbus";
                reg = <0xe0005000 0xd8>;
-               ranges = <0x3 0x0 0xf0000000 0x210>;
+               ranges = <0x0 0x0 0xfe000000 0x1000000  /* flash */
+                         0x1 0x0 0xf8000000 0x20000    /* VSC 7385 */
+                         0x2 0x0 0xf9000000 0x200000   /* exp slot */
+                         0x3 0x0 0xf0000000 0x210>;    /* CF slot */
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0x0      0x0 0x800000>;
+                       bank-width = <2>;
+                       device-width = <1>;
+               };
+
+               flash@0,800000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "cfi-flash";
+                       reg = <0x0 0x800000 0x800000>;
+                       bank-width = <2>;
+                       device-width = <1>;
+               };
 
                pata@3,0 {
                        compatible = "fsl,mpc8349emitx-pata", "ata-generic";
index 31605ee..e576ee8 100644 (file)
 
                                fpga@2,4000 {
                                        compatible = "pika,fpga-sd";
-                                       reg = <0x00000002 0x00004000 0x00000A00>;
+                                       reg = <0x00000002 0x00004000 0x00004000>;
                                };
 
                                nor@0,0 {
index 50609ea..8f2a6b3 100644 (file)
@@ -86,7 +86,7 @@ static void ug_putc(char ch)
 
        while (!ug_is_txfifo_ready() && count--)
                barrier();
-       if (count)
+       if (count >= 0)
                ug_raw_putc(ch);
 }
 
index fc90592..826a65d 100644 (file)
@@ -757,7 +757,7 @@ CONFIG_SUNGEM=y
 # CONFIG_B44 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
-CONFIG_ACENIC=y
+CONFIG_ACENIC=m
 CONFIG_ACENIC_OMIT_TIGON_I=y
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -794,8 +794,8 @@ CONFIG_NETDEV_10000=y
 # CONFIG_BNX2X is not set
 # CONFIG_QLGE is not set
 # CONFIG_SFC is not set
-CONFIG_TR=y
-CONFIG_IBMOL=y
+# CONFIG_TR is not set
+# CONFIG_IBMOL is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
 
index f925c55..76982c5 100644 (file)
@@ -714,8 +714,8 @@ CONFIG_NETDEV_10000=y
 # CONFIG_BNX2X is not set
 # CONFIG_QLGE is not set
 # CONFIG_SFC is not set
-CONFIG_TR=y
-CONFIG_IBMOL=y
+# CONFIG_TR is not set
+# CONFIG_IBMOL is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
 
index 2524018..7b3804a 100644 (file)
@@ -304,11 +304,11 @@ CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+CONFIG_HZ=100
 CONFIG_SCHED_HRTICK=y
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
@@ -980,7 +980,7 @@ CONFIG_E100=y
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
-CONFIG_ACENIC=y
+CONFIG_ACENIC=m
 CONFIG_ACENIC_OMIT_TIGON_I=y
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -1023,8 +1023,8 @@ CONFIG_PASEMI_MAC=y
 # CONFIG_BNX2X is not set
 # CONFIG_QLGE is not set
 # CONFIG_SFC is not set
-CONFIG_TR=y
-CONFIG_IBMOL=y
+# CONFIG_TR is not set
+# CONFIG_IBMOL is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
 
@@ -1863,7 +1863,7 @@ CONFIG_HFSPLUS_FS=m
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_CRAMFS=y
+CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
index 18af460..8195f16 100644 (file)
@@ -1008,8 +1008,8 @@ CONFIG_IXGB=m
 # CONFIG_QLGE is not set
 # CONFIG_SFC is not set
 # CONFIG_BE2NET is not set
-CONFIG_TR=y
-CONFIG_IBMOL=y
+# CONFIG_TR is not set
+# CONFIG_IBMOL is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
 CONFIG_WLAN=y
index c568329..ca9ff9a 100644 (file)
@@ -230,11 +230,11 @@ CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+CONFIG_HZ=100
 CONFIG_SCHED_HRTICK=y
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
@@ -796,7 +796,7 @@ CONFIG_E100=y
 # CONFIG_NET_POCKET is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
-CONFIG_ACENIC=y
+CONFIG_ACENIC=m
 CONFIG_ACENIC_OMIT_TIGON_I=y
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -834,8 +834,8 @@ CONFIG_S2IO=m
 # CONFIG_BNX2X is not set
 # CONFIG_QLGE is not set
 # CONFIG_SFC is not set
-CONFIG_TR=y
-CONFIG_IBMOL=y
+# CONFIG_TR is not set
+# CONFIG_IBMOL is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
 
@@ -1494,7 +1494,7 @@ CONFIG_CONFIGFS_FS=m
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_CRAMFS=y
+CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
index 64e1fdc..2c15212 100644 (file)
@@ -68,7 +68,7 @@
                _EMIT_BUG_ENTRY                                 \
                : : "i" (__FILE__), "i" (__LINE__),             \
                    "i" (0), "i"  (sizeof(struct bug_entry)));  \
-       for(;;) ;                                               \
+       unreachable();                                          \
 } while (0)
 
 #define BUG_ON(x) do {                                         \
index ea04632..38762ed 100644 (file)
@@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio)
        return __gpio_cansleep(gpio);
 }
 
-/*
- * Not implemented, yet.
- */
 static inline int gpio_to_irq(unsigned int gpio)
 {
-       return -ENOSYS;
+       return __gpio_to_irq(gpio);
 }
 
 static inline int irq_to_gpio(unsigned int irq)
index 3839839..b876e98 100644 (file)
@@ -642,10 +642,14 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,
  */
 static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
                       unsigned int areg, struct pt_regs *regs,
-                      unsigned int flags, unsigned int length)
+                      unsigned int flags, unsigned int length,
+                      unsigned int elsize)
 {
        char *ptr;
+       unsigned long *lptr;
        int ret = 0;
+       int sw = 0;
+       int i, j;
 
        flush_vsx_to_thread(current);
 
@@ -654,19 +658,35 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
        else
                ptr = (char *) &current->thread.vr[reg - 32];
 
-       if (flags & ST)
-               ret = __copy_to_user(addr, ptr, length);
-        else {
-               if (flags & SPLT){
-                       ret = __copy_from_user(ptr, addr, length);
-                       ptr += length;
+       lptr = (unsigned long *) ptr;
+
+       if (flags & SW)
+               sw = elsize-1;
+
+       for (j = 0; j < length; j += elsize) {
+               for (i = 0; i < elsize; ++i) {
+                       if (flags & ST)
+                               ret |= __put_user(ptr[i^sw], addr + i);
+                       else
+                               ret |= __get_user(ptr[i^sw], addr + i);
                }
-               ret |= __copy_from_user(ptr, addr, length);
+               ptr  += elsize;
+               addr += elsize;
        }
-       if (flags & U)
-               regs->gpr[areg] = regs->dar;
-       if (ret)
+
+       if (!ret) {
+               if (flags & U)
+                       regs->gpr[areg] = regs->dar;
+
+               /* Splat load copies the same data to top and bottom 8 bytes */
+               if (flags & SPLT)
+                       lptr[1] = lptr[0];
+               /* For 8 byte loads, zero the top 8 bytes */
+               else if (!(flags & ST) && (8 == length))
+                       lptr[1] = 0;
+       } else
                return -EFAULT;
+
        return 1;
 }
 #endif
@@ -767,16 +787,25 @@ int fix_alignment(struct pt_regs *regs)
 
 #ifdef CONFIG_VSX
        if ((instruction & 0xfc00003e) == 0x7c000018) {
-               /* Additional register addressing bit (64 VSX vs 32 FPR/GPR */
+               unsigned int elsize;
+
+               /* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */
                reg |= (instruction & 0x1) << 5;
                /* Simple inline decoder instead of a table */
+               /* VSX has only 8 and 16 byte memory accesses */
+               nb = 8;
                if (instruction & 0x200)
                        nb = 16;
-               else if (instruction & 0x080)
-                       nb = 8;
-               else
-                       nb = 4;
+
+               /* Vector stores in little-endian mode swap individual
+                  elements, so process them separately */
+               elsize = 4;
+               if (instruction & 0x80)
+                       elsize = 8;
+
                flags = 0;
+               if (regs->msr & MSR_LE)
+                       flags |= SW;
                if (instruction & 0x100)
                        flags |= ST;
                if (instruction & 0x040)
@@ -787,7 +816,7 @@ int fix_alignment(struct pt_regs *regs)
                        nb = 8;
                }
                PPC_WARN_ALIGNMENT(vsx, regs);
-               return emulate_vsx(addr, reg, areg, regs, flags, nb);
+               return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize);
        }
 #endif
        /* A size of 0 indicates an instruction we don't support, with
index 50f867d..3ecdcec 100644 (file)
@@ -340,7 +340,7 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
                        else
                                def->tlbiel = 0;
 
-                       DBG(" %d: shift=%02x, sllp=%04x, avpnm=%08x, "
+                       DBG(" %d: shift=%02x, sllp=%04lx, avpnm=%08lx, "
                            "tlbiel=%d, penc=%d\n",
                            idx, shift, def->sllp, def->avpnm, def->tlbiel,
                            def->penc);
@@ -663,7 +663,7 @@ static void __init htab_initialize(void)
                base = (unsigned long)__va(lmb.memory.region[i].base);
                size = lmb.memory.region[i].size;
 
-               DBG("creating mapping for region: %lx..%lx (prot: %x)\n",
+               DBG("creating mapping for region: %lx..%lx (prot: %lx)\n",
                    base, size, prot);
 
 #ifdef CONFIG_U3_DART
@@ -879,7 +879,7 @@ static inline int subpage_protection(struct mm_struct *mm, unsigned long ea)
  */
 int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 {
-       void *pgdir;
+       pgd_t *pgdir;
        unsigned long vsid;
        struct mm_struct *mm;
        pte_t *ptep;
@@ -1025,7 +1025,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
        else
 #endif /* CONFIG_PPC_HAS_HASH_64K */
        {
-               int spp = subpage_protection(pgdir, ea);
+               int spp = subpage_protection(mm, ea);
                if (access & spp)
                        rc = -2;
                else
@@ -1115,7 +1115,7 @@ void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize,
 {
        unsigned long hash, index, shift, hidx, slot;
 
-       DBG_LOW("flush_hash_page(va=%016x)\n", va);
+       DBG_LOW("flush_hash_page(va=%016lx)\n", va);
        pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
                hash = hpt_hash(va, shift, ssize);
                hidx = __rpte_to_hidx(pte, index);
@@ -1123,7 +1123,7 @@ void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize,
                        hash = ~hash;
                slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
                slot += hidx & _PTEIDX_GROUP_IX;
-               DBG_LOW(" sub %d: hash=%x, hidx=%x\n", index, slot, hidx);
+               DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx);
                ppc_md.hpte_invalidate(slot, va, psize, ssize, local);
        } pte_iterate_hashed_end();
 }
index be4f34c..1044a63 100644 (file)
@@ -353,7 +353,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self,
                read_lock(&tasklist_lock);
                for_each_process(p) {
                        if (p->mm)
-                               cpu_mask_clear_cpu(cpu, mm_cpumask(p->mm));
+                               cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
                }
                read_unlock(&tasklist_lock);
        break;
index 177e403..573b3bd 100644 (file)
@@ -382,7 +382,7 @@ static int __change_page_attr(struct page *page, pgprot_t prot)
                return 0;
        if (!get_pteptr(&init_mm, address, &kpte, &kpmd))
                return -EINVAL;
-       set_pte_at(&init_mm, address, kpte, mk_pte(page, prot));
+       __set_pte_at(&init_mm, address, kpte, mk_pte(page, prot), 0);
        wmb();
 #ifdef CONFIG_PPC_STD_MMU
        flush_hash_pages(0, address, pmd_val(*kpmd), 1);
index d306f07..4380534 100644 (file)
@@ -32,6 +32,7 @@
 #define PMCCR1_NEXT_STATE       0x0C /* Next state for power management */
 #define PMCCR1_NEXT_STATE_SHIFT 2
 #define PMCCR1_CURR_STATE       0x03 /* Current state for power management*/
+#define IMMR_SYSCR_OFFSET       0x100
 #define IMMR_RCW_OFFSET         0x900
 #define RCW_PCI_HOST            0x80000000
 
@@ -78,6 +79,22 @@ struct mpc83xx_clock {
        u32 sccr;
 };
 
+struct mpc83xx_syscr {
+       __be32 sgprl;
+       __be32 sgprh;
+       __be32 spridr;
+       __be32 :32;
+       __be32 spcr;
+       __be32 sicrl;
+       __be32 sicrh;
+};
+
+struct mpc83xx_saved {
+       u32 sicrl;
+       u32 sicrh;
+       u32 sccr;
+};
+
 struct pmc_type {
        int has_deep_sleep;
 };
@@ -87,6 +104,8 @@ static int has_deep_sleep, deep_sleeping;
 static int pmc_irq;
 static struct mpc83xx_pmc __iomem *pmc_regs;
 static struct mpc83xx_clock __iomem *clock_regs;
+static struct mpc83xx_syscr __iomem *syscr_regs;
+static struct mpc83xx_saved saved_regs;
 static int is_pci_agent, wake_from_pci;
 static phys_addr_t immrbase;
 static int pci_pm_state;
@@ -137,6 +156,20 @@ static irqreturn_t pmc_irq_handler(int irq, void *dev_id)
        return ret;
 }
 
+static void mpc83xx_suspend_restore_regs(void)
+{
+       out_be32(&syscr_regs->sicrl, saved_regs.sicrl);
+       out_be32(&syscr_regs->sicrh, saved_regs.sicrh);
+       out_be32(&clock_regs->sccr, saved_regs.sccr);
+}
+
+static void mpc83xx_suspend_save_regs(void)
+{
+       saved_regs.sicrl = in_be32(&syscr_regs->sicrl);
+       saved_regs.sicrh = in_be32(&syscr_regs->sicrh);
+       saved_regs.sccr = in_be32(&clock_regs->sccr);
+}
+
 static int mpc83xx_suspend_enter(suspend_state_t state)
 {
        int ret = -EAGAIN;
@@ -166,6 +199,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state)
         */
 
        if (deep_sleeping) {
+               mpc83xx_suspend_save_regs();
+
                out_be32(&pmc_regs->mask, PMCER_ALL);
 
                out_be32(&pmc_regs->config1,
@@ -179,6 +214,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state)
                         in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF);
 
                out_be32(&pmc_regs->mask, PMCER_PMCI);
+
+               mpc83xx_suspend_restore_regs();
        } else {
                out_be32(&pmc_regs->mask, PMCER_PMCI);
 
@@ -194,7 +231,7 @@ out:
        return ret;
 }
 
-static void mpc83xx_suspend_finish(void)
+static void mpc83xx_suspend_end(void)
 {
        deep_sleeping = 0;
 }
@@ -278,7 +315,7 @@ static struct platform_suspend_ops mpc83xx_suspend_ops = {
        .valid = mpc83xx_suspend_valid,
        .begin = mpc83xx_suspend_begin,
        .enter = mpc83xx_suspend_enter,
-       .finish = mpc83xx_suspend_finish,
+       .end = mpc83xx_suspend_end,
 };
 
 static int pmc_probe(struct of_device *ofdev,
@@ -333,12 +370,23 @@ static int pmc_probe(struct of_device *ofdev,
                goto out_pmc;
        }
 
+       if (has_deep_sleep) {
+               syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET,
+                                    sizeof(*syscr_regs));
+               if (!syscr_regs) {
+                       ret = -ENOMEM;
+                       goto out_syscr;
+               }
+       }
+
        if (is_pci_agent)
                mpc83xx_set_agent();
 
        suspend_set_ops(&mpc83xx_suspend_ops);
        return 0;
 
+out_syscr:
+       iounmap(clock_regs);
 out_pmc:
        iounmap(pmc_regs);
 out:
index c5028a2..21f61b8 100644 (file)
@@ -86,7 +86,7 @@ static int mpc8568_fixup_125_clock(struct phy_device *phydev)
        scr = phy_read(phydev, MV88E1111_SCR);
 
        if (scr < 0)
-               return err;
+               return scr;
 
        err = phy_write(phydev, MV88E1111_SCR, scr | 0x0008);
 
index d596328..c278bd3 100644 (file)
@@ -102,7 +102,7 @@ static int flipper_pic_map(struct irq_host *h, unsigned int virq,
                           irq_hw_number_t hwirq)
 {
        set_irq_chip_data(virq, h->host_data);
-       get_irq_desc(virq)->status |= IRQ_LEVEL;
+       irq_to_desc(virq)->status |= IRQ_LEVEL;
        set_irq_chip_and_handler(virq, &flipper_pic, handle_level_irq);
        return 0;
 }
index dd20bff..a771f91 100644 (file)
@@ -95,7 +95,7 @@ static int hlwd_pic_map(struct irq_host *h, unsigned int virq,
                           irq_hw_number_t hwirq)
 {
        set_irq_chip_data(virq, h->host_data);
-       get_irq_desc(virq)->status |= IRQ_LEVEL;
+       irq_to_desc(virq)->status |= IRQ_LEVEL;
        set_irq_chip_and_handler(virq, &hlwd_pic, handle_level_irq);
        return 0;
 }
@@ -132,9 +132,9 @@ static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
        struct irq_host *irq_host = get_irq_data(cascade_virq);
        unsigned int virq;
 
-       spin_lock(&desc->lock);
+       raw_spin_lock(&desc->lock);
        desc->chip->mask(cascade_virq); /* IRQ_LEVEL */
-       spin_unlock(&desc->lock);
+       raw_spin_unlock(&desc->lock);
 
        virq = __hlwd_pic_get_irq(irq_host);
        if (virq != NO_IRQ)
@@ -142,11 +142,11 @@ static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
        else
                pr_err("spurious interrupt!\n");
 
-       spin_lock(&desc->lock);
+       raw_spin_lock(&desc->lock);
        desc->chip->ack(cascade_virq); /* IRQ_LEVEL */
        if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
                desc->chip->unmask(cascade_virq);
-       spin_unlock(&desc->lock);
+       raw_spin_unlock(&desc->lock);
 }
 
 /*
index edc956c..20a8ed9 100644 (file)
@@ -120,7 +120,7 @@ static void ug_putc(char ch)
 
        while (!ug_is_txfifo_ready() && count--)
                barrier();
-       if (count)
+       if (count >= 0)
                ug_raw_putc(ch);
 }
 
index 0d9343d..6617915 100644 (file)
@@ -855,59 +855,58 @@ static int mf_get_boot_rtc(struct rtc_time *tm)
 }
 
 #ifdef CONFIG_PROC_FS
-
-static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
-               int count, int *eof, void *data)
+static int mf_cmdline_proc_show(struct seq_file *m, void *v)
 {
-       int len;
-       char *p;
+       char *page, *p;
        struct vsp_cmd_data vsp_cmd;
        int rc;
        dma_addr_t dma_addr;
 
        /* The HV appears to return no more than 256 bytes of command line */
-       if (off >= 256)
-               return 0;
-       if ((off + count) > 256)
-               count = 256 - off;
+       page = kmalloc(256, GFP_KERNEL);
+       if (!page)
+               return -ENOMEM;
 
-       dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE);
-       if (dma_addr == DMA_ERROR_CODE)
+       dma_addr = iseries_hv_map(page, 256, DMA_FROM_DEVICE);
+       if (dma_addr == DMA_ERROR_CODE) {
+               kfree(page);
                return -ENOMEM;
-       memset(page, 0, off + count);
+       }
+       memset(page, 0, 256);
        memset(&vsp_cmd, 0, sizeof(vsp_cmd));
        vsp_cmd.cmd = 33;
        vsp_cmd.sub_data.kern.token = dma_addr;
        vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
-       vsp_cmd.sub_data.kern.side = (u64)data;
-       vsp_cmd.sub_data.kern.length = off + count;
+       vsp_cmd.sub_data.kern.side = (u64)m->private;
+       vsp_cmd.sub_data.kern.length = 256;
        mb();
        rc = signal_vsp_instruction(&vsp_cmd);
-       iseries_hv_unmap(dma_addr, off + count, DMA_FROM_DEVICE);
-       if (rc)
+       iseries_hv_unmap(dma_addr, 256, DMA_FROM_DEVICE);
+       if (rc) {
+               kfree(page);
                return rc;
-       if (vsp_cmd.result_code != 0)
+       }
+       if (vsp_cmd.result_code != 0) {
+               kfree(page);
                return -ENOMEM;
+       }
        p = page;
-       len = 0;
-       while (len < (off + count)) {
-               if ((*p == '\0') || (*p == '\n')) {
-                       if (*p == '\0')
-                               *p = '\n';
-                       p++;
-                       len++;
-                       *eof = 1;
+       while (p - page < 256) {
+               if (*p == '\0' || *p == '\n') {
+                       *p = '\n';
                        break;
                }
                p++;
-               len++;
-       }
 
-       if (len < off) {
-               *eof = 1;
-               len = 0;
        }
-       return len;
+       seq_write(m, page, p - page);
+       kfree(page);
+       return 0;
+}
+
+static int mf_cmdline_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mf_cmdline_proc_show, PDE(inode)->data);
 }
 
 #if 0
@@ -962,10 +961,8 @@ static int proc_mf_dump_vmlinux(char *page, char **start, off_t off,
 }
 #endif
 
-static int proc_mf_dump_side(char *page, char **start, off_t off,
-               int count, int *eof, void *data)
+static int mf_side_proc_show(struct seq_file *m, void *v)
 {
-       int len;
        char mf_current_side = ' ';
        struct vsp_cmd_data vsp_cmd;
 
@@ -989,21 +986,17 @@ static int proc_mf_dump_side(char *page, char **start, off_t off,
                }
        }
 
-       len = sprintf(page, "%c\n", mf_current_side);
+       seq_printf(m, "%c\n", mf_current_side);
+       return 0;
+}
 
-       if (len <= (off + count))
-               *eof = 1;
-       *start = page + off;
-       len -= off;
-       if (len > count)
-               len = count;
-       if (len < 0)
-               len = 0;
-       return len;
+static int mf_side_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mf_side_proc_show, NULL);
 }
 
-static int proc_mf_change_side(struct file *file, const char __user *buffer,
-               unsigned long count, void *data)
+static ssize_t mf_side_proc_write(struct file *file, const char __user *buffer,
+                                 size_t count, loff_t *pos)
 {
        char side;
        u64 newSide;
@@ -1041,6 +1034,15 @@ static int proc_mf_change_side(struct file *file, const char __user *buffer,
        return count;
 }
 
+static const struct file_operations mf_side_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = mf_side_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = mf_side_proc_write,
+};
+
 #if 0
 static void mf_getSrcHistory(char *buffer, int size)
 {
@@ -1087,8 +1089,7 @@ static void mf_getSrcHistory(char *buffer, int size)
 }
 #endif
 
-static int proc_mf_dump_src(char *page, char **start, off_t off,
-               int count, int *eof, void *data)
+static int mf_src_proc_show(struct seq_file *m, void *v)
 {
 #if 0
        int len;
@@ -1109,8 +1110,13 @@ static int proc_mf_dump_src(char *page, char **start, off_t off,
 #endif
 }
 
-static int proc_mf_change_src(struct file *file, const char __user *buffer,
-               unsigned long count, void *data)
+static int mf_src_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mf_src_proc_show, NULL);
+}
+
+static ssize_t mf_src_proc_write(struct file *file, const char __user *buffer,
+                                size_t count, loff_t *pos)
 {
        char stkbuf[10];
 
@@ -1135,9 +1141,19 @@ static int proc_mf_change_src(struct file *file, const char __user *buffer,
        return count;
 }
 
-static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
-               unsigned long count, void *data)
+static const struct file_operations mf_src_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = mf_src_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = mf_src_proc_write,
+};
+
+static ssize_t mf_cmdline_proc_write(struct file *file, const char __user *buffer,
+                                    size_t count, loff_t *pos)
 {
+       void *data = PDE(file->f_path.dentry->d_inode)->data;
        struct vsp_cmd_data vsp_cmd;
        dma_addr_t dma_addr;
        char *page;
@@ -1172,6 +1188,15 @@ out:
        return ret;
 }
 
+static const struct file_operations mf_cmdline_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = mf_cmdline_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = mf_cmdline_proc_write,
+};
+
 static ssize_t proc_mf_change_vmlinux(struct file *file,
                                      const char __user *buf,
                                      size_t count, loff_t *ppos)
@@ -1246,12 +1271,10 @@ static int __init mf_proc_init(void)
                if (!mf)
                        return 1;
 
-               ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf);
+               ent = proc_create_data("cmdline", S_IRUSR|S_IWUSR, mf,
+                                      &mf_cmdline_proc_fops, (void *)(long)i);
                if (!ent)
                        return 1;
-               ent->data = (void *)(long)i;
-               ent->read_proc = proc_mf_dump_cmdline;
-               ent->write_proc = proc_mf_change_cmdline;
 
                if (i == 3)     /* no vmlinux entry for 'D' */
                        continue;
@@ -1263,19 +1286,15 @@ static int __init mf_proc_init(void)
                        return 1;
        }
 
-       ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
+       ent = proc_create("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root,
+                         &mf_side_proc_fops);
        if (!ent)
                return 1;
-       ent->data = (void *)0;
-       ent->read_proc = proc_mf_dump_side;
-       ent->write_proc = proc_mf_change_side;
 
-       ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
+       ent = proc_create("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root,
+                         &mf_src_proc_fops);
        if (!ent)
                return 1;
-       ent->data = (void *)0;
-       ent->read_proc = proc_mf_dump_src;
-       ent->write_proc = proc_mf_change_src;
 
        return 0;
 }
index 49ff4dc..5aea94f 100644 (file)
@@ -116,7 +116,7 @@ static int proc_viopath_show(struct seq_file *m, void *v)
        u16 vlanMap;
        dma_addr_t handle;
        HvLpEvent_Rc hvrc;
-       DECLARE_COMPLETION(done);
+       DECLARE_COMPLETION_ONSTACK(done);
        struct device_node *node;
        const char *sysid;
 
index 27554c8..c667f0f 100644 (file)
@@ -2,6 +2,8 @@ config PPC_PSERIES
        depends on PPC64 && PPC_BOOK3S
        bool "IBM pSeries & new (POWER5-based) iSeries"
        select MPIC
+       select PCI_MSI
+       select XICS
        select PPC_I8259
        select PPC_RTAS
        select PPC_RTAS_DAEMON
index bcdcf0c..a277f2e 100644 (file)
 #include <asm/mmu.h>
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
+#include <linux/memory.h>
 
 #include "plpar_wrappers.h"
 
 #define CMM_DRIVER_VERSION     "1.0.0"
 #define CMM_DEFAULT_DELAY      1
+#define CMM_HOTPLUG_DELAY      5
 #define CMM_DEBUG                      0
 #define CMM_DISABLE            0
 #define CMM_OOM_KB             1024
 #define CMM_MIN_MEM_MB         256
 #define KB2PAGES(_p)           ((_p)>>(PAGE_SHIFT-10))
 #define PAGES2KB(_p)           ((_p)<<(PAGE_SHIFT-10))
+/*
+ * The priority level tries to ensure that this notifier is called as
+ * late as possible to reduce thrashing in the shared memory pool.
+ */
+#define CMM_MEM_HOTPLUG_PRI    1
+#define CMM_MEM_ISOLATE_PRI    15
 
 static unsigned int delay = CMM_DEFAULT_DELAY;
+static unsigned int hotplug_delay = CMM_HOTPLUG_DELAY;
 static unsigned int oom_kb = CMM_OOM_KB;
 static unsigned int cmm_debug = CMM_DEBUG;
 static unsigned int cmm_disabled = CMM_DISABLE;
@@ -65,6 +74,10 @@ MODULE_VERSION(CMM_DRIVER_VERSION);
 module_param_named(delay, delay, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. "
                 "[Default=" __stringify(CMM_DEFAULT_DELAY) "]");
+module_param_named(hotplug_delay, hotplug_delay, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(delay, "Delay (in seconds) after memory hotplug remove "
+                "before loaning resumes. "
+                "[Default=" __stringify(CMM_HOTPLUG_DELAY) "]");
 module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. "
                 "[Default=" __stringify(CMM_OOM_KB) "]");
@@ -92,6 +105,9 @@ static unsigned long oom_freed_pages;
 static struct cmm_page_array *cmm_page_list;
 static DEFINE_SPINLOCK(cmm_lock);
 
+static DEFINE_MUTEX(hotplug_mutex);
+static int hotplug_occurred; /* protected by the hotplug mutex */
+
 static struct task_struct *cmm_thread_ptr;
 
 /**
@@ -110,6 +126,17 @@ static long cmm_alloc_pages(long nr)
        cmm_dbg("Begin request for %ld pages\n", nr);
 
        while (nr) {
+               /* Exit if a hotplug operation is in progress or occurred */
+               if (mutex_trylock(&hotplug_mutex)) {
+                       if (hotplug_occurred) {
+                               mutex_unlock(&hotplug_mutex);
+                               break;
+                       }
+                       mutex_unlock(&hotplug_mutex);
+               } else {
+                       break;
+               }
+
                addr = __get_free_page(GFP_NOIO | __GFP_NOWARN |
                                       __GFP_NORETRY | __GFP_NOMEMALLOC);
                if (!addr)
@@ -119,8 +146,9 @@ static long cmm_alloc_pages(long nr)
                if (!pa || pa->index >= CMM_NR_PAGES) {
                        /* Need a new page for the page list. */
                        spin_unlock(&cmm_lock);
-                       npa = (struct cmm_page_array *)__get_free_page(GFP_NOIO | __GFP_NOWARN |
-                                                                      __GFP_NORETRY | __GFP_NOMEMALLOC);
+                       npa = (struct cmm_page_array *)__get_free_page(
+                                       GFP_NOIO | __GFP_NOWARN |
+                                       __GFP_NORETRY | __GFP_NOMEMALLOC);
                        if (!npa) {
                                pr_info("%s: Can not allocate new page list\n", __func__);
                                free_page(addr);
@@ -282,9 +310,28 @@ static int cmm_thread(void *dummy)
        while (1) {
                timeleft = msleep_interruptible(delay * 1000);
 
-               if (kthread_should_stop() || timeleft) {
-                       loaned_pages_target = loaned_pages;
+               if (kthread_should_stop() || timeleft)
                        break;
+
+               if (mutex_trylock(&hotplug_mutex)) {
+                       if (hotplug_occurred) {
+                               hotplug_occurred = 0;
+                               mutex_unlock(&hotplug_mutex);
+                               cmm_dbg("Hotplug operation has occurred, "
+                                               "loaning activity suspended "
+                                               "for %d seconds.\n",
+                                               hotplug_delay);
+                               timeleft = msleep_interruptible(hotplug_delay *
+                                               1000);
+                               if (kthread_should_stop() || timeleft)
+                                       break;
+                               continue;
+                       }
+                       mutex_unlock(&hotplug_mutex);
+               } else {
+                       cmm_dbg("Hotplug operation in progress, activity "
+                                       "suspended\n");
+                       continue;
                }
 
                cmm_get_mpp();
@@ -414,6 +461,193 @@ static struct notifier_block cmm_reboot_nb = {
 };
 
 /**
+ * cmm_count_pages - Count the number of pages loaned in a particular range.
+ *
+ * @arg: memory_isolate_notify structure with address range and count
+ *
+ * Return value:
+ *      0 on success
+ **/
+static unsigned long cmm_count_pages(void *arg)
+{
+       struct memory_isolate_notify *marg = arg;
+       struct cmm_page_array *pa;
+       unsigned long start = (unsigned long)pfn_to_kaddr(marg->start_pfn);
+       unsigned long end = start + (marg->nr_pages << PAGE_SHIFT);
+       unsigned long idx;
+
+       spin_lock(&cmm_lock);
+       pa = cmm_page_list;
+       while (pa) {
+               if ((unsigned long)pa >= start && (unsigned long)pa < end)
+                       marg->pages_found++;
+               for (idx = 0; idx < pa->index; idx++)
+                       if (pa->page[idx] >= start && pa->page[idx] < end)
+                               marg->pages_found++;
+               pa = pa->next;
+       }
+       spin_unlock(&cmm_lock);
+       return 0;
+}
+
+/**
+ * cmm_memory_isolate_cb - Handle memory isolation notifier calls
+ * @self:      notifier block struct
+ * @action:    action to take
+ * @arg:       struct memory_isolate_notify data for handler
+ *
+ * Return value:
+ *     NOTIFY_OK or notifier error based on subfunction return value
+ **/
+static int cmm_memory_isolate_cb(struct notifier_block *self,
+                                unsigned long action, void *arg)
+{
+       int ret = 0;
+
+       if (action == MEM_ISOLATE_COUNT)
+               ret = cmm_count_pages(arg);
+
+       if (ret)
+               ret = notifier_from_errno(ret);
+       else
+               ret = NOTIFY_OK;
+
+       return ret;
+}
+
+static struct notifier_block cmm_mem_isolate_nb = {
+       .notifier_call = cmm_memory_isolate_cb,
+       .priority = CMM_MEM_ISOLATE_PRI
+};
+
+/**
+ * cmm_mem_going_offline - Unloan pages where memory is to be removed
+ * @arg: memory_notify structure with page range to be offlined
+ *
+ * Return value:
+ *     0 on success
+ **/
+static int cmm_mem_going_offline(void *arg)
+{
+       struct memory_notify *marg = arg;
+       unsigned long start_page = (unsigned long)pfn_to_kaddr(marg->start_pfn);
+       unsigned long end_page = start_page + (marg->nr_pages << PAGE_SHIFT);
+       struct cmm_page_array *pa_curr, *pa_last, *npa;
+       unsigned long idx;
+       unsigned long freed = 0;
+
+       cmm_dbg("Memory going offline, searching 0x%lx (%ld pages).\n",
+                       start_page, marg->nr_pages);
+       spin_lock(&cmm_lock);
+
+       /* Search the page list for pages in the range to be offlined */
+       pa_last = pa_curr = cmm_page_list;
+       while (pa_curr) {
+               for (idx = (pa_curr->index - 1); (idx + 1) > 0; idx--) {
+                       if ((pa_curr->page[idx] < start_page) ||
+                           (pa_curr->page[idx] >= end_page))
+                               continue;
+
+                       plpar_page_set_active(__pa(pa_curr->page[idx]));
+                       free_page(pa_curr->page[idx]);
+                       freed++;
+                       loaned_pages--;
+                       totalram_pages++;
+                       pa_curr->page[idx] = pa_last->page[--pa_last->index];
+                       if (pa_last->index == 0) {
+                               if (pa_curr == pa_last)
+                                       pa_curr = pa_last->next;
+                               pa_last = pa_last->next;
+                               free_page((unsigned long)cmm_page_list);
+                               cmm_page_list = pa_last;
+                               continue;
+                       }
+               }
+               pa_curr = pa_curr->next;
+       }
+
+       /* Search for page list structures in the range to be offlined */
+       pa_last = NULL;
+       pa_curr = cmm_page_list;
+       while (pa_curr) {
+               if (((unsigned long)pa_curr >= start_page) &&
+                               ((unsigned long)pa_curr < end_page)) {
+                       npa = (struct cmm_page_array *)__get_free_page(
+                                       GFP_NOIO | __GFP_NOWARN |
+                                       __GFP_NORETRY | __GFP_NOMEMALLOC);
+                       if (!npa) {
+                               spin_unlock(&cmm_lock);
+                               cmm_dbg("Failed to allocate memory for list "
+                                               "management. Memory hotplug "
+                                               "failed.\n");
+                               return ENOMEM;
+                       }
+                       memcpy(npa, pa_curr, PAGE_SIZE);
+                       if (pa_curr == cmm_page_list)
+                               cmm_page_list = npa;
+                       if (pa_last)
+                               pa_last->next = npa;
+                       free_page((unsigned long) pa_curr);
+                       freed++;
+                       pa_curr = npa;
+               }
+
+               pa_last = pa_curr;
+               pa_curr = pa_curr->next;
+       }
+
+       spin_unlock(&cmm_lock);
+       cmm_dbg("Released %ld pages in the search range.\n", freed);
+
+       return 0;
+}
+
+/**
+ * cmm_memory_cb - Handle memory hotplug notifier calls
+ * @self:      notifier block struct
+ * @action:    action to take
+ * @arg:       struct memory_notify data for handler
+ *
+ * Return value:
+ *     NOTIFY_OK or notifier error based on subfunction return value
+ *
+ **/
+static int cmm_memory_cb(struct notifier_block *self,
+                       unsigned long action, void *arg)
+{
+       int ret = 0;
+
+       switch (action) {
+       case MEM_GOING_OFFLINE:
+               mutex_lock(&hotplug_mutex);
+               hotplug_occurred = 1;
+               ret = cmm_mem_going_offline(arg);
+               break;
+       case MEM_OFFLINE:
+       case MEM_CANCEL_OFFLINE:
+               mutex_unlock(&hotplug_mutex);
+               cmm_dbg("Memory offline operation complete.\n");
+               break;
+       case MEM_GOING_ONLINE:
+       case MEM_ONLINE:
+       case MEM_CANCEL_ONLINE:
+               break;
+       }
+
+       if (ret)
+               ret = notifier_from_errno(ret);
+       else
+               ret = NOTIFY_OK;
+
+       return ret;
+}
+
+static struct notifier_block cmm_mem_nb = {
+       .notifier_call = cmm_memory_cb,
+       .priority = CMM_MEM_HOTPLUG_PRI
+};
+
+/**
  * cmm_init - Module initialization
  *
  * Return value:
@@ -435,18 +669,24 @@ static int cmm_init(void)
        if ((rc = cmm_sysfs_register(&cmm_sysdev)))
                goto out_reboot_notifier;
 
+       if (register_memory_notifier(&cmm_mem_nb) ||
+           register_memory_isolate_notifier(&cmm_mem_isolate_nb))
+               goto out_unregister_notifier;
+
        if (cmm_disabled)
                return rc;
 
        cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
        if (IS_ERR(cmm_thread_ptr)) {
                rc = PTR_ERR(cmm_thread_ptr);
-               goto out_unregister_sysfs;
+               goto out_unregister_notifier;
        }
 
        return rc;
 
-out_unregister_sysfs:
+out_unregister_notifier:
+       unregister_memory_notifier(&cmm_mem_nb);
+       unregister_memory_isolate_notifier(&cmm_mem_isolate_nb);
        cmm_unregister_sysfs(&cmm_sysdev);
 out_reboot_notifier:
        unregister_reboot_notifier(&cmm_reboot_nb);
@@ -467,6 +707,8 @@ static void cmm_exit(void)
                kthread_stop(cmm_thread_ptr);
        unregister_oom_notifier(&cmm_oom_nb);
        unregister_reboot_notifier(&cmm_reboot_nb);
+       unregister_memory_notifier(&cmm_mem_nb);
+       unregister_memory_isolate_notifier(&cmm_mem_isolate_nb);
        cmm_free_pages(loaned_pages);
        cmm_unregister_sysfs(&cmm_sysdev);
 }
index 12df9e8..67b7a10 100644 (file)
@@ -346,12 +346,14 @@ int dlpar_release_drc(u32 drc_index)
 
 static DEFINE_MUTEX(pseries_cpu_hotplug_mutex);
 
-void cpu_hotplug_driver_lock()
+void cpu_hotplug_driver_lock(void)
+__acquires(pseries_cpu_hotplug_mutex)
 {
        mutex_lock(&pseries_cpu_hotplug_mutex);
 }
 
-void cpu_hotplug_driver_unlock()
+void cpu_hotplug_driver_unlock(void)
+__releases(pseries_cpu_hotplug_mutex)
 {
        mutex_unlock(&pseries_cpu_hotplug_mutex);
 }
index 8868c01..b488663 100644 (file)
@@ -144,8 +144,8 @@ static void __devinit smp_pSeries_kick_cpu(int nr)
                hcpuid = get_hard_smp_processor_id(nr);
                rc = plpar_hcall_norets(H_PROD, hcpuid);
                if (rc != H_SUCCESS)
-                       panic("Error: Prod to wake up processor %d Ret= %ld\n",
-                               nr, rc);
+                       printk(KERN_ERR "Error: Prod to wake up processor %d\
+                                               Ret= %ld\n", nr, rc);
        }
 }
 
index 971483f..1709ac5 100644 (file)
@@ -143,13 +143,23 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
        struct irq_desc *desc = irq_to_desc(virq);
        unsigned int vold, vnew, edibit;
 
-       if (flow_type == IRQ_TYPE_NONE)
-               flow_type = IRQ_TYPE_LEVEL_LOW;
-
-       if (flow_type & IRQ_TYPE_EDGE_RISING) {
-               printk(KERN_ERR "CPM2 PIC: sense type 0x%x not supported\n",
-                       flow_type);
-               return -EINVAL;
+       /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or
+        * IRQ_TYPE_EDGE_BOTH (default).  All others are IRQ_TYPE_EDGE_FALLING
+        * or IRQ_TYPE_LEVEL_LOW (default)
+        */
+       if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) {
+               if (flow_type == IRQ_TYPE_NONE)
+                       flow_type = IRQ_TYPE_EDGE_BOTH;
+
+               if (flow_type != IRQ_TYPE_EDGE_BOTH &&
+                   flow_type != IRQ_TYPE_EDGE_FALLING)
+                       goto err_sense;
+       } else {
+               if (flow_type == IRQ_TYPE_NONE)
+                       flow_type = IRQ_TYPE_LEVEL_LOW;
+
+               if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
+                       goto err_sense;
        }
 
        desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
@@ -181,6 +191,10 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
        if (vold != vnew)
                out_be32(&cpm2_intctl->ic_siexr, vnew);
        return 0;
+
+err_sense:
+       pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type);
+       return -EINVAL;
 }
 
 static struct irq_chip cpm2_pic = {
index 4e3a3e3..e1a028c 100644 (file)
@@ -464,8 +464,7 @@ static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus,
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
        struct mpc83xx_pcie_priv *pcie = hose->dn->data;
-       u8 bus_no = bus->number - hose->first_busno;
-       u32 dev_base = bus_no << 24 | devfn << 16;
+       u32 dev_base = bus->number << 24 | devfn << 16;
        int ret;
 
        ret = mpc83xx_pcie_exclude_device(bus, devfn);
@@ -515,12 +514,17 @@ static int mpc83xx_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
 static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
                                     int offset, int len, u32 val)
 {
+       struct pci_controller *hose = pci_bus_to_host(bus);
        void __iomem *cfg_addr;
 
        cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset);
        if (!cfg_addr)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
+       /* PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS */
+       if (offset == PCI_PRIMARY_BUS && bus->number == hose->first_busno)
+               val &= 0xffffff00;
+
        switch (len) {
        case 1:
                out_8(cfg_addr, val);
index 103eace..ee1c0e1 100644 (file)
@@ -54,6 +54,22 @@ static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm)
        mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT);
 }
 
+/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs
+ * defined as output cannot be determined by reading GPDAT register,
+ * so we use shadow data register instead. The status of input pins
+ * is determined by reading GPDAT register.
+ */
+static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+       u32 val;
+       struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+       struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+
+       val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR);
+
+       return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio);
+}
+
 static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
 {
        struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
@@ -136,7 +152,10 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
        gc->ngpio = MPC8XXX_GPIO_PINS;
        gc->direction_input = mpc8xxx_gpio_dir_in;
        gc->direction_output = mpc8xxx_gpio_dir_out;
-       gc->get = mpc8xxx_gpio_get;
+       if (of_device_is_compatible(np, "fsl,mpc8572-gpio"))
+               gc->get = mpc8572_gpio_get;
+       else
+               gc->get = mpc8xxx_gpio_get;
        gc->set = mpc8xxx_gpio_set;
 
        ret = of_mm_gpiochip_add(np, mm_gc);
index aa9d06e..470dc6c 100644 (file)
@@ -567,13 +567,11 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
 #endif /* CONFIG_MPIC_U3_HT_IRQS */
 
 #ifdef CONFIG_SMP
-static int irq_choose_cpu(unsigned int virt_irq)
+static int irq_choose_cpu(const cpumask_t *mask)
 {
-       cpumask_t mask;
        int cpuid;
 
-       cpumask_copy(&mask, irq_to_desc(virt_irq)->affinity);
-       if (cpus_equal(mask, CPU_MASK_ALL)) {
+       if (cpumask_equal(mask, cpu_all_mask)) {
                static int irq_rover;
                static DEFINE_SPINLOCK(irq_rover_lock);
                unsigned long flags;
@@ -594,20 +592,15 @@ static int irq_choose_cpu(unsigned int virt_irq)
 
                spin_unlock_irqrestore(&irq_rover_lock, flags);
        } else {
-               cpumask_t tmp;
-
-               cpus_and(tmp, cpu_online_map, mask);
-
-               if (cpus_empty(tmp))
+               cpuid = cpumask_first_and(mask, cpu_online_mask);
+               if (cpuid >= nr_cpu_ids)
                        goto do_round_robin;
-
-               cpuid = first_cpu(tmp);
        }
 
        return get_hard_smp_processor_id(cpuid);
 }
 #else
-static int irq_choose_cpu(unsigned int virt_irq)
+static int irq_choose_cpu(const cpumask_t *mask)
 {
        return hard_smp_processor_id();
 }
@@ -816,7 +809,7 @@ int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
        unsigned int src = mpic_irq_to_hw(irq);
 
        if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
-               int cpuid = irq_choose_cpu(irq);
+               int cpuid = irq_choose_cpu(cpumask);
 
                mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
        } else {
index 1d44eee..0f67cd7 100644 (file)
@@ -39,7 +39,12 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
 
        pr_debug("mpic: found U3, guessing msi allocator setup\n");
 
-       /* Reserve source numbers we know are reserved in the HW */
+       /* Reserve source numbers we know are reserved in the HW.
+        *
+        * This is a bit of a mix of U3 and U4 reserves but that's going
+        * to work fine, we have plenty enugh numbers left so let's just
+        * mark anything we don't like reserved.
+        */
        for (i = 0;   i < 8;   i++)
                msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
 
@@ -49,6 +54,10 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
        for (i = 100; i < 105; i++)
                msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
 
+       for (i = 124; i < mpic->irq_count; i++)
+               msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
+
+
        np = NULL;
        while ((np = of_find_all_nodes(np))) {
                pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
index d3caf23..bcbfe79 100644 (file)
@@ -64,12 +64,12 @@ static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
        return addr;
 }
 
-static u64 find_ht_magic_addr(struct pci_dev *pdev)
+static u64 find_ht_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
 {
        struct pci_bus *bus;
        unsigned int pos;
 
-       for (bus = pdev->bus; bus; bus = bus->parent) {
+       for (bus = pdev->bus; bus && bus->self; bus = bus->parent) {
                pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING);
                if (pos)
                        return read_ht_magic_addr(bus->self, pos);
@@ -78,13 +78,41 @@ static u64 find_ht_magic_addr(struct pci_dev *pdev)
        return 0;
 }
 
+static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+
+       /* U4 PCIe MSIs need to write to the special register in
+        * the bridge that generates interrupts. There should be
+        * theorically a register at 0xf8005000 where you just write
+        * the MSI number and that triggers the right interrupt, but
+        * unfortunately, this is busted in HW, the bridge endian swaps
+        * the value and hits the wrong nibble in the register.
+        *
+        * So instead we use another register set which is used normally
+        * for converting HT interrupts to MPIC interrupts, which decodes
+        * the interrupt number as part of the low address bits
+        *
+        * This will not work if we ever use more than one legacy MSI in
+        * a block but we never do. For one MSI or multiple MSI-X where
+        * each interrupt address can be specified separately, it works
+        * just fine.
+        */
+       if (of_device_is_compatible(hose->dn, "u4-pcie") ||
+           of_device_is_compatible(hose->dn, "U4-pcie"))
+               return 0xf8004000 | (hwirq << 4);
+
+       return 0;
+}
+
 static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
 {
        if (type == PCI_CAP_ID_MSIX)
                pr_debug("u3msi: MSI-X untested, trying anyway.\n");
 
        /* If we can't find a magic address then MSI ain't gonna work */
-       if (find_ht_magic_addr(pdev) == 0) {
+       if (find_ht_magic_addr(pdev, 0) == 0 &&
+           find_u4_magic_addr(pdev, 0) == 0) {
                pr_debug("u3msi: no magic address found for %s\n",
                         pci_name(pdev));
                return -ENXIO;
@@ -118,10 +146,6 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        u64 addr;
        int hwirq;
 
-       addr = find_ht_magic_addr(pdev);
-       msg.address_lo = addr & 0xFFFFFFFF;
-       msg.address_hi = addr >> 32;
-
        list_for_each_entry(entry, &pdev->msi_list, list) {
                hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
                if (hwirq < 0) {
@@ -129,6 +153,12 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                        return hwirq;
                }
 
+               addr = find_ht_magic_addr(pdev, hwirq);
+               if (addr == 0)
+                       addr = find_u4_magic_addr(pdev, hwirq);
+               msg.address_lo = addr & 0xFFFFFFFF;
+               msg.address_hi = addr >> 32;
+
                virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
                if (virq == NO_IRQ) {
                        pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq);
@@ -143,6 +173,8 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
                          virq, hwirq, (unsigned long)addr);
 
+               printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
+                         virq, hwirq, (unsigned long)addr);
                msg.data = hwirq;
                write_msi_msg(virq, &msg);
 
index 6118890..6be4503 100644 (file)
@@ -174,7 +174,7 @@ static int fallback_init_cip(struct crypto_tfm *tfm)
        if (IS_ERR(sctx->fallback.cip)) {
                pr_err("Allocating AES fallback algorithm %s failed\n",
                       name);
-               return PTR_ERR(sctx->fallback.blk);
+               return PTR_ERR(sctx->fallback.cip);
        }
 
        return 0;
index 77df726..2b92d50 100644 (file)
@@ -164,7 +164,7 @@ static inline void part_hdr__part_name(enum diag204_format type, void *hdr,
                       LPAR_NAME_LEN);
        EBCASC(name, LPAR_NAME_LEN);
        name[LPAR_NAME_LEN] = 0;
-       strstrip(name);
+       strim(name);
 }
 
 struct cpu_info {
@@ -523,7 +523,7 @@ static int diag224_idx2name(int index, char *name)
        memcpy(name, diag224_cpu_names + ((index + 1) * CPU_NAME_LEN),
                CPU_NAME_LEN);
        name[CPU_NAME_LEN] = 0;
-       strstrip(name);
+       strim(name);
        return 0;
 }
 
index d01fc8f..f0b0d31 100644 (file)
@@ -124,7 +124,7 @@ static int hpyfs_vm_create_guest(struct super_block *sb,
        /* guest dir */
        memcpy(guest_name, data->guest_name, NAME_LEN);
        EBCASC(guest_name, NAME_LEN);
-       strstrip(guest_name);
+       strim(guest_name);
        guest_dir = hypfs_mkdir(sb, systems_dir, guest_name);
        if (IS_ERR(guest_dir))
                return PTR_ERR(guest_dir);
index cb5232d..192a720 100644 (file)
 #define        __NR_pwritev            329
 #define __NR_rt_tgsigqueueinfo 330
 #define __NR_perf_event_open   331
-#define NR_syscalls 332
+#define __NR_recvmmsg          332
+#define NR_syscalls 333
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 30de2d0..faeaccc 100644 (file)
@@ -1853,3 +1853,12 @@ sys32_execve_wrapper:
        llgtr   %r3,%r3                 # compat_uptr_t *
        llgtr   %r4,%r4                 # compat_uptr_t *
        jg      sys32_execve            # branch to system call
+
+       .globl  compat_sys_recvmmsg_wrapper
+compat_sys_recvmmsg_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # struct compat_mmsghdr *
+       llgfr   %r4,%r4                 # unsigned int
+       llgfr   %r5,%r5                 # unsigned int
+       llgtr   %r6,%r6                 # struct compat_timespec *
+       jg      compat_sys_recvmmsg
index 4890ac6..4d73296 100644 (file)
@@ -221,7 +221,7 @@ static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj,        \
                const char *buf, size_t len)                            \
 {                                                                      \
        strncpy(_value, buf, sizeof(_value) - 1);                       \
-       strstrip(_value);                                               \
+       strim(_value);                                                  \
        return len;                                                     \
 }                                                                      \
 static struct kobj_attribute sys_##_prefix##_##_name##_attr =          \
@@ -472,7 +472,7 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
                return sprintf(page, "#unknown#\n");
        memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
        EBCASC(loadparm, LOADPARM_LEN);
-       strstrip(loadparm);
+       strim(loadparm);
        return sprintf(page, "%s\n", loadparm);
 }
 
@@ -776,7 +776,7 @@ static void reipl_get_ascii_loadparm(char *loadparm,
        memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN);
        EBCASC(loadparm, LOADPARM_LEN);
        loadparm[LOADPARM_LEN] = 0;
-       strstrip(loadparm);
+       strim(loadparm);
 }
 
 static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb,
index 653c6a1..13815d3 100644 (file)
@@ -959,7 +959,7 @@ static const struct user_regset s390_compat_regsets[] = {
                .set = s390_fpregs_set,
        },
        [REGSET_GENERAL_EXTENDED] = {
-               .core_note_type = NT_PRXSTATUS,
+               .core_note_type = NT_S390_HIGH_GPRS,
                .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
                .size = sizeof(compat_long_t),
                .align = sizeof(compat_long_t),
index 30eca07..4f292c9 100644 (file)
@@ -340,3 +340,4 @@ SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
 SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
 SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo_wrapper) /* 330 */
 SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper)
+SYSCALL(sys_recvmmsg,sys_recvmmsg,compat_sys_recvmmsg_wrapper)
index c2e42cc..6e7ad63 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -382,7 +382,7 @@ void __kprobes do_single_step(struct pt_regs *regs)
                                        SIGTRAP) == NOTIFY_STOP){
                return;
        }
-       if ((current->ptrace & PT_PTRACED) != 0)
+       if (tracehook_consider_fatal_signal(current, SIGTRAP))
                force_sig(SIGTRAP, current);
 }
 
@@ -483,7 +483,7 @@ static void illegal_op(struct pt_regs * regs, long interruption_code)
                if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
                        return;
                if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
-                       if (current->ptrace & PT_PTRACED)
+                       if (tracehook_consider_fatal_signal(current, SIGTRAP))
                                force_sig(SIGTRAP, current);
                        else
                                signal = SIGILL;
index 3b2a5ac..55298e8 100644 (file)
@@ -50,6 +50,8 @@ config X86
        select HAVE_KERNEL_BZIP2
        select HAVE_KERNEL_LZMA
        select HAVE_HW_BREAKPOINT
+       select PERF_EVENTS
+       select ANON_INODES
        select HAVE_ARCH_KMEMCHECK
        select HAVE_USER_RETURN_NOTIFIER
 
index 60d2b2d..56f462c 100644 (file)
@@ -142,6 +142,32 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate)
                return max_cstate;
 }
 
+static inline bool arch_has_acpi_pdc(void)
+{
+       struct cpuinfo_x86 *c = &cpu_data(0);
+       return (c->x86_vendor == X86_VENDOR_INTEL ||
+               c->x86_vendor == X86_VENDOR_CENTAUR);
+}
+
+static inline void arch_acpi_set_pdc_bits(u32 *buf)
+{
+       struct cpuinfo_x86 *c = &cpu_data(0);
+
+       buf[2] |= ACPI_PDC_C_CAPABILITY_SMP;
+
+       if (cpu_has(c, X86_FEATURE_EST))
+               buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
+
+       if (cpu_has(c, X86_FEATURE_ACPI))
+               buf[2] |= ACPI_PDC_T_FFH;
+
+       /*
+        * If mwait/monitor is unsupported, C2/C3_FFH will be disabled
+        */
+       if (!cpu_has(c, X86_FEATURE_MWAIT))
+               buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
+}
+
 #else /* !CONFIG_ACPI */
 
 #define acpi_lapic 0
index 613700f..637e1ec 100644 (file)
 #define X86_FEATURE_SSE5       (6*32+11) /* SSE-5 */
 #define X86_FEATURE_SKINIT     (6*32+12) /* SKINIT/STGI instructions */
 #define X86_FEATURE_WDT                (6*32+13) /* Watchdog timer */
+#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */
 
 /*
  * Auxiliary flags: Linux defined - For features scattered in various
index 08c48a8..eeac829 100644 (file)
@@ -103,7 +103,8 @@ extern int assign_irq_vector(int, struct irq_cfg *, const struct cpumask *);
 extern void send_cleanup_vector(struct irq_cfg *);
 
 struct irq_desc;
-extern unsigned int set_desc_affinity(struct irq_desc *, const struct cpumask *);
+extern unsigned int set_desc_affinity(struct irq_desc *, const struct cpumask *,
+                                     unsigned int *dest_id);
 extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin, struct io_apic_irq_attr *irq_attr);
 extern void setup_ioapic_dest(void);
 
index 4ffe09b..1cd58cd 100644 (file)
@@ -12,6 +12,7 @@
 #define MSR_FS_BASE            0xc0000100 /* 64bit FS base */
 #define MSR_GS_BASE            0xc0000101 /* 64bit GS base */
 #define MSR_KERNEL_GS_BASE     0xc0000102 /* SwapGS GS shadow */
+#define MSR_TSC_AUX            0xc0000103 /* Auxiliary TSC */
 
 /* EFER bits: */
 #define _EFER_SCE              0  /* SYSCALL/SYSRET */
 #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
 #define FAM10H_MMIO_CONF_BASE_MASK     0xfffffff
 #define FAM10H_MMIO_CONF_BASE_SHIFT    20
+#define MSR_FAM10H_NODE_ID             0xc001100c
 
 /* K8 MSRs */
 #define MSR_K8_TOP_MEM1                        0xc001001a
index 2d228fc..c5bc4c2 100644 (file)
@@ -27,6 +27,18 @@ struct msr {
        };
 };
 
+struct msr_info {
+       u32 msr_no;
+       struct msr reg;
+       struct msr *msrs;
+       int err;
+};
+
+struct msr_regs_info {
+       u32 *regs;
+       int err;
+};
+
 static inline unsigned long long native_read_tscp(unsigned int *aux)
 {
        unsigned long low, high;
@@ -240,9 +252,9 @@ do {                                                            \
 #define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val),                \
                                             (u32)((val) >> 32))
 
-#define write_tsc(val1, val2) wrmsr(0x10, (val1), (val2))
+#define write_tsc(val1, val2) wrmsr(MSR_IA32_TSC, (val1), (val2))
 
-#define write_rdtscp_aux(val) wrmsr(0xc0000103, (val), 0)
+#define write_rdtscp_aux(val) wrmsr(MSR_TSC_AUX, (val), 0)
 
 struct msr *msrs_alloc(void);
 void msrs_free(struct msr *msrs);
index 6f8ec1c..fc801ba 100644 (file)
@@ -181,7 +181,7 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
                                unsigned int *ecx, unsigned int *edx)
 {
        /* ecx is often an input as well as an output. */
-       asm("cpuid"
+       asm volatile("cpuid"
            : "=a" (*eax),
              "=b" (*ebx),
              "=c" (*ecx),
index cf86a5e..35e8912 100644 (file)
@@ -5,6 +5,29 @@ extern int kstack_depth_to_print;
 
 int x86_is_stack_id(int id, char *name);
 
+struct thread_info;
+struct stacktrace_ops;
+
+typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo,
+                                     unsigned long *stack,
+                                     unsigned long bp,
+                                     const struct stacktrace_ops *ops,
+                                     void *data,
+                                     unsigned long *end,
+                                     int *graph);
+
+extern unsigned long
+print_context_stack(struct thread_info *tinfo,
+                   unsigned long *stack, unsigned long bp,
+                   const struct stacktrace_ops *ops, void *data,
+                   unsigned long *end, int *graph);
+
+extern unsigned long
+print_context_stack_bp(struct thread_info *tinfo,
+                      unsigned long *stack, unsigned long bp,
+                      const struct stacktrace_ops *ops, void *data,
+                      unsigned long *end, int *graph);
+
 /* Generic stack tracer with callbacks */
 
 struct stacktrace_ops {
@@ -14,6 +37,7 @@ struct stacktrace_ops {
        void (*address)(void *data, unsigned long address, int reliable);
        /* On negative return stop dumping */
        int (*stack)(void *data, char *name);
+       walk_stack_t    walk_stack;
 };
 
 void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
index fd5ca97..6f35260 100644 (file)
@@ -4,7 +4,7 @@ obj-$(CONFIG_ACPI)              += boot.o
 obj-$(CONFIG_ACPI_SLEEP)       += sleep.o wakeup_rm.o wakeup_$(BITS).o
 
 ifneq ($(CONFIG_ACPI_PROCESSOR),)
-obj-y                          += cstate.o processor.o
+obj-y                          += cstate.o
 endif
 
 $(obj)/wakeup_rm.o:    $(obj)/realmode/wakeup.bin
diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c
deleted file mode 100644 (file)
index d85d1b2..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2005 Intel Corporation
- *     Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- *     - Added _PDC for platforms with Intel CPUs
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-
-#include <acpi/processor.h>
-#include <asm/acpi.h>
-
-static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
-{
-       struct acpi_object_list *obj_list;
-       union acpi_object *obj;
-       u32 *buf;
-
-       /* allocate and initialize pdc. It will be used later. */
-       obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
-       if (!obj_list) {
-               printk(KERN_ERR "Memory allocation error\n");
-               return;
-       }
-
-       obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-       if (!obj) {
-               printk(KERN_ERR "Memory allocation error\n");
-               kfree(obj_list);
-               return;
-       }
-
-       buf = kmalloc(12, GFP_KERNEL);
-       if (!buf) {
-               printk(KERN_ERR "Memory allocation error\n");
-               kfree(obj);
-               kfree(obj_list);
-               return;
-       }
-
-       buf[0] = ACPI_PDC_REVISION_ID;
-       buf[1] = 1;
-       buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
-
-       /*
-        * The default of PDC_SMP_T_SWCOORD bit is set for intel x86 cpu so
-        * that OSPM is capable of native ACPI throttling software
-        * coordination using BIOS supplied _TSD info.
-        */
-       buf[2] |= ACPI_PDC_SMP_T_SWCOORD;
-       if (cpu_has(c, X86_FEATURE_EST))
-               buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
-
-       if (cpu_has(c, X86_FEATURE_ACPI))
-               buf[2] |= ACPI_PDC_T_FFH;
-
-       /*
-        * If mwait/monitor is unsupported, C2/C3_FFH will be disabled
-        */
-       if (!cpu_has(c, X86_FEATURE_MWAIT))
-               buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
-
-       obj->type = ACPI_TYPE_BUFFER;
-       obj->buffer.length = 12;
-       obj->buffer.pointer = (u8 *) buf;
-       obj_list->count = 1;
-       obj_list->pointer = obj;
-       pr->pdc = obj_list;
-
-       return;
-}
-
-
-/* Initialize _PDC data based on the CPU vendor */
-void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
-{
-       struct cpuinfo_x86 *c = &cpu_data(pr->id);
-
-       pr->pdc = NULL;
-       if (c->x86_vendor == X86_VENDOR_INTEL ||
-           c->x86_vendor == X86_VENDOR_CENTAUR)
-               init_intel_pdc(pr, c);
-
-       return;
-}
-
-EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
-
-void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr)
-{
-       if (pr->pdc) {
-               kfree(pr->pdc->pointer->buffer.pointer);
-               kfree(pr->pdc->pointer);
-               kfree(pr->pdc);
-               pr->pdc = NULL;
-       }
-}
-
-EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc);
index d0c99ab..eacbd2b 100644 (file)
@@ -306,10 +306,7 @@ physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
                if (cpumask_test_cpu(cpu, cpu_online_mask))
                        break;
        }
-       if (cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_apicid, cpu);
-
-       return BAD_APICID;
+       return per_cpu(x86_cpu_to_apicid, cpu);
 }
 
 struct apic apic_physflat =  {
index 38dcecf..cb804c5 100644 (file)
@@ -131,10 +131,7 @@ static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
                if (cpumask_test_cpu(cpu, cpu_online_mask))
                        break;
        }
-       if (cpu < nr_cpu_ids)
-               return bigsmp_cpu_to_logical_apicid(cpu);
-
-       return BAD_APICID;
+       return bigsmp_cpu_to_logical_apicid(cpu);
 }
 
 static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
index 11a5851..de00c46 100644 (file)
@@ -2276,26 +2276,28 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
 
 /*
  * Either sets desc->affinity to a valid value, and returns
- * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
+ * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and
  * leaves desc->affinity untouched.
  */
 unsigned int
-set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
+set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask,
+                 unsigned int *dest_id)
 {
        struct irq_cfg *cfg;
        unsigned int irq;
 
        if (!cpumask_intersects(mask, cpu_online_mask))
-               return BAD_APICID;
+               return -1;
 
        irq = desc->irq;
        cfg = desc->chip_data;
        if (assign_irq_vector(irq, cfg, mask))
-               return BAD_APICID;
+               return -1;
 
        cpumask_copy(desc->affinity, mask);
 
-       return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+       *dest_id = apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+       return 0;
 }
 
 static int
@@ -2311,12 +2313,11 @@ set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
        cfg = desc->chip_data;
 
        spin_lock_irqsave(&ioapic_lock, flags);
-       dest = set_desc_affinity(desc, mask);
-       if (dest != BAD_APICID) {
+       ret = set_desc_affinity(desc, mask, &dest);
+       if (!ret) {
                /* Only the high 8 bits are valid. */
                dest = SET_APIC_LOGICAL_ID(dest);
                __target_IO_APIC_irq(irq, dest, cfg);
-               ret = 0;
        }
        spin_unlock_irqrestore(&ioapic_lock, flags);
 
@@ -3351,8 +3352,7 @@ static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
        struct msi_msg msg;
        unsigned int dest;
 
-       dest = set_desc_affinity(desc, mask);
-       if (dest == BAD_APICID)
+       if (set_desc_affinity(desc, mask, &dest))
                return -1;
 
        cfg = desc->chip_data;
@@ -3384,8 +3384,7 @@ ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
        if (get_irte(irq, &irte))
                return -1;
 
-       dest = set_desc_affinity(desc, mask);
-       if (dest == BAD_APICID)
+       if (set_desc_affinity(desc, mask, &dest))
                return -1;
 
        irte.vector = cfg->vector;
@@ -3567,8 +3566,7 @@ static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
        struct msi_msg msg;
        unsigned int dest;
 
-       dest = set_desc_affinity(desc, mask);
-       if (dest == BAD_APICID)
+       if (set_desc_affinity(desc, mask, &dest))
                return -1;
 
        cfg = desc->chip_data;
@@ -3623,8 +3621,7 @@ static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
        struct msi_msg msg;
        unsigned int dest;
 
-       dest = set_desc_affinity(desc, mask);
-       if (dest == BAD_APICID)
+       if (set_desc_affinity(desc, mask, &dest))
                return -1;
 
        cfg = desc->chip_data;
@@ -3730,8 +3727,7 @@ static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
        struct irq_cfg *cfg;
        unsigned int dest;
 
-       dest = set_desc_affinity(desc, mask);
-       if (dest == BAD_APICID)
+       if (set_desc_affinity(desc, mask, &dest))
                return -1;
 
        cfg = desc->chip_data;
index a5371ec..cf69c59 100644 (file)
@@ -148,10 +148,7 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
                        break;
        }
 
-       if (cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_logical_apicid, cpu);
-
-       return BAD_APICID;
+       return per_cpu(x86_cpu_to_logical_apicid, cpu);
 }
 
 static unsigned int x2apic_cluster_phys_get_apic_id(unsigned long x)
index a8989aa..8972f38 100644 (file)
@@ -146,10 +146,7 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
                        break;
        }
 
-       if (cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_apicid, cpu);
-
-       return BAD_APICID;
+       return per_cpu(x86_cpu_to_apicid, cpu);
 }
 
 static unsigned int x2apic_phys_get_apic_id(unsigned long x)
index b684bb3..d56b0ef 100644 (file)
@@ -225,10 +225,7 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
                if (cpumask_test_cpu(cpu, cpu_online_mask))
                        break;
        }
-       if (cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_apicid, cpu);
-
-       return BAD_APICID;
+       return per_cpu(x86_cpu_to_apicid, cpu);
 }
 
 static unsigned int x2apic_get_apic_id(unsigned long x)
index 8dc3ea1..e485825 100644 (file)
@@ -254,59 +254,36 @@ static int __cpuinit nearby_node(int apicid)
 
 /*
  * Fixup core topology information for AMD multi-node processors.
- * Assumption 1: Number of cores in each internal node is the same.
- * Assumption 2: Mixed systems with both single-node and dual-node
- *               processors are not supported.
+ * Assumption: Number of cores in each internal node is the same.
  */
 #ifdef CONFIG_X86_HT
 static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
 {
-#ifdef CONFIG_PCI
-       u32 t, cpn;
-       u8 n, n_id;
+       unsigned long long value;
+       u32 nodes, cores_per_node;
        int cpu = smp_processor_id();
 
+       if (!cpu_has(c, X86_FEATURE_NODEID_MSR))
+               return;
+
        /* fixup topology information only once for a core */
        if (cpu_has(c, X86_FEATURE_AMD_DCM))
                return;
 
-       /* check for multi-node processor on boot cpu */
-       t = read_pci_config(0, 24, 3, 0xe8);
-       if (!(t & (1 << 29)))
+       rdmsrl(MSR_FAM10H_NODE_ID, value);
+
+       nodes = ((value >> 3) & 7) + 1;
+       if (nodes == 1)
                return;
 
        set_cpu_cap(c, X86_FEATURE_AMD_DCM);
+       cores_per_node = c->x86_max_cores / nodes;
 
-       /* cores per node: each internal node has half the number of cores */
-       cpn = c->x86_max_cores >> 1;
+       /* store NodeID, use llc_shared_map to store sibling info */
+       per_cpu(cpu_llc_id, cpu) = value & 7;
 
-       /* even-numbered NB_id of this dual-node processor */
-       n = c->phys_proc_id << 1;
-
-       /*
-        * determine internal node id and assign cores fifty-fifty to
-        * each node of the dual-node processor
-        */
-       t = read_pci_config(0, 24 + n, 3, 0xe8);
-       n = (t>>30) & 0x3;
-       if (n == 0) {
-               if (c->cpu_core_id < cpn)
-                       n_id = 0;
-               else
-                       n_id = 1;
-       } else {
-               if (c->cpu_core_id < cpn)
-                       n_id = 1;
-               else
-                       n_id = 0;
-       }
-
-       /* compute entire NodeID, use llc_shared_map to store sibling info */
-       per_cpu(cpu_llc_id, cpu) = (c->phys_proc_id << 1) + n_id;
-
-       /* fixup core id to be in range from 0 to cpn */
-       c->cpu_core_id = c->cpu_core_id % cpn;
-#endif
+       /* fixup core id to be in range from 0 to (cores_per_node - 1) */
+       c->cpu_core_id = c->cpu_core_id % cores_per_node;
 }
 #endif
 
index 9c31e8b..879666f 100644 (file)
@@ -70,7 +70,6 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
        if (c->x86_power & (1 << 8)) {
                set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
                set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
-               set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE);
                sched_clock_stable = 1;
        }
 
index 45506d5..c223b7e 100644 (file)
@@ -2336,6 +2336,7 @@ static const struct stacktrace_ops backtrace_ops = {
        .warning_symbol         = backtrace_warning_symbol,
        .stack                  = backtrace_stack,
        .address                = backtrace_address,
+       .walk_stack             = print_context_stack_bp,
 };
 
 #include "../dumpstack.h"
index 7ef24a7..cb27fd6 100644 (file)
@@ -187,7 +187,8 @@ static int __init cpuid_init(void)
        int i, err = 0;
        i = 0;
 
-       if (register_chrdev(CPUID_MAJOR, "cpu/cpuid", &cpuid_fops)) {
+       if (__register_chrdev(CPUID_MAJOR, 0, NR_CPUS,
+                             "cpu/cpuid", &cpuid_fops)) {
                printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n",
                       CPUID_MAJOR);
                err = -EBUSY;
@@ -216,7 +217,7 @@ out_class:
        }
        class_destroy(cpuid_class);
 out_chrdev:
-       unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
+       __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
 out:
        return err;
 }
index 0a0aa1c..c56bc28 100644 (file)
@@ -109,6 +109,30 @@ print_context_stack(struct thread_info *tinfo,
        }
        return bp;
 }
+EXPORT_SYMBOL_GPL(print_context_stack);
+
+unsigned long
+print_context_stack_bp(struct thread_info *tinfo,
+                      unsigned long *stack, unsigned long bp,
+                      const struct stacktrace_ops *ops, void *data,
+                      unsigned long *end, int *graph)
+{
+       struct stack_frame *frame = (struct stack_frame *)bp;
+       unsigned long *ret_addr = &frame->return_address;
+
+       while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) {
+               unsigned long addr = *ret_addr;
+
+               if (__kernel_text_address(addr)) {
+                       ops->address(data, addr, 1);
+                       frame = frame->next_frame;
+                       ret_addr = &frame->return_address;
+                       print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
+               }
+       }
+       return (unsigned long)frame;
+}
+EXPORT_SYMBOL_GPL(print_context_stack_bp);
 
 
 static void
@@ -141,10 +165,11 @@ static void print_trace_address(void *data, unsigned long addr, int reliable)
 }
 
 static const struct stacktrace_ops print_trace_ops = {
-       .warning = print_trace_warning,
-       .warning_symbol = print_trace_warning_symbol,
-       .stack = print_trace_stack,
-       .address = print_trace_address,
+       .warning                = print_trace_warning,
+       .warning_symbol         = print_trace_warning_symbol,
+       .stack                  = print_trace_stack,
+       .address                = print_trace_address,
+       .walk_stack             = print_context_stack,
 };
 
 void
index 81086c2..4fd1420 100644 (file)
 #define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
 #endif
 
-extern unsigned long
-print_context_stack(struct thread_info *tinfo,
-               unsigned long *stack, unsigned long bp,
-               const struct stacktrace_ops *ops, void *data,
-               unsigned long *end, int *graph);
-
 extern void
 show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
                unsigned long *stack, unsigned long bp, char *log_lvl);
index e0ed4c7..ae775ca 100644 (file)
@@ -58,7 +58,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
 
                context = (struct thread_info *)
                        ((unsigned long)stack & (~(THREAD_SIZE - 1)));
-               bp = print_context_stack(context, stack, bp, ops, data, NULL, &graph);
+               bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph);
 
                stack = (unsigned long *)context->previous_esp;
                if (!stack)
index b13af53..0ad9597 100644 (file)
@@ -188,8 +188,8 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                        if (ops->stack(data, id) < 0)
                                break;
 
-                       bp = print_context_stack(tinfo, stack, bp, ops,
-                                                data, estack_end, &graph);
+                       bp = ops->walk_stack(tinfo, stack, bp, ops,
+                                            data, estack_end, &graph);
                        ops->stack(data, "<EOE>");
                        /*
                         * We link to the next stack via the
index f50447d..05ed7ab 100644 (file)
@@ -724,7 +724,7 @@ core_initcall(e820_mark_nvs_memory);
 /*
  * Early reserved memory areas.
  */
-#define MAX_EARLY_RES 20
+#define MAX_EARLY_RES 32
 
 struct early_res {
        u64 start, end;
index 844c02c..0c86324 100644 (file)
@@ -394,7 +394,7 @@ static enum ucode_state microcode_update_cpu(int cpu)
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
        enum ucode_state ustate;
 
-       if (uci->valid && uci->mc)
+       if (uci->valid)
                ustate = microcode_resume_cpu(cpu);
        else
                ustate = microcode_init_cpu(cpu);
index 572b07e..4bd93c9 100644 (file)
@@ -246,7 +246,7 @@ static int __init msr_init(void)
        int i, err = 0;
        i = 0;
 
-       if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
+       if (__register_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr", &msr_fops)) {
                printk(KERN_ERR "msr: unable to get major %d for msr\n",
                       MSR_MAJOR);
                err = -EBUSY;
@@ -274,7 +274,7 @@ out_class:
                msr_device_destroy(i);
        class_destroy(msr_class);
 out_chrdev:
-       unregister_chrdev(MSR_MAJOR, "cpu/msr");
+       __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
 out:
        return err;
 }
index c3eb207..922eefb 100644 (file)
@@ -53,17 +53,19 @@ save_stack_address_nosched(void *data, unsigned long addr, int reliable)
 }
 
 static const struct stacktrace_ops save_stack_ops = {
-       .warning = save_stack_warning,
-       .warning_symbol = save_stack_warning_symbol,
-       .stack = save_stack_stack,
-       .address = save_stack_address,
+       .warning        = save_stack_warning,
+       .warning_symbol = save_stack_warning_symbol,
+       .stack          = save_stack_stack,
+       .address        = save_stack_address,
+       .walk_stack     = print_context_stack,
 };
 
 static const struct stacktrace_ops save_stack_ops_nosched = {
-       .warning = save_stack_warning,
-       .warning_symbol = save_stack_warning_symbol,
-       .stack = save_stack_stack,
-       .address = save_stack_address_nosched,
+       .warning        = save_stack_warning,
+       .warning_symbol = save_stack_warning_symbol,
+       .stack          = save_stack_stack,
+       .address        = save_stack_address_nosched,
+       .walk_stack     = print_context_stack,
 };
 
 /*
index cd982f4..597683a 100644 (file)
@@ -763,6 +763,7 @@ void mark_tsc_unstable(char *reason)
 {
        if (!tsc_unstable) {
                tsc_unstable = 1;
+               sched_clock_stable = 0;
                printk(KERN_INFO "Marking TSC unstable due to %s\n", reason);
                /* Change only the rating, when not registered */
                if (clocksource_tsc.mult)
index 61d805d..ece73d8 100644 (file)
@@ -215,8 +215,7 @@ static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask)
        unsigned long mmr_offset;
        unsigned mmr_pnode;
 
-       dest = set_desc_affinity(desc, mask);
-       if (dest == BAD_APICID)
+       if (set_desc_affinity(desc, mask, &dest))
                return -1;
 
        mmr_value = 0;
index 45b20e4..cffd754 100644 (file)
@@ -14,7 +14,7 @@ $(obj)/inat.o: $(obj)/inat-tables.c
 
 clean-files := inat-tables.c
 
-obj-$(CONFIG_SMP) := msr.o
+obj-$(CONFIG_SMP) += msr-smp.o
 
 lib-y := delay.o
 lib-y += thunk_$(BITS).o
@@ -22,7 +22,7 @@ lib-y += usercopy_$(BITS).o getuser.o putuser.o
 lib-y += memcpy_$(BITS).o
 lib-$(CONFIG_KPROBES) += insn.o inat.o
 
-obj-y += msr-reg.o msr-reg-export.o
+obj-y += msr.o msr-reg.o msr-reg-export.o
 
 ifeq ($(CONFIG_X86_32),y)
         obj-y += atomic64_32.o
diff --git a/arch/x86/lib/msr-smp.c b/arch/x86/lib/msr-smp.c
new file mode 100644 (file)
index 0000000..a6b1b86
--- /dev/null
@@ -0,0 +1,204 @@
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <linux/smp.h>
+#include <asm/msr.h>
+
+static void __rdmsr_on_cpu(void *info)
+{
+       struct msr_info *rv = info;
+       struct msr *reg;
+       int this_cpu = raw_smp_processor_id();
+
+       if (rv->msrs)
+               reg = per_cpu_ptr(rv->msrs, this_cpu);
+       else
+               reg = &rv->reg;
+
+       rdmsr(rv->msr_no, reg->l, reg->h);
+}
+
+static void __wrmsr_on_cpu(void *info)
+{
+       struct msr_info *rv = info;
+       struct msr *reg;
+       int this_cpu = raw_smp_processor_id();
+
+       if (rv->msrs)
+               reg = per_cpu_ptr(rv->msrs, this_cpu);
+       else
+               reg = &rv->reg;
+
+       wrmsr(rv->msr_no, reg->l, reg->h);
+}
+
+int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
+       *l = rv.reg.l;
+       *h = rv.reg.h;
+
+       return err;
+}
+EXPORT_SYMBOL(rdmsr_on_cpu);
+
+int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       rv.reg.l = l;
+       rv.reg.h = h;
+       err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
+
+       return err;
+}
+EXPORT_SYMBOL(wrmsr_on_cpu);
+
+static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
+                           struct msr *msrs,
+                           void (*msr_func) (void *info))
+{
+       struct msr_info rv;
+       int this_cpu;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msrs   = msrs;
+       rv.msr_no = msr_no;
+
+       this_cpu = get_cpu();
+
+       if (cpumask_test_cpu(this_cpu, mask))
+               msr_func(&rv);
+
+       smp_call_function_many(mask, msr_func, &rv, 1);
+       put_cpu();
+}
+
+/* rdmsr on a bunch of CPUs
+ *
+ * @mask:       which CPUs
+ * @msr_no:     which MSR
+ * @msrs:       array of MSR values
+ *
+ */
+void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
+{
+       __rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu);
+}
+EXPORT_SYMBOL(rdmsr_on_cpus);
+
+/*
+ * wrmsr on a bunch of CPUs
+ *
+ * @mask:       which CPUs
+ * @msr_no:     which MSR
+ * @msrs:       array of MSR values
+ *
+ */
+void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
+{
+       __rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu);
+}
+EXPORT_SYMBOL(wrmsr_on_cpus);
+
+/* These "safe" variants are slower and should be used when the target MSR
+   may not actually exist. */
+static void __rdmsr_safe_on_cpu(void *info)
+{
+       struct msr_info *rv = info;
+
+       rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h);
+}
+
+static void __wrmsr_safe_on_cpu(void *info)
+{
+       struct msr_info *rv = info;
+
+       rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
+}
+
+int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
+       *l = rv.reg.l;
+       *h = rv.reg.h;
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(rdmsr_safe_on_cpu);
+
+int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       rv.reg.l = l;
+       rv.reg.h = h;
+       err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(wrmsr_safe_on_cpu);
+
+/*
+ * These variants are significantly slower, but allows control over
+ * the entire 32-bit GPR set.
+ */
+static void __rdmsr_safe_regs_on_cpu(void *info)
+{
+       struct msr_regs_info *rv = info;
+
+       rv->err = rdmsr_safe_regs(rv->regs);
+}
+
+static void __wrmsr_safe_regs_on_cpu(void *info)
+{
+       struct msr_regs_info *rv = info;
+
+       rv->err = wrmsr_safe_regs(rv->regs);
+}
+
+int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
+{
+       int err;
+       struct msr_regs_info rv;
+
+       rv.regs   = regs;
+       rv.err    = -EIO;
+       err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1);
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
+
+int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
+{
+       int err;
+       struct msr_regs_info rv;
+
+       rv.regs = regs;
+       rv.err  = -EIO;
+       err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1);
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu);
index 8728341..8f8eebd 100644 (file)
@@ -1,123 +1,7 @@
 #include <linux/module.h>
 #include <linux/preempt.h>
-#include <linux/smp.h>
 #include <asm/msr.h>
 
-struct msr_info {
-       u32 msr_no;
-       struct msr reg;
-       struct msr *msrs;
-       int err;
-};
-
-static void __rdmsr_on_cpu(void *info)
-{
-       struct msr_info *rv = info;
-       struct msr *reg;
-       int this_cpu = raw_smp_processor_id();
-
-       if (rv->msrs)
-               reg = per_cpu_ptr(rv->msrs, this_cpu);
-       else
-               reg = &rv->reg;
-
-       rdmsr(rv->msr_no, reg->l, reg->h);
-}
-
-static void __wrmsr_on_cpu(void *info)
-{
-       struct msr_info *rv = info;
-       struct msr *reg;
-       int this_cpu = raw_smp_processor_id();
-
-       if (rv->msrs)
-               reg = per_cpu_ptr(rv->msrs, this_cpu);
-       else
-               reg = &rv->reg;
-
-       wrmsr(rv->msr_no, reg->l, reg->h);
-}
-
-int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
-       int err;
-       struct msr_info rv;
-
-       memset(&rv, 0, sizeof(rv));
-
-       rv.msr_no = msr_no;
-       err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
-       *l = rv.reg.l;
-       *h = rv.reg.h;
-
-       return err;
-}
-EXPORT_SYMBOL(rdmsr_on_cpu);
-
-int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
-       int err;
-       struct msr_info rv;
-
-       memset(&rv, 0, sizeof(rv));
-
-       rv.msr_no = msr_no;
-       rv.reg.l = l;
-       rv.reg.h = h;
-       err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
-
-       return err;
-}
-EXPORT_SYMBOL(wrmsr_on_cpu);
-
-static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
-                           struct msr *msrs,
-                           void (*msr_func) (void *info))
-{
-       struct msr_info rv;
-       int this_cpu;
-
-       memset(&rv, 0, sizeof(rv));
-
-       rv.msrs   = msrs;
-       rv.msr_no = msr_no;
-
-       this_cpu = get_cpu();
-
-       if (cpumask_test_cpu(this_cpu, mask))
-               msr_func(&rv);
-
-       smp_call_function_many(mask, msr_func, &rv, 1);
-       put_cpu();
-}
-
-/* rdmsr on a bunch of CPUs
- *
- * @mask:       which CPUs
- * @msr_no:     which MSR
- * @msrs:       array of MSR values
- *
- */
-void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
-{
-       __rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu);
-}
-EXPORT_SYMBOL(rdmsr_on_cpus);
-
-/*
- * wrmsr on a bunch of CPUs
- *
- * @mask:       which CPUs
- * @msr_no:     which MSR
- * @msrs:       array of MSR values
- *
- */
-void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
-{
-       __rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu);
-}
-EXPORT_SYMBOL(wrmsr_on_cpus);
-
 struct msr *msrs_alloc(void)
 {
        struct msr *msrs = NULL;
@@ -137,100 +21,3 @@ void msrs_free(struct msr *msrs)
        free_percpu(msrs);
 }
 EXPORT_SYMBOL(msrs_free);
-
-/* These "safe" variants are slower and should be used when the target MSR
-   may not actually exist. */
-static void __rdmsr_safe_on_cpu(void *info)
-{
-       struct msr_info *rv = info;
-
-       rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h);
-}
-
-static void __wrmsr_safe_on_cpu(void *info)
-{
-       struct msr_info *rv = info;
-
-       rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
-}
-
-int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
-       int err;
-       struct msr_info rv;
-
-       memset(&rv, 0, sizeof(rv));
-
-       rv.msr_no = msr_no;
-       err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
-       *l = rv.reg.l;
-       *h = rv.reg.h;
-
-       return err ? err : rv.err;
-}
-EXPORT_SYMBOL(rdmsr_safe_on_cpu);
-
-int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
-       int err;
-       struct msr_info rv;
-
-       memset(&rv, 0, sizeof(rv));
-
-       rv.msr_no = msr_no;
-       rv.reg.l = l;
-       rv.reg.h = h;
-       err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
-
-       return err ? err : rv.err;
-}
-EXPORT_SYMBOL(wrmsr_safe_on_cpu);
-
-/*
- * These variants are significantly slower, but allows control over
- * the entire 32-bit GPR set.
- */
-struct msr_regs_info {
-       u32 *regs;
-       int err;
-};
-
-static void __rdmsr_safe_regs_on_cpu(void *info)
-{
-       struct msr_regs_info *rv = info;
-
-       rv->err = rdmsr_safe_regs(rv->regs);
-}
-
-static void __wrmsr_safe_regs_on_cpu(void *info)
-{
-       struct msr_regs_info *rv = info;
-
-       rv->err = wrmsr_safe_regs(rv->regs);
-}
-
-int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
-{
-       int err;
-       struct msr_regs_info rv;
-
-       rv.regs   = regs;
-       rv.err    = -EIO;
-       err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1);
-
-       return err ? err : rv.err;
-}
-EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
-
-int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
-{
-       int err;
-       struct msr_regs_info rv;
-
-       rv.regs = regs;
-       rv.err  = -EIO;
-       err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1);
-
-       return err ? err : rv.err;
-}
-EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu);
index 6f8aa33..9324f13 100644 (file)
@@ -267,6 +267,8 @@ int __init get_memcfg_from_srat(void)
                e820_register_active_regions(chunk->nid, chunk->start_pfn,
                                             min(chunk->end_pfn, max_pfn));
        }
+       /* for out of order entries in SRAT */
+       sort_node_map();
 
        for_each_online_node(nid) {
                unsigned long start = node_start_pfn[nid];
index d890754..a271241 100644 (file)
@@ -317,7 +317,7 @@ static int __init nodes_cover_memory(const struct bootnode *nodes)
                unsigned long s = nodes[i].start >> PAGE_SHIFT;
                unsigned long e = nodes[i].end >> PAGE_SHIFT;
                pxmram += e - s;
-               pxmram -= absent_pages_in_range(s, e);
+               pxmram -= __absent_pages_in_range(i, s, e);
                if ((long)pxmram < 0)
                        pxmram = 0;
        }
@@ -373,6 +373,8 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
        for_each_node_mask(i, nodes_parsed)
                e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
                                                nodes[i].end >> PAGE_SHIFT);
+       /* for out of order entries in SRAT */
+       sort_node_map();
        if (!nodes_cover_memory(nodes)) {
                bad_srat();
                return -1;
index 044897b..3855096 100644 (file)
@@ -41,10 +41,11 @@ static void backtrace_address(void *data, unsigned long addr, int reliable)
 }
 
 static struct stacktrace_ops backtrace_ops = {
-       .warning = backtrace_warning,
-       .warning_symbol = backtrace_warning_symbol,
-       .stack = backtrace_stack,
-       .address = backtrace_address,
+       .warning        = backtrace_warning,
+       .warning_symbol = backtrace_warning_symbol,
+       .stack          = backtrace_stack,
+       .address        = backtrace_address,
+       .walk_stack     = print_context_stack,
 };
 
 struct frame_head {
index 0d13cd9..5bbb5a3 100644 (file)
@@ -9,7 +9,7 @@ BEGIN {
 }
 
 /^GNU/ {
-       split($4, ver, ".");
+       split($3, ver, ".");
        if (ver[1] > od_ver ||
            (ver[1] == od_ver && ver[2] >= od_sver)) {
                exit 1;
index 7a68506..eaf11f5 100644 (file)
@@ -6,8 +6,6 @@
 
 # Awk implementation sanity check
 function check_awk_implement() {
-       if (!match("abc", "[[:lower:]]+"))
-               return "Your awk doesn't support charactor-class."
        if (sprintf("%x", 0) != "0")
                return "Your awk has a printf-format problem."
        return ""
@@ -44,12 +42,12 @@ BEGIN {
        delete gtable
        delete atable
 
-       opnd_expr = "^[[:alpha:]/]"
+       opnd_expr = "^[A-Za-z/]"
        ext_expr = "^\\("
        sep_expr = "^\\|$"
-       group_expr = "^Grp[[:alnum:]]+"
+       group_expr = "^Grp[0-9A-Za-z]+"
 
-       imm_expr = "^[IJAO][[:lower:]]"
+       imm_expr = "^[IJAO][a-z]"
        imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
        imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
        imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
@@ -62,7 +60,7 @@ BEGIN {
        imm_flag["Ob"] = "INAT_MOFFSET"
        imm_flag["Ov"] = "INAT_MOFFSET"
 
-       modrm_expr = "^([CDEGMNPQRSUVW/][[:lower:]]+|NTA|T[012])"
+       modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])"
        force64_expr = "\\([df]64\\)"
        rex_expr = "^REX(\\.[XRWB]+)*"
        fpu_expr = "^ESC" # TODO
index c7b10b4..66cc3f3 100644 (file)
@@ -32,6 +32,7 @@ acpi-$(CONFIG_ACPI_SLEEP)     += proc.o
 #
 acpi-y                         += bus.o glue.o
 acpi-y                         += scan.o
+acpi-y                         += processor_pdc.o
 acpi-y                         += ec.o
 acpi-$(CONFIG_ACPI_DOCK)       += dock.o
 acpi-y                         += pci_root.o pci_link.o pci_irq.o pci_bind.o
index 23e5a05..2815df6 100644 (file)
@@ -185,6 +185,12 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
        acpi_osi_setup("!Windows 2006");
        return 0;
 }
+static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
+{
+       printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
+       acpi_osi_setup("!Windows 2009");
+       return 0;
+}
 
 static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
        {
@@ -211,6 +217,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                     DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"),
                },
        },
+       {
+       .callback = dmi_disable_osi_win7,
+       .ident = "ASUS K50IJ",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
+               },
+       },
 
        /*
         * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
index 65f7e33..cf761b9 100644 (file)
@@ -397,6 +397,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
        union acpi_object *out_obj;
        u8 uuid[16];
        u32 errors;
+       struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
 
        if (!context)
                return AE_ERROR;
@@ -419,16 +420,16 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
        in_params[3].buffer.length      = context->cap.length;
        in_params[3].buffer.pointer     = context->cap.pointer;
 
-       status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret);
+       status = acpi_evaluate_object(handle, "_OSC", &input, &output);
        if (ACPI_FAILURE(status))
                return status;
 
-       /* return buffer should have the same length as cap buffer */
-       if (context->ret.length != context->cap.length)
+       if (!output.length)
                return AE_NULL_OBJECT;
 
-       out_obj = context->ret.pointer;
-       if (out_obj->type != ACPI_TYPE_BUFFER) {
+       out_obj = output.pointer;
+       if (out_obj->type != ACPI_TYPE_BUFFER
+               || out_obj->buffer.length != context->cap.length) {
                acpi_print_osc_error(handle, context,
                        "_OSC evaluation returned wrong type");
                status = AE_TYPE;
@@ -457,11 +458,20 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
                goto out_kfree;
        }
 out_success:
-       return AE_OK;
+       context->ret.length = out_obj->buffer.length;
+       context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL);
+       if (!context->ret.pointer) {
+               status =  AE_NO_MEMORY;
+               goto out_kfree;
+       }
+       memcpy(context->ret.pointer, out_obj->buffer.pointer,
+               context->ret.length);
+       status =  AE_OK;
 
 out_kfree:
-       kfree(context->ret.pointer);
-       context->ret.pointer = NULL;
+       kfree(output.pointer);
+       if (status != AE_OK)
+               context->ret.pointer = NULL;
        return status;
 }
 EXPORT_SYMBOL(acpi_run_osc);
@@ -888,6 +898,8 @@ static int __init acpi_bus_init(void)
                goto error1;
        }
 
+       acpi_early_processor_set_pdc();
+
        /*
         * Maybe EC region is required at bus_scan/acpi_get_devices. So it
         * is necessary to enable it as early as possible.
index 75b147f..fd1801b 100644 (file)
@@ -916,6 +916,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id)
 /* MSI EC needs special treatment, enable it */
 static int ec_flag_msi(const struct dmi_system_id *id)
 {
+       printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n");
        EC_FLAGS_MSI = 1;
        EC_FLAGS_VALIDATE_ECDT = 1;
        return 0;
@@ -928,8 +929,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
        DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL},
        {
        ec_flag_msi, "MSI hardware", {
-       DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star"),
-       DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star") }, NULL},
+       DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star")}, NULL},
+       {
+       ec_flag_msi, "MSI hardware", {
+       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star")}, NULL},
+       {
+       ec_flag_msi, "MSI hardware", {
+       DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL},
        {
        ec_validate_ecdt, "ASUS hardware", {
        DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
index 074cf86..cb28e05 100644 (file)
@@ -43,6 +43,7 @@ int acpi_power_transition(struct acpi_device *device, int state);
 extern int acpi_power_nocheck;
 
 int acpi_wakeup_device_init(void);
+void acpi_early_processor_set_pdc(void);
 
 /* --------------------------------------------------------------------------
                                   Embedded Controller
index 4173123..9863c98 100644 (file)
@@ -124,29 +124,6 @@ static const struct file_operations acpi_processor_info_fops = {
 
 DEFINE_PER_CPU(struct acpi_processor *, processors);
 struct acpi_processor_errata errata __read_mostly;
-static int set_no_mwait(const struct dmi_system_id *id)
-{
-       printk(KERN_NOTICE PREFIX "%s detected - "
-               "disabling mwait for CPU C-states\n", id->ident);
-       idle_nomwait = 1;
-       return 0;
-}
-
-static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
-       {
-       set_no_mwait, "IFL91 board", {
-       DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
-       DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
-       DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
-       DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
-       {
-       set_no_mwait, "Extensa 5220", {
-       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-       DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
-       DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
-       {},
-};
 
 /* --------------------------------------------------------------------------
                                 Errata Handling
@@ -277,45 +254,6 @@ static int acpi_processor_errata(struct acpi_processor *pr)
 }
 
 /* --------------------------------------------------------------------------
-                              Common ACPI processor functions
-   -------------------------------------------------------------------------- */
-
-/*
- * _PDC is required for a BIOS-OS handshake for most of the newer
- * ACPI processor features.
- */
-static int acpi_processor_set_pdc(struct acpi_processor *pr)
-{
-       struct acpi_object_list *pdc_in = pr->pdc;
-       acpi_status status = AE_OK;
-
-
-       if (!pdc_in)
-               return status;
-       if (idle_nomwait) {
-               /*
-                * If mwait is disabled for CPU C-states, the C2C3_FFH access
-                * mode will be disabled in the parameter of _PDC object.
-                * Of course C1_FFH access mode will also be disabled.
-                */
-               union acpi_object *obj;
-               u32 *buffer = NULL;
-
-               obj = pdc_in->pointer;
-               buffer = (u32 *)(obj->buffer.pointer);
-               buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
-
-       }
-       status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL);
-
-       if (ACPI_FAILURE(status))
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                   "Could not evaluate _PDC, using legacy perf. control...\n"));
-
-       return status;
-}
-
-/* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
 
@@ -825,9 +763,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
        }
 
        /* _PDC call should be done before doing anything else (if reqd.). */
-       arch_acpi_processor_init_pdc(pr);
-       acpi_processor_set_pdc(pr);
-       arch_acpi_processor_cleanup_pdc(pr);
+       acpi_processor_set_pdc(pr->handle);
 
 #ifdef CONFIG_CPU_FREQ
        acpi_processor_ppc_has_changed(pr, 0);
@@ -1145,11 +1081,6 @@ static int __init acpi_processor_init(void)
        if (!acpi_processor_dir)
                return -ENOMEM;
 #endif
-       /*
-        * Check whether the system is DMI table. If yes, OSPM
-        * should not use mwait for CPU-states.
-        */
-       dmi_check_system(processor_idle_dmi_table);
        result = cpuidle_register_driver(&acpi_idle_driver);
        if (result < 0)
                goto out_proc;
diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c
new file mode 100644 (file)
index 0000000..30e4dc0
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2005 Intel Corporation
+ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ *     Alex Chiang <achiang@hp.com>
+ *     - Unified x86/ia64 implementations
+ *     Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ *     - Added _PDC for platforms with Intel CPUs
+ */
+#include <linux/dmi.h>
+
+#include <acpi/acpi_drivers.h>
+#include <acpi/processor.h>
+
+#include "internal.h"
+
+#define PREFIX                 "ACPI: "
+#define _COMPONENT             ACPI_PROCESSOR_COMPONENT
+ACPI_MODULE_NAME("processor_pdc");
+
+static int set_no_mwait(const struct dmi_system_id *id)
+{
+       printk(KERN_NOTICE PREFIX "%s detected - "
+               "disabling mwait for CPU C-states\n", id->ident);
+       idle_nomwait = 1;
+       return 0;
+}
+
+static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
+       {
+       set_no_mwait, "IFL91 board", {
+       DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
+       DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
+       DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
+       DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
+       {
+       set_no_mwait, "Extensa 5220", {
+       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+       DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+       DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
+       {},
+};
+
+static void acpi_set_pdc_bits(u32 *buf)
+{
+       buf[0] = ACPI_PDC_REVISION_ID;
+       buf[1] = 1;
+
+       /* Enable coordination with firmware's _TSD info */
+       buf[2] = ACPI_PDC_SMP_T_SWCOORD;
+
+       /* Twiddle arch-specific bits needed for _PDC */
+       arch_acpi_set_pdc_bits(buf);
+}
+
+static struct acpi_object_list *acpi_processor_alloc_pdc(void)
+{
+       struct acpi_object_list *obj_list;
+       union acpi_object *obj;
+       u32 *buf;
+
+       /* allocate and initialize pdc. It will be used later. */
+       obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
+       if (!obj_list) {
+               printk(KERN_ERR "Memory allocation error\n");
+               return NULL;
+       }
+
+       obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+       if (!obj) {
+               printk(KERN_ERR "Memory allocation error\n");
+               kfree(obj_list);
+               return NULL;
+       }
+
+       buf = kmalloc(12, GFP_KERNEL);
+       if (!buf) {
+               printk(KERN_ERR "Memory allocation error\n");
+               kfree(obj);
+               kfree(obj_list);
+               return NULL;
+       }
+
+       acpi_set_pdc_bits(buf);
+
+       obj->type = ACPI_TYPE_BUFFER;
+       obj->buffer.length = 12;
+       obj->buffer.pointer = (u8 *) buf;
+       obj_list->count = 1;
+       obj_list->pointer = obj;
+
+       return obj_list;
+}
+
+/*
+ * _PDC is required for a BIOS-OS handshake for most of the newer
+ * ACPI processor features.
+ */
+static int
+acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
+{
+       acpi_status status = AE_OK;
+
+       if (idle_nomwait) {
+               /*
+                * If mwait is disabled for CPU C-states, the C2C3_FFH access
+                * mode will be disabled in the parameter of _PDC object.
+                * Of course C1_FFH access mode will also be disabled.
+                */
+               union acpi_object *obj;
+               u32 *buffer = NULL;
+
+               obj = pdc_in->pointer;
+               buffer = (u32 *)(obj->buffer.pointer);
+               buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
+
+       }
+       status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
+
+       if (ACPI_FAILURE(status))
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                   "Could not evaluate _PDC, using legacy perf. control.\n"));
+
+       return status;
+}
+
+void acpi_processor_set_pdc(acpi_handle handle)
+{
+       struct acpi_object_list *obj_list;
+
+       if (arch_has_acpi_pdc() == false)
+               return;
+
+       obj_list = acpi_processor_alloc_pdc();
+       if (!obj_list)
+               return;
+
+       acpi_processor_eval_pdc(handle, obj_list);
+
+       kfree(obj_list->pointer->buffer.pointer);
+       kfree(obj_list->pointer);
+       kfree(obj_list);
+}
+EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
+
+static acpi_status
+early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       acpi_processor_set_pdc(handle);
+       return AE_OK;
+}
+
+void acpi_early_processor_set_pdc(void)
+{
+       /*
+        * Check whether the system is DMI table. If yes, OSPM
+        * should not use mwait for CPU-states.
+        */
+       dmi_check_system(processor_idle_dmi_table);
+
+       acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
+                           ACPI_UINT32_MAX,
+                           early_init_pdc, NULL, NULL, NULL);
+}
index 1683ebd..f4ea5a8 100644 (file)
@@ -3022,7 +3022,7 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
        case WRITE_16:
                return ata_scsi_rw_xlat;
 
-       case 0x93 /*WRITE_SAME_16*/:
+       case WRITE_SAME_16:
                return ata_scsi_write_same_xlat;
 
        case SYNCHRONIZE_CACHE:
index efa8773..741065c 100644 (file)
@@ -2275,7 +2275,7 @@ void ata_sff_drain_fifo(struct ata_queued_cmd *qc)
        ap = qc->ap;
        /* Drain up to 64K of data before we give up this recovery method */
        for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
-                                               && count < 32768; count++)
+                                               && count < 65536; count += 2)
                ioread16(ap->ioaddr.data_addr);
 
        /* Can become DEBUG later */
index c4b47a3..02c81f1 100644 (file)
@@ -1557,6 +1557,25 @@ static unsigned short atapi_io_port[] = {
        P_ATAPI_DMARQ,
        P_ATAPI_INTRQ,
        P_ATAPI_IORDY,
+       P_ATAPI_D0A,
+       P_ATAPI_D1A,
+       P_ATAPI_D2A,
+       P_ATAPI_D3A,
+       P_ATAPI_D4A,
+       P_ATAPI_D5A,
+       P_ATAPI_D6A,
+       P_ATAPI_D7A,
+       P_ATAPI_D8A,
+       P_ATAPI_D9A,
+       P_ATAPI_D10A,
+       P_ATAPI_D11A,
+       P_ATAPI_D12A,
+       P_ATAPI_D13A,
+       P_ATAPI_D14A,
+       P_ATAPI_D15A,
+       P_ATAPI_A0A,
+       P_ATAPI_A1A,
+       P_ATAPI_A2A,
        0
 };
 
index dadfc35..0efb1f5 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_cmd64x"
-#define DRV_VERSION "0.3.1"
+#define DRV_VERSION "0.2.5"
 
 /*
  * CMD64x specific registers definition.
@@ -219,7 +219,7 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
                regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift;
                /* Merge the control bits */
                regU |= 1 << adev->devno; /* UDMA on */
-               if (adev->dma_mode > 2) /* 15nS timing */
+               if (adev->dma_mode > XFER_UDMA_2) /* 15nS timing */
                        regU |= 4 << adev->devno;
        } else {
                regU &= ~ (1 << adev->devno);   /* UDMA off */
@@ -254,109 +254,17 @@ static void cmd648_bmdma_stop(struct ata_queued_cmd *qc)
 }
 
 /**
- *     cmd64x_bmdma_stop       -       DMA stop callback
+ *     cmd646r1_dma_stop       -       DMA stop callback
  *     @qc: Command in progress
  *
- *     Track the completion of live DMA commands and clear the
- *     host->private_data DMA tracking flag as we do.
+ *     Stub for now while investigating the r1 quirk in the old driver.
  */
 
-static void cmd64x_bmdma_stop(struct ata_queued_cmd *qc)
+static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc)
 {
-       struct ata_port *ap = qc->ap;
        ata_bmdma_stop(qc);
-       WARN_ON(ap->host->private_data != ap);
-       ap->host->private_data = NULL;
-}
-
-/**
- *     cmd64x_qc_defer         -       Defer logic for chip limits
- *     @qc: queued command
- *
- *     Decide whether we can issue the command. Called under the host lock.
- */
-
-static int cmd64x_qc_defer(struct ata_queued_cmd *qc)
-{
-       struct ata_host *host = qc->ap->host;
-       struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
-       int rc;
-       int dma = 0;
-
-       /* Apply the ATA rules first */
-       rc = ata_std_qc_defer(qc);
-       if (rc)
-               return rc;
-
-       if (qc->tf.protocol == ATAPI_PROT_DMA ||
-                       qc->tf.protocol == ATA_PROT_DMA)
-               dma = 1;
-
-       /* If the other port is not live then issue the command */
-       if (alt == NULL || !alt->qc_active) {
-               if (dma)
-                       host->private_data = qc->ap;
-               return 0;
-       }
-       /* If there is a live DMA command then wait */
-       if (host->private_data != NULL)
-               return  ATA_DEFER_PORT;
-       if (dma)
-               /* Cannot overlap our DMA command */
-               return ATA_DEFER_PORT;
-       return 0;
 }
 
-/**
- *     cmd64x_interrupt - ATA host interrupt handler
- *     @irq: irq line (unused)
- *     @dev_instance: pointer to our ata_host information structure
- *
- *     Our interrupt handler for PCI IDE devices.  Calls
- *     ata_sff_host_intr() for each port that is flagging an IRQ. We cannot
- *     use the defaults as we need to avoid touching status/altstatus during
- *     a DMA.
- *
- *     LOCKING:
- *     Obtains host lock during operation.
- *
- *     RETURNS:
- *     IRQ_NONE or IRQ_HANDLED.
- */
-irqreturn_t cmd64x_interrupt(int irq, void *dev_instance)
-{
-       struct ata_host *host = dev_instance;
-       struct pci_dev *pdev = to_pci_dev(host->dev);
-       unsigned int i;
-       unsigned int handled = 0;
-       unsigned long flags;
-       static const u8 irq_reg[2] = { CFR, ARTTIM23 };
-       static const u8 irq_mask[2] = { 1 << 2, 1 << 4 };
-
-       /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
-       spin_lock_irqsave(&host->lock, flags);
-
-       for (i = 0; i < host->n_ports; i++) {
-               struct ata_port *ap;
-               u8 reg;
-
-               pci_read_config_byte(pdev, irq_reg[i], &reg);
-               ap = host->ports[i];
-               if (ap && (reg & irq_mask[i]) &&
-                   !(ap->flags & ATA_FLAG_DISABLED)) {
-                       struct ata_queued_cmd *qc;
-
-                       qc = ata_qc_from_tag(ap, ap->link.active_tag);
-                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
-                           (qc->flags & ATA_QCFLAG_ACTIVE))
-                               handled |= ata_sff_host_intr(ap, qc);
-               }
-       }
-
-       spin_unlock_irqrestore(&host->lock, flags);
-
-       return IRQ_RETVAL(handled);
-}
 static struct scsi_host_template cmd64x_sht = {
        ATA_BMDMA_SHT(DRV_NAME),
 };
@@ -365,8 +273,6 @@ static const struct ata_port_operations cmd64x_base_ops = {
        .inherits       = &ata_bmdma_port_ops,
        .set_piomode    = cmd64x_set_piomode,
        .set_dmamode    = cmd64x_set_dmamode,
-       .bmdma_stop     = cmd64x_bmdma_stop,
-       .qc_defer       = cmd64x_qc_defer,
 };
 
 static struct ata_port_operations cmd64x_port_ops = {
@@ -376,6 +282,7 @@ static struct ata_port_operations cmd64x_port_ops = {
 
 static struct ata_port_operations cmd646r1_port_ops = {
        .inherits       = &cmd64x_base_ops,
+       .bmdma_stop     = cmd646r1_bmdma_stop,
        .cable_detect   = ata_cable_40wire,
 };
 
@@ -383,7 +290,6 @@ static struct ata_port_operations cmd648_port_ops = {
        .inherits       = &cmd64x_base_ops,
        .bmdma_stop     = cmd648_bmdma_stop,
        .cable_detect   = cmd648_cable_detect,
-       .qc_defer       = ata_std_qc_defer
 };
 
 static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -432,7 +338,6 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL };
        u8 mrdmode;
        int rc;
-       struct ata_host *host;
 
        rc = pcim_enable_device(pdev);
        if (rc)
@@ -450,25 +355,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
                        ppi[0] = &cmd_info[3];
        }
 
-
        pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
        pci_read_config_byte(pdev, MRDMODE, &mrdmode);
        mrdmode &= ~ 0x30;      /* IRQ set up */
        mrdmode |= 0x02;        /* Memory read line enable */
        pci_write_config_byte(pdev, MRDMODE, mrdmode);
 
+       /* Force PIO 0 here.. */
+
        /* PPC specific fixup copied from old driver */
 #ifdef CONFIG_PPC
        pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
 #endif
-       rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
-       if (rc)
-               return rc;
-       /* We use this pointer to track the AP which has DMA running */
-       host->private_data = NULL;
 
-       pci_set_master(pdev);
-       return ata_pci_sff_activate_host(host, cmd64x_interrupt, &cmd64x_sht);
+       return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL);
 }
 
 #ifdef CONFIG_PM
index 9a09a1b..dd26bc7 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright (C) 1999-2003             Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001         Sun Microsystems, Inc.
  * Portions Copyright (C) 2003         Red Hat Inc
- * Portions Copyright (C) 2005-2007    MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2009    MontaVista Software, Inc.
  *
  *
  * TODO
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_hpt3x2n"
-#define DRV_VERSION    "0.3.7"
+#define DRV_VERSION    "0.3.8"
 
 enum {
        HPT_PCI_FAST    =       (1 << 31),
@@ -264,7 +264,7 @@ static void hpt3x2n_bmdma_stop(struct ata_queued_cmd *qc)
 
 static void hpt3x2n_set_clock(struct ata_port *ap, int source)
 {
-       void __iomem *bmdma = ap->ioaddr.bmdma_addr;
+       void __iomem *bmdma = ap->ioaddr.bmdma_addr - ap->port_no * 8;
 
        /* Tristate the bus */
        iowrite8(0x80, bmdma+0x73);
@@ -274,9 +274,9 @@ static void hpt3x2n_set_clock(struct ata_port *ap, int source)
        iowrite8(source, bmdma+0x7B);
        iowrite8(0xC0, bmdma+0x79);
 
-       /* Reset state machines */
-       iowrite8(0x37, bmdma+0x70);
-       iowrite8(0x37, bmdma+0x74);
+       /* Reset state machines, avoid enabling the disabled channels */
+       iowrite8(ioread8(bmdma+0x70) | 0x32, bmdma+0x70);
+       iowrite8(ioread8(bmdma+0x74) | 0x32, bmdma+0x74);
 
        /* Complete reset */
        iowrite8(0x00, bmdma+0x79);
@@ -286,21 +286,10 @@ static void hpt3x2n_set_clock(struct ata_port *ap, int source)
        iowrite8(0x00, bmdma+0x77);
 }
 
-/* Check if our partner interface is busy */
-
-static int hpt3x2n_pair_idle(struct ata_port *ap)
-{
-       struct ata_host *host = ap->host;
-       struct ata_port *pair = host->ports[ap->port_no ^ 1];
-
-       if (pair->hsm_task_state == HSM_ST_IDLE)
-               return 1;
-       return 0;
-}
-
 static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
 {
        long flags = (long)ap->host->private_data;
+
        /* See if we should use the DPLL */
        if (writing)
                return USE_DPLL;        /* Needed for write */
@@ -309,20 +298,35 @@ static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
        return 0;
 }
 
+static int hpt3x2n_qc_defer(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct ata_port *alt = ap->host->ports[ap->port_no ^ 1];
+       int rc, flags = (long)ap->host->private_data;
+       int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE);
+
+       /* First apply the usual rules */
+       rc = ata_std_qc_defer(qc);
+       if (rc != 0)
+               return rc;
+
+       if ((flags & USE_DPLL) != dpll && alt->qc_active)
+               return ATA_DEFER_PORT;
+       return 0;
+}
+
 static unsigned int hpt3x2n_qc_issue(struct ata_queued_cmd *qc)
 {
-       struct ata_taskfile *tf = &qc->tf;
        struct ata_port *ap = qc->ap;
        int flags = (long)ap->host->private_data;
+       int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE);
 
-       if (hpt3x2n_pair_idle(ap)) {
-               int dpll = hpt3x2n_use_dpll(ap, (tf->flags & ATA_TFLAG_WRITE));
-               if ((flags & USE_DPLL) != dpll) {
-                       if (dpll == 1)
-                               hpt3x2n_set_clock(ap, 0x21);
-                       else
-                               hpt3x2n_set_clock(ap, 0x23);
-               }
+       if ((flags & USE_DPLL) != dpll) {
+               flags &= ~USE_DPLL;
+               flags |= dpll;
+               ap->host->private_data = (void *)(long)flags;
+
+               hpt3x2n_set_clock(ap, dpll ? 0x21 : 0x23);
        }
        return ata_sff_qc_issue(qc);
 }
@@ -339,6 +343,8 @@ static struct ata_port_operations hpt3x2n_port_ops = {
        .inherits       = &ata_bmdma_port_ops,
 
        .bmdma_stop     = hpt3x2n_bmdma_stop,
+
+       .qc_defer       = hpt3x2n_qc_defer,
        .qc_issue       = hpt3x2n_qc_issue,
 
        .cable_detect   = hpt3x2n_cable_detect,
@@ -454,7 +460,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        unsigned int f_low, f_high;
        int adjust;
        unsigned long iobase = pci_resource_start(dev, 4);
-       void *hpriv = NULL;
+       void *hpriv = (void *)USE_DPLL;
        int rc;
 
        rc = pcim_enable_device(dev);
@@ -539,7 +545,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        /* Set our private data up. We only need a few flags so we use
           it directly */
        if (pci_mhz > 60) {
-               hpriv = (void *)PCI66;
+               hpriv = (void *)(PCI66 | USE_DPLL);
                /*
                 * On  HPT371N, if ATA clock is 66 MHz we must set bit 2 in
                 * the MISC. register to stretch the UltraDMA Tss timing.
index d6f6956..37ef416 100644 (file)
@@ -853,7 +853,7 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)
                        return -EINVAL;
 
                cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start,
-                                          res_cs0->end - res_cs1->start + 1);
+                                          resource_size(res_cs1));
 
                if (!cs1)
                        return -ENOMEM;
index a8a7be0..df8ee32 100644 (file)
@@ -59,6 +59,7 @@
 #include <linux/dmapool.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
+#include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/ata_platform.h>
 #include <linux/mbus.h>
@@ -538,6 +539,7 @@ struct mv_port_signal {
 
 struct mv_host_priv {
        u32                     hp_flags;
+       unsigned int            board_idx;
        u32                     main_irq_mask;
        struct mv_port_signal   signal[8];
        const struct mv_hw_ops  *ops;
@@ -548,6 +550,10 @@ struct mv_host_priv {
        u32                     irq_cause_offset;
        u32                     irq_mask_offset;
        u32                     unmask_all_irqs;
+
+#if defined(CONFIG_HAVE_CLK)
+       struct clk              *clk;
+#endif
        /*
         * These consistent DMA memory pools give us guaranteed
         * alignment for hardware-accessed data structures,
@@ -2775,7 +2781,7 @@ static void mv_port_intr(struct ata_port *ap, u32 port_cause)
        struct mv_port_priv *pp;
        int edma_was_enabled;
 
-       if (!ap || (ap->flags & ATA_FLAG_DISABLED)) {
+       if (ap->flags & ATA_FLAG_DISABLED) {
                mv_unexpected_intr(ap, 0);
                return;
        }
@@ -3393,7 +3399,7 @@ static void mv_soc_reset_hc_port(struct mv_host_priv *hpriv,
        ZERO(0x024);            /* respq outp */
        ZERO(0x020);            /* respq inp */
        ZERO(0x02c);            /* test control */
-       writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
+       writel(0x800, port_mmio + EDMA_IORDY_TMOUT);
 }
 
 #undef ZERO
@@ -3854,7 +3860,6 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
 /**
  *      mv_init_host - Perform some early initialization of the host.
  *     @host: ATA host to initialize
- *      @board_idx: controller index
  *
  *      If possible, do an early global reset of the host.  Then do
  *      our port init and clear/unmask all/relevant host interrupts.
@@ -3862,13 +3867,13 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
  *      LOCKING:
  *      Inherited from caller.
  */
-static int mv_init_host(struct ata_host *host, unsigned int board_idx)
+static int mv_init_host(struct ata_host *host)
 {
        int rc = 0, n_hc, port, hc;
        struct mv_host_priv *hpriv = host->private_data;
        void __iomem *mmio = hpriv->base;
 
-       rc = mv_chip_id(host, board_idx);
+       rc = mv_chip_id(host, hpriv->board_idx);
        if (rc)
                goto done;
 
@@ -3905,14 +3910,6 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
                void __iomem *port_mmio = mv_port_base(mmio, port);
 
                mv_port_init(&ap->ioaddr, port_mmio);
-
-#ifdef CONFIG_PCI
-               if (!IS_SOC(hpriv)) {
-                       unsigned int offset = port_mmio - mmio;
-                       ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
-                       ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
-               }
-#endif
        }
 
        for (hc = 0; hc < n_hc; hc++) {
@@ -4035,12 +4032,21 @@ static int mv_platform_probe(struct platform_device *pdev)
                return -ENOMEM;
        host->private_data = hpriv;
        hpriv->n_ports = n_ports;
+       hpriv->board_idx = chip_soc;
 
        host->iomap = NULL;
        hpriv->base = devm_ioremap(&pdev->dev, res->start,
                                   resource_size(res));
        hpriv->base -= SATAHC0_REG_BASE;
 
+#if defined(CONFIG_HAVE_CLK)
+       hpriv->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(hpriv->clk))
+               dev_notice(&pdev->dev, "cannot get clkdev\n");
+       else
+               clk_enable(hpriv->clk);
+#endif
+
        /*
         * (Re-)program MBUS remapping windows if we are asked to.
         */
@@ -4049,12 +4055,12 @@ static int mv_platform_probe(struct platform_device *pdev)
 
        rc = mv_create_dma_pools(hpriv, &pdev->dev);
        if (rc)
-               return rc;
+               goto err;
 
        /* initialize adapter */
-       rc = mv_init_host(host, chip_soc);
+       rc = mv_init_host(host);
        if (rc)
-               return rc;
+               goto err;
 
        dev_printk(KERN_INFO, &pdev->dev,
                   "slots %u ports %d\n", (unsigned)MV_MAX_Q_DEPTH,
@@ -4062,6 +4068,15 @@ static int mv_platform_probe(struct platform_device *pdev)
 
        return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt,
                                 IRQF_SHARED, &mv6_sht);
+err:
+#if defined(CONFIG_HAVE_CLK)
+       if (!IS_ERR(hpriv->clk)) {
+               clk_disable(hpriv->clk);
+               clk_put(hpriv->clk);
+       }
+#endif
+
+       return rc;
 }
 
 /*
@@ -4076,14 +4091,66 @@ static int __devexit mv_platform_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ata_host *host = dev_get_drvdata(dev);
-
+#if defined(CONFIG_HAVE_CLK)
+       struct mv_host_priv *hpriv = host->private_data;
+#endif
        ata_host_detach(host);
+
+#if defined(CONFIG_HAVE_CLK)
+       if (!IS_ERR(hpriv->clk)) {
+               clk_disable(hpriv->clk);
+               clk_put(hpriv->clk);
+       }
+#endif
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int mv_platform_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       if (host)
+               return ata_host_suspend(host, state);
+       else
+               return 0;
+}
+
+static int mv_platform_resume(struct platform_device *pdev)
+{
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       int ret;
+
+       if (host) {
+               struct mv_host_priv *hpriv = host->private_data;
+               const struct mv_sata_platform_data *mv_platform_data = \
+                       pdev->dev.platform_data;
+               /*
+                * (Re-)program MBUS remapping windows if we are asked to.
+                */
+               if (mv_platform_data->dram != NULL)
+                       mv_conf_mbus_windows(hpriv, mv_platform_data->dram);
+
+               /* initialize adapter */
+               ret = mv_init_host(host);
+               if (ret) {
+                       printk(KERN_ERR DRV_NAME ": Error during HW init\n");
+                       return ret;
+               }
+               ata_host_resume(host);
+       }
+
+       return 0;
+}
+#else
+#define mv_platform_suspend NULL
+#define mv_platform_resume NULL
+#endif
+
 static struct platform_driver mv_platform_driver = {
        .probe                  = mv_platform_probe,
        .remove                 = __devexit_p(mv_platform_remove),
+       .suspend                = mv_platform_suspend,
+       .resume                 = mv_platform_resume,
        .driver                 = {
                                   .name = DRV_NAME,
                                   .owner = THIS_MODULE,
@@ -4094,6 +4161,9 @@ static struct platform_driver mv_platform_driver = {
 #ifdef CONFIG_PCI
 static int mv_pci_init_one(struct pci_dev *pdev,
                           const struct pci_device_id *ent);
+#ifdef CONFIG_PM
+static int mv_pci_device_resume(struct pci_dev *pdev);
+#endif
 
 
 static struct pci_driver mv_pci_driver = {
@@ -4101,6 +4171,11 @@ static struct pci_driver mv_pci_driver = {
        .id_table               = mv_pci_tbl,
        .probe                  = mv_pci_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = mv_pci_device_resume,
+#endif
+
 };
 
 /* move to PCI layer or libata core? */
@@ -4194,7 +4269,7 @@ static int mv_pci_init_one(struct pci_dev *pdev,
        const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
        struct ata_host *host;
        struct mv_host_priv *hpriv;
-       int n_ports, rc;
+       int n_ports, port, rc;
 
        if (!printed_version++)
                dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
@@ -4208,6 +4283,7 @@ static int mv_pci_init_one(struct pci_dev *pdev,
                return -ENOMEM;
        host->private_data = hpriv;
        hpriv->n_ports = n_ports;
+       hpriv->board_idx = board_idx;
 
        /* acquire resources */
        rc = pcim_enable_device(pdev);
@@ -4230,8 +4306,17 @@ static int mv_pci_init_one(struct pci_dev *pdev,
        if (rc)
                return rc;
 
+       for (port = 0; port < host->n_ports; port++) {
+               struct ata_port *ap = host->ports[port];
+               void __iomem *port_mmio = mv_port_base(hpriv->base, port);
+               unsigned int offset = port_mmio - hpriv->base;
+
+               ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
+               ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
+       }
+
        /* initialize adapter */
-       rc = mv_init_host(host, board_idx);
+       rc = mv_init_host(host);
        if (rc)
                return rc;
 
@@ -4247,6 +4332,27 @@ static int mv_pci_init_one(struct pci_dev *pdev,
        return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
                                 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
 }
+
+#ifdef CONFIG_PM
+static int mv_pci_device_resume(struct pci_dev *pdev)
+{
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       int rc;
+
+       rc = ata_pci_device_do_resume(pdev);
+       if (rc)
+               return rc;
+
+       /* initialize adapter */
+       rc = mv_init_host(host);
+       if (rc)
+               return rc;
+
+       ata_host_resume(host);
+
+       return 0;
+}
+#endif
 #endif
 
 static int mv_platform_probe(struct platform_device *pdev);
index 63c143e..c0c5a43 100644 (file)
@@ -703,9 +703,9 @@ int bus_add_driver(struct device_driver *drv)
        return 0;
 
 out_unregister:
+       kobject_put(&priv->kobj);
        kfree(drv->p);
        drv->p = NULL;
-       kobject_put(&priv->kobj);
 out_put_bus:
        bus_put(bus);
        return error;
index f1290cb..2820257 100644 (file)
@@ -446,7 +446,8 @@ struct kset *devices_kset;
  * @dev: device.
  * @attr: device attribute descriptor.
  */
-int device_create_file(struct device *dev, struct device_attribute *attr)
+int device_create_file(struct device *dev,
+                      const struct device_attribute *attr)
 {
        int error = 0;
        if (dev)
@@ -459,7 +460,8 @@ int device_create_file(struct device *dev, struct device_attribute *attr)
  * @dev: device.
  * @attr: device attribute descriptor.
  */
-void device_remove_file(struct device *dev, struct device_attribute *attr)
+void device_remove_file(struct device *dev,
+                       const struct device_attribute *attr)
 {
        if (dev)
                sysfs_remove_file(&dev->kobj, &attr->attr);
@@ -470,7 +472,8 @@ void device_remove_file(struct device *dev, struct device_attribute *attr)
  * @dev: device.
  * @attr: device binary attribute descriptor.
  */
-int device_create_bin_file(struct device *dev, struct bin_attribute *attr)
+int device_create_bin_file(struct device *dev,
+                          const struct bin_attribute *attr)
 {
        int error = -EINVAL;
        if (dev)
@@ -484,7 +487,8 @@ EXPORT_SYMBOL_GPL(device_create_bin_file);
  * @dev: device.
  * @attr: device binary attribute descriptor.
  */
-void device_remove_bin_file(struct device *dev, struct bin_attribute *attr)
+void device_remove_bin_file(struct device *dev,
+                           const struct bin_attribute *attr)
 {
        if (dev)
                sysfs_remove_bin_file(&dev->kobj, attr);
@@ -905,8 +909,10 @@ int device_add(struct device *dev)
                dev->init_name = NULL;
        }
 
-       if (!dev_name(dev))
+       if (!dev_name(dev)) {
+               error = -EINVAL;
                goto name_error;
+       }
 
        pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
 
index 50375bb..090dd48 100644 (file)
@@ -32,7 +32,7 @@ static int dev_mount = 1;
 static int dev_mount;
 #endif
 
-static rwlock_t dirlock;
+static DEFINE_MUTEX(dirlock);
 
 static int __init mount_param(char *str)
 {
@@ -93,7 +93,7 @@ static int create_path(const char *nodepath)
 {
        int err;
 
-       read_lock(&dirlock);
+       mutex_lock(&dirlock);
        err = dev_mkdir(nodepath, 0755);
        if (err == -ENOENT) {
                char *path;
@@ -101,8 +101,10 @@ static int create_path(const char *nodepath)
 
                /* parent directories do not exist, create them */
                path = kstrdup(nodepath, GFP_KERNEL);
-               if (!path)
-                       return -ENOMEM;
+               if (!path) {
+                       err = -ENOMEM;
+                       goto out;
+               }
                s = path;
                for (;;) {
                        s = strchr(s, '/');
@@ -117,7 +119,8 @@ static int create_path(const char *nodepath)
                }
                kfree(path);
        }
-       read_unlock(&dirlock);
+out:
+       mutex_unlock(&dirlock);
        return err;
 }
 
@@ -229,7 +232,7 @@ static int delete_path(const char *nodepath)
        if (!path)
                return -ENOMEM;
 
-       write_lock(&dirlock);
+       mutex_lock(&dirlock);
        for (;;) {
                char *base;
 
@@ -241,7 +244,7 @@ static int delete_path(const char *nodepath)
                if (err)
                        break;
        }
-       write_unlock(&dirlock);
+       mutex_unlock(&dirlock);
 
        kfree(path);
        return err;
@@ -352,8 +355,6 @@ int __init devtmpfs_init(void)
        int err;
        struct vfsmount *mnt;
 
-       rwlock_init(&dirlock);
-
        err = register_filesystem(&dev_fs_type);
        if (err) {
                printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
index f367885..90c9fff 100644 (file)
@@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(driver_find_device);
  * @attr: driver attribute descriptor.
  */
 int driver_create_file(struct device_driver *drv,
-                      struct driver_attribute *attr)
+                      const struct driver_attribute *attr)
 {
        int error;
        if (drv)
@@ -115,7 +115,7 @@ EXPORT_SYMBOL_GPL(driver_create_file);
  * @attr: driver attribute descriptor.
  */
 void driver_remove_file(struct device_driver *drv,
-                       struct driver_attribute *attr)
+                       const struct driver_attribute *attr)
 {
        if (drv)
                sysfs_remove_file(&drv->p->kobj, &attr->attr);
index c4c8f2e..d7d77d4 100644 (file)
@@ -63,6 +63,20 @@ void unregister_memory_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_memory_notifier);
 
+static ATOMIC_NOTIFIER_HEAD(memory_isolate_chain);
+
+int register_memory_isolate_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_register(&memory_isolate_chain, nb);
+}
+EXPORT_SYMBOL(register_memory_isolate_notifier);
+
+void unregister_memory_isolate_notifier(struct notifier_block *nb)
+{
+       atomic_notifier_chain_unregister(&memory_isolate_chain, nb);
+}
+EXPORT_SYMBOL(unregister_memory_isolate_notifier);
+
 /*
  * register_memory - Setup a sysfs device for a memory block
  */
@@ -157,6 +171,11 @@ int memory_notify(unsigned long val, void *v)
        return blocking_notifier_call_chain(&memory_chain, val, v);
 }
 
+int memory_isolate_notify(unsigned long val, void *v)
+{
+       return atomic_notifier_call_chain(&memory_isolate_chain, val, v);
+}
+
 /*
  * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
  * OK to have direct references to sparsemem variables in here.
index 9d2ee25..58efaf2 100644 (file)
@@ -441,6 +441,7 @@ error:
        platform_device_put(pdev);
        return ERR_PTR(retval);
 }
+EXPORT_SYMBOL_GPL(platform_device_register_data);
 
 static int platform_drv_probe(struct device *_dev)
 {
index 1a216c1..48adf80 100644 (file)
@@ -161,6 +161,32 @@ void device_pm_move_last(struct device *dev)
        list_move_tail(&dev->power.entry, &dpm_list);
 }
 
+static ktime_t initcall_debug_start(struct device *dev)
+{
+       ktime_t calltime = ktime_set(0, 0);
+
+       if (initcall_debug) {
+               pr_info("calling  %s+ @ %i\n",
+                               dev_name(dev), task_pid_nr(current));
+               calltime = ktime_get();
+       }
+
+       return calltime;
+}
+
+static void initcall_debug_report(struct device *dev, ktime_t calltime,
+                                 int error)
+{
+       ktime_t delta, rettime;
+
+       if (initcall_debug) {
+               rettime = ktime_get();
+               delta = ktime_sub(rettime, calltime);
+               pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
+                       error, (unsigned long long)ktime_to_ns(delta) >> 10);
+       }
+}
+
 /**
  * pm_op - Execute the PM operation appropriate for given PM event.
  * @dev: Device to handle.
@@ -172,13 +198,9 @@ static int pm_op(struct device *dev,
                 pm_message_t state)
 {
        int error = 0;
-       ktime_t calltime, delta, rettime;
+       ktime_t calltime;
 
-       if (initcall_debug) {
-               pr_info("calling  %s+ @ %i\n",
-                               dev_name(dev), task_pid_nr(current));
-               calltime = ktime_get();
-       }
+       calltime = initcall_debug_start(dev);
 
        switch (state.event) {
 #ifdef CONFIG_SUSPEND
@@ -227,12 +249,7 @@ static int pm_op(struct device *dev,
                error = -EINVAL;
        }
 
-       if (initcall_debug) {
-               rettime = ktime_get();
-               delta = ktime_sub(rettime, calltime);
-               pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
-                       error, (unsigned long long)ktime_to_ns(delta) >> 10);
-       }
+       initcall_debug_report(dev, calltime, error);
 
        return error;
 }
@@ -309,8 +326,9 @@ static int pm_noirq_op(struct device *dev,
        if (initcall_debug) {
                rettime = ktime_get();
                delta = ktime_sub(rettime, calltime);
-               printk("initcall %s_i+ returned %d after %Ld usecs\n", dev_name(dev),
-                       error, (unsigned long long)ktime_to_ns(delta) >> 10);
+               printk("initcall %s_i+ returned %d after %Ld usecs\n",
+                       dev_name(dev), error,
+                       (unsigned long long)ktime_to_ns(delta) >> 10);
        }
 
        return error;
@@ -354,6 +372,23 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
                kobject_name(&dev->kobj), pm_verb(state.event), info, error);
 }
 
+static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
+{
+       ktime_t calltime;
+       s64 usecs64;
+       int usecs;
+
+       calltime = ktime_get();
+       usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
+       do_div(usecs64, NSEC_PER_USEC);
+       usecs = usecs64;
+       if (usecs == 0)
+               usecs = 1;
+       pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n",
+               info ?: "", info ? " " : "", pm_verb(state.event),
+               usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
+}
+
 /*------------------------- Resume routines -------------------------*/
 
 /**
@@ -390,6 +425,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
 void dpm_resume_noirq(pm_message_t state)
 {
        struct device *dev;
+       ktime_t starttime = ktime_get();
 
        mutex_lock(&dpm_list_mtx);
        transition_started = false;
@@ -403,11 +439,32 @@ void dpm_resume_noirq(pm_message_t state)
                                pm_dev_err(dev, state, " early", error);
                }
        mutex_unlock(&dpm_list_mtx);
+       dpm_show_time(starttime, state, "early");
        resume_device_irqs();
 }
 EXPORT_SYMBOL_GPL(dpm_resume_noirq);
 
 /**
+ * legacy_resume - Execute a legacy (bus or class) resume callback for device.
+ * dev: Device to resume.
+ * cb: Resume callback to execute.
+ */
+static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
+{
+       int error;
+       ktime_t calltime;
+
+       calltime = initcall_debug_start(dev);
+
+       error = cb(dev);
+       suspend_report_result(cb, error);
+
+       initcall_debug_report(dev, calltime, error);
+
+       return error;
+}
+
+/**
  * device_resume - Execute "resume" callbacks for given device.
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
@@ -427,7 +484,7 @@ static int device_resume(struct device *dev, pm_message_t state)
                        error = pm_op(dev, dev->bus->pm, state);
                } else if (dev->bus->resume) {
                        pm_dev_dbg(dev, state, "legacy ");
-                       error = dev->bus->resume(dev);
+                       error = legacy_resume(dev, dev->bus->resume);
                }
                if (error)
                        goto End;
@@ -448,7 +505,7 @@ static int device_resume(struct device *dev, pm_message_t state)
                        error = pm_op(dev, dev->class->pm, state);
                } else if (dev->class->resume) {
                        pm_dev_dbg(dev, state, "legacy class ");
-                       error = dev->class->resume(dev);
+                       error = legacy_resume(dev, dev->class->resume);
                }
        }
  End:
@@ -468,6 +525,7 @@ static int device_resume(struct device *dev, pm_message_t state)
 static void dpm_resume(pm_message_t state)
 {
        struct list_head list;
+       ktime_t starttime = ktime_get();
 
        INIT_LIST_HEAD(&list);
        mutex_lock(&dpm_list_mtx);
@@ -496,6 +554,7 @@ static void dpm_resume(pm_message_t state)
        }
        list_splice(&list, &dpm_list);
        mutex_unlock(&dpm_list_mtx);
+       dpm_show_time(starttime, state, NULL);
 }
 
 /**
@@ -548,7 +607,7 @@ static void dpm_complete(pm_message_t state)
                        mutex_unlock(&dpm_list_mtx);
 
                        device_complete(dev, state);
-                       pm_runtime_put_noidle(dev);
+                       pm_runtime_put_sync(dev);
 
                        mutex_lock(&dpm_list_mtx);
                }
@@ -628,6 +687,7 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
 int dpm_suspend_noirq(pm_message_t state)
 {
        struct device *dev;
+       ktime_t starttime = ktime_get();
        int error = 0;
 
        suspend_device_irqs();
@@ -643,11 +703,34 @@ int dpm_suspend_noirq(pm_message_t state)
        mutex_unlock(&dpm_list_mtx);
        if (error)
                dpm_resume_noirq(resume_event(state));
+       else
+               dpm_show_time(starttime, state, "late");
        return error;
 }
 EXPORT_SYMBOL_GPL(dpm_suspend_noirq);
 
 /**
+ * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
+ * dev: Device to suspend.
+ * cb: Suspend callback to execute.
+ */
+static int legacy_suspend(struct device *dev, pm_message_t state,
+                         int (*cb)(struct device *dev, pm_message_t state))
+{
+       int error;
+       ktime_t calltime;
+
+       calltime = initcall_debug_start(dev);
+
+       error = cb(dev, state);
+       suspend_report_result(cb, error);
+
+       initcall_debug_report(dev, calltime, error);
+
+       return error;
+}
+
+/**
  * device_suspend - Execute "suspend" callbacks for given device.
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
@@ -664,8 +747,7 @@ static int device_suspend(struct device *dev, pm_message_t state)
                        error = pm_op(dev, dev->class->pm, state);
                } else if (dev->class->suspend) {
                        pm_dev_dbg(dev, state, "legacy class ");
-                       error = dev->class->suspend(dev, state);
-                       suspend_report_result(dev->class->suspend, error);
+                       error = legacy_suspend(dev, state, dev->class->suspend);
                }
                if (error)
                        goto End;
@@ -686,8 +768,7 @@ static int device_suspend(struct device *dev, pm_message_t state)
                        error = pm_op(dev, dev->bus->pm, state);
                } else if (dev->bus->suspend) {
                        pm_dev_dbg(dev, state, "legacy ");
-                       error = dev->bus->suspend(dev, state);
-                       suspend_report_result(dev->bus->suspend, error);
+                       error = legacy_suspend(dev, state, dev->bus->suspend);
                }
        }
  End:
@@ -703,6 +784,7 @@ static int device_suspend(struct device *dev, pm_message_t state)
 static int dpm_suspend(pm_message_t state)
 {
        struct list_head list;
+       ktime_t starttime = ktime_get();
        int error = 0;
 
        INIT_LIST_HEAD(&list);
@@ -728,6 +810,8 @@ static int dpm_suspend(pm_message_t state)
        }
        list_splice(&list, dpm_list.prev);
        mutex_unlock(&dpm_list_mtx);
+       if (!error)
+               dpm_show_time(starttime, state, NULL);
        return error;
 }
 
@@ -796,7 +880,7 @@ static int dpm_prepare(pm_message_t state)
                pm_runtime_get_noresume(dev);
                if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) {
                        /* Wake-up requested during system sleep transition. */
-                       pm_runtime_put_noidle(dev);
+                       pm_runtime_put_sync(dev);
                        error = -EBUSY;
                } else {
                        error = device_prepare(dev, state);
index 40d7720..f8b044e 100644 (file)
@@ -85,6 +85,19 @@ static int __pm_runtime_idle(struct device *dev)
                dev->bus->pm->runtime_idle(dev);
 
                spin_lock_irq(&dev->power.lock);
+       } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) {
+               spin_unlock_irq(&dev->power.lock);
+
+               dev->type->pm->runtime_idle(dev);
+
+               spin_lock_irq(&dev->power.lock);
+       } else if (dev->class && dev->class->pm
+           && dev->class->pm->runtime_idle) {
+               spin_unlock_irq(&dev->power.lock);
+
+               dev->class->pm->runtime_idle(dev);
+
+               spin_lock_irq(&dev->power.lock);
        }
 
        dev->power.idle_notification = false;
@@ -194,6 +207,22 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
 
                spin_lock_irq(&dev->power.lock);
                dev->power.runtime_error = retval;
+       } else if (dev->type && dev->type->pm
+           && dev->type->pm->runtime_suspend) {
+               spin_unlock_irq(&dev->power.lock);
+
+               retval = dev->type->pm->runtime_suspend(dev);
+
+               spin_lock_irq(&dev->power.lock);
+               dev->power.runtime_error = retval;
+       } else if (dev->class && dev->class->pm
+           && dev->class->pm->runtime_suspend) {
+               spin_unlock_irq(&dev->power.lock);
+
+               retval = dev->class->pm->runtime_suspend(dev);
+
+               spin_lock_irq(&dev->power.lock);
+               dev->power.runtime_error = retval;
        } else {
                retval = -ENOSYS;
        }
@@ -359,6 +388,22 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
 
                spin_lock_irq(&dev->power.lock);
                dev->power.runtime_error = retval;
+       } else if (dev->type && dev->type->pm
+           && dev->type->pm->runtime_resume) {
+               spin_unlock_irq(&dev->power.lock);
+
+               retval = dev->type->pm->runtime_resume(dev);
+
+               spin_lock_irq(&dev->power.lock);
+               dev->power.runtime_error = retval;
+       } else if (dev->class && dev->class->pm
+           && dev->class->pm->runtime_resume) {
+               spin_unlock_irq(&dev->power.lock);
+
+               retval = dev->class->pm->runtime_resume(dev);
+
+               spin_lock_irq(&dev->power.lock);
+               dev->power.runtime_error = retval;
        } else {
                retval = -ENOSYS;
        }
index 4d29059..a699f09 100644 (file)
@@ -307,6 +307,7 @@ static void btusb_bulk_complete(struct urb *urb)
                return;
 
        usb_anchor_urb(urb, &data->bulk_anchor);
+       usb_mark_last_busy(data->udev);
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
index d3400b2..7d73cd4 100644 (file)
@@ -358,7 +358,7 @@ struct port {
        u8 update_flow_control;
        struct ctrl_ul ctrl_ul;
        struct ctrl_dl ctrl_dl;
-       struct kfifo *fifo_ul;
+       struct kfifo fifo_ul;
        void __iomem *dl_addr[2];
        u32 dl_size[2];
        u8 toggle_dl;
@@ -685,8 +685,6 @@ static int nozomi_read_config_table(struct nozomi *dc)
                dump_table(dc);
 
                for (i = PORT_MDM; i < MAX_PORT; i++) {
-                       dc->port[i].fifo_ul =
-                           kfifo_alloc(FIFO_BUFFER_SIZE_UL, GFP_ATOMIC, NULL);
                        memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl));
                        memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul));
                }
@@ -798,7 +796,7 @@ static int send_data(enum port_type index, struct nozomi *dc)
        struct tty_struct *tty = tty_port_tty_get(&port->port);
 
        /* Get data from tty and place in buf for now */
-       size = __kfifo_get(port->fifo_ul, dc->send_buf,
+       size = kfifo_out(&port->fifo_ul, dc->send_buf,
                           ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX);
 
        if (size == 0) {
@@ -988,11 +986,11 @@ static int receive_flow_control(struct nozomi *dc)
 
        } else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) {
 
-               if (__kfifo_len(dc->port[port].fifo_ul)) {
+               if (kfifo_len(&dc->port[port].fifo_ul)) {
                        DBG1("Enable interrupt (0x%04X) on port: %d",
                                enable_ier, port);
                        DBG1("Data in buffer [%d], enable transmit! ",
-                               __kfifo_len(dc->port[port].fifo_ul));
+                               kfifo_len(&dc->port[port].fifo_ul));
                        enable_transmit_ul(port, dc);
                } else {
                        DBG1("No data in buffer...");
@@ -1433,6 +1431,16 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
                goto err_free_sbuf;
        }
 
+       for (i = PORT_MDM; i < MAX_PORT; i++) {
+               if (kfifo_alloc(&dc->port[i].fifo_ul,
+                     FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) {
+                       dev_err(&pdev->dev,
+                                       "Could not allocate kfifo buffer\n");
+                       ret = -ENOMEM;
+                       goto err_free_kfifo;
+               }
+       }
+
        spin_lock_init(&dc->spin_mutex);
 
        nozomi_setup_private_data(dc);
@@ -1445,7 +1453,7 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
                        NOZOMI_NAME, dc);
        if (unlikely(ret)) {
                dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq);
-               goto err_free_sbuf;
+               goto err_free_kfifo;
        }
 
        DBG1("base_addr: %p", dc->base_addr);
@@ -1464,13 +1472,28 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
        dc->state = NOZOMI_STATE_ENABLED;
 
        for (i = 0; i < MAX_PORT; i++) {
+               struct device *tty_dev;
+
                mutex_init(&dc->port[i].tty_sem);
                tty_port_init(&dc->port[i].port);
-               tty_register_device(ntty_driver, dc->index_start + i,
+               tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
                                                        &pdev->dev);
+
+               if (IS_ERR(tty_dev)) {
+                       ret = PTR_ERR(tty_dev);
+                       dev_err(&pdev->dev, "Could not allocate tty?\n");
+                       goto err_free_tty;
+               }
        }
+
        return 0;
 
+err_free_tty:
+       for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
+               tty_unregister_device(ntty_driver, i);
+err_free_kfifo:
+       for (i = 0; i < MAX_PORT; i++)
+               kfifo_free(&dc->port[i].fifo_ul);
 err_free_sbuf:
        kfree(dc->send_buf);
        iounmap(dc->base_addr);
@@ -1536,8 +1559,7 @@ static void __devexit nozomi_card_exit(struct pci_dev *pdev)
        free_irq(pdev->irq, dc);
 
        for (i = 0; i < MAX_PORT; i++)
-               if (dc->port[i].fifo_ul)
-                       kfifo_free(dc->port[i].fifo_ul);
+               kfifo_free(&dc->port[i].fifo_ul);
 
        kfree(dc->send_buf);
 
@@ -1673,7 +1695,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
                goto exit;
        }
 
-       rval = __kfifo_put(port->fifo_ul, (unsigned char *)buffer, count);
+       rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count);
 
        /* notify card */
        if (unlikely(dc == NULL)) {
@@ -1721,7 +1743,7 @@ static int ntty_write_room(struct tty_struct *tty)
        if (!port->port.count)
                goto exit;
 
-       room = port->fifo_ul->size - __kfifo_len(port->fifo_ul);
+       room = port->fifo_ul.size - kfifo_len(&port->fifo_ul);
 
 exit:
        mutex_unlock(&port->tty_sem);
@@ -1878,7 +1900,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty)
                goto exit_in_buffer;
        }
 
-       rval = __kfifo_len(port->fifo_ul);
+       rval = kfifo_len(&port->fifo_ul);
 
 exit_in_buffer:
        return rval;
index 8c262aa..0798754 100644 (file)
@@ -487,7 +487,7 @@ static struct sonypi_device {
        int camera_power;
        int bluetooth_power;
        struct mutex lock;
-       struct kfifo *fifo;
+       struct kfifo fifo;
        spinlock_t fifo_lock;
        wait_queue_head_t fifo_proc_list;
        struct fasync_struct *fifo_async;
@@ -496,7 +496,7 @@ static struct sonypi_device {
        struct input_dev *input_jog_dev;
        struct input_dev *input_key_dev;
        struct work_struct input_work;
-       struct kfifo *input_fifo;
+       struct kfifo input_fifo;
        spinlock_t input_fifo_lock;
 } sonypi_device;
 
@@ -777,8 +777,9 @@ static void input_keyrelease(struct work_struct *work)
 {
        struct sonypi_keypress kp;
 
-       while (kfifo_get(sonypi_device.input_fifo, (unsigned char *)&kp,
-                        sizeof(kp)) == sizeof(kp)) {
+       while (kfifo_out_locked(&sonypi_device.input_fifo, (unsigned char *)&kp,
+                        sizeof(kp), &sonypi_device.input_fifo_lock)
+                       == sizeof(kp)) {
                msleep(10);
                input_report_key(kp.dev, kp.key, 0);
                input_sync(kp.dev);
@@ -827,8 +828,9 @@ static void sonypi_report_input_event(u8 event)
        if (kp.dev) {
                input_report_key(kp.dev, kp.key, 1);
                input_sync(kp.dev);
-               kfifo_put(sonypi_device.input_fifo,
-                         (unsigned char *)&kp, sizeof(kp));
+               kfifo_in_locked(&sonypi_device.input_fifo,
+                       (unsigned char *)&kp, sizeof(kp),
+                       &sonypi_device.input_fifo_lock);
                schedule_work(&sonypi_device.input_work);
        }
 }
@@ -880,7 +882,8 @@ found:
                acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event);
 #endif
 
-       kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event));
+       kfifo_in_locked(&sonypi_device.fifo, (unsigned char *)&event,
+                       sizeof(event), &sonypi_device.fifo_lock);
        kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN);
        wake_up_interruptible(&sonypi_device.fifo_proc_list);
 
@@ -906,7 +909,7 @@ static int sonypi_misc_open(struct inode *inode, struct file *file)
        mutex_lock(&sonypi_device.lock);
        /* Flush input queue on first open */
        if (!sonypi_device.open_count)
-               kfifo_reset(sonypi_device.fifo);
+               kfifo_reset(&sonypi_device.fifo);
        sonypi_device.open_count++;
        mutex_unlock(&sonypi_device.lock);
        unlock_kernel();
@@ -919,17 +922,18 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
        ssize_t ret;
        unsigned char c;
 
-       if ((kfifo_len(sonypi_device.fifo) == 0) &&
+       if ((kfifo_len(&sonypi_device.fifo) == 0) &&
            (file->f_flags & O_NONBLOCK))
                return -EAGAIN;
 
        ret = wait_event_interruptible(sonypi_device.fifo_proc_list,
-                                      kfifo_len(sonypi_device.fifo) != 0);
+                                      kfifo_len(&sonypi_device.fifo) != 0);
        if (ret)
                return ret;
 
        while (ret < count &&
-              (kfifo_get(sonypi_device.fifo, &c, sizeof(c)) == sizeof(c))) {
+              (kfifo_out_locked(&sonypi_device.fifo, &c, sizeof(c),
+                                &sonypi_device.fifo_lock) == sizeof(c))) {
                if (put_user(c, buf++))
                        return -EFAULT;
                ret++;
@@ -946,7 +950,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
 static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
 {
        poll_wait(file, &sonypi_device.fifo_proc_list, wait);
-       if (kfifo_len(sonypi_device.fifo))
+       if (kfifo_len(&sonypi_device.fifo))
                return POLLIN | POLLRDNORM;
        return 0;
 }
@@ -1313,11 +1317,10 @@ static int __devinit sonypi_probe(struct platform_device *dev)
                        "http://www.linux.it/~malattia/wiki/index.php/Sony_drivers\n");
 
        spin_lock_init(&sonypi_device.fifo_lock);
-       sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
-                                        &sonypi_device.fifo_lock);
-       if (IS_ERR(sonypi_device.fifo)) {
+       error = kfifo_alloc(&sonypi_device.fifo, SONYPI_BUF_SIZE, GFP_KERNEL);
+       if (error) {
                printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
-               return PTR_ERR(sonypi_device.fifo);
+               return error;
        }
 
        init_waitqueue_head(&sonypi_device.fifo_proc_list);
@@ -1393,12 +1396,10 @@ static int __devinit sonypi_probe(struct platform_device *dev)
                }
 
                spin_lock_init(&sonypi_device.input_fifo_lock);
-               sonypi_device.input_fifo =
-                       kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
-                                   &sonypi_device.input_fifo_lock);
-               if (IS_ERR(sonypi_device.input_fifo)) {
+               error = kfifo_alloc(&sonypi_device.input_fifo, SONYPI_BUF_SIZE,
+                               GFP_KERNEL);
+               if (error) {
                        printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
-                       error = PTR_ERR(sonypi_device.input_fifo);
                        goto err_inpdev_unregister;
                }
 
@@ -1423,7 +1424,7 @@ static int __devinit sonypi_probe(struct platform_device *dev)
                pci_disable_device(pcidev);
  err_put_pcidev:
        pci_dev_put(pcidev);
-       kfifo_free(sonypi_device.fifo);
+       kfifo_free(&sonypi_device.fifo);
 
        return error;
 }
@@ -1438,7 +1439,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
        if (useinput) {
                input_unregister_device(sonypi_device.input_key_dev);
                input_unregister_device(sonypi_device.input_jog_dev);
-               kfifo_free(sonypi_device.input_fifo);
+               kfifo_free(&sonypi_device.input_fifo);
        }
 
        misc_deregister(&sonypi_misc_device);
@@ -1451,7 +1452,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
                pci_dev_put(sonypi_device.dev);
        }
 
-       kfifo_free(sonypi_device.fifo);
+       kfifo_free(&sonypi_device.fifo);
 
        return 0;
 }
index ff2f104..766c468 100644 (file)
@@ -434,11 +434,11 @@ static int drm_version(struct drm_device *dev, void *data,
  * Looks up the ioctl function in the ::ioctls table, checking for root
  * previleges if so required, and dispatches to the respective function.
  */
-int drm_ioctl(struct inode *inode, struct file *filp,
+long drm_ioctl(struct file *filp,
              unsigned int cmd, unsigned long arg)
 {
        struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->minor->dev;
+       struct drm_device *dev;
        struct drm_ioctl_desc *ioctl;
        drm_ioctl_t *func;
        unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -446,6 +446,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
        char stack_kdata[128];
        char *kdata = NULL;
 
+       dev = file_priv->minor->dev;
        atomic_inc(&dev->ioctl_count);
        atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
        ++file_priv->ioctl_count;
@@ -501,7 +502,13 @@ int drm_ioctl(struct inode *inode, struct file *filp,
                                goto err_i1;
                        }
                }
-               retcode = func(dev, kdata, file_priv);
+               if (ioctl->flags & DRM_UNLOCKED)
+                       retcode = func(dev, kdata, file_priv);
+               else {
+                       lock_kernel();
+                       retcode = func(dev, kdata, file_priv);
+                       unlock_kernel();
+               }
 
                if (cmd & IOC_OUT) {
                        if (copy_to_user((void __user *)arg, kdata,
index c39b26f..5c9f798 100644 (file)
@@ -913,7 +913,7 @@ static int drm_cvt_modes(struct drm_connector *connector,
        const int rates[] = { 60, 85, 75, 60, 50 };
 
        for (i = 0; i < 4; i++) {
-               int width, height;
+               int uninitialized_var(width), height;
                cvt = &(timing->data.other_data.data.cvt[i]);
 
                height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 8) + 1) * 2;
index 282d9fd..d61d185 100644 (file)
@@ -104,7 +104,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
                          &version->desc))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+       err = drm_ioctl(file,
                        DRM_IOCTL_VERSION, (unsigned long)version);
        if (err)
                return err;
@@ -145,8 +145,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
                          &u->unique))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
+       err = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
        if (err)
                return err;
 
@@ -174,8 +173,7 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
                          &u->unique))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
+       return drm_ioctl(file, DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
 }
 
 typedef struct drm_map32 {
@@ -205,8 +203,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
        if (__put_user(idx, &map->offset))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_GET_MAP, (unsigned long)map);
+       err = drm_ioctl(file, DRM_IOCTL_GET_MAP, (unsigned long)map);
        if (err)
                return err;
 
@@ -246,8 +243,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
            || __put_user(m32.flags, &map->flags))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_ADD_MAP, (unsigned long)map);
+       err = drm_ioctl(file, DRM_IOCTL_ADD_MAP, (unsigned long)map);
        if (err)
                return err;
 
@@ -284,8 +280,7 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd,
        if (__put_user((void *)(unsigned long)handle, &map->handle))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RM_MAP, (unsigned long)map);
+       return drm_ioctl(file, DRM_IOCTL_RM_MAP, (unsigned long)map);
 }
 
 typedef struct drm_client32 {
@@ -314,8 +309,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
        if (__put_user(idx, &client->idx))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_GET_CLIENT, (unsigned long)client);
+       err = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, (unsigned long)client);
        if (err)
                return err;
 
@@ -351,8 +345,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
        if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_GET_STATS, (unsigned long)stats);
+       err = drm_ioctl(file, DRM_IOCTL_GET_STATS, (unsigned long)stats);
        if (err)
                return err;
 
@@ -395,8 +388,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd,
            || __put_user(agp_start, &buf->agp_start))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
+       err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
        if (err)
                return err;
 
@@ -427,8 +419,7 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd,
            || __put_user(b32.high_mark, &buf->high_mark))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
+       return drm_ioctl(file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
 }
 
 typedef struct drm_buf_info32 {
@@ -469,8 +460,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
            || __put_user(list, &request->list))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_INFO_BUFS, (unsigned long)request);
+       err = drm_ioctl(file, DRM_IOCTL_INFO_BUFS, (unsigned long)request);
        if (err)
                return err;
 
@@ -531,8 +521,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
            || __put_user(list, &request->list))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_MAP_BUFS, (unsigned long)request);
+       err = drm_ioctl(file, DRM_IOCTL_MAP_BUFS, (unsigned long)request);
        if (err)
                return err;
 
@@ -578,8 +567,7 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd,
                          &request->list))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_FREE_BUFS, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_FREE_BUFS, (unsigned long)request);
 }
 
 typedef struct drm_ctx_priv_map32 {
@@ -605,8 +593,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
                          &request->handle))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
 }
 
 static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
@@ -628,8 +615,7 @@ static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
        if (__put_user(ctx_id, &request->ctx_id))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
+       err = drm_ioctl(file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
        if (err)
                return err;
 
@@ -664,8 +650,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
                          &res->contexts))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_RES_CTX, (unsigned long)res);
+       err = drm_ioctl(file, DRM_IOCTL_RES_CTX, (unsigned long)res);
        if (err)
                return err;
 
@@ -718,8 +703,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd,
                          &d->request_sizes))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_DMA, (unsigned long)d);
+       err = drm_ioctl(file, DRM_IOCTL_DMA, (unsigned long)d);
        if (err)
                return err;
 
@@ -751,8 +735,7 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
        if (put_user(m32.mode, &mode->mode))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
+       return drm_ioctl(file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
 }
 
 typedef struct drm_agp_info32 {
@@ -781,8 +764,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd,
        if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_AGP_INFO, (unsigned long)info);
+       err = drm_ioctl(file, DRM_IOCTL_AGP_INFO, (unsigned long)info);
        if (err)
                return err;
 
@@ -827,16 +809,14 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
            || __put_user(req32.type, &request->type))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
+       err = drm_ioctl(file, DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
        if (err)
                return err;
 
        if (__get_user(req32.handle, &request->handle)
            || __get_user(req32.physical, &request->physical)
            || copy_to_user(argp, &req32, sizeof(req32))) {
-               drm_ioctl(file->f_path.dentry->d_inode, file,
-                         DRM_IOCTL_AGP_FREE, (unsigned long)request);
+               drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
                return -EFAULT;
        }
 
@@ -856,8 +836,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd,
            || __put_user(handle, &request->handle))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_AGP_FREE, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
 }
 
 typedef struct drm_agp_binding32 {
@@ -881,8 +860,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
            || __put_user(req32.offset, &request->offset))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_AGP_BIND, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_AGP_BIND, (unsigned long)request);
 }
 
 static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
@@ -898,8 +876,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
            || __put_user(handle, &request->handle))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
 }
 #endif                         /* __OS_HAS_AGP */
 
@@ -923,8 +900,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
            || __put_user(x, &request->size))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_SG_ALLOC, (unsigned long)request);
+       err = drm_ioctl(file, DRM_IOCTL_SG_ALLOC, (unsigned long)request);
        if (err)
                return err;
 
@@ -950,8 +926,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
            || __put_user(x << PAGE_SHIFT, &request->handle))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_SG_FREE, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_SG_FREE, (unsigned long)request);
 }
 
 #if defined(CONFIG_X86) || defined(CONFIG_IA64)
@@ -981,8 +956,7 @@ static int compat_drm_update_draw(struct file *file, unsigned int cmd,
            __put_user(update32.data, &request->data))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_UPDATE_DRAW, (unsigned long)request);
+       err = drm_ioctl(file, DRM_IOCTL_UPDATE_DRAW, (unsigned long)request);
        return err;
 }
 #endif
@@ -1023,8 +997,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
            || __put_user(req32.request.signal, &request->request.signal))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
+       err = drm_ioctl(file, DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
        if (err)
                return err;
 
@@ -1094,16 +1067,14 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
         * than always failing.
         */
        if (nr >= ARRAY_SIZE(drm_compat_ioctls))
-               return drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+               return drm_ioctl(filp, cmd, arg);
 
        fn = drm_compat_ioctls[nr];
 
-       lock_kernel();          /* XXX for now */
        if (fn != NULL)
                ret = (*fn) (filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
+               ret = drm_ioctl(filp, cmd, arg);
 
        return ret;
 }
index d7d7eac..cdec329 100644 (file)
@@ -358,7 +358,7 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
                if (entry->size >= size + wasted) {
                        if (!best_match)
                                return entry;
-                       if (size < best_size) {
+                       if (entry->size < best_size) {
                                best = entry;
                                best_size = entry->size;
                        }
@@ -408,7 +408,7 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
                if (entry->size >= size + wasted) {
                        if (!best_match)
                                return entry;
-                       if (size < best_size) {
+                       if (entry->size < best_size) {
                                best = entry;
                                best_size = entry->size;
                        }
index 9422a74..81681a0 100644 (file)
@@ -408,6 +408,11 @@ static int ch7006_probe(struct i2c_client *client, const struct i2c_device_id *i
 
        ch7006_info(client, "Detected version ID: %x\n", val);
 
+       /* I don't know what this is for, but otherwise I get no
+        * signal.
+        */
+       ch7006_write(client, 0x3d, 0x0);
+
        return 0;
 
 fail:
index 87f5445..e447dfb 100644 (file)
@@ -427,11 +427,6 @@ void ch7006_state_load(struct i2c_client *client,
        ch7006_load_reg(client, state, CH7006_SUBC_INC7);
        ch7006_load_reg(client, state, CH7006_PLL_CONTROL);
        ch7006_load_reg(client, state, CH7006_CALC_SUBC_INC0);
-
-       /* I don't know what this is for, but otherwise I get no
-        * signal.
-        */
-       ch7006_write(client, 0x3d, 0x0);
 }
 
 void ch7006_state_save(struct i2c_client *client,
index 7d1d88c..de32d22 100644 (file)
@@ -115,7 +115,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 static const struct file_operations i810_buffer_fops = {
        .open = drm_open,
        .release = drm_release,
-       .ioctl = drm_ioctl,
+       .unlocked_ioctl = drm_ioctl,
        .mmap = i810_mmap_buffers,
        .fasync = drm_fasync,
 };
index fabb9a8..c1e0275 100644 (file)
@@ -59,7 +59,7 @@ static struct drm_driver driver = {
                 .owner = THIS_MODULE,
                 .open = drm_open,
                 .release = drm_release,
-                .ioctl = drm_ioctl,
+                .unlocked_ioctl = drm_ioctl,
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
index 877bf6c..06bd732 100644 (file)
@@ -117,7 +117,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 static const struct file_operations i830_buffer_fops = {
        .open = drm_open,
        .release = drm_release,
-       .ioctl = drm_ioctl,
+       .unlocked_ioctl = drm_ioctl,
        .mmap = i830_mmap_buffers,
        .fasync = drm_fasync,
 };
index 389597e..44f990b 100644 (file)
@@ -70,7 +70,7 @@ static struct drm_driver driver = {
                 .owner = THIS_MODULE,
                 .open = drm_open,
                 .release = drm_release,
-                .ioctl = drm_ioctl,
+                .unlocked_ioctl = drm_ioctl,
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
index 2fa2178..24286ca 100644 (file)
@@ -329,7 +329,7 @@ static struct drm_driver driver = {
                 .owner = THIS_MODULE,
                 .open = drm_open,
                 .release = drm_release,
-                .ioctl = drm_ioctl,
+                .unlocked_ioctl = drm_ioctl,
                 .mmap = drm_gem_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
index 1fe68a2..13b0289 100644 (file)
@@ -66,8 +66,7 @@ static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
                          &batchbuffer->cliprects))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_I915_BATCHBUFFER,
+       return drm_ioctl(file, DRM_IOCTL_I915_BATCHBUFFER,
                         (unsigned long)batchbuffer);
 }
 
@@ -102,8 +101,8 @@ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
                          &cmdbuffer->cliprects))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
+       return drm_ioctl(file, DRM_IOCTL_I915_CMDBUFFER,
+                        (unsigned long)cmdbuffer);
 }
 
 typedef struct drm_i915_irq_emit32 {
@@ -125,8 +124,8 @@ static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
                          &request->irq_seq))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_I915_IRQ_EMIT,
+                        (unsigned long)request);
 }
 typedef struct drm_i915_getparam32 {
        int param;
@@ -149,8 +148,8 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd,
                          &request->value))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_I915_GETPARAM,
+                        (unsigned long)request);
 }
 
 typedef struct drm_i915_mem_alloc32 {
@@ -178,8 +177,8 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd,
                          &request->region_offset))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_I915_ALLOC, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_I915_ALLOC,
+                        (unsigned long)request);
 }
 
 drm_ioctl_compat_t *i915_compat_ioctls[] = {
@@ -211,12 +210,10 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
                fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
 
-       lock_kernel();          /* XXX for now */
        if (fn != NULL)
                ret = (*fn) (filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
+               ret = drm_ioctl(filp, cmd, arg);
 
        return ret;
 }
index 97ee566..ddfe161 100644 (file)
@@ -68,7 +68,7 @@ static struct drm_driver driver = {
                .owner = THIS_MODULE,
                .open = drm_open,
                .release = drm_release,
-               .ioctl = drm_ioctl,
+               .unlocked_ioctl = drm_ioctl,
                .mmap = drm_mmap,
                .poll = drm_poll,
                .fasync = drm_fasync,
index 30d0047..c1f877b 100644 (file)
@@ -100,8 +100,7 @@ static int compat_mga_init(struct file *file, unsigned int cmd,
        if (err)
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_MGA_INIT, (unsigned long)init);
+       return drm_ioctl(file, DRM_IOCTL_MGA_INIT, (unsigned long)init);
 }
 
 typedef struct drm_mga_getparam32 {
@@ -125,8 +124,7 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd,
                          &getparam->value))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
+       return drm_ioctl(file, DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
 }
 
 typedef struct drm_mga_drm_bootstrap32 {
@@ -166,8 +164,7 @@ static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
            || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_MGA_DMA_BOOTSTRAP,
+       err = drm_ioctl(file, DRM_IOCTL_MGA_DMA_BOOTSTRAP,
                        (unsigned long)dma_bootstrap);
        if (err)
                return err;
@@ -220,12 +217,10 @@ long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls))
                fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
 
-       lock_kernel();          /* XXX for now */
        if (fn != NULL)
                ret = (*fn) (filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
+               ret = drm_ioctl(filp, cmd, arg);
 
        return ret;
 }
index 1d90d4d..48c290b 100644 (file)
@@ -8,14 +8,15 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
              nouveau_sgdma.o nouveau_dma.o \
              nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
              nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
-            nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
-            nouveau_dp.o \
+             nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
+             nouveau_dp.o nouveau_grctx.o \
              nv04_timer.o \
              nv04_mc.o nv40_mc.o nv50_mc.o \
              nv04_fb.o nv10_fb.o nv40_fb.o \
              nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
              nv04_graph.o nv10_graph.o nv20_graph.o \
              nv40_graph.o nv50_graph.o \
+             nv40_grctx.o \
              nv04_instmem.o nv50_instmem.o \
              nv50_crtc.o nv50_dac.o nv50_sor.o \
              nv50_cursor.o nv50_display.o nv50_fbcon.o \
index 5eec5ed..ba14397 100644 (file)
@@ -181,43 +181,42 @@ struct methods {
        const char desc[8];
        void (*loadbios)(struct drm_device *, uint8_t *);
        const bool rw;
-       int score;
 };
 
 static struct methods nv04_methods[] = {
        { "PROM", load_vbios_prom, false },
        { "PRAMIN", load_vbios_pramin, true },
        { "PCIROM", load_vbios_pci, true },
-       { }
 };
 
 static struct methods nv50_methods[] = {
        { "PRAMIN", load_vbios_pramin, true },
        { "PROM", load_vbios_prom, false },
        { "PCIROM", load_vbios_pci, true },
-       { }
 };
 
+#define METHODCNT 3
+
 static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct methods *methods, *method;
+       struct methods *methods;
+       int i;
        int testscore = 3;
+       int scores[METHODCNT];
 
        if (nouveau_vbios) {
-               method = nv04_methods;
-               while (method->loadbios) {
-                       if (!strcasecmp(nouveau_vbios, method->desc))
+               methods = nv04_methods;
+               for (i = 0; i < METHODCNT; i++)
+                       if (!strcasecmp(nouveau_vbios, methods[i].desc))
                                break;
-                       method++;
-               }
 
-               if (method->loadbios) {
+               if (i < METHODCNT) {
                        NV_INFO(dev, "Attempting to use BIOS image from %s\n",
-                               method->desc);
+                               methods[i].desc);
 
-                       method->loadbios(dev, data);
-                       if (score_vbios(dev, data, method->rw))
+                       methods[i].loadbios(dev, data);
+                       if (score_vbios(dev, data, methods[i].rw))
                                return true;
                }
 
@@ -229,28 +228,24 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data)
        else
                methods = nv50_methods;
 
-       method = methods;
-       while (method->loadbios) {
+       for (i = 0; i < METHODCNT; i++) {
                NV_TRACE(dev, "Attempting to load BIOS image from %s\n",
-                        method->desc);
+                        methods[i].desc);
                data[0] = data[1] = 0;  /* avoid reuse of previous image */
-               method->loadbios(dev, data);
-               method->score = score_vbios(dev, data, method->rw);
-               if (method->score == testscore)
+               methods[i].loadbios(dev, data);
+               scores[i] = score_vbios(dev, data, methods[i].rw);
+               if (scores[i] == testscore)
                        return true;
-               method++;
        }
 
        while (--testscore > 0) {
-               method = methods;
-               while (method->loadbios) {
-                       if (method->score == testscore) {
+               for (i = 0; i < METHODCNT; i++) {
+                       if (scores[i] == testscore) {
                                NV_TRACE(dev, "Using BIOS image from %s\n",
-                                        method->desc);
-                               method->loadbios(dev, data);
+                                        methods[i].desc);
+                               methods[i].loadbios(dev, data);
                                return true;
                        }
-                       method++;
                }
        }
 
@@ -261,10 +256,7 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data)
 struct init_tbl_entry {
        char *name;
        uint8_t id;
-       int length;
-       int length_offset;
-       int length_multiplier;
-       bool (*handler)(struct nvbios *, uint16_t, struct init_exec *);
+       int (*handler)(struct nvbios *, uint16_t, struct init_exec *);
 };
 
 struct bit_entry {
@@ -820,7 +812,7 @@ static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
        }
 }
 
-static bool
+static int
 init_io_restrict_prog(struct nvbios *bios, uint16_t offset,
                      struct init_exec *iexec)
 {
@@ -852,9 +844,10 @@ init_io_restrict_prog(struct nvbios *bios, uint16_t offset,
        uint32_t reg = ROM32(bios->data[offset + 7]);
        uint8_t config;
        uint32_t configval;
+       int len = 11 + count * 4;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, "
                      "Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
@@ -865,7 +858,7 @@ init_io_restrict_prog(struct nvbios *bios, uint16_t offset,
                NV_ERROR(bios->dev,
                         "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
                         offset, config, count);
-               return false;
+               return 0;
        }
 
        configval = ROM32(bios->data[offset + 11 + config * 4]);
@@ -874,10 +867,10 @@ init_io_restrict_prog(struct nvbios *bios, uint16_t offset,
 
        bios_wr32(bios, reg, configval);
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -912,10 +905,10 @@ init_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 
        iexec->repeat = false;
 
-       return true;
+       return 2;
 }
 
-static bool
+static int
 init_io_restrict_pll(struct nvbios *bios, uint16_t offset,
                     struct init_exec *iexec)
 {
@@ -951,9 +944,10 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset,
        uint32_t reg = ROM32(bios->data[offset + 8]);
        uint8_t config;
        uint16_t freq;
+       int len = 12 + count * 2;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, "
                      "Shift: 0x%02X, IO Flag Condition: 0x%02X, "
@@ -966,7 +960,7 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset,
                NV_ERROR(bios->dev,
                         "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
                         offset, config, count);
-               return false;
+               return 0;
        }
 
        freq = ROM16(bios->data[offset + 12 + config * 2]);
@@ -986,10 +980,10 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset,
 
        setPLL(bios, reg, freq * 10);
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_end_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1007,12 +1001,12 @@ init_end_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         * we're not in repeat mode
         */
        if (iexec->repeat)
-               return false;
+               return 0;
 
-       return true;
+       return 1;
 }
 
-static bool
+static int
 init_copy(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1041,7 +1035,7 @@ init_copy(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t crtcdata;
 
        if (!iexec->execute)
-               return true;
+               return 11;
 
        BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%02X, "
                      "Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X\n",
@@ -1060,10 +1054,10 @@ init_copy(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        crtcdata |= (uint8_t)data;
        bios_idxprt_wr(bios, crtcport, crtcindex, crtcdata);
 
-       return true;
+       return 11;
 }
 
-static bool
+static int
 init_not(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1079,10 +1073,10 @@ init_not(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                BIOSLOG(bios, "0x%04X: ------ Executing following commands ------\n", offset);
 
        iexec->execute = !iexec->execute;
-       return true;
+       return 1;
 }
 
-static bool
+static int
 init_io_flag_condition(struct nvbios *bios, uint16_t offset,
                       struct init_exec *iexec)
 {
@@ -1100,7 +1094,7 @@ init_io_flag_condition(struct nvbios *bios, uint16_t offset,
        uint8_t cond = bios->data[offset + 1];
 
        if (!iexec->execute)
-               return true;
+               return 2;
 
        if (io_flag_condition_met(bios, offset, cond))
                BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset);
@@ -1109,10 +1103,10 @@ init_io_flag_condition(struct nvbios *bios, uint16_t offset,
                iexec->execute = false;
        }
 
-       return true;
+       return 2;
 }
 
-static bool
+static int
 init_idx_addr_latched(struct nvbios *bios, uint16_t offset,
                      struct init_exec *iexec)
 {
@@ -1140,11 +1134,12 @@ init_idx_addr_latched(struct nvbios *bios, uint16_t offset,
        uint32_t mask = ROM32(bios->data[offset + 9]);
        uint32_t data = ROM32(bios->data[offset + 13]);
        uint8_t count = bios->data[offset + 17];
+       int len = 18 + count * 2;
        uint32_t value;
        int i;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        BIOSLOG(bios, "0x%04X: ControlReg: 0x%08X, DataReg: 0x%08X, "
                      "Mask: 0x%08X, Data: 0x%08X, Count: 0x%02X\n",
@@ -1164,10 +1159,10 @@ init_idx_addr_latched(struct nvbios *bios, uint16_t offset,
                bios_wr32(bios, controlreg, value);
        }
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_io_restrict_pll2(struct nvbios *bios, uint16_t offset,
                      struct init_exec *iexec)
 {
@@ -1196,25 +1191,26 @@ init_io_restrict_pll2(struct nvbios *bios, uint16_t offset,
        uint8_t shift = bios->data[offset + 5];
        uint8_t count = bios->data[offset + 6];
        uint32_t reg = ROM32(bios->data[offset + 7]);
+       int len = 11 + count * 4;
        uint8_t config;
        uint32_t freq;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, "
                      "Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
                offset, crtcport, crtcindex, mask, shift, count, reg);
 
        if (!reg)
-               return true;
+               return len;
 
        config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift;
        if (config > count) {
                NV_ERROR(bios->dev,
                         "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
                         offset, config, count);
-               return false;
+               return 0;
        }
 
        freq = ROM32(bios->data[offset + 11 + config * 4]);
@@ -1224,10 +1220,10 @@ init_io_restrict_pll2(struct nvbios *bios, uint16_t offset,
 
        setPLL(bios, reg, freq);
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_pll2(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1244,16 +1240,16 @@ init_pll2(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint32_t freq = ROM32(bios->data[offset + 5]);
 
        if (!iexec->execute)
-               return true;
+               return 9;
 
        BIOSLOG(bios, "0x%04X: Reg: 0x%04X, Freq: %dkHz\n",
                offset, reg, freq);
 
        setPLL(bios, reg, freq);
-       return true;
+       return 9;
 }
 
-static bool
+static int
 init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1277,12 +1273,13 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t i2c_index = bios->data[offset + 1];
        uint8_t i2c_address = bios->data[offset + 2];
        uint8_t count = bios->data[offset + 3];
+       int len = 4 + count * 3;
        struct nouveau_i2c_chan *chan;
        struct i2c_msg msg;
        int i;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, "
                      "Count: 0x%02X\n",
@@ -1290,7 +1287,7 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 
        chan = init_i2c_device_find(bios->dev, i2c_index);
        if (!chan)
-               return false;
+               return 0;
 
        for (i = 0; i < count; i++) {
                uint8_t i2c_reg = bios->data[offset + 4 + i * 3];
@@ -1303,7 +1300,7 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                msg.len = 1;
                msg.buf = &value;
                if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
-                       return false;
+                       return 0;
 
                BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, "
                              "Mask: 0x%02X, Data: 0x%02X\n",
@@ -1317,14 +1314,14 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                        msg.len = 1;
                        msg.buf = &value;
                        if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
-                               return false;
+                               return 0;
                }
        }
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1346,12 +1343,13 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t i2c_index = bios->data[offset + 1];
        uint8_t i2c_address = bios->data[offset + 2];
        uint8_t count = bios->data[offset + 3];
+       int len = 4 + count * 2;
        struct nouveau_i2c_chan *chan;
        struct i2c_msg msg;
        int i;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, "
                      "Count: 0x%02X\n",
@@ -1359,7 +1357,7 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 
        chan = init_i2c_device_find(bios->dev, i2c_index);
        if (!chan)
-               return false;
+               return 0;
 
        for (i = 0; i < count; i++) {
                uint8_t i2c_reg = bios->data[offset + 4 + i * 2];
@@ -1374,14 +1372,14 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                        msg.len = 1;
                        msg.buf = &data;
                        if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
-                               return false;
+                               return 0;
                }
        }
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1401,13 +1399,14 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t i2c_index = bios->data[offset + 1];
        uint8_t i2c_address = bios->data[offset + 2];
        uint8_t count = bios->data[offset + 3];
+       int len = 4 + count;
        struct nouveau_i2c_chan *chan;
        struct i2c_msg msg;
        uint8_t data[256];
        int i;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, "
                      "Count: 0x%02X\n",
@@ -1415,7 +1414,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 
        chan = init_i2c_device_find(bios->dev, i2c_index);
        if (!chan)
-               return false;
+               return 0;
 
        for (i = 0; i < count; i++) {
                data[i] = bios->data[offset + 4 + i];
@@ -1429,13 +1428,13 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                msg.len = count;
                msg.buf = data;
                if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
-                       return false;
+                       return 0;
        }
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1460,7 +1459,7 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint32_t reg, value;
 
        if (!iexec->execute)
-               return true;
+               return 5;
 
        BIOSLOG(bios, "0x%04X: MagicLookupValue: 0x%02X, TMDSAddr: 0x%02X, "
                      "Mask: 0x%02X, Data: 0x%02X\n",
@@ -1468,7 +1467,7 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 
        reg = get_tmds_index_reg(bios->dev, mlv);
        if (!reg)
-               return false;
+               return 0;
 
        bios_wr32(bios, reg,
                  tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
@@ -1476,10 +1475,10 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        bios_wr32(bios, reg + 4, value);
        bios_wr32(bios, reg, tmdsaddr);
 
-       return true;
+       return 5;
 }
 
-static bool
+static int
 init_zm_tmds_group(struct nvbios *bios, uint16_t offset,
                   struct init_exec *iexec)
 {
@@ -1500,18 +1499,19 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset,
 
        uint8_t mlv = bios->data[offset + 1];
        uint8_t count = bios->data[offset + 2];
+       int len = 3 + count * 2;
        uint32_t reg;
        int i;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        BIOSLOG(bios, "0x%04X: MagicLookupValue: 0x%02X, Count: 0x%02X\n",
                offset, mlv, count);
 
        reg = get_tmds_index_reg(bios->dev, mlv);
        if (!reg)
-               return false;
+               return 0;
 
        for (i = 0; i < count; i++) {
                uint8_t tmdsaddr = bios->data[offset + 3 + i * 2];
@@ -1521,10 +1521,10 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset,
                bios_wr32(bios, reg, tmdsaddr);
        }
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_cr_idx_adr_latch(struct nvbios *bios, uint16_t offset,
                      struct init_exec *iexec)
 {
@@ -1547,11 +1547,12 @@ init_cr_idx_adr_latch(struct nvbios *bios, uint16_t offset,
        uint8_t crtcindex2 = bios->data[offset + 2];
        uint8_t baseaddr = bios->data[offset + 3];
        uint8_t count = bios->data[offset + 4];
+       int len = 5 + count;
        uint8_t oldaddr, data;
        int i;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        BIOSLOG(bios, "0x%04X: Index1: 0x%02X, Index2: 0x%02X, "
                      "BaseAddr: 0x%02X, Count: 0x%02X\n",
@@ -1568,10 +1569,10 @@ init_cr_idx_adr_latch(struct nvbios *bios, uint16_t offset,
 
        bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex1, oldaddr);
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1592,7 +1593,7 @@ init_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t value;
 
        if (!iexec->execute)
-               return true;
+               return 4;
 
        BIOSLOG(bios, "0x%04X: Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
                offset, crtcindex, mask, data);
@@ -1601,10 +1602,10 @@ init_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        value |= data;
        bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex, value);
 
-       return true;
+       return 4;
 }
 
-static bool
+static int
 init_zm_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1621,14 +1622,14 @@ init_zm_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t data = bios->data[offset + 2];
 
        if (!iexec->execute)
-               return true;
+               return 3;
 
        bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex, data);
 
-       return true;
+       return 3;
 }
 
-static bool
+static int
 init_zm_cr_group(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1645,18 +1646,19 @@ init_zm_cr_group(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         */
 
        uint8_t count = bios->data[offset + 1];
+       int len = 2 + count * 2;
        int i;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        for (i = 0; i < count; i++)
                init_zm_cr(bios, offset + 2 + 2 * i - 1, iexec);
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_condition_time(struct nvbios *bios, uint16_t offset,
                    struct init_exec *iexec)
 {
@@ -1680,7 +1682,7 @@ init_condition_time(struct nvbios *bios, uint16_t offset,
        unsigned cnt;
 
        if (!iexec->execute)
-               return true;
+               return 3;
 
        if (retries > 100)
                retries = 100;
@@ -1711,10 +1713,10 @@ init_condition_time(struct nvbios *bios, uint16_t offset,
                iexec->execute = false;
        }
 
-       return true;
+       return 3;
 }
 
-static bool
+static int
 init_zm_reg_sequence(struct nvbios *bios, uint16_t offset,
                     struct init_exec *iexec)
 {
@@ -1734,10 +1736,11 @@ init_zm_reg_sequence(struct nvbios *bios, uint16_t offset,
 
        uint32_t basereg = ROM32(bios->data[offset + 1]);
        uint32_t count = bios->data[offset + 5];
+       int len = 6 + count * 4;
        int i;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        BIOSLOG(bios, "0x%04X: BaseReg: 0x%08X, Count: 0x%02X\n",
                offset, basereg, count);
@@ -1749,10 +1752,10 @@ init_zm_reg_sequence(struct nvbios *bios, uint16_t offset,
                bios_wr32(bios, reg, data);
        }
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1768,7 +1771,7 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint16_t sub_offset = ROM16(bios->data[offset + 1]);
 
        if (!iexec->execute)
-               return true;
+               return 3;
 
        BIOSLOG(bios, "0x%04X: Executing subroutine at 0x%04X\n",
                offset, sub_offset);
@@ -1777,10 +1780,10 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 
        BIOSLOG(bios, "0x%04X: End of 0x%04X subroutine\n", offset, sub_offset);
 
-       return true;
+       return 3;
 }
 
-static bool
+static int
 init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1808,7 +1811,7 @@ init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint32_t srcvalue, dstvalue;
 
        if (!iexec->execute)
-               return true;
+               return 22;
 
        BIOSLOG(bios, "0x%04X: SrcReg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%08X, "
                      "Xor: 0x%08X, DstReg: 0x%08X, DstMask: 0x%08X\n",
@@ -1827,10 +1830,10 @@ init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 
        bios_wr32(bios, dstreg, dstvalue | srcvalue);
 
-       return true;
+       return 22;
 }
 
-static bool
+static int
 init_zm_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1848,14 +1851,14 @@ init_zm_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t data = bios->data[offset + 4];
 
        if (!iexec->execute)
-               return true;
+               return 5;
 
        bios_idxprt_wr(bios, crtcport, crtcindex, data);
 
-       return true;
+       return 5;
 }
 
-static bool
+static int
 init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1904,7 +1907,7 @@ init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
 
        if (dev_priv->card_type >= NV_50)
-               return true;
+               return 1;
 
        /*
         * On every card I've seen, this step gets done for us earlier in
@@ -1922,10 +1925,10 @@ init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        /* write back the saved configuration value */
        bios_wr32(bios, NV_PFB_CFG0, bios->state.saved_nv_pfb_cfg0);
 
-       return true;
+       return 1;
 }
 
-static bool
+static int
 init_reset(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -1959,10 +1962,10 @@ init_reset(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        pci_nv_20 &= ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED;     /* 0xfffffffe */
        bios_wr32(bios, NV_PBUS_PCI_NV_20, pci_nv_20);
 
-       return true;
+       return 13;
 }
 
-static bool
+static int
 init_configure_mem(struct nvbios *bios, uint16_t offset,
                   struct init_exec *iexec)
 {
@@ -1983,7 +1986,7 @@ init_configure_mem(struct nvbios *bios, uint16_t offset,
        uint32_t reg, data;
 
        if (bios->major_version > 2)
-               return false;
+               return 0;
 
        bios_idxprt_wr(bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX, bios_idxprt_rd(
                       bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX) | 0x20);
@@ -2015,10 +2018,10 @@ init_configure_mem(struct nvbios *bios, uint16_t offset,
                bios_wr32(bios, reg, data);
        }
 
-       return true;
+       return 1;
 }
 
-static bool
+static int
 init_configure_clk(struct nvbios *bios, uint16_t offset,
                   struct init_exec *iexec)
 {
@@ -2038,7 +2041,7 @@ init_configure_clk(struct nvbios *bios, uint16_t offset,
        int clock;
 
        if (bios->major_version > 2)
-               return false;
+               return 0;
 
        clock = ROM16(bios->data[meminitoffs + 4]) * 10;
        setPLL(bios, NV_PRAMDAC_NVPLL_COEFF, clock);
@@ -2048,10 +2051,10 @@ init_configure_clk(struct nvbios *bios, uint16_t offset,
                clock *= 2;
        setPLL(bios, NV_PRAMDAC_MPLL_COEFF, clock);
 
-       return true;
+       return 1;
 }
 
-static bool
+static int
 init_configure_preinit(struct nvbios *bios, uint16_t offset,
                       struct init_exec *iexec)
 {
@@ -2071,15 +2074,15 @@ init_configure_preinit(struct nvbios *bios, uint16_t offset,
        uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6));
 
        if (bios->major_version > 2)
-               return false;
+               return 0;
 
        bios_idxprt_wr(bios, NV_CIO_CRX__COLOR,
                             NV_CIO_CRE_SCRATCH4__INDEX, cr3c);
 
-       return true;
+       return 1;
 }
 
-static bool
+static int
 init_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2099,7 +2102,7 @@ init_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t data = bios->data[offset + 4];
 
        if (!iexec->execute)
-               return true;
+               return 5;
 
        BIOSLOG(bios, "0x%04X: Port: 0x%04X, Mask: 0x%02X, Data: 0x%02X\n",
                offset, crtcport, mask, data);
@@ -2158,15 +2161,15 @@ init_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                for (i = 0; i < 2; i++)
                        bios_wr32(bios, 0x614108 + (i*0x800), bios_rd32(
                                  bios, 0x614108 + (i*0x800)) & 0x0fffffff);
-               return true;
+               return 5;
        }
 
        bios_port_wr(bios, crtcport, (bios_port_rd(bios, crtcport) & mask) |
                                                                        data);
-       return true;
+       return 5;
 }
 
-static bool
+static int
 init_sub(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2181,7 +2184,7 @@ init_sub(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t sub = bios->data[offset + 1];
 
        if (!iexec->execute)
-               return true;
+               return 2;
 
        BIOSLOG(bios, "0x%04X: Calling script %d\n", offset, sub);
 
@@ -2191,10 +2194,10 @@ init_sub(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 
        BIOSLOG(bios, "0x%04X: End of script %d\n", offset, sub);
 
-       return true;
+       return 2;
 }
 
-static bool
+static int
 init_ram_condition(struct nvbios *bios, uint16_t offset,
                   struct init_exec *iexec)
 {
@@ -2215,7 +2218,7 @@ init_ram_condition(struct nvbios *bios, uint16_t offset,
        uint8_t data;
 
        if (!iexec->execute)
-               return true;
+               return 3;
 
        data = bios_rd32(bios, NV_PFB_BOOT_0) & mask;
 
@@ -2229,10 +2232,10 @@ init_ram_condition(struct nvbios *bios, uint16_t offset,
                iexec->execute = false;
        }
 
-       return true;
+       return 3;
 }
 
-static bool
+static int
 init_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2251,17 +2254,17 @@ init_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint32_t data = ROM32(bios->data[offset + 9]);
 
        if (!iexec->execute)
-               return true;
+               return 13;
 
        BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Mask: 0x%08X, Data: 0x%08X\n",
                offset, reg, mask, data);
 
        bios_wr32(bios, reg, (bios_rd32(bios, reg) & mask) | data);
 
-       return true;
+       return 13;
 }
 
-static bool
+static int
 init_macro(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2285,7 +2288,7 @@ init_macro(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        int i;
 
        if (!iexec->execute)
-               return true;
+               return 2;
 
        BIOSLOG(bios, "0x%04X: Macro: 0x%02X, MacroTableIndex: 0x%02X, "
                      "Count: 0x%02X\n",
@@ -2300,10 +2303,10 @@ init_macro(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                bios_wr32(bios, reg, data);
        }
 
-       return true;
+       return 2;
 }
 
-static bool
+static int
 init_done(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2315,10 +2318,10 @@ init_done(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         */
 
        /* mild retval abuse to stop parsing this table */
-       return false;
+       return 0;
 }
 
-static bool
+static int
 init_resume(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2330,15 +2333,15 @@ init_resume(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         */
 
        if (iexec->execute)
-               return true;
+               return 1;
 
        iexec->execute = true;
        BIOSLOG(bios, "0x%04X: ---- Executing following commands ----\n", offset);
 
-       return true;
+       return 1;
 }
 
-static bool
+static int
 init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2353,7 +2356,7 @@ init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        unsigned time = ROM16(bios->data[offset + 1]);
 
        if (!iexec->execute)
-               return true;
+               return 3;
 
        BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X microseconds\n",
                offset, time);
@@ -2363,10 +2366,10 @@ init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        else
                msleep((time + 900) / 1000);
 
-       return true;
+       return 3;
 }
 
-static bool
+static int
 init_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2383,7 +2386,7 @@ init_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t cond = bios->data[offset + 1];
 
        if (!iexec->execute)
-               return true;
+               return 2;
 
        BIOSLOG(bios, "0x%04X: Condition: 0x%02X\n", offset, cond);
 
@@ -2394,10 +2397,10 @@ init_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                iexec->execute = false;
        }
 
-       return true;
+       return 2;
 }
 
-static bool
+static int
 init_io_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2414,7 +2417,7 @@ init_io_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t cond = bios->data[offset + 1];
 
        if (!iexec->execute)
-               return true;
+               return 2;
 
        BIOSLOG(bios, "0x%04X: IO condition: 0x%02X\n", offset, cond);
 
@@ -2425,10 +2428,10 @@ init_io_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                iexec->execute = false;
        }
 
-       return true;
+       return 2;
 }
 
-static bool
+static int
 init_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2451,7 +2454,7 @@ init_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint8_t value;
 
        if (!iexec->execute)
-               return true;
+               return 6;
 
        BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, "
                      "Data: 0x%02X\n",
@@ -2460,10 +2463,10 @@ init_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        value = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) | data;
        bios_idxprt_wr(bios, crtcport, crtcindex, value);
 
-       return true;
+       return 6;
 }
 
-static bool
+static int
 init_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2481,16 +2484,16 @@ init_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint16_t freq = ROM16(bios->data[offset + 5]);
 
        if (!iexec->execute)
-               return true;
+               return 7;
 
        BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n", offset, reg, freq);
 
        setPLL(bios, reg, freq * 10);
 
-       return true;
+       return 7;
 }
 
-static bool
+static int
 init_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2507,17 +2510,17 @@ init_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint32_t value = ROM32(bios->data[offset + 5]);
 
        if (!iexec->execute)
-               return true;
+               return 9;
 
        if (reg == 0x000200)
                value |= 1;
 
        bios_wr32(bios, reg, value);
 
-       return true;
+       return 9;
 }
 
-static bool
+static int
 init_ram_restrict_pll(struct nvbios *bios, uint16_t offset,
                      struct init_exec *iexec)
 {
@@ -2543,14 +2546,15 @@ init_ram_restrict_pll(struct nvbios *bios, uint16_t offset,
        uint8_t type = bios->data[offset + 1];
        uint32_t freq = ROM32(bios->data[offset + 2 + (index * 4)]);
        uint8_t *pll_limits = &bios->data[bios->pll_limit_tbl_ptr], *entry;
+       int len = 2 + bios->ram_restrict_group_count * 4;
        int i;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        if (!bios->pll_limit_tbl_ptr || (pll_limits[0] & 0xf0) != 0x30) {
                NV_ERROR(dev, "PLL limits table not version 3.x\n");
-               return true; /* deliberate, allow default clocks to remain */
+               return len; /* deliberate, allow default clocks to remain */
        }
 
        entry = pll_limits + pll_limits[1];
@@ -2563,15 +2567,15 @@ init_ram_restrict_pll(struct nvbios *bios, uint16_t offset,
                                offset, type, reg, freq);
 
                        setPLL(bios, reg, freq);
-                       return true;
+                       return len;
                }
        }
 
        NV_ERROR(dev, "PLL type 0x%02x not found in PLL limits table", type);
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_8c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2581,10 +2585,10 @@ init_8c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         *
         */
 
-       return true;
+       return 1;
 }
 
-static bool
+static int
 init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2594,10 +2598,10 @@ init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         *
         */
 
-       return true;
+       return 1;
 }
 
-static bool
+static int
 init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2615,14 +2619,17 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        const uint8_t *gpio_entry;
        int i;
 
+       if (!iexec->execute)
+               return 1;
+
        if (bios->bdcb.version != 0x40) {
                NV_ERROR(bios->dev, "DCB table not version 4.0\n");
-               return false;
+               return 0;
        }
 
        if (!bios->bdcb.gpio_table_ptr) {
                NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n");
-               return false;
+               return 0;
        }
 
        gpio_entry = gpio_table + gpio_table[1];
@@ -2660,13 +2667,10 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                bios_wr32(bios, r, v);
        }
 
-       return true;
+       return 1;
 }
 
-/* hack to avoid moving the itbl_entry array before this function */
-int init_ram_restrict_zm_reg_group_blocklen;
-
-static bool
+static int
 init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset,
                               struct init_exec *iexec)
 {
@@ -2692,21 +2696,21 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset,
        uint8_t regincrement = bios->data[offset + 5];
        uint8_t count = bios->data[offset + 6];
        uint32_t strap_ramcfg, data;
-       uint16_t blocklen;
+       /* previously set by 'M' BIT table */
+       uint16_t blocklen = bios->ram_restrict_group_count * 4;
+       int len = 7 + count * blocklen;
        uint8_t index;
        int i;
 
-       /* previously set by 'M' BIT table */
-       blocklen = init_ram_restrict_zm_reg_group_blocklen;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        if (!blocklen) {
                NV_ERROR(bios->dev,
                         "0x%04X: Zero block length - has the M table "
                         "been parsed?\n", offset);
-               return false;
+               return 0;
        }
 
        strap_ramcfg = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 2) & 0xf;
@@ -2724,10 +2728,10 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset,
                reg += regincrement;
        }
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_copy_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2744,14 +2748,14 @@ init_copy_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        uint32_t dstreg = ROM32(bios->data[offset + 5]);
 
        if (!iexec->execute)
-               return true;
+               return 9;
 
        bios_wr32(bios, dstreg, bios_rd32(bios, srcreg));
 
-       return true;
+       return 9;
 }
 
-static bool
+static int
 init_zm_reg_group_addr_latched(struct nvbios *bios, uint16_t offset,
                               struct init_exec *iexec)
 {
@@ -2769,20 +2773,21 @@ init_zm_reg_group_addr_latched(struct nvbios *bios, uint16_t offset,
 
        uint32_t reg = ROM32(bios->data[offset + 1]);
        uint8_t count = bios->data[offset + 5];
+       int len = 6 + count * 4;
        int i;
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        for (i = 0; i < count; i++) {
                uint32_t data = ROM32(bios->data[offset + 6 + 4 * i]);
                bios_wr32(bios, reg, data);
        }
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_reserved(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2793,10 +2798,10 @@ init_reserved(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         * Seemingly does nothing
         */
 
-       return true;
+       return 1;
 }
 
-static bool
+static int
 init_96(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2829,13 +2834,13 @@ init_96(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        val <<= bios->data[offset + 16];
 
        if (!iexec->execute)
-               return true;
+               return 17;
 
        bios_wr32(bios, reg, (bios_rd32(bios, reg) & mask) | val);
-       return true;
+       return 17;
 }
 
-static bool
+static int
 init_97(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2859,13 +2864,13 @@ init_97(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        val = (val & mask) | ((val + add) & ~mask);
 
        if (!iexec->execute)
-               return true;
+               return 13;
 
        bios_wr32(bios, reg, val);
-       return true;
+       return 13;
 }
 
-static bool
+static int
 init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2883,32 +2888,33 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        struct drm_device *dev = bios->dev;
        struct nouveau_i2c_chan *auxch;
        uint32_t addr = ROM32(bios->data[offset + 1]);
-       uint8_t len = bios->data[offset + 5];
+       uint8_t count = bios->data[offset + 5];
+       int len = 6 + count * 2;
        int ret, i;
 
        if (!bios->display.output) {
                NV_ERROR(dev, "INIT_AUXCH: no active output\n");
-               return false;
+               return 0;
        }
 
        auxch = init_i2c_device_find(dev, bios->display.output->i2c_index);
        if (!auxch) {
                NV_ERROR(dev, "INIT_AUXCH: couldn't get auxch %d\n",
                         bios->display.output->i2c_index);
-               return false;
+               return 0;
        }
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        offset += 6;
-       for (i = 0; i < len; i++, offset += 2) {
+       for (i = 0; i < count; i++, offset += 2) {
                uint8_t data;
 
                ret = nouveau_dp_auxch(auxch, 9, addr, &data, 1);
                if (ret) {
                        NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret);
-                       return false;
+                       return 0;
                }
 
                data &= bios->data[offset + 0];
@@ -2917,14 +2923,14 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
                ret = nouveau_dp_auxch(auxch, 8, addr, &data, 1);
                if (ret) {
                        NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret);
-                       return false;
+                       return 0;
                }
        }
 
-       return true;
+       return len;
 }
 
-static bool
+static int
 init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
        /*
@@ -2941,106 +2947,99 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        struct drm_device *dev = bios->dev;
        struct nouveau_i2c_chan *auxch;
        uint32_t addr = ROM32(bios->data[offset + 1]);
-       uint8_t len = bios->data[offset + 5];
+       uint8_t count = bios->data[offset + 5];
+       int len = 6 + count;
        int ret, i;
 
        if (!bios->display.output) {
                NV_ERROR(dev, "INIT_ZM_AUXCH: no active output\n");
-               return false;
+               return 0;
        }
 
        auxch = init_i2c_device_find(dev, bios->display.output->i2c_index);
        if (!auxch) {
                NV_ERROR(dev, "INIT_ZM_AUXCH: couldn't get auxch %d\n",
                         bios->display.output->i2c_index);
-               return false;
+               return 0;
        }
 
        if (!iexec->execute)
-               return true;
+               return len;
 
        offset += 6;
-       for (i = 0; i < len; i++, offset++) {
+       for (i = 0; i < count; i++, offset++) {
                ret = nouveau_dp_auxch(auxch, 8, addr, &bios->data[offset], 1);
                if (ret) {
                        NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret);
-                       return false;
+                       return 0;
                }
        }
 
-       return true;
+       return len;
 }
 
 static struct init_tbl_entry itbl_entry[] = {
        /* command name                       , id  , length  , offset  , mult    , command handler                 */
        /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */
-       { "INIT_IO_RESTRICT_PROG"             , 0x32, 11      , 6       , 4       , init_io_restrict_prog           },
-       { "INIT_REPEAT"                       , 0x33, 2       , 0       , 0       , init_repeat                     },
-       { "INIT_IO_RESTRICT_PLL"              , 0x34, 12      , 7       , 2       , init_io_restrict_pll            },
-       { "INIT_END_REPEAT"                   , 0x36, 1       , 0       , 0       , init_end_repeat                 },
-       { "INIT_COPY"                         , 0x37, 11      , 0       , 0       , init_copy                       },
-       { "INIT_NOT"                          , 0x38, 1       , 0       , 0       , init_not                        },
-       { "INIT_IO_FLAG_CONDITION"            , 0x39, 2       , 0       , 0       , init_io_flag_condition          },
-       { "INIT_INDEX_ADDRESS_LATCHED"        , 0x49, 18      , 17      , 2       , init_idx_addr_latched           },
-       { "INIT_IO_RESTRICT_PLL2"             , 0x4A, 11      , 6       , 4       , init_io_restrict_pll2           },
-       { "INIT_PLL2"                         , 0x4B, 9       , 0       , 0       , init_pll2                       },
-       { "INIT_I2C_BYTE"                     , 0x4C, 4       , 3       , 3       , init_i2c_byte                   },
-       { "INIT_ZM_I2C_BYTE"                  , 0x4D, 4       , 3       , 2       , init_zm_i2c_byte                },
-       { "INIT_ZM_I2C"                       , 0x4E, 4       , 3       , 1       , init_zm_i2c                     },
-       { "INIT_TMDS"                         , 0x4F, 5       , 0       , 0       , init_tmds                       },
-       { "INIT_ZM_TMDS_GROUP"                , 0x50, 3       , 2       , 2       , init_zm_tmds_group              },
-       { "INIT_CR_INDEX_ADDRESS_LATCHED"     , 0x51, 5       , 4       , 1       , init_cr_idx_adr_latch           },
-       { "INIT_CR"                           , 0x52, 4       , 0       , 0       , init_cr                         },
-       { "INIT_ZM_CR"                        , 0x53, 3       , 0       , 0       , init_zm_cr                      },
-       { "INIT_ZM_CR_GROUP"                  , 0x54, 2       , 1       , 2       , init_zm_cr_group                },
-       { "INIT_CONDITION_TIME"               , 0x56, 3       , 0       , 0       , init_condition_time             },
-       { "INIT_ZM_REG_SEQUENCE"              , 0x58, 6       , 5       , 4       , init_zm_reg_sequence            },
+       { "INIT_IO_RESTRICT_PROG"             , 0x32, init_io_restrict_prog           },
+       { "INIT_REPEAT"                       , 0x33, init_repeat                     },
+       { "INIT_IO_RESTRICT_PLL"              , 0x34, init_io_restrict_pll            },
+       { "INIT_END_REPEAT"                   , 0x36, init_end_repeat                 },
+       { "INIT_COPY"                         , 0x37, init_copy                       },
+       { "INIT_NOT"                          , 0x38, init_not                        },
+       { "INIT_IO_FLAG_CONDITION"            , 0x39, init_io_flag_condition          },
+       { "INIT_INDEX_ADDRESS_LATCHED"        , 0x49, init_idx_addr_latched           },
+       { "INIT_IO_RESTRICT_PLL2"             , 0x4A, init_io_restrict_pll2           },
+       { "INIT_PLL2"                         , 0x4B, init_pll2                       },
+       { "INIT_I2C_BYTE"                     , 0x4C, init_i2c_byte                   },
+       { "INIT_ZM_I2C_BYTE"                  , 0x4D, init_zm_i2c_byte                },
+       { "INIT_ZM_I2C"                       , 0x4E, init_zm_i2c                     },
+       { "INIT_TMDS"                         , 0x4F, init_tmds                       },
+       { "INIT_ZM_TMDS_GROUP"                , 0x50, init_zm_tmds_group              },
+       { "INIT_CR_INDEX_ADDRESS_LATCHED"     , 0x51, init_cr_idx_adr_latch           },
+       { "INIT_CR"                           , 0x52, init_cr                         },
+       { "INIT_ZM_CR"                        , 0x53, init_zm_cr                      },
+       { "INIT_ZM_CR_GROUP"                  , 0x54, init_zm_cr_group                },
+       { "INIT_CONDITION_TIME"               , 0x56, init_condition_time             },
+       { "INIT_ZM_REG_SEQUENCE"              , 0x58, init_zm_reg_sequence            },
        /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */
-       { "INIT_SUB_DIRECT"                   , 0x5B, 3       , 0       , 0       , init_sub_direct                 },
-       { "INIT_COPY_NV_REG"                  , 0x5F, 22      , 0       , 0       , init_copy_nv_reg                },
-       { "INIT_ZM_INDEX_IO"                  , 0x62, 5       , 0       , 0       , init_zm_index_io                },
-       { "INIT_COMPUTE_MEM"                  , 0x63, 1       , 0       , 0       , init_compute_mem                },
-       { "INIT_RESET"                        , 0x65, 13      , 0       , 0       , init_reset                      },
-       { "INIT_CONFIGURE_MEM"                , 0x66, 1       , 0       , 0       , init_configure_mem              },
-       { "INIT_CONFIGURE_CLK"                , 0x67, 1       , 0       , 0       , init_configure_clk              },
-       { "INIT_CONFIGURE_PREINIT"            , 0x68, 1       , 0       , 0       , init_configure_preinit          },
-       { "INIT_IO"                           , 0x69, 5       , 0       , 0       , init_io                         },
-       { "INIT_SUB"                          , 0x6B, 2       , 0       , 0       , init_sub                        },
-       { "INIT_RAM_CONDITION"                , 0x6D, 3       , 0       , 0       , init_ram_condition              },
-       { "INIT_NV_REG"                       , 0x6E, 13      , 0       , 0       , init_nv_reg                     },
-       { "INIT_MACRO"                        , 0x6F, 2       , 0       , 0       , init_macro                      },
-       { "INIT_DONE"                         , 0x71, 1       , 0       , 0       , init_done                       },
-       { "INIT_RESUME"                       , 0x72, 1       , 0       , 0       , init_resume                     },
+       { "INIT_SUB_DIRECT"                   , 0x5B, init_sub_direct                 },
+       { "INIT_COPY_NV_REG"                  , 0x5F, init_copy_nv_reg                },
+       { "INIT_ZM_INDEX_IO"                  , 0x62, init_zm_index_io                },
+       { "INIT_COMPUTE_MEM"                  , 0x63, init_compute_mem                },
+       { "INIT_RESET"                        , 0x65, init_reset                      },
+       { "INIT_CONFIGURE_MEM"                , 0x66, init_configure_mem              },
+       { "INIT_CONFIGURE_CLK"                , 0x67, init_configure_clk              },
+       { "INIT_CONFIGURE_PREINIT"            , 0x68, init_configure_preinit          },
+       { "INIT_IO"                           , 0x69, init_io                         },
+       { "INIT_SUB"                          , 0x6B, init_sub                        },
+       { "INIT_RAM_CONDITION"                , 0x6D, init_ram_condition              },
+       { "INIT_NV_REG"                       , 0x6E, init_nv_reg                     },
+       { "INIT_MACRO"                        , 0x6F, init_macro                      },
+       { "INIT_DONE"                         , 0x71, init_done                       },
+       { "INIT_RESUME"                       , 0x72, init_resume                     },
        /* INIT_RAM_CONDITION2 (0x73, 9, 0, 0) removed due to no example of use */
-       { "INIT_TIME"                         , 0x74, 3       , 0       , 0       , init_time                       },
-       { "INIT_CONDITION"                    , 0x75, 2       , 0       , 0       , init_condition                  },
-       { "INIT_IO_CONDITION"                 , 0x76, 2       , 0       , 0       , init_io_condition               },
-       { "INIT_INDEX_IO"                     , 0x78, 6       , 0       , 0       , init_index_io                   },
-       { "INIT_PLL"                          , 0x79, 7       , 0       , 0       , init_pll                        },
-       { "INIT_ZM_REG"                       , 0x7A, 9       , 0       , 0       , init_zm_reg                     },
-       /* INIT_RAM_RESTRICT_PLL's length is adjusted by the BIT M table */
-       { "INIT_RAM_RESTRICT_PLL"             , 0x87, 2       , 0       , 0       , init_ram_restrict_pll           },
-       { "INIT_8C"                           , 0x8C, 1       , 0       , 0       , init_8c                         },
-       { "INIT_8D"                           , 0x8D, 1       , 0       , 0       , init_8d                         },
-       { "INIT_GPIO"                         , 0x8E, 1       , 0       , 0       , init_gpio                       },
-       /* INIT_RAM_RESTRICT_ZM_REG_GROUP's mult is loaded by M table in BIT */
-       { "INIT_RAM_RESTRICT_ZM_REG_GROUP"    , 0x8F, 7       , 6       , 0       , init_ram_restrict_zm_reg_group  },
-       { "INIT_COPY_ZM_REG"                  , 0x90, 9       , 0       , 0       , init_copy_zm_reg                },
-       { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, 6       , 5       , 4       , init_zm_reg_group_addr_latched  },
-       { "INIT_RESERVED"                     , 0x92, 1       , 0       , 0       , init_reserved                   },
-       { "INIT_96"                           , 0x96, 17      , 0       , 0       , init_96                         },
-       { "INIT_97"                           , 0x97, 13      , 0       , 0       , init_97                         },
-       { "INIT_AUXCH"                        , 0x98, 6       , 5       , 2       , init_auxch                      },
-       { "INIT_ZM_AUXCH"                     , 0x99, 6       , 5       , 1       , init_zm_auxch                   },
-       { NULL                                , 0   , 0       , 0       , 0       , NULL                            }
+       { "INIT_TIME"                         , 0x74, init_time                       },
+       { "INIT_CONDITION"                    , 0x75, init_condition                  },
+       { "INIT_IO_CONDITION"                 , 0x76, init_io_condition               },
+       { "INIT_INDEX_IO"                     , 0x78, init_index_io                   },
+       { "INIT_PLL"                          , 0x79, init_pll                        },
+       { "INIT_ZM_REG"                       , 0x7A, init_zm_reg                     },
+       { "INIT_RAM_RESTRICT_PLL"             , 0x87, init_ram_restrict_pll           },
+       { "INIT_8C"                           , 0x8C, init_8c                         },
+       { "INIT_8D"                           , 0x8D, init_8d                         },
+       { "INIT_GPIO"                         , 0x8E, init_gpio                       },
+       { "INIT_RAM_RESTRICT_ZM_REG_GROUP"    , 0x8F, init_ram_restrict_zm_reg_group  },
+       { "INIT_COPY_ZM_REG"                  , 0x90, init_copy_zm_reg                },
+       { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, init_zm_reg_group_addr_latched  },
+       { "INIT_RESERVED"                     , 0x92, init_reserved                   },
+       { "INIT_96"                           , 0x96, init_96                         },
+       { "INIT_97"                           , 0x97, init_97                         },
+       { "INIT_AUXCH"                        , 0x98, init_auxch                      },
+       { "INIT_ZM_AUXCH"                     , 0x99, init_zm_auxch                   },
+       { NULL                                , 0   , NULL                            }
 };
 
-static unsigned int get_init_table_entry_length(struct nvbios *bios, unsigned int offset, int i)
-{
-       /* Calculates the length of a given init table entry. */
-       return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
-}
-
 #define MAX_TABLE_OPS 1000
 
 static int
@@ -3056,7 +3055,7 @@ parse_init_table(struct nvbios *bios, unsigned int offset,
         * is changed back to EXECUTE.
         */
 
-       int count = 0, i;
+       int count = 0, i, res;
        uint8_t id;
 
        /*
@@ -3076,22 +3075,21 @@ parse_init_table(struct nvbios *bios, unsigned int offset,
                                offset, itbl_entry[i].id, itbl_entry[i].name);
 
                        /* execute eventual command handler */
-                       if (itbl_entry[i].handler)
-                               if (!(*itbl_entry[i].handler)(bios, offset, iexec))
-                                       break;
+                       res = (*itbl_entry[i].handler)(bios, offset, iexec);
+                       if (!res)
+                               break;
+                       /*
+                        * Add the offset of the current command including all data
+                        * of that command. The offset will then be pointing on the
+                        * next op code.
+                        */
+                       offset += res;
                } else {
                        NV_ERROR(bios->dev,
                                 "0x%04X: Init table command not found: "
                                 "0x%02X\n", offset, id);
                        return -ENOENT;
                }
-
-               /*
-                * Add the offset of the current command including all data
-                * of that command. The offset will then be pointing on the
-                * next op code.
-                */
-               offset += get_init_table_entry_length(bios, offset, i);
        }
 
        if (offset >= bios->length)
@@ -3854,7 +3852,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
         * script tables is a pointer to the script to execute.
         */
 
-       NV_DEBUG(dev, "Searching for output entry for %d %d %d\n",
+       NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n",
                        dcbent->type, dcbent->location, dcbent->or);
        otable = bios_output_config_match(dev, dcbent, table[1] +
                                          bios->display.script_table_ptr,
@@ -3884,7 +3882,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
        if (pxclk == 0) {
                script = ROM16(otable[6]);
                if (!script) {
-                       NV_DEBUG(dev, "output script 0 not found\n");
+                       NV_DEBUG_KMS(dev, "output script 0 not found\n");
                        return 1;
                }
 
@@ -3894,7 +3892,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
        if (pxclk == -1) {
                script = ROM16(otable[8]);
                if (!script) {
-                       NV_DEBUG(dev, "output script 1 not found\n");
+                       NV_DEBUG_KMS(dev, "output script 1 not found\n");
                        return 1;
                }
 
@@ -3907,7 +3905,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
                else
                        script = 0;
                if (!script) {
-                       NV_DEBUG(dev, "output script 2 not found\n");
+                       NV_DEBUG_KMS(dev, "output script 2 not found\n");
                        return 1;
                }
 
@@ -3931,7 +3929,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
                if (script)
                        script = clkcmptable(bios, script, -pxclk);
                if (!script) {
-                       NV_DEBUG(dev, "clock script 1 not found\n");
+                       NV_DEBUG_KMS(dev, "clock script 1 not found\n");
                        return 1;
                }
 
@@ -4606,10 +4604,6 @@ parse_bit_M_tbl_entry(struct drm_device *dev, struct nvbios *bios,
         * stuff that we don't use - their use currently unknown
         */
 
-       uint16_t rr_strap_xlat;
-       uint8_t rr_group_count;
-       int i;
-
        /*
         * Older bios versions don't have a sufficiently long table for
         * what we want
@@ -4618,24 +4612,13 @@ parse_bit_M_tbl_entry(struct drm_device *dev, struct nvbios *bios,
                return 0;
 
        if (bitentry->id[1] < 2) {
-               rr_group_count = bios->data[bitentry->offset + 2];
-               rr_strap_xlat = ROM16(bios->data[bitentry->offset + 3]);
+               bios->ram_restrict_group_count = bios->data[bitentry->offset + 2];
+               bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 3]);
        } else {
-               rr_group_count = bios->data[bitentry->offset + 0];
-               rr_strap_xlat = ROM16(bios->data[bitentry->offset + 1]);
+               bios->ram_restrict_group_count = bios->data[bitentry->offset + 0];
+               bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 1]);
        }
 
-       /* adjust length of INIT_87 */
-       for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != 0x87); i++);
-       itbl_entry[i].length += rr_group_count * 4;
-
-       /* set up multiplier for INIT_RAM_RESTRICT_ZM_REG_GROUP */
-       for (; itbl_entry[i].name && (itbl_entry[i].id != 0x8f); i++);
-       itbl_entry[i].length_multiplier = rr_group_count * 4;
-
-       init_ram_restrict_zm_reg_group_blocklen = itbl_entry[i].length_multiplier;
-       bios->ram_restrict_tbl_ptr = rr_strap_xlat;
-
        return 0;
 }
 
@@ -5234,7 +5217,7 @@ parse_dcb_connector_table(struct nvbios *bios)
        int i;
 
        if (!bios->bdcb.connector_table_ptr) {
-               NV_DEBUG(dev, "No DCB connector table present\n");
+               NV_DEBUG_KMS(dev, "No DCB connector table present\n");
                return;
        }
 
index 1d5f10b..058e98c 100644 (file)
@@ -227,6 +227,7 @@ struct nvbios {
 
        uint16_t pll_limit_tbl_ptr;
        uint16_t ram_restrict_tbl_ptr;
+       uint8_t ram_restrict_group_count;
 
        uint16_t some_script_ptr; /* BIT I + 14 */
        uint16_t init96_tbl_ptr; /* BIT I + 16 */
index aa2dfbc..0cad6d8 100644 (file)
@@ -154,6 +154,11 @@ nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t memtype)
        nvbo->placement.busy_placement = nvbo->placements;
        nvbo->placement.num_placement = n;
        nvbo->placement.num_busy_placement = n;
+
+       if (nvbo->pin_refcnt) {
+               while (n--)
+                       nvbo->placements[n] |= TTM_PL_FLAG_NO_EVICT;
+       }
 }
 
 int
@@ -400,10 +405,16 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
        struct nouveau_bo *nvbo = nouveau_bo(bo);
 
        switch (bo->mem.mem_type) {
+       case TTM_PL_VRAM:
+               nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT |
+                                        TTM_PL_FLAG_SYSTEM);
+               break;
        default:
                nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_SYSTEM);
                break;
        }
+
+       *pl = nvbo->placement;
 }
 
 
@@ -455,11 +466,8 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, int no_wait,
        int ret;
 
        chan = nvbo->channel;
-       if (!chan || nvbo->tile_flags || nvbo->no_vm) {
+       if (!chan || nvbo->tile_flags || nvbo->no_vm)
                chan = dev_priv->channel;
-               if (!chan)
-                       return -EINVAL;
-       }
 
        src_offset = old_mem->mm_node->start << PAGE_SHIFT;
        dst_offset = new_mem->mm_node->start << PAGE_SHIFT;
@@ -625,7 +633,8 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
                        return ret;
        }
 
-       if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE)
+       if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE ||
+           !dev_priv->channel)
                return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
 
        if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
index 032cf09..5a10deb 100644 (file)
@@ -86,7 +86,7 @@ nouveau_connector_destroy(struct drm_connector *drm_connector)
        struct nouveau_connector *connector = nouveau_connector(drm_connector);
        struct drm_device *dev = connector->base.dev;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        if (!connector)
                return;
@@ -420,7 +420,7 @@ nouveau_connector_native_mode(struct nouveau_connector *connector)
        /* Use preferred mode if there is one.. */
        list_for_each_entry(mode, &connector->base.probed_modes, head) {
                if (mode->type & DRM_MODE_TYPE_PREFERRED) {
-                       NV_DEBUG(dev, "native mode from preferred\n");
+                       NV_DEBUG_KMS(dev, "native mode from preferred\n");
                        return drm_mode_duplicate(dev, mode);
                }
        }
@@ -445,7 +445,7 @@ nouveau_connector_native_mode(struct nouveau_connector *connector)
                largest = mode;
        }
 
-       NV_DEBUG(dev, "native mode from largest: %dx%d@%d\n",
+       NV_DEBUG_KMS(dev, "native mode from largest: %dx%d@%d\n",
                      high_w, high_h, high_v);
        return largest ? drm_mode_duplicate(dev, largest) : NULL;
 }
@@ -725,7 +725,7 @@ nouveau_connector_create(struct drm_device *dev, int index, int type)
        struct drm_encoder *encoder;
        int ret;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
        if (!nv_connector)
index de61f46..9e2926c 100644 (file)
@@ -187,7 +187,7 @@ nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config)
        if (ret)
                return false;
 
-       NV_DEBUG(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]);
+       NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]);
 
        /* Keep all lanes at the same level.. */
        for (i = 0; i < nv_encoder->dp.link_nr; i++) {
@@ -228,7 +228,7 @@ nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config)
        int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
        int dpe_headerlen, ret, i;
 
-       NV_DEBUG(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n",
+       NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n",
                 config[0], config[1], config[2], config[3]);
 
        dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
@@ -276,12 +276,12 @@ nouveau_dp_link_train(struct drm_encoder *encoder)
        bool cr_done, cr_max_vs, eq_done;
        int ret = 0, i, tries, voltage;
 
-       NV_DEBUG(dev, "link training!!\n");
+       NV_DEBUG_KMS(dev, "link training!!\n");
 train:
        cr_done = eq_done = false;
 
        /* set link configuration */
-       NV_DEBUG(dev, "\tbegin train: bw %d, lanes %d\n",
+       NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n",
                 nv_encoder->dp.link_bw, nv_encoder->dp.link_nr);
 
        ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw);
@@ -297,7 +297,7 @@ train:
                return false;
 
        /* clock recovery */
-       NV_DEBUG(dev, "\tbegin cr\n");
+       NV_DEBUG_KMS(dev, "\tbegin cr\n");
        ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1);
        if (ret)
                goto stop;
@@ -314,7 +314,7 @@ train:
                ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2);
                if (ret)
                        break;
-               NV_DEBUG(dev, "\t\tstatus: 0x%02x 0x%02x\n",
+               NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n",
                         status[0], status[1]);
 
                cr_done = true;
@@ -346,7 +346,7 @@ train:
                goto stop;
 
        /* channel equalisation */
-       NV_DEBUG(dev, "\tbegin eq\n");
+       NV_DEBUG_KMS(dev, "\tbegin eq\n");
        ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2);
        if (ret)
                goto stop;
@@ -357,7 +357,7 @@ train:
                ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3);
                if (ret)
                        break;
-               NV_DEBUG(dev, "\t\tstatus: 0x%02x 0x%02x\n",
+               NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n",
                         status[0], status[1]);
 
                eq_done = true;
@@ -395,9 +395,9 @@ stop:
 
        /* retry at a lower setting, if possible */
        if (!ret && !(eq_done && cr_done)) {
-               NV_DEBUG(dev, "\twe failed\n");
+               NV_DEBUG_KMS(dev, "\twe failed\n");
                if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62) {
-                       NV_DEBUG(dev, "retry link training at low rate\n");
+                       NV_DEBUG_KMS(dev, "retry link training at low rate\n");
                        nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
                        goto train;
                }
@@ -418,7 +418,7 @@ nouveau_dp_detect(struct drm_encoder *encoder)
        if (ret)
                return false;
 
-       NV_DEBUG(dev, "encoder: link_bw %d, link_nr %d\n"
+       NV_DEBUG_KMS(dev, "encoder: link_bw %d, link_nr %d\n"
                      "display: link_bw %d, link_nr %d version 0x%02x\n",
                 nv_encoder->dcb->dpconf.link_bw,
                 nv_encoder->dcb->dpconf.link_nr,
@@ -446,7 +446,7 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
        uint32_t tmp, ctrl, stat = 0, data32[4] = {};
        int ret = 0, i, index = auxch->rd;
 
-       NV_DEBUG(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr);
+       NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr);
 
        tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
        nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000);
@@ -472,7 +472,7 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
        if (!(cmd & 1)) {
                memcpy(data32, data, data_nr);
                for (i = 0; i < 4; i++) {
-                       NV_DEBUG(dev, "wr %d: 0x%08x\n", i, data32[i]);
+                       NV_DEBUG_KMS(dev, "wr %d: 0x%08x\n", i, data32[i]);
                        nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]);
                }
        }
@@ -504,7 +504,7 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
        if (cmd & 1) {
                for (i = 0; i < 4; i++) {
                        data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i));
-                       NV_DEBUG(dev, "rd %d: 0x%08x\n", i, data32[i]);
+                       NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]);
                }
                memcpy(data, data32, data_nr);
        }
index 35249c3..06eb993 100644 (file)
 
 #include "drm_pciids.h"
 
+MODULE_PARM_DESC(ctxfw, "Use external firmware blob for grctx init (NV40)");
+int nouveau_ctxfw = 0;
+module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
+
 MODULE_PARM_DESC(noagp, "Disable AGP");
 int nouveau_noagp;
 module_param_named(noagp, nouveau_noagp, int, 0400);
@@ -273,7 +277,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
 
                for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
                        chan = dev_priv->fifos[i];
-                       if (!chan)
+                       if (!chan || !chan->pushbuf_bo)
                                continue;
 
                        for (j = 0; j < NOUVEAU_DMA_SKIPS; j++)
@@ -341,7 +345,7 @@ static struct drm_driver driver = {
                .owner = THIS_MODULE,
                .open = drm_open,
                .release = drm_release,
-               .ioctl = drm_ioctl,
+               .unlocked_ioctl = drm_ioctl,
                .mmap = nouveau_ttm_mmap,
                .poll = drm_poll,
                .fasync = drm_fasync,
index 88b4c7b..5f8cbb7 100644 (file)
@@ -54,6 +54,7 @@ struct nouveau_fpriv {
 #include "nouveau_drm.h"
 #include "nouveau_reg.h"
 #include "nouveau_bios.h"
+struct nouveau_grctx;
 
 #define MAX_NUM_DCB_ENTRIES 16
 
@@ -317,6 +318,7 @@ struct nouveau_pgraph_engine {
        bool accel_blocked;
        void *ctxprog;
        void *ctxvals;
+       int grctx_size;
 
        int  (*init)(struct drm_device *);
        void (*takedown)(struct drm_device *);
@@ -647,6 +649,7 @@ extern int nouveau_fbpercrtc;
 extern char *nouveau_tv_norm;
 extern int nouveau_reg_debug;
 extern char *nouveau_vbios;
+extern int nouveau_ctxfw;
 
 /* nouveau_state.c */
 extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
@@ -959,9 +962,7 @@ extern int  nv40_graph_create_context(struct nouveau_channel *);
 extern void nv40_graph_destroy_context(struct nouveau_channel *);
 extern int  nv40_graph_load_context(struct nouveau_channel *);
 extern int  nv40_graph_unload_context(struct drm_device *);
-extern int  nv40_grctx_init(struct drm_device *);
-extern void nv40_grctx_fini(struct drm_device *);
-extern void nv40_grctx_vals_load(struct drm_device *, struct nouveau_gpuobj *);
+extern void nv40_grctx_init(struct nouveau_grctx *);
 
 /* nv50_graph.c */
 extern struct nouveau_pgraph_object_class nv50_graph_grclass[];
@@ -975,6 +976,12 @@ extern int  nv50_graph_load_context(struct nouveau_channel *);
 extern int  nv50_graph_unload_context(struct drm_device *);
 extern void nv50_graph_context_switch(struct drm_device *);
 
+/* nouveau_grctx.c */
+extern int  nouveau_grctx_prog_load(struct drm_device *);
+extern void nouveau_grctx_vals_load(struct drm_device *,
+                                   struct nouveau_gpuobj *);
+extern void nouveau_grctx_fini(struct drm_device *);
+
 /* nv04_instmem.c */
 extern int  nv04_instmem_init(struct drm_device *);
 extern void nv04_instmem_takedown(struct drm_device *);
@@ -1207,14 +1214,24 @@ static inline void nv_wo32(struct drm_device *dev, struct nouveau_gpuobj *obj,
                                        pci_name(d->pdev), ##arg)
 #ifndef NV_DEBUG_NOTRACE
 #define NV_DEBUG(d, fmt, arg...) do {                                          \
-       if (drm_debug) {                                                       \
+       if (drm_debug & DRM_UT_DRIVER) {                                       \
+               NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__,             \
+                         __LINE__, ##arg);                                    \
+       }                                                                      \
+} while (0)
+#define NV_DEBUG_KMS(d, fmt, arg...) do {                                      \
+       if (drm_debug & DRM_UT_KMS) {                                          \
                NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__,             \
                          __LINE__, ##arg);                                    \
        }                                                                      \
 } while (0)
 #else
 #define NV_DEBUG(d, fmt, arg...) do {                                          \
-       if (drm_debug)                                                         \
+       if (drm_debug & DRM_UT_DRIVER)                                         \
+               NV_PRINTK(KERN_DEBUG, d, fmt, ##arg);                          \
+} while (0)
+#define NV_DEBUG_KMS(d, fmt, arg...) do {                                      \
+       if (drm_debug & DRM_UT_KMS)                                            \
                NV_PRINTK(KERN_DEBUG, d, fmt, ##arg);                          \
 } while (0)
 #endif
index 36e8c5e..84af25c 100644 (file)
@@ -58,7 +58,7 @@ nouveau_fbcon_sync(struct fb_info *info)
        struct nouveau_channel *chan = dev_priv->channel;
        int ret, i;
 
-       if (!chan->accel_done ||
+       if (!chan || !chan->accel_done ||
            info->state != FBINFO_STATE_RUNNING ||
            info->flags & FBINFO_HWACCEL_DISABLED)
                return 0;
@@ -318,14 +318,16 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
        par->nouveau_fb = nouveau_fb;
        par->dev = dev;
 
-       switch (dev_priv->card_type) {
-       case NV_50:
-               nv50_fbcon_accel_init(info);
-               break;
-       default:
-               nv04_fbcon_accel_init(info);
-               break;
-       };
+       if (dev_priv->channel) {
+               switch (dev_priv->card_type) {
+               case NV_50:
+                       nv50_fbcon_accel_init(info);
+                       break;
+               default:
+                       nv04_fbcon_accel_init(info);
+                       break;
+               };
+       }
 
        nouveau_fbcon_zfill(dev);
 
@@ -347,7 +349,7 @@ out:
 int
 nouveau_fbcon_probe(struct drm_device *dev)
 {
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        return drm_fb_helper_single_fb_probe(dev, 32, nouveau_fbcon_create);
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.c b/drivers/gpu/drm/nouveau/nouveau_grctx.c
new file mode 100644 (file)
index 0000000..419f4c2
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2009 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <linux/firmware.h>
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+
+struct nouveau_ctxprog {
+       uint32_t signature;
+       uint8_t  version;
+       uint16_t length;
+       uint32_t data[];
+} __attribute__ ((packed));
+
+struct nouveau_ctxvals {
+       uint32_t signature;
+       uint8_t  version;
+       uint32_t length;
+       struct {
+               uint32_t offset;
+               uint32_t value;
+       } data[];
+} __attribute__ ((packed));
+
+int
+nouveau_grctx_prog_load(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+       const int chipset = dev_priv->chipset;
+       const struct firmware *fw;
+       const struct nouveau_ctxprog *cp;
+       const struct nouveau_ctxvals *cv;
+       char name[32];
+       int ret, i;
+
+       if (pgraph->accel_blocked)
+               return -ENODEV;
+
+       if (!pgraph->ctxprog) {
+               sprintf(name, "nouveau/nv%02x.ctxprog", chipset);
+               ret = request_firmware(&fw, name, &dev->pdev->dev);
+               if (ret) {
+                       NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset);
+                       return ret;
+               }
+
+               pgraph->ctxprog = kmalloc(fw->size, GFP_KERNEL);
+               if (!pgraph->ctxprog) {
+                       NV_ERROR(dev, "OOM copying ctxprog\n");
+                       release_firmware(fw);
+                       return -ENOMEM;
+               }
+               memcpy(pgraph->ctxprog, fw->data, fw->size);
+
+               cp = pgraph->ctxprog;
+               if (le32_to_cpu(cp->signature) != 0x5043564e ||
+                   cp->version != 0 ||
+                   le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) {
+                       NV_ERROR(dev, "ctxprog invalid\n");
+                       release_firmware(fw);
+                       nouveau_grctx_fini(dev);
+                       return -EINVAL;
+               }
+               release_firmware(fw);
+       }
+
+       if (!pgraph->ctxvals) {
+               sprintf(name, "nouveau/nv%02x.ctxvals", chipset);
+               ret = request_firmware(&fw, name, &dev->pdev->dev);
+               if (ret) {
+                       NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset);
+                       nouveau_grctx_fini(dev);
+                       return ret;
+               }
+
+               pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL);
+               if (!pgraph->ctxprog) {
+                       NV_ERROR(dev, "OOM copying ctxprog\n");
+                       release_firmware(fw);
+                       nouveau_grctx_fini(dev);
+                       return -ENOMEM;
+               }
+               memcpy(pgraph->ctxvals, fw->data, fw->size);
+
+               cv = (void *)pgraph->ctxvals;
+               if (le32_to_cpu(cv->signature) != 0x5643564e ||
+                   cv->version != 0 ||
+                   le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) {
+                       NV_ERROR(dev, "ctxvals invalid\n");
+                       release_firmware(fw);
+                       nouveau_grctx_fini(dev);
+                       return -EINVAL;
+               }
+               release_firmware(fw);
+       }
+
+       cp = pgraph->ctxprog;
+
+       nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
+       for (i = 0; i < le16_to_cpu(cp->length); i++)
+               nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA,
+                       le32_to_cpu(cp->data[i]));
+
+       return 0;
+}
+
+void
+nouveau_grctx_fini(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+
+       if (pgraph->ctxprog) {
+               kfree(pgraph->ctxprog);
+               pgraph->ctxprog = NULL;
+       }
+
+       if (pgraph->ctxvals) {
+               kfree(pgraph->ctxprog);
+               pgraph->ctxvals = NULL;
+       }
+}
+
+void
+nouveau_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+       struct nouveau_ctxvals *cv = pgraph->ctxvals;
+       int i;
+
+       if (!cv)
+               return;
+
+       for (i = 0; i < le32_to_cpu(cv->length); i++)
+               nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset),
+                       le32_to_cpu(cv->data[i].value));
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.h b/drivers/gpu/drm/nouveau/nouveau_grctx.h
new file mode 100644 (file)
index 0000000..5d39c4c
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef __NOUVEAU_GRCTX_H__
+#define __NOUVEAU_GRCTX_H__
+
+struct nouveau_grctx {
+       struct drm_device *dev;
+
+       enum {
+               NOUVEAU_GRCTX_PROG,
+               NOUVEAU_GRCTX_VALS
+       } mode;
+       void *data;
+
+       uint32_t ctxprog_max;
+       uint32_t ctxprog_len;
+       uint32_t ctxprog_reg;
+       int      ctxprog_label[32];
+       uint32_t ctxvals_pos;
+       uint32_t ctxvals_base;
+};
+
+#ifdef CP_CTX
+static inline void
+cp_out(struct nouveau_grctx *ctx, uint32_t inst)
+{
+       uint32_t *ctxprog = ctx->data;
+
+       if (ctx->mode != NOUVEAU_GRCTX_PROG)
+               return;
+
+       BUG_ON(ctx->ctxprog_len == ctx->ctxprog_max);
+       ctxprog[ctx->ctxprog_len++] = inst;
+}
+
+static inline void
+cp_lsr(struct nouveau_grctx *ctx, uint32_t val)
+{
+       cp_out(ctx, CP_LOAD_SR | val);
+}
+
+static inline void
+cp_ctx(struct nouveau_grctx *ctx, uint32_t reg, uint32_t length)
+{
+       ctx->ctxprog_reg = (reg - 0x00400000) >> 2;
+
+       ctx->ctxvals_base = ctx->ctxvals_pos;
+       ctx->ctxvals_pos = ctx->ctxvals_base + length;
+
+       if (length > (CP_CTX_COUNT >> CP_CTX_COUNT_SHIFT)) {
+               cp_lsr(ctx, length);
+               length = 0;
+       }
+
+       cp_out(ctx, CP_CTX | (length << CP_CTX_COUNT_SHIFT) | ctx->ctxprog_reg);
+}
+
+static inline void
+cp_name(struct nouveau_grctx *ctx, int name)
+{
+       uint32_t *ctxprog = ctx->data;
+       int i;
+
+       if (ctx->mode != NOUVEAU_GRCTX_PROG)
+               return;
+
+       ctx->ctxprog_label[name] = ctx->ctxprog_len;
+       for (i = 0; i < ctx->ctxprog_len; i++) {
+               if ((ctxprog[i] & 0xfff00000) != 0xff400000)
+                       continue;
+               if ((ctxprog[i] & CP_BRA_IP) != ((name) << CP_BRA_IP_SHIFT))
+                       continue;
+               ctxprog[i] = (ctxprog[i] & 0x00ff00ff) |
+                            (ctx->ctxprog_len << CP_BRA_IP_SHIFT);
+       }
+}
+
+static inline void
+_cp_bra(struct nouveau_grctx *ctx, u32 mod, int flag, int state, int name)
+{
+       int ip = 0;
+
+       if (mod != 2) {
+               ip = ctx->ctxprog_label[name] << CP_BRA_IP_SHIFT;
+               if (ip == 0)
+                       ip = 0xff000000 | (name << CP_BRA_IP_SHIFT);
+       }
+
+       cp_out(ctx, CP_BRA | (mod << 18) | ip | flag |
+                   (state ? 0 : CP_BRA_IF_CLEAR));
+}
+#define cp_bra(c,f,s,n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n)
+#ifdef CP_BRA_MOD
+#define cp_cal(c,f,s,n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n)
+#define cp_ret(c,f,s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0)
+#endif
+
+static inline void
+_cp_wait(struct nouveau_grctx *ctx, int flag, int state)
+{
+       cp_out(ctx, CP_WAIT | flag | (state ? CP_WAIT_SET : 0));
+}
+#define cp_wait(c,f,s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s)
+
+static inline void
+_cp_set(struct nouveau_grctx *ctx, int flag, int state)
+{
+       cp_out(ctx, CP_SET | flag | (state ? CP_SET_1 : 0));
+}
+#define cp_set(c,f,s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s)
+
+static inline void
+cp_pos(struct nouveau_grctx *ctx, int offset)
+{
+       ctx->ctxvals_pos = offset;
+       ctx->ctxvals_base = ctx->ctxvals_pos;
+
+       cp_lsr(ctx, ctx->ctxvals_pos);
+       cp_out(ctx, CP_SET_CONTEXT_POINTER);
+}
+
+static inline void
+gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val)
+{
+       if (ctx->mode != NOUVEAU_GRCTX_VALS)
+               return;
+
+       reg = (reg - 0x00400000) / 4;
+       reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base;
+
+       nv_wo32(ctx->dev, ctx->data, reg, val);
+}
+#endif
+
+#endif
index a2c30f4..475ba81 100644 (file)
@@ -61,12 +61,10 @@ long nouveau_compat_ioctl(struct file *filp, unsigned int cmd,
        if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls))
                fn = nouveau_compat_ioctls[nr - DRM_COMMAND_BASE];
 #endif
-       lock_kernel();    /* XXX for now */
        if (fn != NULL)
                ret = (*fn)(filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
+               ret = drm_ioctl(filp, cmd, arg);
 
        return ret;
 }
index 2ed41d3..e76ec2d 100644 (file)
@@ -299,12 +299,57 @@ nouveau_vga_set_decode(void *priv, bool state)
                return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }
 
+static int
+nouveau_card_init_channel(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *gpuobj;
+       int ret;
+
+       ret = nouveau_channel_alloc(dev, &dev_priv->channel,
+                                   (struct drm_file *)-2,
+                                   NvDmaFB, NvDmaTT);
+       if (ret)
+               return ret;
+
+       gpuobj = NULL;
+       ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
+                                    0, nouveau_mem_fb_amount(dev),
+                                    NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM,
+                                    &gpuobj);
+       if (ret)
+               goto out_err;
+
+       ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM,
+                                    gpuobj, NULL);
+       if (ret)
+               goto out_err;
+
+       gpuobj = NULL;
+       ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0,
+                                         dev_priv->gart_info.aper_size,
+                                         NV_DMA_ACCESS_RW, &gpuobj, NULL);
+       if (ret)
+               goto out_err;
+
+       ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART,
+                                    gpuobj, NULL);
+       if (ret)
+               goto out_err;
+
+       return 0;
+out_err:
+       nouveau_gpuobj_del(dev, &gpuobj);
+       nouveau_channel_free(dev_priv->channel);
+       dev_priv->channel = NULL;
+       return ret;
+}
+
 int
 nouveau_card_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_engine *engine;
-       struct nouveau_gpuobj *gpuobj;
        int ret;
 
        NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
@@ -317,7 +362,7 @@ nouveau_card_init(struct drm_device *dev)
        /* Initialise internal driver API hooks */
        ret = nouveau_init_engine_ptrs(dev);
        if (ret)
-               return ret;
+               goto out;
        engine = &dev_priv->engine;
        dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
 
@@ -325,12 +370,12 @@ nouveau_card_init(struct drm_device *dev)
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                ret = nouveau_bios_init(dev);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
        ret = nouveau_gpuobj_early_init(dev);
        if (ret)
-               return ret;
+               goto out_bios;
 
        /* Initialise instance memory, must happen before mem_init so we
         * know exactly how much VRAM we're able to use for "normal"
@@ -338,100 +383,68 @@ nouveau_card_init(struct drm_device *dev)
         */
        ret = engine->instmem.init(dev);
        if (ret)
-               return ret;
+               goto out_gpuobj_early;
 
        /* Setup the memory manager */
        ret = nouveau_mem_init(dev);
        if (ret)
-               return ret;
+               goto out_instmem;
 
        ret = nouveau_gpuobj_init(dev);
        if (ret)
-               return ret;
+               goto out_mem;
 
        /* PMC */
        ret = engine->mc.init(dev);
        if (ret)
-               return ret;
+               goto out_gpuobj;
 
        /* PTIMER */
        ret = engine->timer.init(dev);
        if (ret)
-               return ret;
+               goto out_mc;
 
        /* PFB */
        ret = engine->fb.init(dev);
        if (ret)
-               return ret;
+               goto out_timer;
 
        /* PGRAPH */
        ret = engine->graph.init(dev);
        if (ret)
-               return ret;
+               goto out_fb;
 
        /* PFIFO */
        ret = engine->fifo.init(dev);
        if (ret)
-               return ret;
+               goto out_graph;
 
        /* this call irq_preinstall, register irq handler and
         * call irq_postinstall
         */
        ret = drm_irq_install(dev);
        if (ret)
-               return ret;
+               goto out_fifo;
 
        ret = drm_vblank_init(dev, 0);
        if (ret)
-               return ret;
+               goto out_irq;
 
        /* what about PVIDEO/PCRTC/PRAMDAC etc? */
 
-       ret = nouveau_channel_alloc(dev, &dev_priv->channel,
-                                   (struct drm_file *)-2,
-                                   NvDmaFB, NvDmaTT);
-       if (ret)
-               return ret;
-
-       gpuobj = NULL;
-       ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
-                                    0, nouveau_mem_fb_amount(dev),
-                                    NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM,
-                                    &gpuobj);
-       if (ret)
-               return ret;
-
-       ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM,
-                                    gpuobj, NULL);
-       if (ret) {
-               nouveau_gpuobj_del(dev, &gpuobj);
-               return ret;
-       }
-
-       gpuobj = NULL;
-       ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0,
-                                         dev_priv->gart_info.aper_size,
-                                         NV_DMA_ACCESS_RW, &gpuobj, NULL);
-       if (ret)
-               return ret;
-
-       ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART,
-                                    gpuobj, NULL);
-       if (ret) {
-               nouveau_gpuobj_del(dev, &gpuobj);
-               return ret;
+       if (!engine->graph.accel_blocked) {
+               ret = nouveau_card_init_channel(dev);
+               if (ret)
+                       goto out_irq;
        }
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               if (dev_priv->card_type >= NV_50) {
+               if (dev_priv->card_type >= NV_50)
                        ret = nv50_display_create(dev);
-                       if (ret)
-                               return ret;
-               } else {
+               else
                        ret = nv04_display_create(dev);
-                       if (ret)
-                               return ret;
-               }
+               if (ret)
+                       goto out_irq;
        }
 
        ret = nouveau_backlight_init(dev);
@@ -444,6 +457,32 @@ nouveau_card_init(struct drm_device *dev)
                drm_helper_initial_config(dev);
 
        return 0;
+
+out_irq:
+       drm_irq_uninstall(dev);
+out_fifo:
+       engine->fifo.takedown(dev);
+out_graph:
+       engine->graph.takedown(dev);
+out_fb:
+       engine->fb.takedown(dev);
+out_timer:
+       engine->timer.takedown(dev);
+out_mc:
+       engine->mc.takedown(dev);
+out_gpuobj:
+       nouveau_gpuobj_takedown(dev);
+out_mem:
+       nouveau_mem_close(dev);
+out_instmem:
+       engine->instmem.takedown(dev);
+out_gpuobj_early:
+       nouveau_gpuobj_late_takedown(dev);
+out_bios:
+       nouveau_bios_takedown(dev);
+out:
+       vga_client_register(dev->pdev, NULL, NULL, NULL);
+       return ret;
 }
 
 static void nouveau_card_takedown(struct drm_device *dev)
index b913636..d2f143e 100644 (file)
@@ -143,10 +143,10 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod
        state->pllsel |= nv_crtc->index ? PLLSEL_VPLL2_MASK : PLLSEL_VPLL1_MASK;
 
        if (pv->NM2)
-               NV_TRACE(dev, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n",
+               NV_DEBUG_KMS(dev, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n",
                         pv->N1, pv->N2, pv->M1, pv->M2, pv->log2P);
        else
-               NV_TRACE(dev, "vpll: n %d m %d log2p %d\n",
+               NV_DEBUG_KMS(dev, "vpll: n %d m %d log2p %d\n",
                         pv->N1, pv->M1, pv->log2P);
 
        nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset);
@@ -160,7 +160,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
        unsigned char seq1 = 0, crtc17 = 0;
        unsigned char crtc1A;
 
-       NV_TRACE(dev, "Setting dpms mode %d on CRTC %d\n", mode,
+       NV_DEBUG_KMS(dev, "Setting dpms mode %d on CRTC %d\n", mode,
                                                        nv_crtc->index);
 
        if (nv_crtc->last_dpms == mode) /* Don't do unnecesary mode changes. */
@@ -603,7 +603,7 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-       NV_DEBUG(dev, "CTRC mode on CRTC %d:\n", nv_crtc->index);
+       NV_DEBUG_KMS(dev, "CTRC mode on CRTC %d:\n", nv_crtc->index);
        drm_mode_debug_printmodeline(adjusted_mode);
 
        /* unlock must come after turning off FP_TG_CONTROL in output_prepare */
@@ -703,7 +703,7 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
 {
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 
-       NV_DEBUG(crtc->dev, "\n");
+       NV_DEBUG_KMS(crtc->dev, "\n");
 
        if (!nv_crtc)
                return;
index a5fa517..d9f3287 100644 (file)
@@ -205,7 +205,7 @@ out:
        NVWriteVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1);
 
        if (blue == 0x18) {
-               NV_TRACE(dev, "Load detected on head A\n");
+               NV_INFO(dev, "Load detected on head A\n");
                return connector_status_connected;
        }
 
@@ -350,14 +350,10 @@ static void nv04_dac_mode_set(struct drm_encoder *encoder,
                              struct drm_display_mode *mode,
                              struct drm_display_mode *adjusted_mode)
 {
-       struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct drm_device *dev = encoder->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        int head = nouveau_crtc(encoder->crtc)->index;
 
-       NV_TRACE(dev, "%s called for encoder %d\n", __func__,
-                     nv_encoder->dcb->index);
-
        if (nv_gf4_disp_arch(dev)) {
                struct drm_encoder *rebind;
                uint32_t dac_offset = nv04_dac_output_offset(encoder);
@@ -466,7 +462,7 @@ static void nv04_dac_destroy(struct drm_encoder *encoder)
 {
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 
-       NV_DEBUG(encoder->dev, "\n");
+       NV_DEBUG_KMS(encoder->dev, "\n");
 
        drm_encoder_cleanup(encoder);
        kfree(nv_encoder);
index e5b3333..483f875 100644 (file)
@@ -261,7 +261,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
        struct drm_display_mode *output_mode = &nv_encoder->mode;
        uint32_t mode_ratio, panel_ratio;
 
-       NV_DEBUG(dev, "Output mode on CRTC %d:\n", nv_crtc->index);
+       NV_DEBUG_KMS(dev, "Output mode on CRTC %d:\n", nv_crtc->index);
        drm_mode_debug_printmodeline(output_mode);
 
        /* Initialize the FP registers in this CRTC. */
@@ -413,7 +413,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
        struct dcb_entry *dcbe = nv_encoder->dcb;
        int head = nouveau_crtc(encoder->crtc)->index;
 
-       NV_TRACE(dev, "%s called for encoder %d\n", __func__, nv_encoder->dcb->index);
+       NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
+               drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+               nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 
        if (dcbe->type == OUTPUT_TMDS)
                run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock);
@@ -550,7 +552,7 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder)
 {
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 
-       NV_DEBUG(encoder->dev, "\n");
+       NV_DEBUG_KMS(encoder->dev, "\n");
 
        drm_encoder_cleanup(encoder);
        kfree(nv_encoder);
index b47c757..ef77215 100644 (file)
@@ -99,10 +99,11 @@ nv04_display_create(struct drm_device *dev)
        uint16_t connector[16] = { 0 };
        int i, ret;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        if (nv_two_heads(dev))
                nv04_display_store_initial_head_owner(dev);
+       nouveau_hw_save_vga_fonts(dev, 1);
 
        drm_mode_config_init(dev);
        drm_mode_create_scaling_mode_property(dev);
@@ -203,8 +204,6 @@ nv04_display_create(struct drm_device *dev)
        /* Save previous state */
        NVLockVgaCrtcs(dev, false);
 
-       nouveau_hw_save_vga_fonts(dev, 1);
-
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                crtc->funcs->save(crtc);
 
@@ -223,7 +222,7 @@ nv04_display_destroy(struct drm_device *dev)
        struct drm_encoder *encoder;
        struct drm_crtc *crtc;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        /* Turn every CRTC off. */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -246,9 +245,9 @@ nv04_display_destroy(struct drm_device *dev)
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                crtc->funcs->restore(crtc);
 
-       nouveau_hw_save_vga_fonts(dev, 0);
-
        drm_mode_config_cleanup(dev);
+
+       nouveau_hw_save_vga_fonts(dev, 0);
 }
 
 void
index 396ee92..d561d77 100644 (file)
@@ -543,7 +543,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass,
 
        nv_wi32(dev, instance, tmp);
        nv_wr32(dev, NV04_PGRAPH_CTX_SWITCH1, tmp);
-       nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + subc, tmp);
+       nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp);
        return 0;
 }
 
index 6bf6804..6870e0e 100644 (file)
@@ -389,49 +389,50 @@ struct graph_state {
        int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)];
        int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)];
        struct pipe_state pipe_state;
+       uint32_t lma_window[4];
 };
 
+#define PIPE_SAVE(dev, state, addr)                                    \
+       do {                                                            \
+               int __i;                                                \
+               nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr);           \
+               for (__i = 0; __i < ARRAY_SIZE(state); __i++)           \
+                       state[__i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \
+       } while (0)
+
+#define PIPE_RESTORE(dev, state, addr)                                 \
+       do {                                                            \
+               int __i;                                                \
+               nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr);           \
+               for (__i = 0; __i < ARRAY_SIZE(state); __i++)           \
+                       nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, state[__i]); \
+       } while (0)
+
 static void nv10_graph_save_pipe(struct nouveau_channel *chan)
 {
        struct drm_device *dev = chan->dev;
        struct graph_state *pgraph_ctx = chan->pgraph_ctx;
-       struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
-       int i;
-#define PIPE_SAVE(addr) \
-       do { \
-               nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \
-               for (i = 0; i < ARRAY_SIZE(fifo_pipe_state->pipe_##addr); i++) \
-                       fifo_pipe_state->pipe_##addr[i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \
-       } while (0)
-
-       PIPE_SAVE(0x4400);
-       PIPE_SAVE(0x0200);
-       PIPE_SAVE(0x6400);
-       PIPE_SAVE(0x6800);
-       PIPE_SAVE(0x6c00);
-       PIPE_SAVE(0x7000);
-       PIPE_SAVE(0x7400);
-       PIPE_SAVE(0x7800);
-       PIPE_SAVE(0x0040);
-       PIPE_SAVE(0x0000);
-
-#undef PIPE_SAVE
+       struct pipe_state *pipe = &pgraph_ctx->pipe_state;
+
+       PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
+       PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
+       PIPE_SAVE(dev, pipe->pipe_0x6400, 0x6400);
+       PIPE_SAVE(dev, pipe->pipe_0x6800, 0x6800);
+       PIPE_SAVE(dev, pipe->pipe_0x6c00, 0x6c00);
+       PIPE_SAVE(dev, pipe->pipe_0x7000, 0x7000);
+       PIPE_SAVE(dev, pipe->pipe_0x7400, 0x7400);
+       PIPE_SAVE(dev, pipe->pipe_0x7800, 0x7800);
+       PIPE_SAVE(dev, pipe->pipe_0x0040, 0x0040);
+       PIPE_SAVE(dev, pipe->pipe_0x0000, 0x0000);
 }
 
 static void nv10_graph_load_pipe(struct nouveau_channel *chan)
 {
        struct drm_device *dev = chan->dev;
        struct graph_state *pgraph_ctx = chan->pgraph_ctx;
-       struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
-       int i;
+       struct pipe_state *pipe = &pgraph_ctx->pipe_state;
        uint32_t xfmode0, xfmode1;
-#define PIPE_RESTORE(addr) \
-       do { \
-               nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \
-               for (i = 0; i < ARRAY_SIZE(fifo_pipe_state->pipe_##addr); i++) \
-                       nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, fifo_pipe_state->pipe_##addr[i]); \
-       } while (0)
-
+       int i;
 
        nouveau_wait_for_idle(dev);
        /* XXX check haiku comments */
@@ -457,24 +458,22 @@ static void nv10_graph_load_pipe(struct nouveau_channel *chan)
        nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008);
 
 
-       PIPE_RESTORE(0x0200);
+       PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200);
        nouveau_wait_for_idle(dev);
 
        /* restore XFMODE */
        nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0);
        nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1);
-       PIPE_RESTORE(0x6400);
-       PIPE_RESTORE(0x6800);
-       PIPE_RESTORE(0x6c00);
-       PIPE_RESTORE(0x7000);
-       PIPE_RESTORE(0x7400);
-       PIPE_RESTORE(0x7800);
-       PIPE_RESTORE(0x4400);
-       PIPE_RESTORE(0x0000);
-       PIPE_RESTORE(0x0040);
+       PIPE_RESTORE(dev, pipe->pipe_0x6400, 0x6400);
+       PIPE_RESTORE(dev, pipe->pipe_0x6800, 0x6800);
+       PIPE_RESTORE(dev, pipe->pipe_0x6c00, 0x6c00);
+       PIPE_RESTORE(dev, pipe->pipe_0x7000, 0x7000);
+       PIPE_RESTORE(dev, pipe->pipe_0x7400, 0x7400);
+       PIPE_RESTORE(dev, pipe->pipe_0x7800, 0x7800);
+       PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400);
+       PIPE_RESTORE(dev, pipe->pipe_0x0000, 0x0000);
+       PIPE_RESTORE(dev, pipe->pipe_0x0040, 0x0040);
        nouveau_wait_for_idle(dev);
-
-#undef PIPE_RESTORE
 }
 
 static void nv10_graph_create_pipe(struct nouveau_channel *chan)
@@ -832,6 +831,9 @@ int nv10_graph_init(struct drm_device *dev)
                                      (1<<31));
        if (dev_priv->chipset >= 0x17) {
                nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000);
+               nv_wr32(dev, 0x400a10, 0x3ff3fb6);
+               nv_wr32(dev, 0x400838, 0x2f8684);
+               nv_wr32(dev, 0x40083c, 0x115f3f);
                nv_wr32(dev, 0x004006b0, 0x40000020);
        } else
                nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000);
@@ -867,6 +869,115 @@ void nv10_graph_takedown(struct drm_device *dev)
 {
 }
 
+static int
+nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass,
+                          int mthd, uint32_t data)
+{
+       struct drm_device *dev = chan->dev;
+       struct graph_state *ctx = chan->pgraph_ctx;
+       struct pipe_state *pipe = &ctx->pipe_state;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+       uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3];
+       uint32_t xfmode0, xfmode1;
+       int i;
+
+       ctx->lma_window[(mthd - 0x1638) / 4] = data;
+
+       if (mthd != 0x1644)
+               return 0;
+
+       nouveau_wait_for_idle(dev);
+
+       PIPE_SAVE(dev, pipe_0x0040, 0x0040);
+       PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
+
+       PIPE_RESTORE(dev, ctx->lma_window, 0x6790);
+
+       nouveau_wait_for_idle(dev);
+
+       xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0);
+       xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1);
+
+       PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
+       PIPE_SAVE(dev, pipe_0x64c0, 0x64c0);
+       PIPE_SAVE(dev, pipe_0x6ab0, 0x6ab0);
+       PIPE_SAVE(dev, pipe_0x6a80, 0x6a80);
+
+       nouveau_wait_for_idle(dev);
+
+       nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000);
+       nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000);
+       nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
+       for (i = 0; i < 4; i++)
+               nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
+       for (i = 0; i < 4; i++)
+               nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
+
+       nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
+       for (i = 0; i < 3; i++)
+               nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
+
+       nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
+       for (i = 0; i < 3; i++)
+               nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
+
+       nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
+       nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008);
+
+       PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200);
+
+       nouveau_wait_for_idle(dev);
+
+       PIPE_RESTORE(dev, pipe_0x0040, 0x0040);
+
+       nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0);
+       nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1);
+
+       PIPE_RESTORE(dev, pipe_0x64c0, 0x64c0);
+       PIPE_RESTORE(dev, pipe_0x6ab0, 0x6ab0);
+       PIPE_RESTORE(dev, pipe_0x6a80, 0x6a80);
+       PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400);
+
+       nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0);
+       nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
+
+       nouveau_wait_for_idle(dev);
+
+       pgraph->fifo_access(dev, true);
+
+       return 0;
+}
+
+static int
+nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass,
+                          int mthd, uint32_t data)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+
+       nouveau_wait_for_idle(dev);
+
+       nv_wr32(dev, NV10_PGRAPH_DEBUG_4,
+               nv_rd32(dev, NV10_PGRAPH_DEBUG_4) | 0x1 << 8);
+       nv_wr32(dev, 0x004006b0,
+               nv_rd32(dev, 0x004006b0) | 0x8 << 24);
+
+       pgraph->fifo_access(dev, true);
+
+       return 0;
+}
+
+static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = {
+       { 0x1638, nv17_graph_mthd_lma_window },
+       { 0x163c, nv17_graph_mthd_lma_window },
+       { 0x1640, nv17_graph_mthd_lma_window },
+       { 0x1644, nv17_graph_mthd_lma_window },
+       { 0x1658, nv17_graph_mthd_lma_enable },
+       {}
+};
+
 struct nouveau_pgraph_object_class nv10_graph_grclass[] = {
        { 0x0030, false, NULL }, /* null */
        { 0x0039, false, NULL }, /* m2mf */
@@ -887,6 +998,6 @@ struct nouveau_pgraph_object_class nv10_graph_grclass[] = {
        { 0x0095, false, NULL }, /* multitex_tri */
        { 0x0056, false, NULL }, /* celcius (nv10) */
        { 0x0096, false, NULL }, /* celcius (nv11) */
-       { 0x0099, false, NULL }, /* celcius (nv17) */
+       { 0x0099, false, nv17_graph_celsius_mthds }, /* celcius (nv17) */
        {}
 };
index 46cfd9c..81c0135 100644 (file)
@@ -219,7 +219,7 @@ static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode)
                return;
        nouveau_encoder(encoder)->last_dpms = mode;
 
-       NV_TRACE(dev, "Setting dpms mode %d on TV encoder (output %d)\n",
+       NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n",
                 mode, nouveau_encoder(encoder)->dcb->index);
 
        regs->ptv_200 &= ~1;
@@ -619,7 +619,7 @@ static void nv17_tv_destroy(struct drm_encoder *encoder)
 {
        struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 
-       NV_DEBUG(encoder->dev, "\n");
+       NV_DEBUG_KMS(encoder->dev, "\n");
 
        drm_encoder_cleanup(encoder);
        kfree(tv_enc);
index 7e8547c..2b332bb 100644 (file)
  *
  */
 
-#include <linux/firmware.h>
-
 #include "drmP.h"
 #include "drm.h"
 #include "nouveau_drv.h"
-
-MODULE_FIRMWARE("nouveau/nv40.ctxprog");
-MODULE_FIRMWARE("nouveau/nv40.ctxvals");
-MODULE_FIRMWARE("nouveau/nv41.ctxprog");
-MODULE_FIRMWARE("nouveau/nv41.ctxvals");
-MODULE_FIRMWARE("nouveau/nv42.ctxprog");
-MODULE_FIRMWARE("nouveau/nv42.ctxvals");
-MODULE_FIRMWARE("nouveau/nv43.ctxprog");
-MODULE_FIRMWARE("nouveau/nv43.ctxvals");
-MODULE_FIRMWARE("nouveau/nv44.ctxprog");
-MODULE_FIRMWARE("nouveau/nv44.ctxvals");
-MODULE_FIRMWARE("nouveau/nv46.ctxprog");
-MODULE_FIRMWARE("nouveau/nv46.ctxvals");
-MODULE_FIRMWARE("nouveau/nv47.ctxprog");
-MODULE_FIRMWARE("nouveau/nv47.ctxvals");
-MODULE_FIRMWARE("nouveau/nv49.ctxprog");
-MODULE_FIRMWARE("nouveau/nv49.ctxvals");
-MODULE_FIRMWARE("nouveau/nv4a.ctxprog");
-MODULE_FIRMWARE("nouveau/nv4a.ctxvals");
-MODULE_FIRMWARE("nouveau/nv4b.ctxprog");
-MODULE_FIRMWARE("nouveau/nv4b.ctxvals");
-MODULE_FIRMWARE("nouveau/nv4c.ctxprog");
-MODULE_FIRMWARE("nouveau/nv4c.ctxvals");
-MODULE_FIRMWARE("nouveau/nv4e.ctxprog");
-MODULE_FIRMWARE("nouveau/nv4e.ctxvals");
+#include "nouveau_grctx.h"
 
 struct nouveau_channel *
 nv40_graph_channel(struct drm_device *dev)
@@ -83,27 +57,30 @@ nv40_graph_create_context(struct nouveau_channel *chan)
 {
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_gpuobj *ctx;
+       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
        int ret;
 
-       /* Allocate a 175KiB block of PRAMIN to store the context.  This
-        * is massive overkill for a lot of chipsets, but it should be safe
-        * until we're able to implement this properly (will happen at more
-        * or less the same time we're able to write our own context programs.
-        */
-       ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 175*1024, 16,
-                                         NVOBJ_FLAG_ZERO_ALLOC,
-                                         &chan->ramin_grctx);
+       ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size,
+                                    16, NVOBJ_FLAG_ZERO_ALLOC,
+                                    &chan->ramin_grctx);
        if (ret)
                return ret;
-       ctx = chan->ramin_grctx->gpuobj;
 
        /* Initialise default context values */
        dev_priv->engine.instmem.prepare_access(dev, true);
-       nv40_grctx_vals_load(dev, ctx);
-       nv_wo32(dev, ctx, 0, ctx->im_pramin->start);
-       dev_priv->engine.instmem.finish_access(dev);
+       if (!pgraph->ctxprog) {
+               struct nouveau_grctx ctx = {};
 
+               ctx.dev = chan->dev;
+               ctx.mode = NOUVEAU_GRCTX_VALS;
+               ctx.data = chan->ramin_grctx->gpuobj;
+               nv40_grctx_init(&ctx);
+       } else {
+               nouveau_grctx_vals_load(dev, chan->ramin_grctx->gpuobj);
+       }
+       nv_wo32(dev, chan->ramin_grctx->gpuobj, 0,
+                    chan->ramin_grctx->gpuobj->im_pramin->start);
+       dev_priv->engine.instmem.finish_access(dev);
        return 0;
 }
 
@@ -204,139 +181,6 @@ nv40_graph_unload_context(struct drm_device *dev)
        return ret;
 }
 
-struct nouveau_ctxprog {
-       uint32_t signature;
-       uint8_t  version;
-       uint16_t length;
-       uint32_t data[];
-} __attribute__ ((packed));
-
-struct nouveau_ctxvals {
-       uint32_t signature;
-       uint8_t  version;
-       uint32_t length;
-       struct {
-               uint32_t offset;
-               uint32_t value;
-       } data[];
-} __attribute__ ((packed));
-
-int
-nv40_grctx_init(struct drm_device *dev)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-       const int chipset = dev_priv->chipset;
-       const struct firmware *fw;
-       const struct nouveau_ctxprog *cp;
-       const struct nouveau_ctxvals *cv;
-       char name[32];
-       int ret, i;
-
-       pgraph->accel_blocked = true;
-
-       if (!pgraph->ctxprog) {
-               sprintf(name, "nouveau/nv%02x.ctxprog", chipset);
-               ret = request_firmware(&fw, name, &dev->pdev->dev);
-               if (ret) {
-                       NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset);
-                       return ret;
-               }
-
-               pgraph->ctxprog = kmalloc(fw->size, GFP_KERNEL);
-               if (!pgraph->ctxprog) {
-                       NV_ERROR(dev, "OOM copying ctxprog\n");
-                       release_firmware(fw);
-                       return -ENOMEM;
-               }
-               memcpy(pgraph->ctxprog, fw->data, fw->size);
-
-               cp = pgraph->ctxprog;
-               if (le32_to_cpu(cp->signature) != 0x5043564e ||
-                   cp->version != 0 ||
-                   le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) {
-                       NV_ERROR(dev, "ctxprog invalid\n");
-                       release_firmware(fw);
-                       nv40_grctx_fini(dev);
-                       return -EINVAL;
-               }
-               release_firmware(fw);
-       }
-
-       if (!pgraph->ctxvals) {
-               sprintf(name, "nouveau/nv%02x.ctxvals", chipset);
-               ret = request_firmware(&fw, name, &dev->pdev->dev);
-               if (ret) {
-                       NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset);
-                       nv40_grctx_fini(dev);
-                       return ret;
-               }
-
-               pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL);
-               if (!pgraph->ctxprog) {
-                       NV_ERROR(dev, "OOM copying ctxprog\n");
-                       release_firmware(fw);
-                       nv40_grctx_fini(dev);
-                       return -ENOMEM;
-               }
-               memcpy(pgraph->ctxvals, fw->data, fw->size);
-
-               cv = (void *)pgraph->ctxvals;
-               if (le32_to_cpu(cv->signature) != 0x5643564e ||
-                   cv->version != 0 ||
-                   le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) {
-                       NV_ERROR(dev, "ctxvals invalid\n");
-                       release_firmware(fw);
-                       nv40_grctx_fini(dev);
-                       return -EINVAL;
-               }
-               release_firmware(fw);
-       }
-
-       cp = pgraph->ctxprog;
-
-       nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
-       for (i = 0; i < le16_to_cpu(cp->length); i++)
-               nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA,
-                       le32_to_cpu(cp->data[i]));
-
-       pgraph->accel_blocked = false;
-       return 0;
-}
-
-void
-nv40_grctx_fini(struct drm_device *dev)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-
-       if (pgraph->ctxprog) {
-               kfree(pgraph->ctxprog);
-               pgraph->ctxprog = NULL;
-       }
-
-       if (pgraph->ctxvals) {
-               kfree(pgraph->ctxprog);
-               pgraph->ctxvals = NULL;
-       }
-}
-
-void
-nv40_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-       struct nouveau_ctxvals *cv = pgraph->ctxvals;
-       int i;
-
-       if (!cv)
-               return;
-
-       for (i = 0; i < le32_to_cpu(cv->length); i++)
-               nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset),
-                       le32_to_cpu(cv->data[i].value));
-}
-
 /*
  * G70         0x47
  * G71         0x49
@@ -359,7 +203,26 @@ nv40_graph_init(struct drm_device *dev)
        nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
                         NV_PMC_ENABLE_PGRAPH);
 
-       nv40_grctx_init(dev);
+       if (nouveau_ctxfw) {
+               nouveau_grctx_prog_load(dev);
+               dev_priv->engine.graph.grctx_size = 175 * 1024;
+       }
+
+       if (!dev_priv->engine.graph.ctxprog) {
+               struct nouveau_grctx ctx = {};
+               uint32_t cp[256];
+
+               ctx.dev = dev;
+               ctx.mode = NOUVEAU_GRCTX_PROG;
+               ctx.data = cp;
+               ctx.ctxprog_max = 256;
+               nv40_grctx_init(&ctx);
+               dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4;
+
+               nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
+               for (i = 0; i < ctx.ctxprog_len; i++)
+                       nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]);
+       }
 
        /* No context present currently */
        nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
@@ -539,6 +402,7 @@ nv40_graph_init(struct drm_device *dev)
 
 void nv40_graph_takedown(struct drm_device *dev)
 {
+       nouveau_grctx_fini(dev);
 }
 
 struct nouveau_pgraph_object_class nv40_graph_grclass[] = {
diff --git a/drivers/gpu/drm/nouveau/nv40_grctx.c b/drivers/gpu/drm/nouveau/nv40_grctx.c
new file mode 100644 (file)
index 0000000..11b11c3
--- /dev/null
@@ -0,0 +1,678 @@
+/*
+ * Copyright 2009 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+/* NVIDIA context programs handle a number of other conditions which are
+ * not implemented in our versions.  It's not clear why NVIDIA context
+ * programs have this code, nor whether it's strictly necessary for
+ * correct operation.  We'll implement additional handling if/when we
+ * discover it's necessary.
+ *
+ * - On context save, NVIDIA set 0x400314 bit 0 to 1 if the "3D state"
+ *   flag is set, this gets saved into the context.
+ * - On context save, the context program for all cards load nsource
+ *   into a flag register and check for ILLEGAL_MTHD.  If it's set,
+ *   opcode 0x60000d is called before resuming normal operation.
+ * - Some context programs check more conditions than the above.  NV44
+ *   checks: ((nsource & 0x0857) || (0x400718 & 0x0100) || (intr & 0x0001))
+ *   and calls 0x60000d before resuming normal operation.
+ * - At the very beginning of NVIDIA's context programs, flag 9 is checked
+ *   and if true 0x800001 is called with count=0, pos=0, the flag is cleared
+ *   and then the ctxprog is aborted.  It looks like a complicated NOP,
+ *   its purpose is unknown.
+ * - In the section of code that loads the per-vs state, NVIDIA check
+ *   flag 10.  If it's set, they only transfer the small 0x300 byte block
+ *   of state + the state for a single vs as opposed to the state for
+ *   all vs units.  It doesn't seem likely that it'll occur in normal
+ *   operation, especially seeing as it appears NVIDIA may have screwed
+ *   up the ctxprogs for some cards and have an invalid instruction
+ *   rather than a cp_lsr(ctx, dwords_for_1_vs_unit) instruction.
+ * - There's a number of places where context offset 0 (where we place
+ *   the PRAMIN offset of the context) is loaded into either 0x408000,
+ *   0x408004 or 0x408008.  Not sure what's up there either.
+ * - The ctxprogs for some cards save 0x400a00 again during the cleanup
+ *   path for auto-loadctx.
+ */
+
+#define CP_FLAG_CLEAR                 0
+#define CP_FLAG_SET                   1
+#define CP_FLAG_SWAP_DIRECTION        ((0 * 32) + 0)
+#define CP_FLAG_SWAP_DIRECTION_LOAD   0
+#define CP_FLAG_SWAP_DIRECTION_SAVE   1
+#define CP_FLAG_USER_SAVE             ((0 * 32) + 5)
+#define CP_FLAG_USER_SAVE_NOT_PENDING 0
+#define CP_FLAG_USER_SAVE_PENDING     1
+#define CP_FLAG_USER_LOAD             ((0 * 32) + 6)
+#define CP_FLAG_USER_LOAD_NOT_PENDING 0
+#define CP_FLAG_USER_LOAD_PENDING     1
+#define CP_FLAG_STATUS                ((3 * 32) + 0)
+#define CP_FLAG_STATUS_IDLE           0
+#define CP_FLAG_STATUS_BUSY           1
+#define CP_FLAG_AUTO_SAVE             ((3 * 32) + 4)
+#define CP_FLAG_AUTO_SAVE_NOT_PENDING 0
+#define CP_FLAG_AUTO_SAVE_PENDING     1
+#define CP_FLAG_AUTO_LOAD             ((3 * 32) + 5)
+#define CP_FLAG_AUTO_LOAD_NOT_PENDING 0
+#define CP_FLAG_AUTO_LOAD_PENDING     1
+#define CP_FLAG_UNK54                 ((3 * 32) + 6)
+#define CP_FLAG_UNK54_CLEAR           0
+#define CP_FLAG_UNK54_SET             1
+#define CP_FLAG_ALWAYS                ((3 * 32) + 8)
+#define CP_FLAG_ALWAYS_FALSE          0
+#define CP_FLAG_ALWAYS_TRUE           1
+#define CP_FLAG_UNK57                 ((3 * 32) + 9)
+#define CP_FLAG_UNK57_CLEAR           0
+#define CP_FLAG_UNK57_SET             1
+
+#define CP_CTX                   0x00100000
+#define CP_CTX_COUNT             0x000fc000
+#define CP_CTX_COUNT_SHIFT               14
+#define CP_CTX_REG               0x00003fff
+#define CP_LOAD_SR               0x00200000
+#define CP_LOAD_SR_VALUE         0x000fffff
+#define CP_BRA                   0x00400000
+#define CP_BRA_IP                0x0000ff00
+#define CP_BRA_IP_SHIFT                   8
+#define CP_BRA_IF_CLEAR          0x00000080
+#define CP_BRA_FLAG              0x0000007f
+#define CP_WAIT                  0x00500000
+#define CP_WAIT_SET              0x00000080
+#define CP_WAIT_FLAG             0x0000007f
+#define CP_SET                   0x00700000
+#define CP_SET_1                 0x00000080
+#define CP_SET_FLAG              0x0000007f
+#define CP_NEXT_TO_SWAP          0x00600007
+#define CP_NEXT_TO_CURRENT       0x00600009
+#define CP_SET_CONTEXT_POINTER   0x0060000a
+#define CP_END                   0x0060000e
+#define CP_LOAD_MAGIC_UNK01      0x00800001 /* unknown */
+#define CP_LOAD_MAGIC_NV44TCL    0x00800029 /* per-vs state (0x4497) */
+#define CP_LOAD_MAGIC_NV40TCL    0x00800041 /* per-vs state (0x4097) */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_grctx.h"
+
+/* TODO:
+ *  - get vs count from 0x1540
+ *  - document unimplemented bits compared to nvidia
+ *    - nsource handling
+ *    - R0 & 0x0200 handling
+ *    - single-vs handling
+ *    - 400314 bit 0
+ */
+
+static int
+nv40_graph_4097(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if ((dev_priv->chipset & 0xf0) == 0x60)
+               return 0;
+
+       return !!(0x0baf & (1 << dev_priv->chipset));
+}
+
+static int
+nv40_graph_vs_count(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       switch (dev_priv->chipset) {
+       case 0x47:
+       case 0x49:
+       case 0x4b:
+               return 8;
+       case 0x40:
+               return 6;
+       case 0x41:
+       case 0x42:
+               return 5;
+       case 0x43:
+       case 0x44:
+       case 0x46:
+       case 0x4a:
+               return 3;
+       case 0x4c:
+       case 0x4e:
+       case 0x67:
+       default:
+               return 1;
+       }
+}
+
+
+enum cp_label {
+       cp_check_load = 1,
+       cp_setup_auto_load,
+       cp_setup_load,
+       cp_setup_save,
+       cp_swap_state,
+       cp_swap_state3d_3_is_save,
+       cp_prepare_exit,
+       cp_exit,
+};
+
+static void
+nv40_graph_construct_general(struct nouveau_grctx *ctx)
+{
+       struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+       int i;
+
+       cp_ctx(ctx, 0x4000a4, 1);
+       gr_def(ctx, 0x4000a4, 0x00000008);
+       cp_ctx(ctx, 0x400144, 58);
+       gr_def(ctx, 0x400144, 0x00000001);
+       cp_ctx(ctx, 0x400314, 1);
+       gr_def(ctx, 0x400314, 0x00000000);
+       cp_ctx(ctx, 0x400400, 10);
+       cp_ctx(ctx, 0x400480, 10);
+       cp_ctx(ctx, 0x400500, 19);
+       gr_def(ctx, 0x400514, 0x00040000);
+       gr_def(ctx, 0x400524, 0x55555555);
+       gr_def(ctx, 0x400528, 0x55555555);
+       gr_def(ctx, 0x40052c, 0x55555555);
+       gr_def(ctx, 0x400530, 0x55555555);
+       cp_ctx(ctx, 0x400560, 6);
+       gr_def(ctx, 0x400568, 0x0000ffff);
+       gr_def(ctx, 0x40056c, 0x0000ffff);
+       cp_ctx(ctx, 0x40057c, 5);
+       cp_ctx(ctx, 0x400710, 3);
+       gr_def(ctx, 0x400710, 0x20010001);
+       gr_def(ctx, 0x400714, 0x0f73ef00);
+       cp_ctx(ctx, 0x400724, 1);
+       gr_def(ctx, 0x400724, 0x02008821);
+       cp_ctx(ctx, 0x400770, 3);
+       if (dev_priv->chipset == 0x40) {
+               cp_ctx(ctx, 0x400814, 4);
+               cp_ctx(ctx, 0x400828, 5);
+               cp_ctx(ctx, 0x400840, 5);
+               gr_def(ctx, 0x400850, 0x00000040);
+               cp_ctx(ctx, 0x400858, 4);
+               gr_def(ctx, 0x400858, 0x00000040);
+               gr_def(ctx, 0x40085c, 0x00000040);
+               gr_def(ctx, 0x400864, 0x80000000);
+               cp_ctx(ctx, 0x40086c, 9);
+               gr_def(ctx, 0x40086c, 0x80000000);
+               gr_def(ctx, 0x400870, 0x80000000);
+               gr_def(ctx, 0x400874, 0x80000000);
+               gr_def(ctx, 0x400878, 0x80000000);
+               gr_def(ctx, 0x400888, 0x00000040);
+               gr_def(ctx, 0x40088c, 0x80000000);
+               cp_ctx(ctx, 0x4009c0, 8);
+               gr_def(ctx, 0x4009cc, 0x80000000);
+               gr_def(ctx, 0x4009dc, 0x80000000);
+       } else {
+               cp_ctx(ctx, 0x400840, 20);
+               if (!nv40_graph_4097(ctx->dev)) {
+                       for (i = 0; i < 8; i++)
+                               gr_def(ctx, 0x400860 + (i * 4), 0x00000001);
+               }
+               gr_def(ctx, 0x400880, 0x00000040);
+               gr_def(ctx, 0x400884, 0x00000040);
+               gr_def(ctx, 0x400888, 0x00000040);
+               cp_ctx(ctx, 0x400894, 11);
+               gr_def(ctx, 0x400894, 0x00000040);
+               if (nv40_graph_4097(ctx->dev)) {
+                       for (i = 0; i < 8; i++)
+                               gr_def(ctx, 0x4008a0 + (i * 4), 0x80000000);
+               }
+               cp_ctx(ctx, 0x4008e0, 2);
+               cp_ctx(ctx, 0x4008f8, 2);
+               if (dev_priv->chipset == 0x4c ||
+                   (dev_priv->chipset & 0xf0) == 0x60)
+                       cp_ctx(ctx, 0x4009f8, 1);
+       }
+       cp_ctx(ctx, 0x400a00, 73);
+       gr_def(ctx, 0x400b0c, 0x0b0b0b0c);
+       cp_ctx(ctx, 0x401000, 4);
+       cp_ctx(ctx, 0x405004, 1);
+       switch (dev_priv->chipset) {
+       case 0x47:
+       case 0x49:
+       case 0x4b:
+               cp_ctx(ctx, 0x403448, 1);
+               gr_def(ctx, 0x403448, 0x00001010);
+               break;
+       default:
+               cp_ctx(ctx, 0x403440, 1);
+               switch (dev_priv->chipset) {
+               case 0x40:
+                       gr_def(ctx, 0x403440, 0x00000010);
+                       break;
+               case 0x44:
+               case 0x46:
+               case 0x4a:
+                       gr_def(ctx, 0x403440, 0x00003010);
+                       break;
+               case 0x41:
+               case 0x42:
+               case 0x43:
+               case 0x4c:
+               case 0x4e:
+               case 0x67:
+               default:
+                       gr_def(ctx, 0x403440, 0x00001010);
+                       break;
+               }
+               break;
+       }
+}
+
+static void
+nv40_graph_construct_state3d(struct nouveau_grctx *ctx)
+{
+       struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+       int i;
+
+       if (dev_priv->chipset == 0x40) {
+               cp_ctx(ctx, 0x401880, 51);
+               gr_def(ctx, 0x401940, 0x00000100);
+       } else
+       if (dev_priv->chipset == 0x46 || dev_priv->chipset == 0x47 ||
+           dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) {
+               cp_ctx(ctx, 0x401880, 32);
+               for (i = 0; i < 16; i++)
+                       gr_def(ctx, 0x401880 + (i * 4), 0x00000111);
+               if (dev_priv->chipset == 0x46)
+                       cp_ctx(ctx, 0x401900, 16);
+               cp_ctx(ctx, 0x401940, 3);
+       }
+       cp_ctx(ctx, 0x40194c, 18);
+       gr_def(ctx, 0x401954, 0x00000111);
+       gr_def(ctx, 0x401958, 0x00080060);
+       gr_def(ctx, 0x401974, 0x00000080);
+       gr_def(ctx, 0x401978, 0xffff0000);
+       gr_def(ctx, 0x40197c, 0x00000001);
+       gr_def(ctx, 0x401990, 0x46400000);
+       if (dev_priv->chipset == 0x40) {
+               cp_ctx(ctx, 0x4019a0, 2);
+               cp_ctx(ctx, 0x4019ac, 5);
+       } else {
+               cp_ctx(ctx, 0x4019a0, 1);
+               cp_ctx(ctx, 0x4019b4, 3);
+       }
+       gr_def(ctx, 0x4019bc, 0xffff0000);
+       switch (dev_priv->chipset) {
+       case 0x46:
+       case 0x47:
+       case 0x49:
+       case 0x4b:
+               cp_ctx(ctx, 0x4019c0, 18);
+               for (i = 0; i < 16; i++)
+                       gr_def(ctx, 0x4019c0 + (i * 4), 0x88888888);
+               break;
+       }
+       cp_ctx(ctx, 0x401a08, 8);
+       gr_def(ctx, 0x401a10, 0x0fff0000);
+       gr_def(ctx, 0x401a14, 0x0fff0000);
+       gr_def(ctx, 0x401a1c, 0x00011100);
+       cp_ctx(ctx, 0x401a2c, 4);
+       cp_ctx(ctx, 0x401a44, 26);
+       for (i = 0; i < 16; i++)
+               gr_def(ctx, 0x401a44 + (i * 4), 0x07ff0000);
+       gr_def(ctx, 0x401a8c, 0x4b7fffff);
+       if (dev_priv->chipset == 0x40) {
+               cp_ctx(ctx, 0x401ab8, 3);
+       } else {
+               cp_ctx(ctx, 0x401ab8, 1);
+               cp_ctx(ctx, 0x401ac0, 1);
+       }
+       cp_ctx(ctx, 0x401ad0, 8);
+       gr_def(ctx, 0x401ad0, 0x30201000);
+       gr_def(ctx, 0x401ad4, 0x70605040);
+       gr_def(ctx, 0x401ad8, 0xb8a89888);
+       gr_def(ctx, 0x401adc, 0xf8e8d8c8);
+       cp_ctx(ctx, 0x401b10, dev_priv->chipset == 0x40 ? 2 : 1);
+       gr_def(ctx, 0x401b10, 0x40100000);
+       cp_ctx(ctx, 0x401b18, dev_priv->chipset == 0x40 ? 6 : 5);
+       gr_def(ctx, 0x401b28, dev_priv->chipset == 0x40 ?
+                             0x00000004 : 0x00000000);
+       cp_ctx(ctx, 0x401b30, 25);
+       gr_def(ctx, 0x401b34, 0x0000ffff);
+       gr_def(ctx, 0x401b68, 0x435185d6);
+       gr_def(ctx, 0x401b6c, 0x2155b699);
+       gr_def(ctx, 0x401b70, 0xfedcba98);
+       gr_def(ctx, 0x401b74, 0x00000098);
+       gr_def(ctx, 0x401b84, 0xffffffff);
+       gr_def(ctx, 0x401b88, 0x00ff7000);
+       gr_def(ctx, 0x401b8c, 0x0000ffff);
+       if (dev_priv->chipset != 0x44 && dev_priv->chipset != 0x4a &&
+           dev_priv->chipset != 0x4e)
+               cp_ctx(ctx, 0x401b94, 1);
+       cp_ctx(ctx, 0x401b98, 8);
+       gr_def(ctx, 0x401b9c, 0x00ff0000);
+       cp_ctx(ctx, 0x401bc0, 9);
+       gr_def(ctx, 0x401be0, 0x00ffff00);
+       cp_ctx(ctx, 0x401c00, 192);
+       for (i = 0; i < 16; i++) { /* fragment texture units */
+               gr_def(ctx, 0x401c40 + (i * 4), 0x00018488);
+               gr_def(ctx, 0x401c80 + (i * 4), 0x00028202);
+               gr_def(ctx, 0x401d00 + (i * 4), 0x0000aae4);
+               gr_def(ctx, 0x401d40 + (i * 4), 0x01012000);
+               gr_def(ctx, 0x401d80 + (i * 4), 0x00080008);
+               gr_def(ctx, 0x401e00 + (i * 4), 0x00100008);
+       }
+       for (i = 0; i < 4; i++) { /* vertex texture units */
+               gr_def(ctx, 0x401e90 + (i * 4), 0x0001bc80);
+               gr_def(ctx, 0x401ea0 + (i * 4), 0x00000202);
+               gr_def(ctx, 0x401ec0 + (i * 4), 0x00000008);
+               gr_def(ctx, 0x401ee0 + (i * 4), 0x00080008);
+       }
+       cp_ctx(ctx, 0x400f5c, 3);
+       gr_def(ctx, 0x400f5c, 0x00000002);
+       cp_ctx(ctx, 0x400f84, 1);
+}
+
+static void
+nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx)
+{
+       struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+       int i;
+
+       cp_ctx(ctx, 0x402000, 1);
+       cp_ctx(ctx, 0x402404, dev_priv->chipset == 0x40 ? 1 : 2);
+       switch (dev_priv->chipset) {
+       case 0x40:
+               gr_def(ctx, 0x402404, 0x00000001);
+               break;
+       case 0x4c:
+       case 0x4e:
+       case 0x67:
+               gr_def(ctx, 0x402404, 0x00000020);
+               break;
+       case 0x46:
+       case 0x49:
+       case 0x4b:
+               gr_def(ctx, 0x402404, 0x00000421);
+               break;
+       default:
+               gr_def(ctx, 0x402404, 0x00000021);
+       }
+       if (dev_priv->chipset != 0x40)
+               gr_def(ctx, 0x402408, 0x030c30c3);
+       switch (dev_priv->chipset) {
+       case 0x44:
+       case 0x46:
+       case 0x4a:
+       case 0x4c:
+       case 0x4e:
+       case 0x67:
+               cp_ctx(ctx, 0x402440, 1);
+               gr_def(ctx, 0x402440, 0x00011001);
+               break;
+       default:
+               break;
+       }
+       cp_ctx(ctx, 0x402480, dev_priv->chipset == 0x40 ? 8 : 9);
+       gr_def(ctx, 0x402488, 0x3e020200);
+       gr_def(ctx, 0x40248c, 0x00ffffff);
+       switch (dev_priv->chipset) {
+       case 0x40:
+               gr_def(ctx, 0x402490, 0x60103f00);
+               break;
+       case 0x47:
+               gr_def(ctx, 0x402490, 0x40103f00);
+               break;
+       case 0x41:
+       case 0x42:
+       case 0x49:
+       case 0x4b:
+               gr_def(ctx, 0x402490, 0x20103f00);
+               break;
+       default:
+               gr_def(ctx, 0x402490, 0x0c103f00);
+               break;
+       }
+       gr_def(ctx, 0x40249c, dev_priv->chipset <= 0x43 ?
+                             0x00020000 : 0x00040000);
+       cp_ctx(ctx, 0x402500, 31);
+       gr_def(ctx, 0x402530, 0x00008100);
+       if (dev_priv->chipset == 0x40)
+               cp_ctx(ctx, 0x40257c, 6);
+       cp_ctx(ctx, 0x402594, 16);
+       cp_ctx(ctx, 0x402800, 17);
+       gr_def(ctx, 0x402800, 0x00000001);
+       switch (dev_priv->chipset) {
+       case 0x47:
+       case 0x49:
+       case 0x4b:
+               cp_ctx(ctx, 0x402864, 1);
+               gr_def(ctx, 0x402864, 0x00001001);
+               cp_ctx(ctx, 0x402870, 3);
+               gr_def(ctx, 0x402878, 0x00000003);
+               if (dev_priv->chipset != 0x47) { /* belong at end!! */
+                       cp_ctx(ctx, 0x402900, 1);
+                       cp_ctx(ctx, 0x402940, 1);
+                       cp_ctx(ctx, 0x402980, 1);
+                       cp_ctx(ctx, 0x4029c0, 1);
+                       cp_ctx(ctx, 0x402a00, 1);
+                       cp_ctx(ctx, 0x402a40, 1);
+                       cp_ctx(ctx, 0x402a80, 1);
+                       cp_ctx(ctx, 0x402ac0, 1);
+               }
+               break;
+       case 0x40:
+               cp_ctx(ctx, 0x402844, 1);
+               gr_def(ctx, 0x402844, 0x00000001);
+               cp_ctx(ctx, 0x402850, 1);
+               break;
+       default:
+               cp_ctx(ctx, 0x402844, 1);
+               gr_def(ctx, 0x402844, 0x00001001);
+               cp_ctx(ctx, 0x402850, 2);
+               gr_def(ctx, 0x402854, 0x00000003);
+               break;
+       }
+
+       cp_ctx(ctx, 0x402c00, 4);
+       gr_def(ctx, 0x402c00, dev_priv->chipset == 0x40 ?
+                             0x80800001 : 0x00888001);
+       switch (dev_priv->chipset) {
+       case 0x47:
+       case 0x49:
+       case 0x4b:
+               cp_ctx(ctx, 0x402c20, 40);
+               for (i = 0; i < 32; i++)
+                       gr_def(ctx, 0x402c40 + (i * 4), 0xffffffff);
+               cp_ctx(ctx, 0x4030b8, 13);
+               gr_def(ctx, 0x4030dc, 0x00000005);
+               gr_def(ctx, 0x4030e8, 0x0000ffff);
+               break;
+       default:
+               cp_ctx(ctx, 0x402c10, 4);
+               if (dev_priv->chipset == 0x40)
+                       cp_ctx(ctx, 0x402c20, 36);
+               else
+               if (dev_priv->chipset <= 0x42)
+                       cp_ctx(ctx, 0x402c20, 24);
+               else
+               if (dev_priv->chipset <= 0x4a)
+                       cp_ctx(ctx, 0x402c20, 16);
+               else
+                       cp_ctx(ctx, 0x402c20, 8);
+               cp_ctx(ctx, 0x402cb0, dev_priv->chipset == 0x40 ? 12 : 13);
+               gr_def(ctx, 0x402cd4, 0x00000005);
+               if (dev_priv->chipset != 0x40)
+                       gr_def(ctx, 0x402ce0, 0x0000ffff);
+               break;
+       }
+
+       cp_ctx(ctx, 0x403400, dev_priv->chipset == 0x40 ? 4 : 3);
+       cp_ctx(ctx, 0x403410, dev_priv->chipset == 0x40 ? 4 : 3);
+       cp_ctx(ctx, 0x403420, nv40_graph_vs_count(ctx->dev));
+       for (i = 0; i < nv40_graph_vs_count(ctx->dev); i++)
+               gr_def(ctx, 0x403420 + (i * 4), 0x00005555);
+
+       if (dev_priv->chipset != 0x40) {
+               cp_ctx(ctx, 0x403600, 1);
+               gr_def(ctx, 0x403600, 0x00000001);
+       }
+       cp_ctx(ctx, 0x403800, 1);
+
+       cp_ctx(ctx, 0x403c18, 1);
+       gr_def(ctx, 0x403c18, 0x00000001);
+       switch (dev_priv->chipset) {
+       case 0x46:
+       case 0x47:
+       case 0x49:
+       case 0x4b:
+               cp_ctx(ctx, 0x405018, 1);
+               gr_def(ctx, 0x405018, 0x08e00001);
+               cp_ctx(ctx, 0x405c24, 1);
+               gr_def(ctx, 0x405c24, 0x000e3000);
+               break;
+       }
+       if (dev_priv->chipset != 0x4e)
+               cp_ctx(ctx, 0x405800, 11);
+       cp_ctx(ctx, 0x407000, 1);
+}
+
+static void
+nv40_graph_construct_state3d_3(struct nouveau_grctx *ctx)
+{
+       int len = nv40_graph_4097(ctx->dev) ? 0x0684 : 0x0084;
+
+       cp_out (ctx, 0x300000);
+       cp_lsr (ctx, len - 4);
+       cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_swap_state3d_3_is_save);
+       cp_lsr (ctx, len);
+       cp_name(ctx, cp_swap_state3d_3_is_save);
+       cp_out (ctx, 0x800001);
+
+       ctx->ctxvals_pos += len;
+}
+
+static void
+nv40_graph_construct_shader(struct nouveau_grctx *ctx)
+{
+       struct drm_device *dev = ctx->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *obj = ctx->data;
+       int vs, vs_nr, vs_len, vs_nr_b0, vs_nr_b1, b0_offset, b1_offset;
+       int offset, i;
+
+       vs_nr    = nv40_graph_vs_count(ctx->dev);
+       vs_nr_b0 = 363;
+       vs_nr_b1 = dev_priv->chipset == 0x40 ? 128 : 64;
+       if (dev_priv->chipset == 0x40) {
+               b0_offset = 0x2200/4; /* 33a0 */
+               b1_offset = 0x55a0/4; /* 1500 */
+               vs_len = 0x6aa0/4;
+       } else
+       if (dev_priv->chipset == 0x41 || dev_priv->chipset == 0x42) {
+               b0_offset = 0x2200/4; /* 2200 */
+               b1_offset = 0x4400/4; /* 0b00 */
+               vs_len = 0x4f00/4;
+       } else {
+               b0_offset = 0x1d40/4; /* 2200 */
+               b1_offset = 0x3f40/4; /* 0b00 : 0a40 */
+               vs_len = nv40_graph_4097(dev) ? 0x4a40/4 : 0x4980/4;
+       }
+
+       cp_lsr(ctx, vs_len * vs_nr + 0x300/4);
+       cp_out(ctx, nv40_graph_4097(dev) ? 0x800041 : 0x800029);
+
+       offset = ctx->ctxvals_pos;
+       ctx->ctxvals_pos += (0x0300/4 + (vs_nr * vs_len));
+
+       if (ctx->mode != NOUVEAU_GRCTX_VALS)
+               return;
+
+       offset += 0x0280/4;
+       for (i = 0; i < 16; i++, offset += 2)
+               nv_wo32(dev, obj, offset, 0x3f800000);
+
+       for (vs = 0; vs < vs_nr; vs++, offset += vs_len) {
+               for (i = 0; i < vs_nr_b0 * 6; i += 6)
+                       nv_wo32(dev, obj, offset + b0_offset + i, 0x00000001);
+               for (i = 0; i < vs_nr_b1 * 4; i += 4)
+                       nv_wo32(dev, obj, offset + b1_offset + i, 0x3f800000);
+       }
+}
+
+void
+nv40_grctx_init(struct nouveau_grctx *ctx)
+{
+       /* decide whether we're loading/unloading the context */
+       cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save);
+       cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save);
+
+       cp_name(ctx, cp_check_load);
+       cp_bra (ctx, AUTO_LOAD, PENDING, cp_setup_auto_load);
+       cp_bra (ctx, USER_LOAD, PENDING, cp_setup_load);
+       cp_bra (ctx, ALWAYS, TRUE, cp_exit);
+
+       /* setup for context load */
+       cp_name(ctx, cp_setup_auto_load);
+       cp_wait(ctx, STATUS, IDLE);
+       cp_out (ctx, CP_NEXT_TO_SWAP);
+       cp_name(ctx, cp_setup_load);
+       cp_wait(ctx, STATUS, IDLE);
+       cp_set (ctx, SWAP_DIRECTION, LOAD);
+       cp_out (ctx, 0x00910880); /* ?? */
+       cp_out (ctx, 0x00901ffe); /* ?? */
+       cp_out (ctx, 0x01940000); /* ?? */
+       cp_lsr (ctx, 0x20);
+       cp_out (ctx, 0x0060000b); /* ?? */
+       cp_wait(ctx, UNK57, CLEAR);
+       cp_out (ctx, 0x0060000c); /* ?? */
+       cp_bra (ctx, ALWAYS, TRUE, cp_swap_state);
+
+       /* setup for context save */
+       cp_name(ctx, cp_setup_save);
+       cp_set (ctx, SWAP_DIRECTION, SAVE);
+
+       /* general PGRAPH state */
+       cp_name(ctx, cp_swap_state);
+       cp_pos (ctx, 0x00020/4);
+       nv40_graph_construct_general(ctx);
+       cp_wait(ctx, STATUS, IDLE);
+
+       /* 3D state, block 1 */
+       cp_bra (ctx, UNK54, CLEAR, cp_prepare_exit);
+       nv40_graph_construct_state3d(ctx);
+       cp_wait(ctx, STATUS, IDLE);
+
+       /* 3D state, block 2 */
+       nv40_graph_construct_state3d_2(ctx);
+
+       /* Some other block of "random" state */
+       nv40_graph_construct_state3d_3(ctx);
+
+       /* Per-vertex shader state */
+       cp_pos (ctx, ctx->ctxvals_pos);
+       nv40_graph_construct_shader(ctx);
+
+       /* pre-exit state updates */
+       cp_name(ctx, cp_prepare_exit);
+       cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_check_load);
+       cp_bra (ctx, USER_SAVE, PENDING, cp_exit);
+       cp_out (ctx, CP_NEXT_TO_CURRENT);
+
+       cp_name(ctx, cp_exit);
+       cp_set (ctx, USER_SAVE, NOT_PENDING);
+       cp_set (ctx, USER_LOAD, NOT_PENDING);
+       cp_out (ctx, CP_END);
+}
+
index f8e28a1..118d328 100644 (file)
@@ -45,7 +45,7 @@ nv50_crtc_lut_load(struct drm_crtc *crtc)
        void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo);
        int i;
 
-       NV_DEBUG(crtc->dev, "\n");
+       NV_DEBUG_KMS(crtc->dev, "\n");
 
        for (i = 0; i < 256; i++) {
                writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0);
@@ -68,8 +68,8 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked)
        struct nouveau_channel *evo = dev_priv->evo;
        int index = nv_crtc->index, ret;
 
-       NV_DEBUG(dev, "index %d\n", nv_crtc->index);
-       NV_DEBUG(dev, "%s\n", blanked ? "blanked" : "unblanked");
+       NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
+       NV_DEBUG_KMS(dev, "%s\n", blanked ? "blanked" : "unblanked");
 
        if (blanked) {
                nv_crtc->cursor.hide(nv_crtc, false);
@@ -139,7 +139,7 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update)
        struct nouveau_channel *evo = dev_priv->evo;
        int ret;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        ret = RING_SPACE(evo, 2 + (update ? 2 : 0));
        if (ret) {
@@ -193,7 +193,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update)
        uint32_t outX, outY, horiz, vert;
        int ret;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        switch (scaling_mode) {
        case DRM_MODE_SCALE_NONE:
@@ -301,7 +301,7 @@ nv50_crtc_destroy(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        if (!crtc)
                return;
@@ -433,7 +433,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct drm_encoder *encoder;
 
-       NV_DEBUG(dev, "index %d\n", nv_crtc->index);
+       NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
        /* Disconnect all unused encoders. */
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@@ -458,7 +458,7 @@ nv50_crtc_commit(struct drm_crtc *crtc)
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        int ret;
 
-       NV_DEBUG(dev, "index %d\n", nv_crtc->index);
+       NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
        nv50_crtc_blank(nv_crtc, false);
 
@@ -497,7 +497,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y,
        struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
        int ret, format;
 
-       NV_DEBUG(dev, "index %d\n", nv_crtc->index);
+       NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
        switch (drm_fb->depth) {
        case  8:
@@ -612,7 +612,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 
        *nv_crtc->mode = *adjusted_mode;
 
-       NV_DEBUG(dev, "index %d\n", nv_crtc->index);
+       NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
        hsync_dur = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
        vsync_dur = adjusted_mode->vsync_end - adjusted_mode->vsync_start;
@@ -706,7 +706,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
        struct nouveau_crtc *nv_crtc = NULL;
        int ret, i;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
        if (!nv_crtc)
index e2e79a8..753e723 100644 (file)
@@ -41,7 +41,7 @@ nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update)
        struct drm_device *dev = nv_crtc->base.dev;
        int ret;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        if (update && nv_crtc->cursor.visible)
                return;
@@ -76,7 +76,7 @@ nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
        struct drm_device *dev = nv_crtc->base.dev;
        int ret;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        if (update && !nv_crtc->cursor.visible)
                return;
@@ -116,7 +116,7 @@ nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
 static void
 nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
 {
-       NV_DEBUG(nv_crtc->base.dev, "\n");
+       NV_DEBUG_KMS(nv_crtc->base.dev, "\n");
        if (offset == nv_crtc->cursor.offset)
                return;
 
@@ -143,7 +143,7 @@ nv50_cursor_fini(struct nouveau_crtc *nv_crtc)
        struct drm_device *dev = nv_crtc->base.dev;
        int idx = nv_crtc->index;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0);
        if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx),
index fb5838e..f08f042 100644 (file)
@@ -44,7 +44,7 @@ nv50_dac_disconnect(struct nouveau_encoder *nv_encoder)
        struct nouveau_channel *evo = dev_priv->evo;
        int ret;
 
-       NV_DEBUG(dev, "Disconnecting DAC %d\n", nv_encoder->or);
+       NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or);
 
        ret = RING_SPACE(evo, 2);
        if (ret) {
@@ -81,11 +81,11 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
        /* Use bios provided value if possible. */
        if (dev_priv->vbios->dactestval) {
                load_pattern = dev_priv->vbios->dactestval;
-               NV_DEBUG(dev, "Using bios provided load_pattern of %d\n",
+               NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n",
                          load_pattern);
        } else {
                load_pattern = 340;
-               NV_DEBUG(dev, "Using default load_pattern of %d\n",
+               NV_DEBUG_KMS(dev, "Using default load_pattern of %d\n",
                         load_pattern);
        }
 
@@ -103,9 +103,9 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
                status = connector_status_connected;
 
        if (status == connector_status_connected)
-               NV_DEBUG(dev, "Load was detected on output with or %d\n", or);
+               NV_DEBUG_KMS(dev, "Load was detected on output with or %d\n", or);
        else
-               NV_DEBUG(dev, "Load was not detected on output with or %d\n", or);
+               NV_DEBUG_KMS(dev, "Load was not detected on output with or %d\n", or);
 
        return status;
 }
@@ -118,7 +118,7 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode)
        uint32_t val;
        int or = nv_encoder->or;
 
-       NV_DEBUG(dev, "or %d mode %d\n", or, mode);
+       NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);
 
        /* wait for it to be done */
        if (!nv_wait(NV50_PDISPLAY_DAC_DPMS_CTRL(or),
@@ -173,7 +173,7 @@ nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct nouveau_connector *connector;
 
-       NV_DEBUG(encoder->dev, "or %d\n", nv_encoder->or);
+       NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or);
 
        connector = nouveau_encoder_connector_get(nv_encoder);
        if (!connector) {
@@ -213,7 +213,7 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        uint32_t mode_ctl = 0, mode_ctl2 = 0;
        int ret;
 
-       NV_DEBUG(dev, "or %d\n", nv_encoder->or);
+       NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or);
 
        nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON);
 
@@ -264,7 +264,7 @@ nv50_dac_destroy(struct drm_encoder *encoder)
        if (!encoder)
                return;
 
-       NV_DEBUG(encoder->dev, "\n");
+       NV_DEBUG_KMS(encoder->dev, "\n");
 
        drm_encoder_cleanup(encoder);
        kfree(nv_encoder);
@@ -280,7 +280,7 @@ nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry)
        struct nouveau_encoder *nv_encoder;
        struct drm_encoder *encoder;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
        NV_INFO(dev, "Detected a DAC output\n");
 
        nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
index 12c5ee6..a9263d9 100644 (file)
@@ -188,7 +188,7 @@ nv50_display_init(struct drm_device *dev)
        uint64_t start;
        int ret, i;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004));
        /*
@@ -232,7 +232,7 @@ nv50_display_init(struct drm_device *dev)
        nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0);
        /* RAM is clamped to 256 MiB. */
        ram_amount = nouveau_mem_fb_amount(dev);
-       NV_DEBUG(dev, "ram_amount %d\n", ram_amount);
+       NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount);
        if (ram_amount > 256*1024*1024)
                ram_amount = 256*1024*1024;
        nv_wr32(dev, NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1);
@@ -398,7 +398,7 @@ static int nv50_display_disable(struct drm_device *dev)
        struct drm_crtc *drm_crtc;
        int ret, i;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc);
@@ -469,7 +469,7 @@ int nv50_display_create(struct drm_device *dev)
        uint32_t connector[16] = {};
        int ret, i;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        /* init basic kernel modesetting */
        drm_mode_config_init(dev);
@@ -573,7 +573,7 @@ int nv50_display_destroy(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        drm_mode_config_cleanup(dev);
 
@@ -617,7 +617,7 @@ nv50_display_irq_head(struct drm_device *dev, int *phead,
         * CRTC separately, and submission will be blocked by the GPU
         * until we handle each in turn.
         */
-       NV_DEBUG(dev, "0x610030: 0x%08x\n", unk30);
+       NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
        head = ffs((unk30 >> 9) & 3) - 1;
        if (head < 0)
                return -EINVAL;
@@ -661,7 +661,7 @@ nv50_display_irq_head(struct drm_device *dev, int *phead,
                or = i;
        }
 
-       NV_DEBUG(dev, "type %d, or %d\n", type, or);
+       NV_DEBUG_KMS(dev, "type %d, or %d\n", type, or);
        if (type == OUTPUT_ANY) {
                NV_ERROR(dev, "unknown encoder!!\n");
                return -1;
@@ -811,7 +811,7 @@ nv50_display_unk20_handler(struct drm_device *dev)
        pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff;
        script = nv50_display_script_select(dev, dcbent, pclk);
 
-       NV_DEBUG(dev, "head %d pxclk: %dKHz\n", head, pclk);
+       NV_DEBUG_KMS(dev, "head %d pxclk: %dKHz\n", head, pclk);
 
        if (dcbent->type != OUTPUT_DP)
                nouveau_bios_run_display_table(dev, dcbent, 0, -2);
@@ -870,7 +870,7 @@ nv50_display_irq_handler_bh(struct work_struct *work)
                uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0);
                uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1);
 
-               NV_DEBUG(dev, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1);
+               NV_DEBUG_KMS(dev, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1);
 
                if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK10)
                        nv50_display_unk10_handler(dev);
@@ -974,7 +974,7 @@ nv50_display_irq_handler(struct drm_device *dev)
                uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1);
                uint32_t clock;
 
-               NV_DEBUG(dev, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1);
+               NV_DEBUG_KMS(dev, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1);
 
                if (!intr0 && !(intr1 & ~delayed))
                        break;
index 77ae1aa..b728228 100644 (file)
@@ -416,7 +416,7 @@ nv50_fifo_unload_context(struct drm_device *dev)
        NV_DEBUG(dev, "\n");
 
        chid = pfifo->channel_id(dev);
-       if (chid < 0 || chid >= dev_priv->engine.fifo.channels)
+       if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1)
                return 0;
 
        chan = dev_priv->fifos[chid];
index 177d822..ca79f32 100644 (file)
@@ -107,9 +107,13 @@ nv50_graph_init_regs(struct drm_device *dev)
 static int
 nv50_graph_init_ctxctl(struct drm_device *dev)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
        NV_DEBUG(dev, "\n");
 
-       nv40_grctx_init(dev);
+       nouveau_grctx_prog_load(dev);
+       if (!dev_priv->engine.graph.ctxprog)
+               dev_priv->engine.graph.accel_blocked = true;
 
        nv_wr32(dev, 0x400320, 4);
        nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
@@ -140,7 +144,7 @@ void
 nv50_graph_takedown(struct drm_device *dev)
 {
        NV_DEBUG(dev, "\n");
-       nv40_grctx_fini(dev);
+       nouveau_grctx_fini(dev);
 }
 
 void
@@ -207,7 +211,7 @@ nv50_graph_create_context(struct nouveau_channel *chan)
        dev_priv->engine.instmem.finish_access(dev);
 
        dev_priv->engine.instmem.prepare_access(dev, true);
-       nv40_grctx_vals_load(dev, ctx);
+       nouveau_grctx_vals_load(dev, ctx);
        nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12);
        if ((dev_priv->chipset & 0xf0) == 0xa0)
                nv_wo32(dev, ctx, 0x00004/4, 0x00000000);
index 8c28046..e395c16 100644 (file)
@@ -44,7 +44,7 @@ nv50_sor_disconnect(struct nouveau_encoder *nv_encoder)
        struct nouveau_channel *evo = dev_priv->evo;
        int ret;
 
-       NV_DEBUG(dev, "Disconnecting SOR %d\n", nv_encoder->or);
+       NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or);
 
        ret = RING_SPACE(evo, 2);
        if (ret) {
@@ -70,7 +70,7 @@ nv50_sor_dp_link_train(struct drm_encoder *encoder)
        }
 
        if (dpe->script0) {
-               NV_DEBUG(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
+               NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
                nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0),
                                            nv_encoder->dcb);
        }
@@ -79,7 +79,7 @@ nv50_sor_dp_link_train(struct drm_encoder *encoder)
                NV_ERROR(dev, "SOR-%d: link training failed\n", nv_encoder->or);
 
        if (dpe->script1) {
-               NV_DEBUG(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
+               NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
                nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1),
                                            nv_encoder->dcb);
        }
@@ -93,7 +93,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
        uint32_t val;
        int or = nv_encoder->or;
 
-       NV_DEBUG(dev, "or %d mode %d\n", or, mode);
+       NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);
 
        /* wait for it to be done */
        if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or),
@@ -142,7 +142,7 @@ nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct nouveau_connector *connector;
 
-       NV_DEBUG(encoder->dev, "or %d\n", nv_encoder->or);
+       NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or);
 
        connector = nouveau_encoder_connector_get(nv_encoder);
        if (!connector) {
@@ -182,7 +182,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        uint32_t mode_ctl = 0;
        int ret;
 
-       NV_DEBUG(dev, "or %d\n", nv_encoder->or);
+       NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or);
 
        nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
 
@@ -246,7 +246,7 @@ nv50_sor_destroy(struct drm_encoder *encoder)
        if (!encoder)
                return;
 
-       NV_DEBUG(encoder->dev, "\n");
+       NV_DEBUG_KMS(encoder->dev, "\n");
 
        drm_encoder_cleanup(encoder);
 
@@ -265,7 +265,7 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
        bool dum;
        int type;
 
-       NV_DEBUG(dev, "\n");
+       NV_DEBUG_KMS(dev, "\n");
 
        switch (entry->type) {
        case OUTPUT_TMDS:
index 601f4c0..b806fdc 100644 (file)
@@ -64,7 +64,7 @@ static struct drm_driver driver = {
                .owner = THIS_MODULE,
                .open = drm_open,
                .release = drm_release,
-               .ioctl = drm_ioctl,
+               .unlocked_ioctl = drm_ioctl,
                .mmap = drm_mmap,
                .poll = drm_poll,
                .fasync = drm_fasync,
index d3cb676..51c99fc 100644 (file)
@@ -95,8 +95,7 @@ static int compat_r128_init(struct file *file, unsigned int cmd,
                          &init->agp_textures_offset))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_R128_INIT, (unsigned long)init);
+       return drm_ioctl(file, DRM_IOCTL_R128_INIT, (unsigned long)init);
 }
 
 typedef struct drm_r128_depth32 {
@@ -129,8 +128,7 @@ static int compat_r128_depth(struct file *file, unsigned int cmd,
                          &depth->mask))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
+       return drm_ioctl(file, DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
 
 }
 
@@ -153,8 +151,7 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd,
                          &stipple->mask))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
+       return drm_ioctl(file, DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
 }
 
 typedef struct drm_r128_getparam32 {
@@ -178,8 +175,7 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd,
                          &getparam->value))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
+       return drm_ioctl(file, DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
 }
 
 drm_ioctl_compat_t *r128_compat_ioctls[] = {
@@ -210,12 +206,10 @@ long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls))
                fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE];
 
-       lock_kernel();          /* XXX for now */
        if (fn != NULL)
                ret = (*fn) (filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
+               ret = drm_ioctl(filp, cmd, arg);
 
        return ret;
 }
index 6578d19..388140a 100644 (file)
@@ -58,6 +58,7 @@ typedef struct {
 } atom_exec_context;
 
 int atom_debug = 0;
+static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params);
 void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params);
 
 static uint32_t atom_arg_mask[8] =
@@ -573,7 +574,7 @@ static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg)
        else
                SDEBUG("   table: %d\n", idx);
        if (U16(ctx->ctx->cmd_table + 4 + 2 * idx))
-               atom_execute_table(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
+               atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
 }
 
 static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg)
@@ -1040,7 +1041,7 @@ static struct {
        atom_op_shr, ATOM_ARG_MC}, {
 atom_op_debug, 0},};
 
-void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
+static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params)
 {
        int base = CU16(ctx->cmd_table + 4 + 2 * index);
        int len, ws, ps, ptr;
@@ -1092,6 +1093,13 @@ void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
                kfree(ectx.ws);
 }
 
+void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
+{
+       mutex_lock(&ctx->mutex);
+       atom_execute_table_locked(ctx, index, params);
+       mutex_unlock(&ctx->mutex);
+}
+
 static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
 
 static void atom_index_iio(struct atom_context *ctx, int base)
index 6671848..47fd943 100644 (file)
@@ -120,6 +120,7 @@ struct card_info {
 
 struct atom_context {
        struct card_info *card;
+       struct mutex mutex;
        void *bios;
        uint32_t cmd_table, data_table;
        uint16_t *iio;
index 5f48515..91ad0d1 100644 (file)
@@ -4690,6 +4690,205 @@ typedef struct _ATOM_POWERPLAY_INFO_V3 {
        ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
 } ATOM_POWERPLAY_INFO_V3;
 
+/* New PPlib */
+/**************************************************************************/
+typedef struct _ATOM_PPLIB_THERMALCONTROLLER
+
+{
+    UCHAR ucType;           // one of ATOM_PP_THERMALCONTROLLER_*
+    UCHAR ucI2cLine;        // as interpreted by DAL I2C
+    UCHAR ucI2cAddress;
+    UCHAR ucFanParameters;  // Fan Control Parameters.
+    UCHAR ucFanMinRPM;      // Fan Minimum RPM (hundreds) -- for display purposes only.
+    UCHAR ucFanMaxRPM;      // Fan Maximum RPM (hundreds) -- for display purposes only.
+    UCHAR ucReserved;       // ----
+    UCHAR ucFlags;          // to be defined
+} ATOM_PPLIB_THERMALCONTROLLER;
+
+#define ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f
+#define ATOM_PP_FANPARAMETERS_NOFAN                                 0x80    // No fan is connected to this controller.
+
+#define ATOM_PP_THERMALCONTROLLER_NONE      0
+#define ATOM_PP_THERMALCONTROLLER_LM63      1  // Not used by PPLib
+#define ATOM_PP_THERMALCONTROLLER_ADM1032   2  // Not used by PPLib
+#define ATOM_PP_THERMALCONTROLLER_ADM1030   3  // Not used by PPLib
+#define ATOM_PP_THERMALCONTROLLER_MUA6649   4  // Not used by PPLib
+#define ATOM_PP_THERMALCONTROLLER_LM64      5
+#define ATOM_PP_THERMALCONTROLLER_F75375    6  // Not used by PPLib
+#define ATOM_PP_THERMALCONTROLLER_RV6xx     7
+#define ATOM_PP_THERMALCONTROLLER_RV770     8
+#define ATOM_PP_THERMALCONTROLLER_ADT7473   9
+
+typedef struct _ATOM_PPLIB_STATE
+{
+    UCHAR ucNonClockStateIndex;
+    UCHAR ucClockStateIndices[1]; // variable-sized
+} ATOM_PPLIB_STATE;
+
+//// ATOM_PPLIB_POWERPLAYTABLE::ulPlatformCaps
+#define ATOM_PP_PLATFORM_CAP_BACKBIAS 1
+#define ATOM_PP_PLATFORM_CAP_POWERPLAY 2
+#define ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 4
+#define ATOM_PP_PLATFORM_CAP_ASPM_L0s 8
+#define ATOM_PP_PLATFORM_CAP_ASPM_L1 16
+#define ATOM_PP_PLATFORM_CAP_HARDWAREDC 32
+#define ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY 64
+#define ATOM_PP_PLATFORM_CAP_STEPVDDC 128
+#define ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL 256
+#define ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL 512
+#define ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 1024
+#define ATOM_PP_PLATFORM_CAP_HTLINKCONTROL 2048
+
+typedef struct _ATOM_PPLIB_POWERPLAYTABLE
+{
+      ATOM_COMMON_TABLE_HEADER sHeader;
+
+      UCHAR ucDataRevision;
+
+      UCHAR ucNumStates;
+      UCHAR ucStateEntrySize;
+      UCHAR ucClockInfoSize;
+      UCHAR ucNonClockSize;
+
+      // offset from start of this table to array of ucNumStates ATOM_PPLIB_STATE structures
+      USHORT usStateArrayOffset;
+
+      // offset from start of this table to array of ASIC-specific structures,
+      // currently ATOM_PPLIB_CLOCK_INFO.
+      USHORT usClockInfoArrayOffset;
+
+      // offset from start of this table to array of ATOM_PPLIB_NONCLOCK_INFO
+      USHORT usNonClockInfoArrayOffset;
+
+      USHORT usBackbiasTime;    // in microseconds
+      USHORT usVoltageTime;     // in microseconds
+      USHORT usTableSize;       //the size of this structure, or the extended structure
+
+      ULONG ulPlatformCaps;            // See ATOM_PPLIB_CAPS_*
+
+      ATOM_PPLIB_THERMALCONTROLLER    sThermalController;
+
+      USHORT usBootClockInfoOffset;
+      USHORT usBootNonClockInfoOffset;
+
+} ATOM_PPLIB_POWERPLAYTABLE;
+
+//// ATOM_PPLIB_NONCLOCK_INFO::usClassification
+#define ATOM_PPLIB_CLASSIFICATION_UI_MASK          0x0007
+#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT         0
+#define ATOM_PPLIB_CLASSIFICATION_UI_NONE          0
+#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY       1
+#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED      3
+#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE   5
+// 2, 4, 6, 7 are reserved
+
+#define ATOM_PPLIB_CLASSIFICATION_BOOT                   0x0008
+#define ATOM_PPLIB_CLASSIFICATION_THERMAL                0x0010
+#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE     0x0020
+#define ATOM_PPLIB_CLASSIFICATION_REST                   0x0040
+#define ATOM_PPLIB_CLASSIFICATION_FORCED                 0x0080
+#define ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE          0x0100
+#define ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE      0x0200
+#define ATOM_PPLIB_CLASSIFICATION_UVDSTATE               0x0400
+#define ATOM_PPLIB_CLASSIFICATION_3DLOW                  0x0800
+#define ATOM_PPLIB_CLASSIFICATION_ACPI                   0x1000
+// remaining 3 bits are reserved
+
+//// ATOM_PPLIB_NONCLOCK_INFO::ulCapsAndSettings
+#define ATOM_PPLIB_SINGLE_DISPLAY_ONLY           0x00000001
+#define ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK         0x00000002
+
+// 0 is 2.5Gb/s, 1 is 5Gb/s
+#define ATOM_PPLIB_PCIE_LINK_SPEED_MASK            0x00000004
+#define ATOM_PPLIB_PCIE_LINK_SPEED_SHIFT           2
+
+// lanes - 1: 1, 2, 4, 8, 12, 16 permitted by PCIE spec
+#define ATOM_PPLIB_PCIE_LINK_WIDTH_MASK            0x000000F8
+#define ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT           3
+
+// lookup into reduced refresh-rate table
+#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK  0x00000F00
+#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT 8
+
+#define ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED    0
+#define ATOM_PPLIB_LIMITED_REFRESHRATE_50HZ         1
+// 2-15 TBD as needed.
+
+#define ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING        0x00001000
+#define ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS  0x00002000
+#define ATOM_PPLIB_ENABLE_VARIBRIGHT                     0x00008000
+
+#define ATOM_PPLIB_DISALLOW_ON_DC                       0x00004000
+
+// Contained in an array starting at the offset
+// in ATOM_PPLIB_POWERPLAYTABLE::usNonClockInfoArrayOffset.
+// referenced from ATOM_PPLIB_STATE_INFO::ucNonClockStateIndex
+typedef struct _ATOM_PPLIB_NONCLOCK_INFO
+{
+      USHORT usClassification;
+      UCHAR  ucMinTemperature;
+      UCHAR  ucMaxTemperature;
+      ULONG  ulCapsAndSettings;
+      UCHAR  ucRequiredPower;
+      UCHAR  ucUnused1[3];
+} ATOM_PPLIB_NONCLOCK_INFO;
+
+// Contained in an array starting at the offset
+// in ATOM_PPLIB_POWERPLAYTABLE::usClockInfoArrayOffset.
+// referenced from ATOM_PPLIB_STATE::ucClockStateIndices
+typedef struct _ATOM_PPLIB_R600_CLOCK_INFO
+{
+      USHORT usEngineClockLow;
+      UCHAR ucEngineClockHigh;
+
+      USHORT usMemoryClockLow;
+      UCHAR ucMemoryClockHigh;
+
+      USHORT usVDDC;
+      USHORT usUnused1;
+      USHORT usUnused2;
+
+      ULONG ulFlags; // ATOM_PPLIB_R600_FLAGS_*
+
+} ATOM_PPLIB_R600_CLOCK_INFO;
+
+// ulFlags in ATOM_PPLIB_R600_CLOCK_INFO
+#define ATOM_PPLIB_R600_FLAGS_PCIEGEN2          1
+#define ATOM_PPLIB_R600_FLAGS_UVDSAFE           2
+#define ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE    4
+#define ATOM_PPLIB_R600_FLAGS_MEMORY_ODT_OFF    8
+#define ATOM_PPLIB_R600_FLAGS_MEMORY_DLL_OFF    16
+
+typedef struct _ATOM_PPLIB_RS780_CLOCK_INFO
+
+{
+      USHORT usLowEngineClockLow;         // Low Engine clock in MHz (the same way as on the R600).
+      UCHAR  ucLowEngineClockHigh;
+      USHORT usHighEngineClockLow;        // High Engine clock in MHz.
+      UCHAR  ucHighEngineClockHigh;
+      USHORT usMemoryClockLow;            // For now one of the ATOM_PPLIB_RS780_SPMCLK_XXXX constants.
+      UCHAR  ucMemoryClockHigh;           // Currentyl unused.
+      UCHAR  ucPadding;                   // For proper alignment and size.
+      USHORT usVDDC;                      // For the 780, use: None, Low, High, Variable
+      UCHAR  ucMaxHTLinkWidth;            // From SBIOS - {2, 4, 8, 16}
+      UCHAR  ucMinHTLinkWidth;            // From SBIOS - {2, 4, 8, 16}. Effective only if CDLW enabled. Minimum down stream width could be bigger as display BW requriement.
+      USHORT usHTLinkFreq;                // See definition ATOM_PPLIB_RS780_HTLINKFREQ_xxx or in MHz(>=200).
+      ULONG  ulFlags;
+} ATOM_PPLIB_RS780_CLOCK_INFO;
+
+#define ATOM_PPLIB_RS780_VOLTAGE_NONE       0
+#define ATOM_PPLIB_RS780_VOLTAGE_LOW        1
+#define ATOM_PPLIB_RS780_VOLTAGE_HIGH       2
+#define ATOM_PPLIB_RS780_VOLTAGE_VARIABLE   3
+
+#define ATOM_PPLIB_RS780_SPMCLK_NONE        0   // We cannot change the side port memory clock, leave it as it is.
+#define ATOM_PPLIB_RS780_SPMCLK_LOW         1
+#define ATOM_PPLIB_RS780_SPMCLK_HIGH        2
+
+#define ATOM_PPLIB_RS780_HTLINKFREQ_NONE       0
+#define ATOM_PPLIB_RS780_HTLINKFREQ_LOW        1
+#define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH       2
+
 /**************************************************************************/
 
 /*  Following definitions are for compatiblity issue in different SW components. */
index 84e5df7..7172746 100644 (file)
@@ -2881,6 +2881,10 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track)
 
        for (i = 0; i < track->num_cb; i++) {
                if (track->cb[i].robj == NULL) {
+                       if (!(track->fastfill || track->color_channel_mask ||
+                             track->blend_read_enable)) {
+                               continue;
+                       }
                        DRM_ERROR("[drm] No buffer for color buffer %d !\n", i);
                        return -EINVAL;
                }
index 7188c37..b27a699 100644 (file)
@@ -67,13 +67,15 @@ struct r100_cs_track {
        unsigned                        immd_dwords;
        unsigned                        num_arrays;
        unsigned                        max_indx;
+       unsigned                        color_channel_mask;
        struct r100_cs_track_array      arrays[11];
        struct r100_cs_track_cb         cb[R300_MAX_CB];
        struct r100_cs_track_cb         zb;
        struct r100_cs_track_texture    textures[R300_TRACK_MAX_TEXTURE];
        bool                            z_enabled;
        bool                            separate_cube;
-
+       bool                            fastfill;
+       bool                            blend_read_enable;
 };
 
 int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track);
index 83490c2..3f2cc9e 100644 (file)
@@ -887,6 +887,14 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                        track->textures[i].cpp = 1;
                        track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
                        break;
+               case R300_TX_FORMAT_ATI2N:
+                       if (p->rdev->family < CHIP_R420) {
+                               DRM_ERROR("Invalid texture format %u\n",
+                                         (idx_value & 0x1F));
+                               return -EINVAL;
+                       }
+                       /* The same rules apply as for DXT3/5. */
+                       /* Pass through. */
                case R300_TX_FORMAT_DXT3:
                case R300_TX_FORMAT_DXT5:
                        track->textures[i].cpp = 1;
@@ -951,6 +959,16 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                        track->textures[i].width_11 = tmp;
                        tmp = ((idx_value >> 16) & 1) << 11;
                        track->textures[i].height_11 = tmp;
+
+                       /* ATI1N */
+                       if (idx_value & (1 << 14)) {
+                               /* The same rules apply as for DXT1. */
+                               track->textures[i].compress_format =
+                                       R100_TRACK_COMP_DXT1;
+                       }
+               } else if (idx_value & (1 << 14)) {
+                       DRM_ERROR("Forbidden bit TXFORMAT_MSB\n");
+                       return -EINVAL;
                }
                break;
        case 0x4480:
@@ -992,6 +1010,18 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                }
                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
                break;
+       case 0x4e0c:
+               /* RB3D_COLOR_CHANNEL_MASK */
+               track->color_channel_mask = idx_value;
+               break;
+       case 0x4d1c:
+               /* ZB_BW_CNTL */
+               track->fastfill = !!(idx_value & (1 << 2));
+               break;
+       case 0x4e04:
+               /* RB3D_BLENDCNTL */
+               track->blend_read_enable = !!(idx_value & (1 << 2));
+               break;
        case 0x4be8:
                /* valid register only on RV530 */
                if (p->rdev->family == CHIP_RV530)
index cb2e470..34bffa0 100644 (file)
@@ -990,7 +990,7 @@ static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
        int sz;
        int addr;
        int type;
-       int clamp;
+       int isclamp;
        int stride;
        RING_LOCALS;
 
@@ -999,10 +999,10 @@ static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
        addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo;
 
        type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
-       clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
+       isclamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
 
        addr |= (type << 16);
-       addr |= (clamp << 17);
+       addr |= (isclamp << 17);
 
        stride = type ? 4 : 6;
 
index 4b7afef..1735a2b 100644 (file)
 #      define R300_TX_FORMAT_FL_I32                0x1B
 #      define R300_TX_FORMAT_FL_I32A32             0x1C
 #      define R300_TX_FORMAT_FL_R32G32B32A32       0x1D
+#      define R300_TX_FORMAT_ATI2N                 0x1F
        /* alpha modes, convenience mostly */
        /* if you have alpha, pick constant appropriate to the
           number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */
index 0d82076..44060b9 100644 (file)
@@ -170,7 +170,7 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
                          idx, relocs_chunk->length_dw);
                return -EINVAL;
        }
-       *cs_reloc = &p->relocs[0];
+       *cs_reloc = p->relocs;
        (*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32;
        (*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0];
        return 0;
@@ -717,7 +717,7 @@ static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
        if (p->chunk_relocs_idx == -1) {
                return 0;
        }
-       p->relocs = kcalloc(1, sizeof(struct radeon_cs_reloc), GFP_KERNEL);
+       p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL);
        if (p->relocs == NULL) {
                return -ENOMEM;
        }
index cd650fd..53b5560 100644 (file)
@@ -162,6 +162,7 @@ struct radeon_fence_driver {
        struct list_head                created;
        struct list_head                emited;
        struct list_head                signaled;
+       bool                            initialized;
 };
 
 struct radeon_fence {
@@ -202,8 +203,9 @@ struct radeon_surface_reg {
 struct radeon_mman {
        struct ttm_bo_global_ref        bo_global_ref;
        struct ttm_global_reference     mem_global_ref;
-       bool                            mem_global_referenced;
        struct ttm_bo_device            bdev;
+       bool                            mem_global_referenced;
+       bool                            initialized;
 };
 
 struct radeon_bo {
index 636116b..eb29217 100644 (file)
@@ -33,6 +33,7 @@
  */
 uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev);
 void radeon_legacy_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock);
+uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev);
 void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable);
 
 uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev);
@@ -106,7 +107,7 @@ static struct radeon_asic r100_asic = {
        .copy = &r100_copy_blit,
        .get_engine_clock = &radeon_legacy_get_engine_clock,
        .set_engine_clock = &radeon_legacy_set_engine_clock,
-       .get_memory_clock = NULL,
+       .get_memory_clock = &radeon_legacy_get_memory_clock,
        .set_memory_clock = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
@@ -166,7 +167,7 @@ static struct radeon_asic r300_asic = {
        .copy = &r100_copy_blit,
        .get_engine_clock = &radeon_legacy_get_engine_clock,
        .set_engine_clock = &radeon_legacy_set_engine_clock,
-       .get_memory_clock = NULL,
+       .get_memory_clock = &radeon_legacy_get_memory_clock,
        .set_memory_clock = NULL,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
@@ -259,7 +260,7 @@ static struct radeon_asic rs400_asic = {
        .copy = &r100_copy_blit,
        .get_engine_clock = &radeon_legacy_get_engine_clock,
        .set_engine_clock = &radeon_legacy_set_engine_clock,
-       .get_memory_clock = NULL,
+       .get_memory_clock = &radeon_legacy_get_memory_clock,
        .set_memory_clock = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
index 12a0c76..321044b 100644 (file)
@@ -745,8 +745,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
                else
                        radeon_add_legacy_encoder(dev,
                                                  radeon_get_encoder_id(dev,
-                                                                       (1 <<
-                                                                        i),
+                                                                       (1 << i),
                                                                        dac),
                                                  (1 << i));
        }
@@ -758,32 +757,30 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
                                if (bios_connectors[j].valid && (i != j)) {
                                        if (bios_connectors[i].line_mux ==
                                            bios_connectors[j].line_mux) {
-                                               if (((bios_connectors[i].
-                                                     devices &
-                                                     (ATOM_DEVICE_DFP_SUPPORT))
-                                                    && (bios_connectors[j].
-                                                        devices &
-                                                        (ATOM_DEVICE_CRT_SUPPORT)))
-                                                   ||
-                                                   ((bios_connectors[j].
-                                                     devices &
-                                                     (ATOM_DEVICE_DFP_SUPPORT))
-                                                    && (bios_connectors[i].
-                                                        devices &
-                                                        (ATOM_DEVICE_CRT_SUPPORT)))) {
-                                                       bios_connectors[i].
-                                                           devices |=
-                                                           bios_connectors[j].
-                                                           devices;
-                                                       bios_connectors[i].
-                                                           connector_type =
-                                                           DRM_MODE_CONNECTOR_DVII;
-                                                       if (bios_connectors[j].devices &
-                                                           (ATOM_DEVICE_DFP_SUPPORT))
+                                               /* make sure not to combine LVDS */
+                                               if (bios_connectors[i].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                                                       bios_connectors[i].line_mux = 53;
+                                                       bios_connectors[i].ddc_bus.valid = false;
+                                                       continue;
+                                               }
+                                               if (bios_connectors[j].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                                                       bios_connectors[j].line_mux = 53;
+                                                       bios_connectors[j].ddc_bus.valid = false;
+                                                       continue;
+                                               }
+                                               /* combine analog and digital for DVI-I */
+                                               if (((bios_connectors[i].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
+                                                    (bios_connectors[j].devices & (ATOM_DEVICE_CRT_SUPPORT))) ||
+                                                   ((bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
+                                                    (bios_connectors[i].devices & (ATOM_DEVICE_CRT_SUPPORT)))) {
+                                                       bios_connectors[i].devices |=
+                                                               bios_connectors[j].devices;
+                                                       bios_connectors[i].connector_type =
+                                                               DRM_MODE_CONNECTOR_DVII;
+                                                       if (bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT))
                                                                bios_connectors[i].hpd =
                                                                        bios_connectors[j].hpd;
-                                                       bios_connectors[j].
-                                                           valid = false;
+                                                       bios_connectors[j].valid = false;
                                                }
                                        }
                                }
@@ -1234,6 +1231,61 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
        return true;
 }
 
+enum radeon_tv_std
+radeon_atombios_get_tv_info(struct radeon_device *rdev)
+{
+       struct radeon_mode_info *mode_info = &rdev->mode_info;
+       int index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
+       uint16_t data_offset;
+       uint8_t frev, crev;
+       struct _ATOM_ANALOG_TV_INFO *tv_info;
+       enum radeon_tv_std tv_std = TV_STD_NTSC;
+
+       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
+
+       tv_info = (struct _ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
+
+       switch (tv_info->ucTV_BootUpDefaultStandard) {
+       case ATOM_TV_NTSC:
+               tv_std = TV_STD_NTSC;
+               DRM_INFO("Default TV standard: NTSC\n");
+               break;
+       case ATOM_TV_NTSCJ:
+               tv_std = TV_STD_NTSC_J;
+               DRM_INFO("Default TV standard: NTSC-J\n");
+               break;
+       case ATOM_TV_PAL:
+               tv_std = TV_STD_PAL;
+               DRM_INFO("Default TV standard: PAL\n");
+               break;
+       case ATOM_TV_PALM:
+               tv_std = TV_STD_PAL_M;
+               DRM_INFO("Default TV standard: PAL-M\n");
+               break;
+       case ATOM_TV_PALN:
+               tv_std = TV_STD_PAL_N;
+               DRM_INFO("Default TV standard: PAL-N\n");
+               break;
+       case ATOM_TV_PALCN:
+               tv_std = TV_STD_PAL_CN;
+               DRM_INFO("Default TV standard: PAL-CN\n");
+               break;
+       case ATOM_TV_PAL60:
+               tv_std = TV_STD_PAL_60;
+               DRM_INFO("Default TV standard: PAL-60\n");
+               break;
+       case ATOM_TV_SECAM:
+               tv_std = TV_STD_SECAM;
+               DRM_INFO("Default TV standard: SECAM\n");
+               break;
+       default:
+               tv_std = TV_STD_NTSC;
+               DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
+               break;
+       }
+       return tv_std;
+}
+
 struct radeon_encoder_tv_dac *
 radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
 {
@@ -1269,6 +1321,7 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
                dac = dac_info->ucDAC2_NTSC_DAC_Adjustment;
                tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
 
+               tv_dac->tv_std = radeon_atombios_get_tv_info(rdev);
        }
        return tv_dac;
 }
index b062109..812f24d 100644 (file)
@@ -62,7 +62,7 @@ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev)
 }
 
 /* 10 khz */
-static uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
+uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
 {
        struct radeon_pll *mpll = &rdev->clock.mpll;
        uint32_t fb_div, ref_div, post_div, mclk;
index c5021a3..fd94dbc 100644 (file)
@@ -634,11 +634,10 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
        return p_dac;
 }
 
-static enum radeon_tv_std
-radeon_combios_get_tv_info(struct radeon_encoder *encoder)
+enum radeon_tv_std
+radeon_combios_get_tv_info(struct radeon_device *rdev)
 {
-       struct drm_device *dev = encoder->base.dev;
-       struct radeon_device *rdev = dev->dev_private;
+       struct drm_device *dev = rdev->ddev;
        uint16_t tv_info;
        enum radeon_tv_std tv_std = TV_STD_NTSC;
 
@@ -779,7 +778,7 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
                        tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
                        found = 1;
                }
-               tv_dac->tv_std = radeon_combios_get_tv_info(encoder);
+               tv_dac->tv_std = radeon_combios_get_tv_info(rdev);
        }
        if (!found) {
                /* then check CRT table */
index 5eece18..2016156 100644 (file)
@@ -208,6 +208,18 @@ static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encode
                drm_mode_set_name(mode);
 
                DRM_DEBUG("Adding native panel mode %s\n", mode->name);
+       } else if (native_mode->hdisplay != 0 &&
+                  native_mode->vdisplay != 0) {
+               /* mac laptops without an edid */
+               /* Note that this is not necessarily the exact panel mode,
+                * but an approximation based on the cvt formula.  For these
+                * systems we should ideally read the mode info out of the
+                * registers or add a mode table, but this works and is much
+                * simpler.
+                */
+               mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
+               mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+               DRM_DEBUG("Adding cvt approximation of native panel mode %s\n", mode->name);
        }
        return mode;
 }
@@ -1171,7 +1183,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                      1);
                        drm_connector_attach_property(&radeon_connector->base,
                                                      rdev->mode_info.tv_std_property,
-                                                     1);
+                                                     radeon_atombios_get_tv_info(rdev));
                }
                break;
        case DRM_MODE_CONNECTOR_LVDS:
@@ -1315,7 +1327,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
                                                      1);
                        drm_connector_attach_property(&radeon_connector->base,
                                                      rdev->mode_info.tv_std_property,
-                                                     1);
+                                                     radeon_combios_get_tv_info(rdev));
                }
                break;
        case DRM_MODE_CONNECTOR_LVDS:
index 02bcdb1..7c68480 100644 (file)
@@ -391,6 +391,12 @@ int radeon_asic_init(struct radeon_device *rdev)
                /* FIXME: not supported yet */
                return -EINVAL;
        }
+
+       if (rdev->flags & RADEON_IS_IGP) {
+               rdev->asic->get_memory_clock = NULL;
+               rdev->asic->set_memory_clock = NULL;
+       }
+
        return 0;
 }
 
@@ -481,6 +487,7 @@ int radeon_atombios_init(struct radeon_device *rdev)
        atom_card_info->pll_write = cail_pll_write;
 
        rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios);
+       mutex_init(&rdev->mode_info.atom_context->mutex);
        radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
        atom_allocate_fb_scratch(rdev->mode_info.atom_context);
        return 0;
@@ -539,9 +546,72 @@ void radeon_agp_disable(struct radeon_device *rdev)
        }
 }
 
-/*
- * Radeon device.
- */
+void radeon_check_arguments(struct radeon_device *rdev)
+{
+       /* vramlimit must be a power of two */
+       switch (radeon_vram_limit) {
+       case 0:
+       case 4:
+       case 8:
+       case 16:
+       case 32:
+       case 64:
+       case 128:
+       case 256:
+       case 512:
+       case 1024:
+       case 2048:
+       case 4096:
+               break;
+       default:
+               dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n",
+                               radeon_vram_limit);
+               radeon_vram_limit = 0;
+               break;
+       }
+       radeon_vram_limit = radeon_vram_limit << 20;
+       /* gtt size must be power of two and greater or equal to 32M */
+       switch (radeon_gart_size) {
+       case 4:
+       case 8:
+       case 16:
+               dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n",
+                               radeon_gart_size);
+               radeon_gart_size = 512;
+               break;
+       case 32:
+       case 64:
+       case 128:
+       case 256:
+       case 512:
+       case 1024:
+       case 2048:
+       case 4096:
+               break;
+       default:
+               dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n",
+                               radeon_gart_size);
+               radeon_gart_size = 512;
+               break;
+       }
+       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+       /* AGP mode can only be -1, 1, 2, 4, 8 */
+       switch (radeon_agpmode) {
+       case -1:
+       case 0:
+       case 1:
+       case 2:
+       case 4:
+       case 8:
+               break;
+       default:
+               dev_warn(rdev->dev, "invalid AGP mode %d (valid mode: "
+                               "-1, 0, 1, 2, 4, 8)\n", radeon_agpmode);
+               radeon_agpmode = 0;
+               break;
+       }
+}
+
 int radeon_device_init(struct radeon_device *rdev,
                       struct drm_device *ddev,
                       struct pci_dev *pdev,
@@ -580,9 +650,9 @@ int radeon_device_init(struct radeon_device *rdev,
 
        /* Set asic functions */
        r = radeon_asic_init(rdev);
-       if (r) {
+       if (r)
                return r;
-       }
+       radeon_check_arguments(rdev);
 
        if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) {
                radeon_agp_disable(rdev);
index a133b83..91d72b7 100644 (file)
@@ -739,7 +739,7 @@ static struct drm_prop_enum_list radeon_tv_std_enum_list[] =
        { TV_STD_SECAM, "secam" },
 };
 
-int radeon_modeset_create_props(struct radeon_device *rdev)
+static int radeon_modeset_create_props(struct radeon_device *rdev)
 {
        int i, sz;
 
index dbd56ef..8ba3de7 100644 (file)
@@ -196,7 +196,7 @@ static struct drm_driver driver_old = {
                 .owner = THIS_MODULE,
                 .open = drm_open,
                 .release = drm_release,
-                .ioctl = drm_ioctl,
+                .unlocked_ioctl = drm_ioctl,
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
@@ -284,7 +284,7 @@ static struct drm_driver kms_driver = {
                 .owner = THIS_MODULE,
                 .open = drm_open,
                 .release = drm_release,
-                .ioctl = drm_ioctl,
+                .unlocked_ioctl = drm_ioctl,
                 .mmap = radeon_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
index 0d1d908..ccba95f 100644 (file)
@@ -233,6 +233,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
                if (!ASIC_IS_AVIVO(rdev)) {
                        adjusted_mode->hdisplay = mode->hdisplay;
                        adjusted_mode->vdisplay = mode->vdisplay;
+                       adjusted_mode->crtc_hdisplay = mode->hdisplay;
+                       adjusted_mode->crtc_vdisplay = mode->vdisplay;
                }
                adjusted_mode->base.id = mode_id;
        }
@@ -495,9 +497,9 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
                                args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
                        args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
                        if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                               if (dig->lvds_misc & (1 << 0))
+                               if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL)
                                        args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-                               if (dig->lvds_misc & (1 << 1))
+                               if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
                                        args.v1.ucMisc |= (1 << 1);
                        } else {
                                if (dig_connector->linkb)
@@ -524,18 +526,18 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
                        args.v2.ucTemporal = 0;
                        args.v2.ucFRC = 0;
                        if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                               if (dig->lvds_misc & (1 << 0))
+                               if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL)
                                        args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-                               if (dig->lvds_misc & (1 << 5)) {
+                               if (dig->lvds_misc & ATOM_PANEL_MISC_SPATIAL) {
                                        args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
-                                       if (dig->lvds_misc & (1 << 1))
+                                       if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
                                                args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
                                }
-                               if (dig->lvds_misc & (1 << 6)) {
+                               if (dig->lvds_misc & ATOM_PANEL_MISC_TEMPORAL) {
                                        args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
-                                       if (dig->lvds_misc & (1 << 1))
+                                       if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
                                                args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
-                                       if (((dig->lvds_misc >> 2) & 0x3) == 2)
+                                       if (((dig->lvds_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
                                                args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
                                }
                        } else {
index cb4cd97..4cdd8b4 100644 (file)
@@ -324,7 +324,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev)
        write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
        r = radeon_scratch_get(rdev, &rdev->fence_drv.scratch_reg);
        if (r) {
-               DRM_ERROR("Fence failed to get a scratch register.");
+               dev_err(rdev->dev, "fence failed to get scratch register\n");
                write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
                return r;
        }
@@ -335,9 +335,10 @@ int radeon_fence_driver_init(struct radeon_device *rdev)
        INIT_LIST_HEAD(&rdev->fence_drv.signaled);
        rdev->fence_drv.count_timeout = 0;
        init_waitqueue_head(&rdev->fence_drv.queue);
+       rdev->fence_drv.initialized = true;
        write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
        if (radeon_debugfs_fence_init(rdev)) {
-               DRM_ERROR("Failed to register debugfs file for fence !\n");
+               dev_err(rdev->dev, "fence debugfs file creation failed\n");
        }
        return 0;
 }
@@ -346,11 +347,13 @@ void radeon_fence_driver_fini(struct radeon_device *rdev)
 {
        unsigned long irq_flags;
 
+       if (!rdev->fence_drv.initialized)
+               return;
        wake_up_all(&rdev->fence_drv.queue);
        write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
        radeon_scratch_free(rdev, rdev->fence_drv.scratch_reg);
        write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
-       DRM_INFO("radeon: fence finalized\n");
+       rdev->fence_drv.initialized = false;
 }
 
 
index a1bf11d..48b7cea 100644 (file)
@@ -92,8 +92,7 @@ static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
                          &init->gart_textures_offset))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
+       return drm_ioctl(file, DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
 }
 
 typedef struct drm_radeon_clear32 {
@@ -125,8 +124,7 @@ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
                          &clr->depth_boxes))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
+       return drm_ioctl(file, DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
 }
 
 typedef struct drm_radeon_stipple32 {
@@ -149,8 +147,7 @@ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
                          &request->mask))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
 }
 
 typedef struct drm_radeon_tex_image32 {
@@ -204,8 +201,7 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
                          &image->data))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
 }
 
 typedef struct drm_radeon_vertex2_32 {
@@ -238,8 +234,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
                          &request->prim))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
 }
 
 typedef struct drm_radeon_cmd_buffer32 {
@@ -268,8 +263,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
                          &request->boxes))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
 }
 
 typedef struct drm_radeon_getparam32 {
@@ -293,8 +287,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
                          &request->value))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
 }
 
 typedef struct drm_radeon_mem_alloc32 {
@@ -322,8 +315,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
                          &request->region_offset))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
 }
 
 typedef struct drm_radeon_irq_emit32 {
@@ -345,8 +337,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
                          &request->irq_seq))
                return -EFAULT;
 
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
+       return drm_ioctl(file, DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
 }
 
 /* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
@@ -372,8 +363,7 @@ static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd,
                          &request->value))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request);
+       return drm_ioctl(file, DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request);
 }
 #else
 #define compat_radeon_cp_setparam NULL
@@ -413,12 +403,10 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls))
                fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE];
 
-       lock_kernel();          /* XXX for now */
        if (fn != NULL)
                ret = (*fn) (filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
+               ret = drm_ioctl(filp, cmd, arg);
 
        return ret;
 }
@@ -431,9 +419,7 @@ long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long
        if (nr < DRM_COMMAND_BASE)
                return drm_compat_ioctl(filp, cmd, arg);
 
-       lock_kernel();          /* XXX for now */
-       ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
+       ret = drm_ioctl(filp, cmd, arg);
 
        return ret;
 }
index b82ede9..cc27485 100644 (file)
@@ -43,8 +43,7 @@ static void radeon_overscan_setup(struct drm_crtc *crtc,
 }
 
 static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
-                                      struct drm_display_mode *mode,
-                                      struct drm_display_mode *adjusted_mode)
+                                      struct drm_display_mode *mode)
 {
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
@@ -1059,7 +1058,7 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,
        radeon_set_pll(crtc, adjusted_mode);
        radeon_overscan_setup(crtc, adjusted_mode);
        if (radeon_crtc->crtc_id == 0) {
-               radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode);
+               radeon_legacy_rmx_mode_set(crtc, adjusted_mode);
        } else {
                if (radeon_crtc->rmx_type != RMX_OFF) {
                        /* FIXME: only first crtc has rmx what should we
index df00515..981508f 100644 (file)
@@ -207,6 +207,8 @@ static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
                *adjusted_mode = *native_mode;
                adjusted_mode->hdisplay = mode->hdisplay;
                adjusted_mode->vdisplay = mode->vdisplay;
+               adjusted_mode->crtc_hdisplay = mode->hdisplay;
+               adjusted_mode->crtc_vdisplay = mode->vdisplay;
                adjusted_mode->base.id = mode_id;
        }
 
index 3dcbe13..402369d 100644 (file)
@@ -88,6 +88,7 @@ enum radeon_tv_std {
        TV_STD_SCART_PAL,
        TV_STD_SECAM,
        TV_STD_PAL_CN,
+       TV_STD_PAL_N,
 };
 
 /* radeon gpio-based i2c
@@ -395,6 +396,11 @@ struct radeon_framebuffer {
        struct drm_gem_object *obj;
 };
 
+extern enum radeon_tv_std
+radeon_combios_get_tv_info(struct radeon_device *rdev);
+extern enum radeon_tv_std
+radeon_atombios_get_tv_info(struct radeon_device *rdev);
+
 extern void radeon_connector_hotplug(struct drm_connector *connector);
 extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector);
 extern int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector,
index 391c973..9f5e2f9 100644 (file)
@@ -42,8 +42,8 @@ void radeon_test_moves(struct radeon_device *rdev)
        /* Number of tests =
         * (Total GTT - IB pool - writeback page - ring buffer) / test size
         */
-       n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE -
-            rdev->cp.ring_size) / size;
+       n = ((u32)(rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE -
+            rdev->cp.ring_size)) / size;
 
        gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
        if (!gtt_obj) {
index d7fd160..3b0c07b 100644 (file)
@@ -494,6 +494,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
                DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
                return r;
        }
+       rdev->mman.initialized = true;
        r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM,
                                rdev->mc.real_vram_size >> PAGE_SHIFT);
        if (r) {
@@ -541,6 +542,8 @@ void radeon_ttm_fini(struct radeon_device *rdev)
 {
        int r;
 
+       if (!rdev->mman.initialized)
+               return;
        if (rdev->stollen_vga_memory) {
                r = radeon_bo_reserve(rdev->stollen_vga_memory, false);
                if (r == 0) {
@@ -554,6 +557,7 @@ void radeon_ttm_fini(struct radeon_device *rdev)
        ttm_bo_device_release(&rdev->mman.bdev);
        radeon_gart_fini(rdev);
        radeon_ttm_global_fini(rdev);
+       rdev->mman.initialized = false;
        DRM_INFO("radeon: ttm finalized\n");
 }
 
index eee52aa..021de44 100644 (file)
@@ -50,7 +50,7 @@ static struct drm_driver driver = {
                 .owner = THIS_MODULE,
                 .open = drm_open,
                 .release = drm_release,
-                .ioctl = drm_ioctl,
+                .unlocked_ioctl = drm_ioctl,
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
index e725cc0..4fd1f06 100644 (file)
@@ -80,7 +80,7 @@ static struct drm_driver driver = {
                 .owner = THIS_MODULE,
                 .open = drm_open,
                 .release = drm_release,
-                .ioctl = drm_ioctl,
+                .unlocked_ioctl = drm_ioctl,
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
index 012ff2e..ec5a43e 100644 (file)
@@ -48,7 +48,7 @@ static struct drm_driver driver = {
                 .owner = THIS_MODULE,
                 .open = drm_open,
                 .release = drm_release,
-                .ioctl = drm_ioctl,
+                .unlocked_ioctl = drm_ioctl,
                 .mmap = drm_mmap,
                 .poll = drm_poll,
                 .fasync = drm_fasync,
index bc2f518..7a1b210 100644 (file)
@@ -58,7 +58,7 @@ static struct drm_driver driver = {
                .owner = THIS_MODULE,
                .open = drm_open,
                .release = drm_release,
-               .ioctl = drm_ioctl,
+               .unlocked_ioctl = drm_ioctl,
                .mmap = drm_mmap,
                .poll = drm_poll,
                .fasync = drm_fasync,
index 7b48bb3..1db1ef3 100644 (file)
  */
 
 static struct drm_ioctl_desc vmw_ioctls[] = {
-       VMW_IOCTL_DEF(DRM_IOCTL_VMW_GET_PARAM, vmw_getparam_ioctl, 0),
+       VMW_IOCTL_DEF(DRM_IOCTL_VMW_GET_PARAM, vmw_getparam_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl,
-                     0),
+                     DRM_AUTH | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl,
-                     0),
+                     DRM_AUTH | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_CURSOR_BYPASS,
-                     vmw_kms_cursor_bypass_ioctl, 0),
+                     vmw_kms_cursor_bypass_ioctl,
+                     DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
 
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_CONTROL_STREAM, vmw_overlay_ioctl,
-                     0),
+                     DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
-                     0),
+                     DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
-                     0),
+                     DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
 
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
-                     0),
+                     DRM_AUTH | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
-                     0),
+                     DRM_AUTH | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
-                     0),
+                     DRM_AUTH | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
-                     0),
+                     DRM_AUTH | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_REF_SURFACE, vmw_surface_reference_ioctl,
-                     0),
+                     DRM_AUTH | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_EXECBUF, vmw_execbuf_ioctl,
-                     0),
+                     DRM_AUTH | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
-                     0),
+                     DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
-                     0)
+                     DRM_AUTH | DRM_UNLOCKED)
 };
 
 static struct pci_device_id vmw_pci_id_list[] = {
@@ -460,11 +462,9 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
        struct drm_file *file_priv = filp->private_data;
        struct drm_device *dev = file_priv->minor->dev;
        unsigned int nr = DRM_IOCTL_NR(cmd);
-       long ret;
 
        /*
-        * The driver private ioctls and TTM ioctls should be
-        * thread-safe.
+        * Do extra checking on driver private ioctls.
         */
 
        if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
@@ -477,18 +477,9 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
                                  nr - DRM_COMMAND_BASE);
                        return -EINVAL;
                }
-               return drm_ioctl(filp->f_path.dentry->d_inode,
-                                filp, cmd, arg);
        }
 
-       /*
-        * Not all old drm ioctls are thread-safe.
-        */
-
-       lock_kernel();
-       ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
-       return ret;
+       return drm_ioctl(filp, cmd, arg);
 }
 
 static int vmw_firstopen(struct drm_device *dev)
index 43546d0..e61bd85 100644 (file)
@@ -123,6 +123,7 @@ struct vmw_sw_context{
        uint32_t last_cid;
        bool cid_valid;
        uint32_t last_sid;
+       uint32_t sid_translation;
        bool sid_valid;
        struct ttm_object_file *tfile;
        struct list_head validate_nodes;
@@ -317,9 +318,10 @@ extern void vmw_surface_res_free(struct vmw_resource *res);
 extern int vmw_surface_init(struct vmw_private *dev_priv,
                            struct vmw_surface *srf,
                            void (*res_free) (struct vmw_resource *res));
-extern int vmw_user_surface_lookup(struct vmw_private *dev_priv,
-                                  struct ttm_object_file *tfile,
-                                  int sid, struct vmw_surface **out);
+extern int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
+                                         struct ttm_object_file *tfile,
+                                         uint32_t handle,
+                                         struct vmw_surface **out);
 extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
                                     struct drm_file *file_priv);
 extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
@@ -328,7 +330,7 @@ extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
                                       struct drm_file *file_priv);
 extern int vmw_surface_check(struct vmw_private *dev_priv,
                             struct ttm_object_file *tfile,
-                            int id);
+                            uint32_t handle, int *id);
 extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo);
 extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
                           struct vmw_dma_buffer *vmw_bo,
index 7a39f3e..2e92da5 100644 (file)
@@ -73,21 +73,32 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
 
 static int vmw_cmd_sid_check(struct vmw_private *dev_priv,
                             struct vmw_sw_context *sw_context,
-                            uint32_t sid)
+                            uint32_t *sid)
 {
-       if (unlikely((!sw_context->sid_valid || sid != sw_context->last_sid) &&
-                    sid != SVGA3D_INVALID_ID)) {
-               int ret = vmw_surface_check(dev_priv, sw_context->tfile, sid);
+       if (*sid == SVGA3D_INVALID_ID)
+               return 0;
+
+       if (unlikely((!sw_context->sid_valid  ||
+                     *sid != sw_context->last_sid))) {
+               int real_id;
+               int ret = vmw_surface_check(dev_priv, sw_context->tfile,
+                                           *sid, &real_id);
 
                if (unlikely(ret != 0)) {
-                       DRM_ERROR("Could ot find or use surface %u\n",
-                                 (unsigned) sid);
+                       DRM_ERROR("Could ot find or use surface 0x%08x "
+                                 "address 0x%08lx\n",
+                                 (unsigned int) *sid,
+                                 (unsigned long) sid);
                        return ret;
                }
 
-               sw_context->last_sid = sid;
+               sw_context->last_sid = *sid;
                sw_context->sid_valid = true;
-       }
+               *sid = real_id;
+               sw_context->sid_translation = real_id;
+       } else
+               *sid = sw_context->sid_translation;
+
        return 0;
 }
 
@@ -107,7 +118,8 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
                return ret;
 
        cmd = container_of(header, struct vmw_sid_cmd, header);
-       return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.target.sid);
+       ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.target.sid);
+       return ret;
 }
 
 static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
@@ -121,10 +133,10 @@ static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
        int ret;
 
        cmd = container_of(header, struct vmw_sid_cmd, header);
-       ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.src.sid);
+       ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid);
        if (unlikely(ret != 0))
                return ret;
-       return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.dest.sid);
+       return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid);
 }
 
 static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
@@ -138,10 +150,10 @@ static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
        int ret;
 
        cmd = container_of(header, struct vmw_sid_cmd, header);
-       ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.src.sid);
+       ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid);
        if (unlikely(ret != 0))
                return ret;
-       return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.dest.sid);
+       return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid);
 }
 
 static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
@@ -154,7 +166,7 @@ static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
        } *cmd;
 
        cmd = container_of(header, struct vmw_sid_cmd, header);
-       return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.srcImage.sid);
+       return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid);
 }
 
 static int vmw_cmd_present_check(struct vmw_private *dev_priv,
@@ -167,7 +179,7 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv,
        } *cmd;
 
        cmd = container_of(header, struct vmw_sid_cmd, header);
-       return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.sid);
+       return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid);
 }
 
 static int vmw_cmd_dma(struct vmw_private *dev_priv,
@@ -187,12 +199,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
        uint32_t cur_validate_node;
        struct ttm_validate_buffer *val_buf;
 
-
        cmd = container_of(header, struct vmw_dma_cmd, header);
-       ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->dma.host.sid);
-       if (unlikely(ret != 0))
-               return ret;
-
        handle = cmd->dma.guest.ptr.gmrId;
        ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
        if (unlikely(ret != 0)) {
@@ -228,14 +235,23 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
                ++sw_context->cur_val_buf;
        }
 
-       ret = vmw_user_surface_lookup(dev_priv, sw_context->tfile,
-                                     cmd->dma.host.sid, &srf);
+       ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile,
+                                            cmd->dma.host.sid, &srf);
        if (ret) {
                DRM_ERROR("could not find surface\n");
                goto out_no_reloc;
        }
 
+       /**
+        * Patch command stream with device SID.
+        */
+
+       cmd->dma.host.sid = srf->res.id;
        vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
+       /**
+        * FIXME: May deadlock here when called from the
+        * command parsing code.
+        */
        vmw_surface_unreference(&srf);
 
 out_no_reloc:
@@ -243,6 +259,90 @@ out_no_reloc:
        return ret;
 }
 
+static int vmw_cmd_draw(struct vmw_private *dev_priv,
+                       struct vmw_sw_context *sw_context,
+                       SVGA3dCmdHeader *header)
+{
+       struct vmw_draw_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDrawPrimitives body;
+       } *cmd;
+       SVGA3dVertexDecl *decl = (SVGA3dVertexDecl *)(
+               (unsigned long)header + sizeof(*cmd));
+       SVGA3dPrimitiveRange *range;
+       uint32_t i;
+       uint32_t maxnum;
+       int ret;
+
+       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       if (unlikely(ret != 0))
+               return ret;
+
+       cmd = container_of(header, struct vmw_draw_cmd, header);
+       maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl);
+
+       if (unlikely(cmd->body.numVertexDecls > maxnum)) {
+               DRM_ERROR("Illegal number of vertex declarations.\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) {
+               ret = vmw_cmd_sid_check(dev_priv, sw_context,
+                                       &decl->array.surfaceId);
+               if (unlikely(ret != 0))
+                       return ret;
+       }
+
+       maxnum = (header->size - sizeof(cmd->body) -
+                 cmd->body.numVertexDecls * sizeof(*decl)) / sizeof(*range);
+       if (unlikely(cmd->body.numRanges > maxnum)) {
+               DRM_ERROR("Illegal number of index ranges.\n");
+               return -EINVAL;
+       }
+
+       range = (SVGA3dPrimitiveRange *) decl;
+       for (i = 0; i < cmd->body.numRanges; ++i, ++range) {
+               ret = vmw_cmd_sid_check(dev_priv, sw_context,
+                                       &range->indexArray.surfaceId);
+               if (unlikely(ret != 0))
+                       return ret;
+       }
+       return 0;
+}
+
+
+static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
+                            struct vmw_sw_context *sw_context,
+                            SVGA3dCmdHeader *header)
+{
+       struct vmw_tex_state_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdSetTextureState state;
+       };
+
+       SVGA3dTextureState *last_state = (SVGA3dTextureState *)
+         ((unsigned long) header + header->size + sizeof(header));
+       SVGA3dTextureState *cur_state = (SVGA3dTextureState *)
+               ((unsigned long) header + sizeof(struct vmw_tex_state_cmd));
+       int ret;
+
+       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       if (unlikely(ret != 0))
+               return ret;
+
+       for (; cur_state < last_state; ++cur_state) {
+               if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE))
+                       continue;
+
+               ret = vmw_cmd_sid_check(dev_priv, sw_context,
+                                       &cur_state->value);
+               if (unlikely(ret != 0))
+                       return ret;
+       }
+
+       return 0;
+}
+
 
 typedef int (*vmw_cmd_func) (struct vmw_private *,
                             struct vmw_sw_context *,
@@ -264,7 +364,7 @@ static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
        VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check),
        VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET,
                    &vmw_cmd_set_render_target_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_cid_check),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state),
        VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check),
        VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check),
        VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check),
@@ -276,7 +376,7 @@ static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
        VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check),
        VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_cid_check),
        VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_cid_check),
+       VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw),
        VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check),
        VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_cid_check),
        VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_cid_check),
@@ -291,6 +391,7 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
                         void *buf, uint32_t *size)
 {
        uint32_t cmd_id;
+       uint32_t size_remaining = *size;
        SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
        int ret;
 
@@ -304,6 +405,9 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
        *size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader);
 
        cmd_id -= SVGA_3D_CMD_BASE;
+       if (unlikely(*size > size_remaining))
+               goto out_err;
+
        if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE))
                goto out_err;
 
@@ -326,6 +430,7 @@ static int vmw_cmd_check_all(struct vmw_private *dev_priv,
        int ret;
 
        while (cur_size > 0) {
+               size = cur_size;
                ret = vmw_cmd_check(dev_priv, sw_context, buf, &size);
                if (unlikely(ret != 0))
                        return ret;
@@ -386,7 +491,7 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
                return 0;
 
        ret = vmw_gmr_bind(dev_priv, bo);
-       if (likely(ret == 0 || ret == -ERESTART))
+       if (likely(ret == 0 || ret == -ERESTARTSYS))
                return ret;
 
 
@@ -429,7 +534,7 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
 
        ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
        if (unlikely(ret != 0)) {
-               ret = -ERESTART;
+               ret = -ERESTARTSYS;
                goto out_no_cmd_mutex;
        }
 
index 76b0693..01feb48 100644 (file)
@@ -191,7 +191,7 @@ static int vmw_fifo_wait_noirq(struct vmw_private *dev_priv,
                }
                schedule_timeout(1);
                if (interruptible && signal_pending(current)) {
-                       ret = -ERESTART;
+                       ret = -ERESTARTSYS;
                        break;
                }
        }
@@ -237,9 +237,7 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv,
                    (dev_priv->fifo_queue,
                     !vmw_fifo_is_full(dev_priv, bytes), timeout);
 
-       if (unlikely(ret == -ERESTARTSYS))
-               ret = -ERESTART;
-       else if (unlikely(ret == 0))
+       if (unlikely(ret == 0))
                ret = -EBUSY;
        else if (likely(ret > 0))
                ret = 0;
index 9e0f030..d40086f 100644 (file)
@@ -155,7 +155,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
                                            TASK_UNINTERRUPTIBLE);
                }
                if (interruptible && signal_pending(current)) {
-                       ret = -ERESTART;
+                       ret = -ERESTARTSYS;
                        break;
                }
        }
@@ -218,9 +218,7 @@ int vmw_wait_fence(struct vmw_private *dev_priv,
                     vmw_fence_signaled(dev_priv, sequence),
                     timeout);
 
-       if (unlikely(ret == -ERESTARTSYS))
-               ret = -ERESTART;
-       else if (unlikely(ret == 0))
+       if (unlikely(ret == 0))
                ret = -EBUSY;
        else if (likely(ret > 0))
                ret = 0;
index e9403be..b1af76e 100644 (file)
@@ -106,8 +106,8 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
        int ret;
 
        if (handle) {
-               ret = vmw_user_surface_lookup(dev_priv, tfile,
-                                             handle, &surface);
+               ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
+                                                    handle, &surface);
                if (!ret) {
                        if (!surface->snooper.image) {
                                DRM_ERROR("surface not suitable for cursor\n");
@@ -704,8 +704,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
        struct vmw_dma_buffer *bo = NULL;
        int ret;
 
-       ret = vmw_user_surface_lookup(dev_priv, tfile,
-                                     mode_cmd->handle, &surface);
+       ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
+                                            mode_cmd->handle, &surface);
        if (ret)
                goto try_dmabuf;
 
index a1ceed0..c012d59 100644 (file)
@@ -488,28 +488,44 @@ static void vmw_user_surface_free(struct vmw_resource *res)
        kfree(user_srf);
 }
 
-int vmw_user_surface_lookup(struct vmw_private *dev_priv,
-                           struct ttm_object_file *tfile,
-                           int sid, struct vmw_surface **out)
+int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
+                                  struct ttm_object_file *tfile,
+                                  uint32_t handle, struct vmw_surface **out)
 {
        struct vmw_resource *res;
        struct vmw_surface *srf;
        struct vmw_user_surface *user_srf;
+       struct ttm_base_object *base;
+       int ret = -EINVAL;
 
-       res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, sid);
-       if (unlikely(res == NULL))
+       base = ttm_base_object_lookup(tfile, handle);
+       if (unlikely(base == NULL))
                return -EINVAL;
 
-       if (res->res_free != &vmw_user_surface_free)
-               return -EINVAL;
+       if (unlikely(base->object_type != VMW_RES_SURFACE))
+               goto out_bad_resource;
 
-       srf = container_of(res, struct vmw_surface, res);
-       user_srf = container_of(srf, struct vmw_user_surface, srf);
-       if (user_srf->base.tfile != tfile && !user_srf->base.shareable)
-               return -EPERM;
+       user_srf = container_of(base, struct vmw_user_surface, base);
+       srf = &user_srf->srf;
+       res = &srf->res;
+
+       read_lock(&dev_priv->resource_lock);
+
+       if (!res->avail || res->res_free != &vmw_user_surface_free) {
+               read_unlock(&dev_priv->resource_lock);
+               goto out_bad_resource;
+       }
+
+       kref_get(&res->kref);
+       read_unlock(&dev_priv->resource_lock);
 
        *out = srf;
-       return 0;
+       ret = 0;
+
+out_bad_resource:
+       ttm_base_object_unref(&base);
+
+       return ret;
 }
 
 static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
@@ -526,35 +542,10 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
 int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *file_priv)
 {
-       struct vmw_private *dev_priv = vmw_priv(dev);
-       struct vmw_resource *res;
-       struct vmw_surface *srf;
-       struct vmw_user_surface *user_srf;
        struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-       int ret = 0;
-
-       res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, arg->sid);
-       if (unlikely(res == NULL))
-               return -EINVAL;
-
-       if (res->res_free != &vmw_user_surface_free) {
-               ret = -EINVAL;
-               goto out;
-       }
 
-       srf = container_of(res, struct vmw_surface, res);
-       user_srf = container_of(srf, struct vmw_user_surface, srf);
-       if (user_srf->base.tfile != tfile && !user_srf->base.shareable) {
-               ret = -EPERM;
-               goto out;
-       }
-
-       ttm_ref_object_base_unref(tfile, user_srf->base.hash.key,
-                                 TTM_REF_USAGE);
-out:
-       vmw_resource_unreference(&res);
-       return ret;
+       return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
 }
 
 int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
@@ -649,7 +640,10 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
        }
        srf->snooper.crtc = NULL;
 
-       rep->sid = res->id;
+       rep->sid = user_srf->base.hash.key;
+       if (rep->sid == SVGA3D_INVALID_ID)
+               DRM_ERROR("Created bad Surface ID.\n");
+
        vmw_resource_unreference(&res);
        return 0;
 out_err1:
@@ -662,39 +656,33 @@ out_err0:
 int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *file_priv)
 {
-       struct vmw_private *dev_priv = vmw_priv(dev);
        union drm_vmw_surface_reference_arg *arg =
            (union drm_vmw_surface_reference_arg *)data;
        struct drm_vmw_surface_arg *req = &arg->req;
        struct drm_vmw_surface_create_req *rep = &arg->rep;
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-       struct vmw_resource *res;
        struct vmw_surface *srf;
        struct vmw_user_surface *user_srf;
        struct drm_vmw_size __user *user_sizes;
-       int ret;
+       struct ttm_base_object *base;
+       int ret = -EINVAL;
 
-       res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, req->sid);
-       if (unlikely(res == NULL))
+       base = ttm_base_object_lookup(tfile, req->sid);
+       if (unlikely(base == NULL)) {
+               DRM_ERROR("Could not find surface to reference.\n");
                return -EINVAL;
-
-       if (res->res_free != &vmw_user_surface_free) {
-               ret = -EINVAL;
-               goto out;
        }
 
-       srf = container_of(res, struct vmw_surface, res);
-       user_srf = container_of(srf, struct vmw_user_surface, srf);
-       if (user_srf->base.tfile != tfile && !user_srf->base.shareable) {
-               DRM_ERROR("Tried to reference none shareable surface\n");
-               ret = -EPERM;
-               goto out;
-       }
+       if (unlikely(base->object_type != VMW_RES_SURFACE))
+               goto out_bad_resource;
+
+       user_srf = container_of(base, struct vmw_user_surface, base);
+       srf = &user_srf->srf;
 
        ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL);
        if (unlikely(ret != 0)) {
                DRM_ERROR("Could not add a reference to a surface.\n");
-               goto out;
+               goto out_no_reference;
        }
 
        rep->flags = srf->flags;
@@ -706,40 +694,43 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
        if (user_sizes)
                ret = copy_to_user(user_sizes, srf->sizes,
                                   srf->num_sizes * sizeof(*srf->sizes));
-       if (unlikely(ret != 0)) {
+       if (unlikely(ret != 0))
                DRM_ERROR("copy_to_user failed %p %u\n",
                          user_sizes, srf->num_sizes);
-               /**
-                * FIXME: Unreference surface here?
-                */
-               goto out;
-       }
-out:
-       vmw_resource_unreference(&res);
+out_bad_resource:
+out_no_reference:
+       ttm_base_object_unref(&base);
+
        return ret;
 }
 
 int vmw_surface_check(struct vmw_private *dev_priv,
                      struct ttm_object_file *tfile,
-                     int id)
+                     uint32_t handle, int *id)
 {
-       struct vmw_resource *res;
-       int ret = 0;
+       struct ttm_base_object *base;
+       struct vmw_user_surface *user_srf;
 
-       read_lock(&dev_priv->resource_lock);
-       res = idr_find(&dev_priv->surface_idr, id);
-       if (res && res->avail) {
-               struct vmw_surface *srf =
-                       container_of(res, struct vmw_surface, res);
-               struct vmw_user_surface *usrf =
-                       container_of(srf, struct vmw_user_surface, srf);
+       int ret = -EPERM;
 
-               if (usrf->base.tfile != tfile && !usrf->base.shareable)
-                       ret = -EPERM;
-       } else
-               ret = -EINVAL;
-       read_unlock(&dev_priv->resource_lock);
+       base = ttm_base_object_lookup(tfile, handle);
+       if (unlikely(base == NULL))
+               return -EINVAL;
+
+       if (unlikely(base->object_type != VMW_RES_SURFACE))
+               goto out_bad_surface;
 
+       user_srf = container_of(base, struct vmw_user_surface, base);
+       *id = user_srf->srf.res.id;
+       ret = 0;
+
+out_bad_surface:
+       /**
+        * FIXME: May deadlock here when called from the
+        * command parsing code.
+        */
+
+       ttm_base_object_unref(&base);
        return ret;
 }
 
index bfd03bf..f3d440c 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include <linux/kfifo.h>
 
 #include "t3_cpl.h"
 #include "t3cdev.h"
@@ -75,13 +76,13 @@ struct cxio_hal_ctrl_qp {
 };
 
 struct cxio_hal_resource {
-       struct kfifo *tpt_fifo;
+       struct kfifo tpt_fifo;
        spinlock_t tpt_fifo_lock;
-       struct kfifo *qpid_fifo;
+       struct kfifo qpid_fifo;
        spinlock_t qpid_fifo_lock;
-       struct kfifo *cqid_fifo;
+       struct kfifo cqid_fifo;
        spinlock_t cqid_fifo_lock;
-       struct kfifo *pdid_fifo;
+       struct kfifo pdid_fifo;
        spinlock_t pdid_fifo_lock;
 };
 
index bd233c0..31f9201 100644 (file)
 #include "cxio_resource.h"
 #include "cxio_hal.h"
 
-static struct kfifo *rhdl_fifo;
+static struct kfifo rhdl_fifo;
 static spinlock_t rhdl_fifo_lock;
 
 #define RANDOM_SIZE 16
 
-static int __cxio_init_resource_fifo(struct kfifo **fifo,
+static int __cxio_init_resource_fifo(struct kfifo *fifo,
                                   spinlock_t *fifo_lock,
                                   u32 nr, u32 skip_low,
                                   u32 skip_high,
@@ -55,12 +55,11 @@ static int __cxio_init_resource_fifo(struct kfifo **fifo,
        u32 rarray[16];
        spin_lock_init(fifo_lock);
 
-       *fifo = kfifo_alloc(nr * sizeof(u32), GFP_KERNEL, fifo_lock);
-       if (IS_ERR(*fifo))
+       if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL))
                return -ENOMEM;
 
        for (i = 0; i < skip_low + skip_high; i++)
-               __kfifo_put(*fifo, (unsigned char *) &entry, sizeof(u32));
+               kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32));
        if (random) {
                j = 0;
                random_bytes = random32();
@@ -72,33 +71,35 @@ static int __cxio_init_resource_fifo(struct kfifo **fifo,
                                random_bytes = random32();
                        }
                        idx = (random_bytes >> (j * 2)) & 0xF;
-                       __kfifo_put(*fifo,
+                       kfifo_in(fifo,
                                (unsigned char *) &rarray[idx],
                                sizeof(u32));
                        rarray[idx] = i;
                        j++;
                }
                for (i = 0; i < RANDOM_SIZE; i++)
-                       __kfifo_put(*fifo,
+                       kfifo_in(fifo,
                                (unsigned char *) &rarray[i],
                                sizeof(u32));
        } else
                for (i = skip_low; i < nr - skip_high; i++)
-                       __kfifo_put(*fifo, (unsigned char *) &i, sizeof(u32));
+                       kfifo_in(fifo, (unsigned char *) &i, sizeof(u32));
 
        for (i = 0; i < skip_low + skip_high; i++)
-               kfifo_get(*fifo, (unsigned char *) &entry, sizeof(u32));
+               if (kfifo_out_locked(fifo, (unsigned char *) &entry,
+                               sizeof(u32), fifo_lock) != sizeof(u32))
+                                       break;
        return 0;
 }
 
-static int cxio_init_resource_fifo(struct kfifo **fifo, spinlock_t * fifo_lock,
+static int cxio_init_resource_fifo(struct kfifo *fifo, spinlock_t * fifo_lock,
                                   u32 nr, u32 skip_low, u32 skip_high)
 {
        return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
                                          skip_high, 0));
 }
 
-static int cxio_init_resource_fifo_random(struct kfifo **fifo,
+static int cxio_init_resource_fifo_random(struct kfifo *fifo,
                                   spinlock_t * fifo_lock,
                                   u32 nr, u32 skip_low, u32 skip_high)
 {
@@ -113,15 +114,13 @@ static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p)
 
        spin_lock_init(&rdev_p->rscp->qpid_fifo_lock);
 
-       rdev_p->rscp->qpid_fifo = kfifo_alloc(T3_MAX_NUM_QP * sizeof(u32),
-                                             GFP_KERNEL,
-                                             &rdev_p->rscp->qpid_fifo_lock);
-       if (IS_ERR(rdev_p->rscp->qpid_fifo))
+       if (kfifo_alloc(&rdev_p->rscp->qpid_fifo, T3_MAX_NUM_QP * sizeof(u32),
+                                             GFP_KERNEL))
                return -ENOMEM;
 
        for (i = 16; i < T3_MAX_NUM_QP; i++)
                if (!(i & rdev_p->qpmask))
-                       __kfifo_put(rdev_p->rscp->qpid_fifo,
+                       kfifo_in(&rdev_p->rscp->qpid_fifo,
                                    (unsigned char *) &i, sizeof(u32));
        return 0;
 }
@@ -134,7 +133,7 @@ int cxio_hal_init_rhdl_resource(u32 nr_rhdl)
 
 void cxio_hal_destroy_rhdl_resource(void)
 {
-       kfifo_free(rhdl_fifo);
+       kfifo_free(&rhdl_fifo);
 }
 
 /* nr_* must be power of 2 */
@@ -167,11 +166,11 @@ int cxio_hal_init_resource(struct cxio_rdev *rdev_p,
                goto pdid_err;
        return 0;
 pdid_err:
-       kfifo_free(rscp->cqid_fifo);
+       kfifo_free(&rscp->cqid_fifo);
 cqid_err:
-       kfifo_free(rscp->qpid_fifo);
+       kfifo_free(&rscp->qpid_fifo);
 qpid_err:
-       kfifo_free(rscp->tpt_fifo);
+       kfifo_free(&rscp->tpt_fifo);
 tpt_err:
        return -ENOMEM;
 }
@@ -179,33 +178,37 @@ tpt_err:
 /*
  * returns 0 if no resource available
  */
-static u32 cxio_hal_get_resource(struct kfifo *fifo)
+static u32 cxio_hal_get_resource(struct kfifo *fifo, spinlock_t * lock)
 {
        u32 entry;
-       if (kfifo_get(fifo, (unsigned char *) &entry, sizeof(u32)))
+       if (kfifo_out_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock))
                return entry;
        else
                return 0;       /* fifo emptry */
 }
 
-static void cxio_hal_put_resource(struct kfifo *fifo, u32 entry)
+static void cxio_hal_put_resource(struct kfifo *fifo, spinlock_t * lock,
+               u32 entry)
 {
-       BUG_ON(kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)) == 0);
+       BUG_ON(
+       kfifo_in_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock)
+       == 0);
 }
 
 u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp)
 {
-       return cxio_hal_get_resource(rscp->tpt_fifo);
+       return cxio_hal_get_resource(&rscp->tpt_fifo, &rscp->tpt_fifo_lock);
 }
 
 void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag)
 {
-       cxio_hal_put_resource(rscp->tpt_fifo, stag);
+       cxio_hal_put_resource(&rscp->tpt_fifo, &rscp->tpt_fifo_lock, stag);
 }
 
 u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp)
 {
-       u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo);
+       u32 qpid = cxio_hal_get_resource(&rscp->qpid_fifo,
+                       &rscp->qpid_fifo_lock);
        PDBG("%s qpid 0x%x\n", __func__, qpid);
        return qpid;
 }
@@ -213,35 +216,35 @@ u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp)
 void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid)
 {
        PDBG("%s qpid 0x%x\n", __func__, qpid);
-       cxio_hal_put_resource(rscp->qpid_fifo, qpid);
+       cxio_hal_put_resource(&rscp->qpid_fifo, &rscp->qpid_fifo_lock, qpid);
 }
 
 u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp)
 {
-       return cxio_hal_get_resource(rscp->cqid_fifo);
+       return cxio_hal_get_resource(&rscp->cqid_fifo, &rscp->cqid_fifo_lock);
 }
 
 void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid)
 {
-       cxio_hal_put_resource(rscp->cqid_fifo, cqid);
+       cxio_hal_put_resource(&rscp->cqid_fifo, &rscp->cqid_fifo_lock, cqid);
 }
 
 u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp)
 {
-       return cxio_hal_get_resource(rscp->pdid_fifo);
+       return cxio_hal_get_resource(&rscp->pdid_fifo, &rscp->pdid_fifo_lock);
 }
 
 void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid)
 {
-       cxio_hal_put_resource(rscp->pdid_fifo, pdid);
+       cxio_hal_put_resource(&rscp->pdid_fifo, &rscp->pdid_fifo_lock, pdid);
 }
 
 void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp)
 {
-       kfifo_free(rscp->tpt_fifo);
-       kfifo_free(rscp->cqid_fifo);
-       kfifo_free(rscp->qpid_fifo);
-       kfifo_free(rscp->pdid_fifo);
+       kfifo_free(&rscp->tpt_fifo);
+       kfifo_free(&rscp->cqid_fifo);
+       kfifo_free(&rscp->qpid_fifo);
+       kfifo_free(&rscp->pdid_fifo);
        kfree(rscp);
 }
 
index 7e5f30d..f1e8af5 100644 (file)
@@ -661,7 +661,7 @@ l1oip_socket_thread(void *data)
        size_t recvbuf_size = 1500;
        int recvlen;
        struct socket *socket = NULL;
-       DECLARE_COMPLETION(wait);
+       DECLARE_COMPLETION_ONSTACK(wait);
 
        /* allocate buffer memory */
        recvbuf = kmalloc(recvbuf_size, GFP_KERNEL);
index 3ccc8af..2bf57a4 100644 (file)
@@ -124,15 +124,12 @@ struct cx23888_ir_state {
        atomic_t rxclk_divider;
        atomic_t rx_invert;
 
-       struct kfifo *rx_kfifo;
+       struct kfifo rx_kfifo;
        spinlock_t rx_kfifo_lock;
 
        struct v4l2_subdev_ir_parameters tx_params;
        struct mutex tx_params_lock;
        atomic_t txclk_divider;
-
-       struct kfifo *tx_kfifo;
-       spinlock_t tx_kfifo_lock;
 };
 
 static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd)
@@ -522,6 +519,7 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
 {
        struct cx23888_ir_state *state = to_state(sd);
        struct cx23885_dev *dev = state->dev;
+       unsigned long flags;
 
        u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
        u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
@@ -594,8 +592,9 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
                        if (i == 0)
                                break;
                        j = i * sizeof(u32);
-                       k = kfifo_put(state->rx_kfifo,
-                                     (unsigned char *) rx_data, j);
+                       k = kfifo_in_locked(&state->rx_kfifo,
+                                     (unsigned char *) rx_data, j,
+                                     &state->rx_kfifo_lock);
                        if (k != j)
                                kror++; /* rx_kfifo over run */
                }
@@ -631,8 +630,11 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
                cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl);
                *handled = true;
        }
-       if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
+
+       spin_lock_irqsave(&state->rx_kfifo_lock, flags);
+       if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
                events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
+       spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
 
        if (events)
                v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
@@ -657,7 +659,7 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
                return 0;
        }
 
-       n = kfifo_get(state->rx_kfifo, buf, n);
+       n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock);
 
        n /= sizeof(u32);
        *num = n * sizeof(u32);
@@ -785,7 +787,12 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
        o->interrupt_enable = p->interrupt_enable;
        o->enable = p->enable;
        if (p->enable) {
-               kfifo_reset(state->rx_kfifo);
+               unsigned long flags;
+
+               spin_lock_irqsave(&state->rx_kfifo_lock, flags);
+               kfifo_reset(&state->rx_kfifo);
+               /* reset tx_fifo too if there is one... */
+               spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
                if (p->interrupt_enable)
                        irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
                control_rx_enable(dev, p->enable);
@@ -892,7 +899,6 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
        o->interrupt_enable = p->interrupt_enable;
        o->enable = p->enable;
        if (p->enable) {
-               kfifo_reset(state->tx_kfifo);
                if (p->interrupt_enable)
                        irqenable_tx(dev, IRQEN_TSE);
                control_tx_enable(dev, p->enable);
@@ -1168,18 +1174,8 @@ int cx23888_ir_probe(struct cx23885_dev *dev)
                return -ENOMEM;
 
        spin_lock_init(&state->rx_kfifo_lock);
-       state->rx_kfifo = kfifo_alloc(CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL,
-                                     &state->rx_kfifo_lock);
-       if (state->rx_kfifo == NULL)
-               return -ENOMEM;
-
-       spin_lock_init(&state->tx_kfifo_lock);
-       state->tx_kfifo = kfifo_alloc(CX23888_IR_TX_KFIFO_SIZE, GFP_KERNEL,
-                                     &state->tx_kfifo_lock);
-       if (state->tx_kfifo == NULL) {
-               kfifo_free(state->rx_kfifo);
+       if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL))
                return -ENOMEM;
-       }
 
        state->dev = dev;
        state->id = V4L2_IDENT_CX23888_IR;
@@ -1211,8 +1207,7 @@ int cx23888_ir_probe(struct cx23885_dev *dev)
                       sizeof(struct v4l2_subdev_ir_parameters));
                v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
        } else {
-               kfifo_free(state->rx_kfifo);
-               kfifo_free(state->tx_kfifo);
+               kfifo_free(&state->rx_kfifo);
        }
        return ret;
 }
@@ -1231,8 +1226,7 @@ int cx23888_ir_remove(struct cx23885_dev *dev)
 
        state = to_state(sd);
        v4l2_device_unregister_subdev(sd);
-       kfifo_free(state->rx_kfifo);
-       kfifo_free(state->tx_kfifo);
+       kfifo_free(&state->rx_kfifo);
        kfree(state);
        /* Nothing more to free() as state held the actual v4l2_subdev object */
        return 0;
index 6ffa64c..b421858 100644 (file)
@@ -800,8 +800,8 @@ again:
                return IRQ_HANDLED;
 
        if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) {
-               if (kfifo_get(meye.grabq, (unsigned char *)&reqnr,
-                             sizeof(int)) != sizeof(int)) {
+               if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
+                             sizeof(int), &meye.grabq_lock) != sizeof(int)) {
                        mchip_free_frame();
                        return IRQ_HANDLED;
                }
@@ -811,7 +811,8 @@ again:
                meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
                do_gettimeofday(&meye.grab_buffer[reqnr].timestamp);
                meye.grab_buffer[reqnr].sequence = sequence++;
-               kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int));
+               kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
+                               sizeof(int), &meye.doneq_lock);
                wake_up_interruptible(&meye.proc_list);
        } else {
                int size;
@@ -820,8 +821,8 @@ again:
                        mchip_free_frame();
                        goto again;
                }
-               if (kfifo_get(meye.grabq, (unsigned char *)&reqnr,
-                             sizeof(int)) != sizeof(int)) {
+               if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
+                             sizeof(int), &meye.grabq_lock) != sizeof(int)) {
                        mchip_free_frame();
                        goto again;
                }
@@ -831,7 +832,8 @@ again:
                meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
                do_gettimeofday(&meye.grab_buffer[reqnr].timestamp);
                meye.grab_buffer[reqnr].sequence = sequence++;
-               kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int));
+               kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
+                               sizeof(int), &meye.doneq_lock);
                wake_up_interruptible(&meye.proc_list);
        }
        mchip_free_frame();
@@ -859,8 +861,8 @@ static int meye_open(struct file *file)
 
        for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
                meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
-       kfifo_reset(meye.grabq);
-       kfifo_reset(meye.doneq);
+       kfifo_reset(&meye.grabq);
+       kfifo_reset(&meye.doneq);
        return 0;
 }
 
@@ -933,7 +935,8 @@ static int meyeioc_qbuf_capt(int *nb)
                mchip_cont_compression_start();
 
        meye.grab_buffer[*nb].state = MEYE_BUF_USING;
-       kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
+       kfifo_in_locked(&meye.grabq, (unsigned char *)nb, sizeof(int),
+                        &meye.grabq_lock);
        mutex_unlock(&meye.lock);
 
        return 0;
@@ -965,7 +968,9 @@ static int meyeioc_sync(struct file *file, void *fh, int *i)
                /* fall through */
        case MEYE_BUF_DONE:
                meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
-               kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
+               if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused,
+                               sizeof(int), &meye.doneq_lock) != sizeof(int))
+                                       break;
        }
        *i = meye.grab_buffer[*i].size;
        mutex_unlock(&meye.lock);
@@ -1452,7 +1457,8 @@ static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
        buf->flags |= V4L2_BUF_FLAG_QUEUED;
        buf->flags &= ~V4L2_BUF_FLAG_DONE;
        meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
-       kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
+       kfifo_in_locked(&meye.grabq, (unsigned char *)&buf->index,
+                       sizeof(int), &meye.grabq_lock);
        mutex_unlock(&meye.lock);
 
        return 0;
@@ -1467,19 +1473,19 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 
        mutex_lock(&meye.lock);
 
-       if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
+       if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
                mutex_unlock(&meye.lock);
                return -EAGAIN;
        }
 
        if (wait_event_interruptible(meye.proc_list,
-                                    kfifo_len(meye.doneq) != 0) < 0) {
+                                    kfifo_len(&meye.doneq) != 0) < 0) {
                mutex_unlock(&meye.lock);
                return -EINTR;
        }
 
-       if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
-                      sizeof(int))) {
+       if (!kfifo_out_locked(&meye.doneq, (unsigned char *)&reqnr,
+                      sizeof(int), &meye.doneq_lock)) {
                mutex_unlock(&meye.lock);
                return -EBUSY;
        }
@@ -1529,8 +1535,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
 {
        mutex_lock(&meye.lock);
        mchip_hic_stop();
-       kfifo_reset(meye.grabq);
-       kfifo_reset(meye.doneq);
+       kfifo_reset(&meye.grabq);
+       kfifo_reset(&meye.doneq);
 
        for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
                meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
@@ -1572,7 +1578,7 @@ static unsigned int meye_poll(struct file *file, poll_table *wait)
 
        mutex_lock(&meye.lock);
        poll_wait(file, &meye.proc_list, wait);
-       if (kfifo_len(meye.doneq))
+       if (kfifo_len(&meye.doneq))
                res = POLLIN | POLLRDNORM;
        mutex_unlock(&meye.lock);
        return res;
@@ -1745,16 +1751,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        }
 
        spin_lock_init(&meye.grabq_lock);
-       meye.grabq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL,
-                                &meye.grabq_lock);
-       if (IS_ERR(meye.grabq)) {
+       if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS,
+                               GFP_KERNEL)) {
                printk(KERN_ERR "meye: fifo allocation failed\n");
                goto outkfifoalloc1;
        }
        spin_lock_init(&meye.doneq_lock);
-       meye.doneq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL,
-                                &meye.doneq_lock);
-       if (IS_ERR(meye.doneq)) {
+       if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS,
+                               GFP_KERNEL)) {
                printk(KERN_ERR "meye: fifo allocation failed\n");
                goto outkfifoalloc2;
        }
@@ -1868,9 +1872,9 @@ outregions:
 outenabledev:
        sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
 outsonypienable:
-       kfifo_free(meye.doneq);
+       kfifo_free(&meye.doneq);
 outkfifoalloc2:
-       kfifo_free(meye.grabq);
+       kfifo_free(&meye.grabq);
 outkfifoalloc1:
        vfree(meye.grab_temp);
 outvmalloc:
@@ -1901,8 +1905,8 @@ static void __devexit meye_remove(struct pci_dev *pcidev)
 
        sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
 
-       kfifo_free(meye.doneq);
-       kfifo_free(meye.grabq);
+       kfifo_free(&meye.doneq);
+       kfifo_free(&meye.grabq);
 
        vfree(meye.grab_temp);
 
index 5f70a10..1321ad5 100644 (file)
@@ -303,9 +303,9 @@ struct meye {
        struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS];
        int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */
        struct mutex lock;              /* mutex for open/mmap... */
-       struct kfifo *grabq;            /* queue for buffers to be grabbed */
+       struct kfifo grabq;             /* queue for buffers to be grabbed */
        spinlock_t grabq_lock;          /* lock protecting the queue */
-       struct kfifo *doneq;            /* queue for grabbed buffers */
+       struct kfifo doneq;             /* queue for grabbed buffers */
        spinlock_t doneq_lock;          /* lock protecting the queue */
        wait_queue_head_t proc_list;    /* wait queue */
        struct video_device *video_dev; /* video device parameters */
index 4bfc808..65df1de 100644 (file)
@@ -653,12 +653,20 @@ static void
 bnx2_netif_stop(struct bnx2 *bp)
 {
        bnx2_cnic_stop(bp);
-       bnx2_disable_int_sync(bp);
        if (netif_running(bp->dev)) {
+               int i;
+
                bnx2_napi_disable(bp);
                netif_tx_disable(bp->dev);
-               bp->dev->trans_start = jiffies; /* prevent tx timeout */
+               /* prevent tx timeout */
+               for (i = 0; i <  bp->dev->num_tx_queues; i++) {
+                       struct netdev_queue *txq;
+
+                       txq = netdev_get_tx_queue(bp->dev, i);
+                       txq->trans_start = jiffies;
+               }
        }
+       bnx2_disable_int_sync(bp);
 }
 
 static void
index d0ec178..166cc7e 100644 (file)
@@ -1037,7 +1037,7 @@ static int __init at91_can_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
-       if (!res || !irq) {
+       if (!res || irq <= 0) {
                err = -ENODEV;
                goto exit_put;
        }
index 8edac89..34e0310 100644 (file)
@@ -2272,7 +2272,7 @@ static int emac_mii_reset(struct mii_bus *bus)
        unsigned int clk_div;
        int mdio_bus_freq = emac_bus_frequency;
 
-       if (mdio_max_freq & mdio_bus_freq)
+       if (mdio_max_freq && mdio_bus_freq)
                clk_div = ((mdio_bus_freq / mdio_max_freq) - 1);
        else
                clk_div = 0xFF;
index 929701c..839fb2b 100644 (file)
@@ -1829,6 +1829,7 @@ static int e100_alloc_cbs(struct nic *nic)
                                  &nic->cbs_dma_addr);
        if (!nic->cbs)
                return -ENOMEM;
+       memset(nic->cbs, 0, count * sizeof(struct cb));
 
        for (cb = nic->cbs, i = 0; i < count; cb++, i++) {
                cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;
@@ -1837,7 +1838,6 @@ static int e100_alloc_cbs(struct nic *nic)
                cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb);
                cb->link = cpu_to_le32(nic->cbs_dma_addr +
                        ((i+1) % count) * sizeof(struct cb));
-               cb->skb = NULL;
        }
 
        nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs;
index c1a42cf..b979464 100644 (file)
@@ -1290,7 +1290,6 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
 static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
 {
        u32 ctrl;
-       u32 led_ctrl;
        s32 ret_val;
 
        ctrl = er32(CTRL);
@@ -1305,11 +1304,6 @@ static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
                break;
        case e1000_phy_igp_2:
                ret_val = e1000e_copper_link_setup_igp(hw);
-               /* Setup activity LED */
-               led_ctrl = er32(LEDCTL);
-               led_ctrl &= IGP_ACTIVITY_LED_MASK;
-               led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
-               ew32(LEDCTL, led_ctrl);
                break;
        default:
                return -E1000_ERR_PHY;
index 6850dc0..e0620d0 100644 (file)
@@ -357,8 +357,11 @@ static void gfar_init_mac(struct net_device *ndev)
        /* Configure the coalescing support */
        gfar_configure_coalescing(priv, 0xFF, 0xFF);
 
-       if (priv->rx_filer_enable)
+       if (priv->rx_filer_enable) {
                rctrl |= RCTRL_FILREN;
+               /* Program the RIR0 reg with the required distribution */
+               gfar_write(&regs->rir0, DEFAULT_RIR0);
+       }
 
        if (priv->rx_csum_enable)
                rctrl |= RCTRL_CHECKSUMMING;
@@ -414,6 +417,36 @@ static void gfar_init_mac(struct net_device *ndev)
        gfar_write(&regs->fifo_tx_starve_shutoff, priv->fifo_starve_off);
 }
 
+static struct net_device_stats *gfar_get_stats(struct net_device *dev)
+{
+       struct gfar_private *priv = netdev_priv(dev);
+       struct netdev_queue *txq;
+       unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0;
+       unsigned long tx_packets = 0, tx_bytes = 0;
+       int i = 0;
+
+       for (i = 0; i < priv->num_rx_queues; i++) {
+               rx_packets += priv->rx_queue[i]->stats.rx_packets;
+               rx_bytes += priv->rx_queue[i]->stats.rx_bytes;
+               rx_dropped += priv->rx_queue[i]->stats.rx_dropped;
+       }
+
+       dev->stats.rx_packets = rx_packets;
+       dev->stats.rx_bytes = rx_bytes;
+       dev->stats.rx_dropped = rx_dropped;
+
+       for (i = 0; i < priv->num_tx_queues; i++) {
+               txq = netdev_get_tx_queue(dev, i);
+               tx_bytes += txq->tx_bytes;
+               tx_packets += txq->tx_packets;
+       }
+
+       dev->stats.tx_bytes = tx_bytes;
+       dev->stats.tx_packets = tx_packets;
+
+       return &dev->stats;
+}
+
 static const struct net_device_ops gfar_netdev_ops = {
        .ndo_open = gfar_enet_open,
        .ndo_start_xmit = gfar_start_xmit,
@@ -423,6 +456,7 @@ static const struct net_device_ops gfar_netdev_ops = {
        .ndo_tx_timeout = gfar_timeout,
        .ndo_do_ioctl = gfar_ioctl,
        .ndo_select_queue = gfar_select_queue,
+       .ndo_get_stats = gfar_get_stats,
        .ndo_vlan_rx_register = gfar_vlan_rx_register,
        .ndo_set_mac_address = eth_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
@@ -1022,6 +1056,9 @@ static int gfar_probe(struct of_device *ofdev,
                priv->rx_queue[i]->rxic = DEFAULT_RXIC;
        }
 
+       /* enable filer if using multiple RX queues*/
+       if(priv->num_rx_queues > 1)
+               priv->rx_filer_enable = 1;
        /* Enable most messages by default */
        priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
 
@@ -1937,7 +1974,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        /* Update transmit stats */
-       dev->stats.tx_bytes += skb->len;
+       txq->tx_bytes += skb->len;
+       txq->tx_packets ++;
 
        txbdp = txbdp_start = tx_queue->cur_tx;
 
@@ -2295,8 +2333,6 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
        tx_queue->skb_dirtytx = skb_dirtytx;
        tx_queue->dirty_tx = bdp;
 
-       dev->stats.tx_packets += howmany;
-
        return howmany;
 }
 
@@ -2510,14 +2546,14 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
                        }
                } else {
                        /* Increment the number of packets */
-                       dev->stats.rx_packets++;
+                       rx_queue->stats.rx_packets++;
                        howmany++;
 
                        if (likely(skb)) {
                                pkt_len = bdp->length - ETH_FCS_LEN;
                                /* Remove the FCS from the packet length */
                                skb_put(skb, pkt_len);
-                               dev->stats.rx_bytes += pkt_len;
+                               rx_queue->stats.rx_bytes += pkt_len;
 
                                gfar_process_frame(dev, skb, amount_pull);
 
@@ -2525,7 +2561,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
                                if (netif_msg_rx_err(priv))
                                        printk(KERN_WARNING
                                               "%s: Missing skb!\n", dev->name);
-                               dev->stats.rx_dropped++;
+                               rx_queue->stats.rx_dropped++;
                                priv->extra_stats.rx_skbmissing++;
                        }
 
index cbb4510..3d72dc4 100644 (file)
@@ -333,7 +333,7 @@ extern const char gfar_driver_version[];
 #define IMASK_BSY               0x20000000
 #define IMASK_EBERR             0x10000000
 #define IMASK_MSRO             0x04000000
-#define IMASK_GRSC              0x02000000
+#define IMASK_GTSC              0x02000000
 #define IMASK_BABT             0x01000000
 #define IMASK_TXC               0x00800000
 #define IMASK_TXEEN            0x00400000
@@ -344,7 +344,7 @@ extern const char gfar_driver_version[];
 #define IMASK_XFUN             0x00010000
 #define IMASK_RXB0              0x00008000
 #define IMASK_MAG              0x00000800
-#define IMASK_GTSC              0x00000100
+#define IMASK_GRSC              0x00000100
 #define IMASK_RXFEN0           0x00000080
 #define IMASK_FIR              0x00000008
 #define IMASK_FIQ              0x00000004
@@ -401,6 +401,10 @@ extern const char gfar_driver_version[];
 #define FPR_FILER_MASK 0xFFFFFFFF
 #define MAX_FILER_IDX  0xFF
 
+/* This default RIR value directly corresponds
+ * to the 3-bit hash value generated */
+#define DEFAULT_RIR0   0x05397700
+
 /* RQFCR register bits */
 #define RQFCR_GPI              0x80000000
 #define RQFCR_HASHTBL_Q                0x00000000
@@ -936,6 +940,15 @@ struct gfar_priv_tx_q {
        unsigned short txtime;
 };
 
+/*
+ * Per RX queue stats
+ */
+struct rx_q_stats {
+       unsigned long rx_packets;
+       unsigned long rx_bytes;
+       unsigned long rx_dropped;
+};
+
 /**
  *     struct gfar_priv_rx_q - per rx queue structure
  *     @rxlock: per queue rx spin lock
@@ -958,6 +971,7 @@ struct gfar_priv_rx_q {
        struct  rxbd8 *cur_rx;
        struct  net_device *dev;
        struct gfar_priv_grp *grp;
+       struct rx_q_stats stats;
        u16     skb_currx;
        u16     qindex;
        unsigned int    rx_ring_size;
index f499684..6cae26a 100644 (file)
@@ -57,7 +57,9 @@ static int use_msi = 1;
 
 static int use_msi_x = 1;
 
-static unsigned long auto_fw_reset = AUTO_FW_RESET_ENABLED;
+static int auto_fw_reset = AUTO_FW_RESET_ENABLED;
+module_param(auto_fw_reset, int, 0644);
+MODULE_PARM_DESC(auto_fw_reset,"Auto firmware reset (0=disabled, 1=enabled");
 
 static int __devinit netxen_nic_probe(struct pci_dev *pdev,
                const struct pci_device_id *ent);
@@ -2534,42 +2536,6 @@ static struct bin_attribute bin_attr_mem = {
        .write = netxen_sysfs_write_mem,
 };
 
-#ifdef CONFIG_MODULES
-static ssize_t
-netxen_store_auto_fw_reset(struct module_attribute *mattr,
-               struct module *mod, const char *buf, size_t count)
-
-{
-       unsigned long new;
-
-       if (strict_strtoul(buf, 16, &new))
-               return -EINVAL;
-
-       if ((new == AUTO_FW_RESET_ENABLED) || (new == AUTO_FW_RESET_DISABLED)) {
-               auto_fw_reset = new;
-               return count;
-       }
-
-       return -EINVAL;
-}
-
-static ssize_t
-netxen_show_auto_fw_reset(struct module_attribute *mattr,
-               struct module *mod, char *buf)
-
-{
-       if (auto_fw_reset == AUTO_FW_RESET_ENABLED)
-               return sprintf(buf, "enabled\n");
-       else
-               return sprintf(buf, "disabled\n");
-}
-
-static struct module_attribute mod_attr_fw_reset = {
-       .attr = {.name = "auto_fw_reset", .mode = (S_IRUGO | S_IWUSR)},
-       .show = netxen_show_auto_fw_reset,
-       .store = netxen_store_auto_fw_reset,
-};
-#endif
 
 static void
 netxen_create_sysfs_entries(struct netxen_adapter *adapter)
@@ -2775,23 +2741,12 @@ static struct pci_driver netxen_driver = {
 
 static int __init netxen_init_module(void)
 {
-#ifdef CONFIG_MODULES
-       struct module *mod = THIS_MODULE;
-#endif
-
        printk(KERN_INFO "%s\n", netxen_nic_driver_string);
 
 #ifdef CONFIG_INET
        register_netdevice_notifier(&netxen_netdev_cb);
        register_inetaddr_notifier(&netxen_inetaddr_cb);
 #endif
-
-#ifdef CONFIG_MODULES
-       if (sysfs_create_file(&mod->mkobj.kobj, &mod_attr_fw_reset.attr))
-               printk(KERN_ERR "%s: Failed to create auto_fw_reset "
-                               "sysfs entry.", netxen_nic_driver_name);
-#endif
-
        return pci_register_driver(&netxen_driver);
 }
 
@@ -2799,12 +2754,6 @@ module_init(netxen_init_module);
 
 static void __exit netxen_exit_module(void)
 {
-#ifdef CONFIG_MODULES
-       struct module *mod = THIS_MODULE;
-
-       sysfs_remove_file(&mod->mkobj.kobj, &mod_attr_fw_reset.attr);
-#endif
-
        pci_unregister_driver(&netxen_driver);
 
 #ifdef CONFIG_INET
index f63c96a..c13cf64 100644 (file)
@@ -326,7 +326,8 @@ error:
 
 static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
 {
-       u32 val, orig;
+       u32 orig;
+       int val;
        bool clk125en = true;
 
        /* Abort if we are using an untested phy. */
index b9b371b..42611be 100644 (file)
@@ -1365,7 +1365,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
        priv->dnld_sent = DNLD_RES_RECEIVED;
 
        /* If nothing to do, go back to sleep (?) */
-       if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx])
+       if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx])
                priv->psstate = PS_STATE_SLEEP;
 
        spin_unlock_irqrestore(&priv->driver_lock, flags);
@@ -1439,7 +1439,7 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv)
        }
 
        /* Pending events or command responses? */
-       if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
+       if (kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
                allowed = 0;
                lbs_deb_host("pending events or command responses\n");
        }
index 6a8d2b2..05bb298 100644 (file)
@@ -10,7 +10,7 @@
 #include "scan.h"
 #include "assoc.h"
 
-
+#include <linux/kfifo.h>
 
 /** sleep_params */
 struct sleep_params {
@@ -120,7 +120,7 @@ struct lbs_private {
        u32 resp_len[2];
 
        /* Events sent from hardware to driver */
-       struct kfifo *event_fifo;
+       struct kfifo event_fifo;
 
        /** thread to service interrupts */
        struct task_struct *main_thread;
index db38a5a..c2975c8 100644 (file)
@@ -459,7 +459,7 @@ static int lbs_thread(void *data)
                else if (!list_empty(&priv->cmdpendingq) &&
                                        !(priv->wakeup_dev_required))
                        shouldsleep = 0;        /* We have a command to send */
-               else if (__kfifo_len(priv->event_fifo))
+               else if (kfifo_len(&priv->event_fifo))
                        shouldsleep = 0;        /* We have an event to process */
                else
                        shouldsleep = 1;        /* No command */
@@ -511,10 +511,13 @@ static int lbs_thread(void *data)
 
                /* Process hardware events, e.g. card removed, link lost */
                spin_lock_irq(&priv->driver_lock);
-               while (__kfifo_len(priv->event_fifo)) {
+               while (kfifo_len(&priv->event_fifo)) {
                        u32 event;
-                       __kfifo_get(priv->event_fifo, (unsigned char *) &event,
-                               sizeof(event));
+
+                       if (kfifo_out(&priv->event_fifo,
+                               (unsigned char *) &event, sizeof(event)) !=
+                               sizeof(event))
+                                       break;
                        spin_unlock_irq(&priv->driver_lock);
                        lbs_process_event(priv, event);
                        spin_lock_irq(&priv->driver_lock);
@@ -883,10 +886,9 @@ static int lbs_init_adapter(struct lbs_private *priv)
        priv->resp_len[0] = priv->resp_len[1] = 0;
 
        /* Create the event FIFO */
-       priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL);
-       if (IS_ERR(priv->event_fifo)) {
+       ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL);
+       if (ret) {
                lbs_pr_err("Out of memory allocating event FIFO buffer\n");
-               ret = -ENOMEM;
                goto out;
        }
 
@@ -901,8 +903,7 @@ static void lbs_free_adapter(struct lbs_private *priv)
        lbs_deb_enter(LBS_DEB_MAIN);
 
        lbs_free_cmd_buffer(priv);
-       if (priv->event_fifo)
-               kfifo_free(priv->event_fifo);
+       kfifo_free(&priv->event_fifo);
        del_timer(&priv->command_timer);
        del_timer(&priv->auto_deepsleep_timer);
        kfree(priv->networks);
@@ -1177,7 +1178,7 @@ void lbs_queue_event(struct lbs_private *priv, u32 event)
        if (priv->psstate == PS_STATE_SLEEP)
                priv->psstate = PS_STATE_AWAKE;
 
-       __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32));
+       kfifo_in(&priv->event_fifo, (unsigned char *) &event, sizeof(u32));
 
        wake_up_interruptible(&priv->waitq);
 
index bcd4ba8..b66029b 100644 (file)
@@ -164,7 +164,7 @@ struct fujitsu_hotkey_t {
        struct input_dev *input;
        char phys[32];
        struct platform_device *pf_device;
-       struct kfifo *fifo;
+       struct kfifo fifo;
        spinlock_t fifo_lock;
        int rfkill_supported;
        int rfkill_state;
@@ -824,12 +824,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
 
        /* kfifo */
        spin_lock_init(&fujitsu_hotkey->fifo_lock);
-       fujitsu_hotkey->fifo =
-           kfifo_alloc(RINGBUFFERSIZE * sizeof(int), GFP_KERNEL,
-                       &fujitsu_hotkey->fifo_lock);
-       if (IS_ERR(fujitsu_hotkey->fifo)) {
+       error = kfifo_alloc(&fujitsu_hotkey->fifo, RINGBUFFERSIZE * sizeof(int),
+                       GFP_KERNEL);
+       if (error) {
                printk(KERN_ERR "kfifo_alloc failed\n");
-               error = PTR_ERR(fujitsu_hotkey->fifo);
                goto err_stop;
        }
 
@@ -934,7 +932,7 @@ err_unregister_input_dev:
 err_free_input_dev:
        input_free_device(input);
 err_free_fifo:
-       kfifo_free(fujitsu_hotkey->fifo);
+       kfifo_free(&fujitsu_hotkey->fifo);
 err_stop:
        return result;
 }
@@ -956,7 +954,7 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
 
        input_free_device(input);
 
-       kfifo_free(fujitsu_hotkey->fifo);
+       kfifo_free(&fujitsu_hotkey->fifo);
 
        fujitsu_hotkey->acpi_handle = NULL;
 
@@ -1008,9 +1006,10 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event)
                                vdbg_printk(FUJLAPTOP_DBG_TRACE,
                                        "Push keycode into ringbuffer [%d]\n",
                                        keycode);
-                               status = kfifo_put(fujitsu_hotkey->fifo,
+                               status = kfifo_in_locked(&fujitsu_hotkey->fifo,
                                                   (unsigned char *)&keycode,
-                                                  sizeof(keycode));
+                                                  sizeof(keycode),
+                                                  &fujitsu_hotkey->fifo_lock);
                                if (status != sizeof(keycode)) {
                                        vdbg_printk(FUJLAPTOP_DBG_WARN,
                                            "Could not push keycode [0x%x]\n",
@@ -1021,11 +1020,12 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event)
                                }
                        } else if (keycode == 0) {
                                while ((status =
-                                       kfifo_get
-                                       (fujitsu_hotkey->fifo, (unsigned char *)
-                                        &keycode_r,
-                                        sizeof
-                                        (keycode_r))) == sizeof(keycode_r)) {
+                                       kfifo_out_locked(
+                                        &fujitsu_hotkey->fifo,
+                                        (unsigned char *) &keycode_r,
+                                        sizeof(keycode_r),
+                                        &fujitsu_hotkey->fifo_lock))
+                                        == sizeof(keycode_r)) {
                                        input_report_key(input, keycode_r, 0);
                                        input_sync(input);
                                        vdbg_printk(FUJLAPTOP_DBG_TRACE,
index 7a2cc8a..2896ca4 100644 (file)
@@ -142,7 +142,7 @@ struct sony_laptop_input_s {
        atomic_t                users;
        struct input_dev        *jog_dev;
        struct input_dev        *key_dev;
-       struct kfifo            *fifo;
+       struct kfifo            fifo;
        spinlock_t              fifo_lock;
        struct workqueue_struct *wq;
 };
@@ -300,8 +300,9 @@ static void do_sony_laptop_release_key(struct work_struct *work)
 {
        struct sony_laptop_keypress kp;
 
-       while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp,
-                        sizeof(kp)) == sizeof(kp)) {
+       while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp,
+                       sizeof(kp), &sony_laptop_input.fifo_lock)
+                       == sizeof(kp)) {
                msleep(10);
                input_report_key(kp.dev, kp.key, 0);
                input_sync(kp.dev);
@@ -362,8 +363,9 @@ static void sony_laptop_report_input_event(u8 event)
                /* we emit the scancode so we can always remap the key */
                input_event(kp.dev, EV_MSC, MSC_SCAN, event);
                input_sync(kp.dev);
-               kfifo_put(sony_laptop_input.fifo,
-                         (unsigned char *)&kp, sizeof(kp));
+               kfifo_in_locked(&sony_laptop_input.fifo,
+                         (unsigned char *)&kp, sizeof(kp),
+                         &sony_laptop_input.fifo_lock);
 
                if (!work_pending(&sony_laptop_release_key_work))
                        queue_work(sony_laptop_input.wq,
@@ -385,12 +387,10 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
 
        /* kfifo */
        spin_lock_init(&sony_laptop_input.fifo_lock);
-       sony_laptop_input.fifo =
-               kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
-                           &sony_laptop_input.fifo_lock);
-       if (IS_ERR(sony_laptop_input.fifo)) {
+       error =
+        kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
+       if (error) {
                printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
-               error = PTR_ERR(sony_laptop_input.fifo);
                goto err_dec_users;
        }
 
@@ -474,7 +474,7 @@ err_destroy_wq:
        destroy_workqueue(sony_laptop_input.wq);
 
 err_free_kfifo:
-       kfifo_free(sony_laptop_input.fifo);
+       kfifo_free(&sony_laptop_input.fifo);
 
 err_dec_users:
        atomic_dec(&sony_laptop_input.users);
@@ -500,7 +500,7 @@ static void sony_laptop_remove_input(void)
        }
 
        destroy_workqueue(sony_laptop_input.wq);
-       kfifo_free(sony_laptop_input.fifo);
+       kfifo_free(&sony_laptop_input.fifo);
 }
 
 /*********** Platform Device ***********/
@@ -2079,7 +2079,7 @@ static struct attribute_group spic_attribute_group = {
 
 struct sonypi_compat_s {
        struct fasync_struct    *fifo_async;
-       struct kfifo            *fifo;
+       struct kfifo            fifo;
        spinlock_t              fifo_lock;
        wait_queue_head_t       fifo_proc_list;
        atomic_t                open_count;
@@ -2104,12 +2104,12 @@ static int sonypi_misc_open(struct inode *inode, struct file *file)
        /* Flush input queue on first open */
        unsigned long flags;
 
-       spin_lock_irqsave(sonypi_compat.fifo->lock, flags);
+       spin_lock_irqsave(&sonypi_compat.fifo_lock, flags);
 
        if (atomic_inc_return(&sonypi_compat.open_count) == 1)
-               __kfifo_reset(sonypi_compat.fifo);
+               kfifo_reset(&sonypi_compat.fifo);
 
-       spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags);
+       spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags);
 
        return 0;
 }
@@ -2120,17 +2120,18 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
        ssize_t ret;
        unsigned char c;
 
-       if ((kfifo_len(sonypi_compat.fifo) == 0) &&
+       if ((kfifo_len(&sonypi_compat.fifo) == 0) &&
            (file->f_flags & O_NONBLOCK))
                return -EAGAIN;
 
        ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
-                                      kfifo_len(sonypi_compat.fifo) != 0);
+                                      kfifo_len(&sonypi_compat.fifo) != 0);
        if (ret)
                return ret;
 
        while (ret < count &&
-              (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) {
+              (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c),
+                         &sonypi_compat.fifo_lock) == sizeof(c))) {
                if (put_user(c, buf++))
                        return -EFAULT;
                ret++;
@@ -2147,7 +2148,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
 static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
 {
        poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
-       if (kfifo_len(sonypi_compat.fifo))
+       if (kfifo_len(&sonypi_compat.fifo))
                return POLLIN | POLLRDNORM;
        return 0;
 }
@@ -2309,7 +2310,8 @@ static struct miscdevice sonypi_misc_device = {
 
 static void sonypi_compat_report_event(u8 event)
 {
-       kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event));
+       kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event,
+                       sizeof(event), &sonypi_compat.fifo_lock);
        kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
        wake_up_interruptible(&sonypi_compat.fifo_proc_list);
 }
@@ -2319,11 +2321,11 @@ static int sonypi_compat_init(void)
        int error;
 
        spin_lock_init(&sonypi_compat.fifo_lock);
-       sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
-                                        &sonypi_compat.fifo_lock);
-       if (IS_ERR(sonypi_compat.fifo)) {
+       error =
+        kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
+       if (error) {
                printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
-               return PTR_ERR(sonypi_compat.fifo);
+               return error;
        }
 
        init_waitqueue_head(&sonypi_compat.fifo_proc_list);
@@ -2342,14 +2344,14 @@ static int sonypi_compat_init(void)
        return 0;
 
 err_free_kfifo:
-       kfifo_free(sonypi_compat.fifo);
+       kfifo_free(&sonypi_compat.fifo);
        return error;
 }
 
 static void sonypi_compat_exit(void)
 {
        misc_deregister(&sonypi_misc_device);
-       kfifo_free(sonypi_compat.fifo);
+       kfifo_free(&sonypi_compat.fifo);
 }
 #else
 static int sonypi_compat_init(void) { return 0; }
index fd12317..148b1dd 100644 (file)
@@ -218,7 +218,7 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
                spin_unlock_irqrestore(&aliastree.lock, flags);
                newlcu = _allocate_lcu(uid);
                if (IS_ERR(newlcu))
-                       return PTR_ERR(lcu);
+                       return PTR_ERR(newlcu);
                spin_lock_irqsave(&aliastree.lock, flags);
                lcu = _find_lcu(server, uid);
                if (!lcu) {
index f64d0db..6e14863 100644 (file)
@@ -8,7 +8,7 @@
  *
  */
 
-#define KMSG_COMPONENT "dasd-diag"
+#define KMSG_COMPONENT "dasd"
 
 #include <linux/stddef.h>
 #include <linux/kernel.h>
@@ -146,16 +146,16 @@ dasd_diag_erp(struct dasd_device *device)
        rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);
        if (rc == 4) {
                if (!(device->features & DASD_FEATURE_READONLY)) {
-                       dev_warn(&device->cdev->dev,
-                                "The access mode of a DIAG device changed"
-                                " to read-only");
+                       pr_warning("%s: The access mode of a DIAG device "
+                                  "changed to read-only\n",
+                                  dev_name(&device->cdev->dev));
                        device->features |= DASD_FEATURE_READONLY;
                }
                rc = 0;
        }
        if (rc)
-               dev_warn(&device->cdev->dev, "DIAG ERP failed with "
-                           "rc=%d\n", rc);
+               pr_warning("%s: DIAG ERP failed with "
+                           "rc=%d\n", dev_name(&device->cdev->dev), rc);
 }
 
 /* Start a given request at the device. Return zero on success, non-zero
@@ -371,8 +371,9 @@ dasd_diag_check_device(struct dasd_device *device)
                private->pt_block = 2;
                break;
        default:
-               dev_warn(&device->cdev->dev, "Device type %d is not supported "
-                           "in DIAG mode\n", private->rdc_data.vdev_class);
+               pr_warning("%s: Device type %d is not supported "
+                          "in DIAG mode\n", dev_name(&device->cdev->dev),
+                          private->rdc_data.vdev_class);
                rc = -EOPNOTSUPP;
                goto out;
        }
@@ -413,8 +414,8 @@ dasd_diag_check_device(struct dasd_device *device)
                private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
                rc = dia250(&private->iob, RW_BIO);
                if (rc == 3) {
-                       dev_warn(&device->cdev->dev,
-                               "A 64-bit DIAG call failed\n");
+                       pr_warning("%s: A 64-bit DIAG call failed\n",
+                                  dev_name(&device->cdev->dev));
                        rc = -EOPNOTSUPP;
                        goto out_label;
                }
@@ -423,8 +424,9 @@ dasd_diag_check_device(struct dasd_device *device)
                        break;
        }
        if (bsize > PAGE_SIZE) {
-               dev_warn(&device->cdev->dev, "Accessing the DASD failed because"
-                        " of an incorrect format (rc=%d)\n", rc);
+               pr_warning("%s: Accessing the DASD failed because of an "
+                          "incorrect format (rc=%d)\n",
+                          dev_name(&device->cdev->dev), rc);
                rc = -EIO;
                goto out_label;
        }
@@ -442,18 +444,18 @@ dasd_diag_check_device(struct dasd_device *device)
                block->s2b_shift++;
        rc = mdsk_init_io(device, block->bp_block, 0, NULL);
        if (rc && (rc != 4)) {
-               dev_warn(&device->cdev->dev, "DIAG initialization "
-                       "failed with rc=%d\n", rc);
+               pr_warning("%s: DIAG initialization failed with rc=%d\n",
+                          dev_name(&device->cdev->dev), rc);
                rc = -EIO;
        } else {
                if (rc == 4)
                        device->features |= DASD_FEATURE_READONLY;
-               dev_info(&device->cdev->dev,
-                        "New DASD with %ld byte/block, total size %ld KB%s\n",
-                        (unsigned long) block->bp_block,
-                        (unsigned long) (block->blocks <<
-                                         block->s2b_shift) >> 1,
-                        (rc == 4) ? ", read-only device" : "");
+               pr_info("%s: New DASD with %ld byte/block, total size %ld "
+                       "KB%s\n", dev_name(&device->cdev->dev),
+                       (unsigned long) block->bp_block,
+                       (unsigned long) (block->blocks <<
+                                        block->s2b_shift) >> 1,
+                       (rc == 4) ? ", read-only device" : "");
                rc = 0;
        }
 out_label:
index 28e4649..247b2b9 100644 (file)
@@ -467,7 +467,7 @@ fs3270_open(struct inode *inode, struct file *filp)
        if (IS_ERR(ib)) {
                raw3270_put_view(&fp->view);
                raw3270_del_view(&fp->view);
-               rc = PTR_ERR(fp);
+               rc = PTR_ERR(ib);
                goto out;
        }
        fp->rdbuf = ib;
index 3657fe1..cb70fa1 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #define KMSG_COMPONENT "tape_34xx"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/module.h>
 #include <linux/init.h>
index 0c72aad..9821c58 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #define KMSG_COMPONENT "tape_3590"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/module.h>
 #include <linux/init.h>
@@ -136,7 +137,7 @@ static void int_to_ext_kekl(struct tape3592_kekl *in,
                out->type_on_tape = TAPE390_KEKL_TYPE_LABEL;
        memcpy(out->label, in->label, sizeof(in->label));
        EBCASC(out->label, sizeof(in->label));
-       strstrip(out->label);
+       strim(out->label);
 }
 
 static void int_to_ext_kekl_pair(struct tape3592_kekl_pair *in,
index 4799cc2..9681614 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #define KMSG_COMPONENT "tape"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/fs.h>
 #include <linux/module.h>
index 23d773a..2125ec7 100644 (file)
@@ -10,6 +10,9 @@
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
+#define KMSG_COMPONENT "tape"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
index ddc914c..b2864e3 100644 (file)
@@ -7,6 +7,10 @@
  * Author: Stefan Bader <shbader@de.ibm.com>
  * Based on simple class device code by Greg K-H
  */
+
+#define KMSG_COMPONENT "tape"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include "tape_class.h"
 
 MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>");
index f5d6802..81b094e 100644 (file)
@@ -12,6 +12,8 @@
  */
 
 #define KMSG_COMPONENT "tape"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>             // for kernel parameters
 #include <linux/kmod.h>             // for requesting modules
index ebd820c..0ceb379 100644 (file)
@@ -11,6 +11,9 @@
  * PROCFS Functions
  */
 
+#define KMSG_COMPONENT "tape"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/seq_file.h>
index 750354a..03f07e5 100644 (file)
@@ -11,6 +11,9 @@
  *              Stefan Bader <shbader@de.ibm.com>
  */
 
+#define KMSG_COMPONENT "tape"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/bio.h>
index 9509e38..7a28a30 100644 (file)
@@ -49,7 +49,6 @@ static u16 ccwreq_next_path(struct ccw_device *cdev)
  */
 static void ccwreq_stop(struct ccw_device *cdev, int rc)
 {
-       struct subchannel *sch = to_subchannel(cdev->dev.parent);
        struct ccw_request *req = &cdev->private->req;
 
        if (req->done)
@@ -57,7 +56,6 @@ static void ccwreq_stop(struct ccw_device *cdev, int rc)
        req->done = 1;
        ccw_device_set_timeout(cdev, 0);
        memset(&cdev->private->irb, 0, sizeof(struct irb));
-       sch->lpm = sch->schib.pmcw.pam;
        if (rc && rc != -ENODEV && req->drc)
                rc = req->drc;
        req->callback(cdev, req->data, rc);
@@ -80,7 +78,6 @@ static void ccwreq_do(struct ccw_device *cdev)
                        continue;
                }
                /* Perform start function. */
-               sch->lpm = 0xff;
                memset(&cdev->private->irb, 0, sizeof(struct irb));
                rc = cio_start(sch, cp, (u8) req->mask);
                if (rc == 0) {
index 73901c9..a6c7d54 100644 (file)
@@ -1519,6 +1519,7 @@ static int ccw_device_console_enable(struct ccw_device *cdev,
        sch->driver = &io_subchannel_driver;
        /* Initialize the ccw_device structure. */
        cdev->dev.parent= &sch->dev;
+       sch_set_cdev(sch, cdev);
        io_subchannel_recog(cdev, sch);
        /* Now wait for the async. recognition to come to an end. */
        spin_lock_irq(cdev->ccwlock);
index aad188e..6facb54 100644 (file)
@@ -142,7 +142,7 @@ static void spid_do(struct ccw_device *cdev)
        u8 fn;
 
        /* Use next available path that is not already in correct state. */
-       req->lpm = lpm_adjust(req->lpm, sch->schib.pmcw.pam & ~sch->vpm);
+       req->lpm = lpm_adjust(req->lpm, cdev->private->pgid_todo_mask);
        if (!req->lpm)
                goto out_nopath;
        /* Channel program setup. */
@@ -254,15 +254,15 @@ static void pgid_analyze(struct ccw_device *cdev, struct pgid **p,
        *p = first;
 }
 
-static u8 pgid_to_vpm(struct ccw_device *cdev)
+static u8 pgid_to_donepm(struct ccw_device *cdev)
 {
        struct subchannel *sch = to_subchannel(cdev->dev.parent);
        struct pgid *pgid;
        int i;
        int lpm;
-       u8 vpm = 0;
+       u8 donepm = 0;
 
-       /* Set VPM bits for paths which are already in the target state. */
+       /* Set bits for paths which are already in the target state. */
        for (i = 0; i < 8; i++) {
                lpm = 0x80 >> i;
                if ((cdev->private->pgid_valid_mask & lpm) == 0)
@@ -282,10 +282,10 @@ static u8 pgid_to_vpm(struct ccw_device *cdev)
                        if (pgid->inf.ps.state3 != SNID_STATE3_SINGLE_PATH)
                                continue;
                }
-               vpm |= lpm;
+               donepm |= lpm;
        }
 
-       return vpm;
+       return donepm;
 }
 
 static void pgid_fill(struct ccw_device *cdev, struct pgid *pgid)
@@ -307,6 +307,7 @@ static void snid_done(struct ccw_device *cdev, int rc)
        int mismatch = 0;
        int reserved = 0;
        int reset = 0;
+       u8 donepm;
 
        if (rc)
                goto out;
@@ -316,18 +317,20 @@ static void snid_done(struct ccw_device *cdev, int rc)
        else if (mismatch)
                rc = -EOPNOTSUPP;
        else {
-               sch->vpm = pgid_to_vpm(cdev);
+               donepm = pgid_to_donepm(cdev);
+               sch->vpm = donepm & sch->opm;
+               cdev->private->pgid_todo_mask &= ~donepm;
                pgid_fill(cdev, pgid);
        }
 out:
        CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x vpm=%02x "
-                     "mism=%d rsvd=%d reset=%d\n", id->ssid, id->devno, rc,
-                     cdev->private->pgid_valid_mask, sch->vpm, mismatch,
-                     reserved, reset);
+                     "todo=%02x mism=%d rsvd=%d reset=%d\n", id->ssid,
+                     id->devno, rc, cdev->private->pgid_valid_mask, sch->vpm,
+                     cdev->private->pgid_todo_mask, mismatch, reserved, reset);
        switch (rc) {
        case 0:
                /* Anything left to do? */
-               if (sch->vpm == sch->schib.pmcw.pam) {
+               if (cdev->private->pgid_todo_mask == 0) {
                        verify_done(cdev, sch->vpm == 0 ? -EACCES : 0);
                        return;
                }
@@ -411,6 +414,7 @@ static void verify_start(struct ccw_device *cdev)
        struct ccw_dev_id *devid = &cdev->private->dev_id;
 
        sch->vpm = 0;
+       sch->lpm = sch->schib.pmcw.pam;
        /* Initialize request data. */
        memset(req, 0, sizeof(*req));
        req->timeout    = PGID_TIMEOUT;
@@ -442,11 +446,14 @@ static void verify_start(struct ccw_device *cdev)
  */
 void ccw_device_verify_start(struct ccw_device *cdev)
 {
+       struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
        CIO_TRACE_EVENT(4, "vrfy");
        CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id));
        /* Initialize PGID data. */
        memset(cdev->private->pgid, 0, sizeof(cdev->private->pgid));
        cdev->private->pgid_valid_mask = 0;
+       cdev->private->pgid_todo_mask = sch->schib.pmcw.pam;
        /*
         * Initialize pathgroup and multipath state with target values.
         * They may change in the course of path verification.
index 61677df..ca5e9bb 100644 (file)
@@ -163,7 +163,7 @@ void tcw_finalize(struct tcw *tcw, int num_tidaws)
        /* Add tcat to tccb. */
        tccb = tcw_get_tccb(tcw);
        tcat = (struct tccb_tcat *) &tccb->tca[tca_size(tccb)];
-       memset(tcat, 0, sizeof(tcat));
+       memset(tcat, 0, sizeof(*tcat));
        /* Calculate tcw input/output count and tcat transport count. */
        count = calc_dcw_count(tccb);
        if (tcw->w && (tcw->flags & TCW_FLAGS_OUTPUT_TIDA))
@@ -269,7 +269,7 @@ EXPORT_SYMBOL(tccb_init);
  */
 void tsb_init(struct tsb *tsb)
 {
-       memset(tsb, 0, sizeof(tsb));
+       memset(tsb, 0, sizeof(*tsb));
 }
 EXPORT_SYMBOL(tsb_init);
 
index d72ae4c..b9ce712 100644 (file)
@@ -150,6 +150,7 @@ struct ccw_device_private {
        struct ccw_request req;         /* internal I/O request */
        int iretry;
        u8 pgid_valid_mask;             /* mask of valid PGIDs */
+       u8 pgid_todo_mask;              /* mask of PGIDs to be adjusted */
        struct {
                unsigned int fast:1;    /* post with "channel end" */
                unsigned int repall:1;  /* report every interrupt status */
index 4be6e84..b2275c5 100644 (file)
@@ -486,7 +486,8 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
        case SLSB_P_INPUT_PRIMED:
                inbound_primed(q, count);
                q->first_to_check = add_buf(q->first_to_check, count);
-               atomic_sub(count, &q->nr_buf_used);
+               if (atomic_sub(count, &q->nr_buf_used) == 0)
+                       qdio_perf_stat_inc(&perf_stats.inbound_queue_full);
                break;
        case SLSB_P_INPUT_ERROR:
                announce_buffer_error(q, count);
index 968e3c7..54f7c32 100644 (file)
@@ -64,6 +64,8 @@ static int qdio_perf_proc_show(struct seq_file *m, void *v)
                   (long)atomic_long_read(&perf_stats.fast_requeue));
        seq_printf(m, "Number of outbound target full condition\t: %li\n",
                   (long)atomic_long_read(&perf_stats.outbound_target_full));
+       seq_printf(m, "Number of inbound queue full condition\t\t: %li\n",
+                  (long)atomic_long_read(&perf_stats.inbound_queue_full));
        seq_printf(m, "Number of outbound tasklet mod_timer calls\t: %li\n",
                   (long)atomic_long_read(&perf_stats.debug_tl_out_timer));
        seq_printf(m, "Number of stop polling calls\t\t\t: %li\n",
index ff4504c..1245423 100644 (file)
@@ -36,6 +36,7 @@ struct qdio_perf_stats {
        atomic_long_t outbound_handler;
        atomic_long_t fast_requeue;
        atomic_long_t outbound_target_full;
+       atomic_long_t inbound_queue_full;
 
        /* for debugging */
        atomic_long_t debug_tl_out_timer;
index 18d54fc..8c2dea5 100644 (file)
@@ -48,7 +48,6 @@ static void set_impl_params(struct qdio_irq *irq_ptr,
        if (!irq_ptr)
                return;
 
-       WARN_ON((unsigned long)&irq_ptr->qib & 0xff);
        irq_ptr->qib.pfmt = qib_param_field_format;
        if (qib_param_field)
                memcpy(irq_ptr->qib.parm, qib_param_field,
@@ -82,14 +81,12 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues)
                q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL);
                if (!q)
                        return -ENOMEM;
-               WARN_ON((unsigned long)q & 0xff);
 
                q->slib = (struct slib *) __get_free_page(GFP_KERNEL);
                if (!q->slib) {
                        kmem_cache_free(qdio_q_cache, q);
                        return -ENOMEM;
                }
-               WARN_ON((unsigned long)q->slib & 0x7ff);
                irq_ptr_qs[i] = q;
        }
        return 0;
@@ -131,7 +128,7 @@ static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
        /* fill in sbal */
        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) {
                q->sbal[j] = *sbals_array++;
-               WARN_ON((unsigned long)q->sbal[j] & 0xff);
+               BUG_ON((unsigned long)q->sbal[j] & 0xff);
        }
 
        /* fill in slib */
@@ -147,11 +144,6 @@ static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
        /* fill in sl */
        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
                q->sl->element[j].sbal = (unsigned long)q->sbal[j];
-
-       DBF_EVENT("sl-slsb-sbal");
-       DBF_HEX(q->sl, sizeof(void *));
-       DBF_HEX(&q->slsb, sizeof(void *));
-       DBF_HEX(q->sbal, sizeof(void *));
 }
 
 static void setup_queues(struct qdio_irq *irq_ptr,
index b7689f3..c28a712 100644 (file)
@@ -517,7 +517,7 @@ static void iscsi_free_task(struct iscsi_task *task)
        if (conn->login_task == task)
                return;
 
-       __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*));
+       kfifo_in(&session->cmdpool.queue, (void*)&task, sizeof(void*));
 
        if (sc) {
                task->sc = NULL;
@@ -737,7 +737,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
                BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
                BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
 
-               if (!__kfifo_get(session->cmdpool.queue,
+               if (!kfifo_out(&session->cmdpool.queue,
                                 (void*)&task, sizeof(void*)))
                        return NULL;
        }
@@ -1567,7 +1567,7 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn,
 {
        struct iscsi_task *task;
 
-       if (!__kfifo_get(conn->session->cmdpool.queue,
+       if (!kfifo_out(&conn->session->cmdpool.queue,
                         (void *) &task, sizeof(void *)))
                return NULL;
 
@@ -2461,12 +2461,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
        if (q->pool == NULL)
                return -ENOMEM;
 
-       q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
-                             GFP_KERNEL, NULL);
-       if (IS_ERR(q->queue)) {
-               q->queue = NULL;
-               goto enomem;
-       }
+       kfifo_init(&q->queue, (void*)q->pool, max * sizeof(void*));
 
        for (i = 0; i < max; i++) {
                q->pool[i] = kzalloc(item_size, GFP_KERNEL);
@@ -2474,7 +2469,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
                        q->max = i;
                        goto enomem;
                }
-               __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*));
+               kfifo_in(&q->queue, (void*)&q->pool[i], sizeof(void*));
        }
 
        if (items) {
@@ -2497,7 +2492,6 @@ void iscsi_pool_free(struct iscsi_pool *q)
        for (i = 0; i < q->max; i++)
                kfree(q->pool[i]);
        kfree(q->pool);
-       kfree(q->queue);
 }
 EXPORT_SYMBOL_GPL(iscsi_pool_free);
 
@@ -2825,7 +2819,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
 
        /* allocate login_task used for the login/text sequences */
        spin_lock_bh(&session->lock);
-       if (!__kfifo_get(session->cmdpool.queue,
+       if (!kfifo_out(&session->cmdpool.queue,
                          (void*)&conn->login_task,
                         sizeof(void*))) {
                spin_unlock_bh(&session->lock);
@@ -2845,7 +2839,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
        return cls_conn;
 
 login_task_data_alloc_fail:
-       __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task,
+       kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task,
                    sizeof(void*));
 login_task_alloc_fail:
        iscsi_destroy_conn(cls_conn);
@@ -2908,7 +2902,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
        free_pages((unsigned long) conn->data,
                   get_order(ISCSI_DEF_MAX_RECV_SEG_LEN));
        kfree(conn->persistent_address);
-       __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task,
+       kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task,
                    sizeof(void*));
        if (session->leadconn == conn)
                session->leadconn = NULL;
index ca25ee5..db6856c 100644 (file)
@@ -445,15 +445,15 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task)
                return;
 
        /* flush task's r2t queues */
-       while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) {
-               __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+       while (kfifo_out(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) {
+               kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
                            sizeof(void*));
                ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n");
        }
 
        r2t = tcp_task->r2t;
        if (r2t != NULL) {
-               __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+               kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
                            sizeof(void*));
                tcp_task->r2t = NULL;
        }
@@ -541,7 +541,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
                return 0;
        }
 
-       rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
+       rc = kfifo_out(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
        if (!rc) {
                iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
                                  "Target has sent more R2Ts than it "
@@ -554,7 +554,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
        if (r2t->data_length == 0) {
                iscsi_conn_printk(KERN_ERR, conn,
                                  "invalid R2T with zero data len\n");
-               __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+               kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
                            sizeof(void*));
                return ISCSI_ERR_DATALEN;
        }
@@ -570,7 +570,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
                                  "invalid R2T with data len %u at offset %u "
                                  "and total length %d\n", r2t->data_length,
                                  r2t->data_offset, scsi_out(task->sc)->length);
-               __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+               kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
                            sizeof(void*));
                return ISCSI_ERR_DATALEN;
        }
@@ -580,7 +580,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
        r2t->sent = 0;
 
        tcp_task->exp_datasn = r2tsn + 1;
-       __kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*));
+       kfifo_in(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*));
        conn->r2t_pdus_cnt++;
 
        iscsi_requeue_task(task);
@@ -951,7 +951,7 @@ int iscsi_tcp_task_init(struct iscsi_task *task)
                return conn->session->tt->init_pdu(task, 0, task->data_count);
        }
 
-       BUG_ON(__kfifo_len(tcp_task->r2tqueue));
+       BUG_ON(kfifo_len(&tcp_task->r2tqueue));
        tcp_task->exp_datasn = 0;
 
        /* Prepare PDU, optionally w/ immediate data */
@@ -982,7 +982,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
                        if (r2t->data_length <= r2t->sent) {
                                ISCSI_DBG_TCP(task->conn,
                                              "  done with r2t %p\n", r2t);
-                               __kfifo_put(tcp_task->r2tpool.queue,
+                               kfifo_in(&tcp_task->r2tpool.queue,
                                            (void *)&tcp_task->r2t,
                                            sizeof(void *));
                                tcp_task->r2t = r2t = NULL;
@@ -990,8 +990,13 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
                }
 
                if (r2t == NULL) {
-                       __kfifo_get(tcp_task->r2tqueue,
-                                   (void *)&tcp_task->r2t, sizeof(void *));
+                       if (kfifo_out(&tcp_task->r2tqueue,
+                           (void *)&tcp_task->r2t, sizeof(void *)) !=
+                           sizeof(void *)) {
+                               WARN_ONCE(1, "unexpected fifo state");
+                               r2t = NULL;
+                       }
+
                        r2t = tcp_task->r2t;
                }
                spin_unlock_bh(&session->lock);
@@ -1127,9 +1132,8 @@ int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session)
                }
 
                /* R2T xmit queue */
-               tcp_task->r2tqueue = kfifo_alloc(
-                     session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
-               if (tcp_task->r2tqueue == ERR_PTR(-ENOMEM)) {
+               if (kfifo_alloc(&tcp_task->r2tqueue,
+                     session->max_r2t * 4 * sizeof(void*), GFP_KERNEL)) {
                        iscsi_pool_free(&tcp_task->r2tpool);
                        goto r2t_alloc_fail;
                }
@@ -1142,7 +1146,7 @@ r2t_alloc_fail:
                struct iscsi_task *task = session->cmds[i];
                struct iscsi_tcp_task *tcp_task = task->dd_data;
 
-               kfifo_free(tcp_task->r2tqueue);
+               kfifo_free(&tcp_task->r2tqueue);
                iscsi_pool_free(&tcp_task->r2tpool);
        }
        return -ENOMEM;
@@ -1157,7 +1161,7 @@ void iscsi_tcp_r2tpool_free(struct iscsi_session *session)
                struct iscsi_task *task = session->cmds[i];
                struct iscsi_tcp_task *tcp_task = task->dd_data;
 
-               kfifo_free(tcp_task->r2tqueue);
+               kfifo_free(&tcp_task->r2tqueue);
                iscsi_pool_free(&tcp_task->r2tpool);
        }
 }
index 9ad38e8..ab19b3b 100644 (file)
@@ -58,19 +58,15 @@ static int srp_iu_pool_alloc(struct srp_queue *q, size_t max,
                goto free_pool;
 
        spin_lock_init(&q->lock);
-       q->queue = kfifo_init((void *) q->pool, max * sizeof(void *),
-                             GFP_KERNEL, &q->lock);
-       if (IS_ERR(q->queue))
-               goto free_item;
+       kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *));
 
        for (i = 0, iue = q->items; i < max; i++) {
-               __kfifo_put(q->queue, (void *) &iue, sizeof(void *));
+               kfifo_in(&q->queue, (void *) &iue, sizeof(void *));
                iue->sbuf = ring[i];
                iue++;
        }
        return 0;
 
-free_item:
        kfree(q->items);
 free_pool:
        kfree(q->pool);
@@ -167,7 +163,11 @@ struct iu_entry *srp_iu_get(struct srp_target *target)
 {
        struct iu_entry *iue = NULL;
 
-       kfifo_get(target->iu_queue.queue, (void *) &iue, sizeof(void *));
+       if (kfifo_out_locked(&target->iu_queue.queue, (void *) &iue,
+               sizeof(void *), &target->iu_queue.lock) != sizeof(void *)) {
+                       WARN_ONCE(1, "unexpected fifo state");
+                       return NULL;
+       }
        if (!iue)
                return iue;
        iue->target = target;
@@ -179,7 +179,8 @@ EXPORT_SYMBOL_GPL(srp_iu_get);
 
 void srp_iu_put(struct iu_entry *iue)
 {
-       kfifo_put(iue->target->iu_queue.queue, (void *) &iue, sizeof(void *));
+       kfifo_in_locked(&iue->target->iu_queue.queue, (void *) &iue,
+                       sizeof(void *), &iue->target->iu_queue.lock);
 }
 EXPORT_SYMBOL_GPL(srp_iu_put);
 
index 093f57a..94eb863 100644 (file)
@@ -87,8 +87,6 @@ source "drivers/staging/frontier/Kconfig"
 
 source "drivers/staging/dream/Kconfig"
 
-source "drivers/staging/dst/Kconfig"
-
 source "drivers/staging/pohmelfs/Kconfig"
 
 source "drivers/staging/b3dfg/Kconfig"
@@ -145,5 +143,7 @@ source "drivers/staging/wavelan/Kconfig"
 
 source "drivers/staging/netwave/Kconfig"
 
+source "drivers/staging/sm7xx/Kconfig"
+
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
index 069864f..b5e67b8 100644 (file)
@@ -26,7 +26,6 @@ obj-$(CONFIG_RTL8192E)                += rtl8192e/
 obj-$(CONFIG_INPUT_MIMIO)      += mimio/
 obj-$(CONFIG_TRANZPORT)                += frontier/
 obj-$(CONFIG_DREAM)            += dream/
-obj-$(CONFIG_DST)              += dst/
 obj-$(CONFIG_POHMELFS)         += pohmelfs/
 obj-$(CONFIG_B3DFG)            += b3dfg/
 obj-$(CONFIG_IDE_PHISON)       += phison/
@@ -53,3 +52,4 @@ obj-$(CONFIG_ARLAN)           += arlan/
 obj-$(CONFIG_WAVELAN)          += wavelan/
 obj-$(CONFIG_PCMCIA_WAVELAN)   += wavelan/
 obj-$(CONFIG_PCMCIA_NETWAVE)   += netwave/
+obj-$(CONFIG_FB_SM7XX)         += sm7xx/
index 7632f57..1d74dab 100644 (file)
@@ -4,6 +4,7 @@
 
 config BATMAN_ADV
        tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
+       depends on PROC_FS && PACKET
         default n
        ---help---
 
index d724798..eb61750 100644 (file)
@@ -363,8 +363,10 @@ void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len)
                return;
 
        forw_packet->packet_buff = kmalloc(packet_len, GFP_ATOMIC);
-       if (!forw_packet->packet_buff)
+       if (!forw_packet->packet_buff) {
+               kfree(forw_packet);
                return;
+       }
 
        forw_packet->packet_len = packet_len;
        memcpy(forw_packet->packet_buff, packet_buff, forw_packet->packet_len);
index ccc5cdc..b559a9c 100644 (file)
 
 #define COMEDI_CB_EOS          1       /* end of scan */
 #define COMEDI_CB_EOA          2       /* end of acquisition */
-#define COMEDI_CB_BLOCK                4       /* DEPRECATED: convenient block size */
+#define COMEDI_CB_BLOCK                4       /* data has arrived: wakes up read() / write() */
 #define COMEDI_CB_EOBUF                8       /* DEPRECATED: end of buffer */
 #define COMEDI_CB_ERROR                16      /* card error during acquisition */
 #define COMEDI_CB_OVERFLOW     32      /* buffer overflow/underflow */
index 0d2c2eb..bd39784 100644 (file)
@@ -849,8 +849,11 @@ static int jr3_pci_attach(struct comedi_device *dev,
        }
 
        devpriv->pci_enabled = 1;
-       devpriv->iobase =
-           ioremap(pci_resource_start(card, 0), sizeof(struct jr3_t));
+       devpriv->iobase = ioremap(pci_resource_start(card, 0),
+                       offsetof(struct jr3_t, channel[devpriv->n_channels]));
+       if (!devpriv->iobase)
+               return -ENOMEM;
+
        result = alloc_subdevices(dev, devpriv->n_channels);
        if (result < 0)
                goto out;
index 06c0204..9a1b559 100644 (file)
@@ -1,4 +1,4 @@
-#define DRIVER_VERSION "v2.3"
+#define DRIVER_VERSION "v2.4"
 #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
 #define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com"
 /*
@@ -81,6 +81,8 @@ sampling rate. If you sample two channels you get 4kHz and so on.
  * 2.1:  changed PWM API
  * 2.2:  added firmware kernel request to fix an udev problem
  * 2.3:  corrected a bug in bulk timeouts which were far too short
+ * 2.4:  fixed a bug which causes the driver to hang when it ran out of data.
+ *       Thanks to Jan-Matthias Braun and Ian to spot the bug and fix it.
  *
  */
 
@@ -532,6 +534,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
                }
        }
        /* tell comedi that data is there */
+       s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
        comedi_event(this_usbduxsub->comedidev, s);
 }
 
diff --git a/drivers/staging/dst/Kconfig b/drivers/staging/dst/Kconfig
deleted file mode 100644 (file)
index 448d342..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-config DST
-       tristate "Distributed storage"
-       depends on NET && CRYPTO && SYSFS && BLK_DEV
-       select CONNECTOR
-       ---help---
-       DST is a network block device storage, which can be used to organize
-       exported storage on the remote nodes into the local block device.
-
-       DST works on top of any network media and protocol; it is just a matter
-       of configuration utility to understand the correct addresses. The most
-       common example is TCP over IP, which allows to pass through firewalls and
-       create remote backup storage in a different datacenter. DST requires
-       single port to be enabled on the exporting node and outgoing connections
-       on the local node.
-
-       DST works with in-kernel client and server, which improves performance by
-       eliminating unneded data copies and by not depending on the version
-       of the external IO components. It requires userspace configuration utility
-       though.
-
-       DST uses transaction model, when each store has to be explicitly acked
-       from the remote node to be considered as successfully written. There
-       may be lots of in-flight transactions. When remote host does not ack
-       the transaction it will be resent predefined number of times with specified
-       timeouts between them. All those parameters are configurable. Transactions
-       are marked as failed after all resends complete unsuccessfully; having
-       long enough resend timeout and/or large number of resends allows not to
-       return error to the higher (FS usually) layer in case of short network
-       problems or remote node outages. In case of network RAID setup this means
-       that storage will not degrade until transactions are marked as failed, and
-       thus will not force checksum recalculation and data rebuild. In case of
-       connection failure DST will try to reconnect to the remote node automatically.
-       DST sends ping commands at idle time to detect if remote node is alive.
-
-       Because of transactional model it is possible to use zero-copy sending
-       without worry of data corruption (which in turn could be detected by the
-       strong checksums though).
-
-       DST may fully encrypt the data channel in case of untrusted channel and implement
-       strong checksum of the transferred data. It is possible to configure algorithms
-       and crypto keys; they should match on both sides of the network channel.
-       Crypto processing does not introduce noticeble performance overhead, since DST
-       uses configurable pool of threads to perform crypto processing.
-
-       DST utilizes memory pool model of all its transaction allocations (it is the
-       only additional allocation on the client) and server allocations (bio pools,
-       while pages are allocated from the slab).
-
-       At startup DST performs a simple negotiation with the export node to determine
-       access permissions and size of the exported storage. It can be extended if
-       new parameters should be autonegotiated.
-
-       DST carries block IO flags in the protocol, which allows to transparently implement
-       barriers and sync/flush operations. Those flags are used in the export node where
-       IO against the local storage is performed, which means that sync write will be sync
-       on the remote node too, which in turn improves data integrity and improved resistance
-       to errors and data corruption during power outages or storage damages.
-
-       Homepage: http://www.ioremap.net/projects/dst
-       Userspace configuration utility and the latest releases: http://www.ioremap.net/archive/dst/
-
-config DST_DEBUG
-       bool "DST debug"
-       depends on DST
-       ---help---
-       This option will enable HEAVY debugging of the DST.
-       Turn it on ONLY if you have to debug some really obscure problem.
diff --git a/drivers/staging/dst/Makefile b/drivers/staging/dst/Makefile
deleted file mode 100644 (file)
index 3a8b0cf..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DST) += nst.o
-
-nst-y := dcore.o state.o export.o thread_pool.o crypto.o trans.o
diff --git a/drivers/staging/dst/crypto.c b/drivers/staging/dst/crypto.c
deleted file mode 100644 (file)
index 351295c..0000000
+++ /dev/null
@@ -1,733 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
-
-#include <linux/bio.h>
-#include <linux/crypto.h>
-#include <linux/dst.h>
-#include <linux/kernel.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-
-/*
- * Tricky bastard, but IV can be more complex with time...
- */
-static inline u64 dst_gen_iv(struct dst_trans *t)
-{
-       return t->gen;
-}
-
-/*
- * Crypto machinery: hash/cipher support for the given crypto controls.
- */
-static struct crypto_hash *dst_init_hash(struct dst_crypto_ctl *ctl, u8 *key)
-{
-       int err;
-       struct crypto_hash *hash;
-
-       hash = crypto_alloc_hash(ctl->hash_algo, 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(hash)) {
-               err = PTR_ERR(hash);
-               dprintk("%s: failed to allocate hash '%s', err: %d.\n",
-                               __func__, ctl->hash_algo, err);
-               goto err_out_exit;
-       }
-
-       ctl->crypto_attached_size = crypto_hash_digestsize(hash);
-
-       if (!ctl->hash_keysize)
-               return hash;
-
-       err = crypto_hash_setkey(hash, key, ctl->hash_keysize);
-       if (err) {
-               dprintk("%s: failed to set key for hash '%s', err: %d.\n",
-                               __func__, ctl->hash_algo, err);
-               goto err_out_free;
-       }
-
-       return hash;
-
-err_out_free:
-       crypto_free_hash(hash);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-static struct crypto_ablkcipher *dst_init_cipher(struct dst_crypto_ctl *ctl,
-               u8 *key)
-{
-       int err = -EINVAL;
-       struct crypto_ablkcipher *cipher;
-
-       if (!ctl->cipher_keysize)
-               goto err_out_exit;
-
-       cipher = crypto_alloc_ablkcipher(ctl->cipher_algo, 0, 0);
-       if (IS_ERR(cipher)) {
-               err = PTR_ERR(cipher);
-               dprintk("%s: failed to allocate cipher '%s', err: %d.\n",
-                               __func__, ctl->cipher_algo, err);
-               goto err_out_exit;
-       }
-
-       crypto_ablkcipher_clear_flags(cipher, ~0);
-
-       err = crypto_ablkcipher_setkey(cipher, key, ctl->cipher_keysize);
-       if (err) {
-               dprintk("%s: failed to set key for cipher '%s', err: %d.\n",
-                               __func__, ctl->cipher_algo, err);
-               goto err_out_free;
-       }
-
-       return cipher;
-
-err_out_free:
-       crypto_free_ablkcipher(cipher);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-/*
- * Crypto engine has a pool of pages to encrypt data into before sending
- * it over the network. This pool is freed/allocated here.
- */
-static void dst_crypto_pages_free(struct dst_crypto_engine *e)
-{
-       unsigned int i;
-
-       for (i = 0; i < e->page_num; ++i)
-               __free_page(e->pages[i]);
-       kfree(e->pages);
-}
-
-static int dst_crypto_pages_alloc(struct dst_crypto_engine *e, int num)
-{
-       int i;
-
-       e->pages = kmalloc(num * sizeof(struct page **), GFP_KERNEL);
-       if (!e->pages)
-               return -ENOMEM;
-
-       for (i = 0; i < num; ++i) {
-               e->pages[i] = alloc_page(GFP_KERNEL);
-               if (!e->pages[i])
-                       goto err_out_free_pages;
-       }
-
-       e->page_num = num;
-       return 0;
-
-err_out_free_pages:
-       while (--i >= 0)
-               __free_page(e->pages[i]);
-
-       kfree(e->pages);
-       return -ENOMEM;
-}
-
-/*
- * Initialize crypto engine for given node.
- * Setup cipher/hash, keys, pool of threads and private data.
- */
-static int dst_crypto_engine_init(struct dst_crypto_engine *e,
-               struct dst_node *n)
-{
-       int err;
-       struct dst_crypto_ctl *ctl = &n->crypto;
-
-       err = dst_crypto_pages_alloc(e, n->max_pages);
-       if (err)
-               goto err_out_exit;
-
-       e->size = PAGE_SIZE;
-       e->data = kmalloc(e->size, GFP_KERNEL);
-       if (!e->data) {
-               err = -ENOMEM;
-               goto err_out_free_pages;
-       }
-
-       if (ctl->hash_algo[0]) {
-               e->hash = dst_init_hash(ctl, n->hash_key);
-               if (IS_ERR(e->hash)) {
-                       err = PTR_ERR(e->hash);
-                       e->hash = NULL;
-                       goto err_out_free;
-               }
-       }
-
-       if (ctl->cipher_algo[0]) {
-               e->cipher = dst_init_cipher(ctl, n->cipher_key);
-               if (IS_ERR(e->cipher)) {
-                       err = PTR_ERR(e->cipher);
-                       e->cipher = NULL;
-                       goto err_out_free_hash;
-               }
-       }
-
-       return 0;
-
-err_out_free_hash:
-       crypto_free_hash(e->hash);
-err_out_free:
-       kfree(e->data);
-err_out_free_pages:
-       dst_crypto_pages_free(e);
-err_out_exit:
-       return err;
-}
-
-static void dst_crypto_engine_exit(struct dst_crypto_engine *e)
-{
-       if (e->hash)
-               crypto_free_hash(e->hash);
-       if (e->cipher)
-               crypto_free_ablkcipher(e->cipher);
-       dst_crypto_pages_free(e);
-       kfree(e->data);
-}
-
-/*
- * Waiting for cipher processing to be completed.
- */
-struct dst_crypto_completion {
-       struct completion               complete;
-       int                             error;
-};
-
-static void dst_crypto_complete(struct crypto_async_request *req, int err)
-{
-       struct dst_crypto_completion *c = req->data;
-
-       if (err == -EINPROGRESS)
-               return;
-
-       dprintk("%s: req: %p, err: %d.\n", __func__, req, err);
-       c->error = err;
-       complete(&c->complete);
-}
-
-static int dst_crypto_process(struct ablkcipher_request *req,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src,
-               void *iv, int enc, unsigned long timeout)
-{
-       struct dst_crypto_completion c;
-       int err;
-
-       init_completion(&c.complete);
-       c.error = -EINPROGRESS;
-
-       ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                       dst_crypto_complete, &c);
-
-       ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv);
-
-       if (enc)
-               err = crypto_ablkcipher_encrypt(req);
-       else
-               err = crypto_ablkcipher_decrypt(req);
-
-       switch (err) {
-       case -EINPROGRESS:
-       case -EBUSY:
-               err = wait_for_completion_interruptible_timeout(&c.complete,
-                               timeout);
-               if (!err)
-                       err = -ETIMEDOUT;
-               else
-                       err = c.error;
-               break;
-       default:
-               break;
-       }
-
-       return err;
-}
-
-/*
- * DST uses generic iteration approach for data crypto processing.
- * Single block IO request is switched into array of scatterlists,
- * which are submitted to the crypto processing iterator.
- *
- * Input and output iterator initialization are different, since
- * in output case we can not encrypt data in-place and need a
- * temporary storage, which is then being sent to the remote peer.
- */
-static int dst_trans_iter_out(struct bio *bio, struct dst_crypto_engine *e,
-               int (*iterator) (struct dst_crypto_engine *e,
-                                 struct scatterlist *dst,
-                                 struct scatterlist *src))
-{
-       struct bio_vec *bv;
-       int err, i;
-
-       sg_init_table(e->src, bio->bi_vcnt);
-       sg_init_table(e->dst, bio->bi_vcnt);
-
-       bio_for_each_segment(bv, bio, i) {
-               sg_set_page(&e->src[i], bv->bv_page, bv->bv_len, bv->bv_offset);
-               sg_set_page(&e->dst[i], e->pages[i], bv->bv_len, bv->bv_offset);
-
-               err = iterator(e, &e->dst[i], &e->src[i]);
-               if (err)
-                       return err;
-       }
-
-       return 0;
-}
-
-static int dst_trans_iter_in(struct bio *bio, struct dst_crypto_engine *e,
-               int (*iterator) (struct dst_crypto_engine *e,
-                                 struct scatterlist *dst,
-                                 struct scatterlist *src))
-{
-       struct bio_vec *bv;
-       int err, i;
-
-       sg_init_table(e->src, bio->bi_vcnt);
-       sg_init_table(e->dst, bio->bi_vcnt);
-
-       bio_for_each_segment(bv, bio, i) {
-               sg_set_page(&e->src[i], bv->bv_page, bv->bv_len, bv->bv_offset);
-               sg_set_page(&e->dst[i], bv->bv_page, bv->bv_len, bv->bv_offset);
-
-               err = iterator(e, &e->dst[i], &e->src[i]);
-               if (err)
-                       return err;
-       }
-
-       return 0;
-}
-
-static int dst_crypt_iterator(struct dst_crypto_engine *e,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src)
-{
-       struct ablkcipher_request *req = e->data;
-       u8 iv[32];
-
-       memset(iv, 0, sizeof(iv));
-
-       memcpy(iv, &e->iv, sizeof(e->iv));
-
-       return dst_crypto_process(req, sg_dst, sg_src, iv, e->enc, e->timeout);
-}
-
-static int dst_crypt(struct dst_crypto_engine *e, struct bio *bio)
-{
-       struct ablkcipher_request *req = e->data;
-
-       memset(req, 0, sizeof(struct ablkcipher_request));
-       ablkcipher_request_set_tfm(req, e->cipher);
-
-       if (e->enc)
-               return dst_trans_iter_out(bio, e, dst_crypt_iterator);
-       else
-               return dst_trans_iter_in(bio, e, dst_crypt_iterator);
-}
-
-static int dst_hash_iterator(struct dst_crypto_engine *e,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src)
-{
-       return crypto_hash_update(e->data, sg_src, sg_src->length);
-}
-
-static int dst_hash(struct dst_crypto_engine *e, struct bio *bio, void *dst)
-{
-       struct hash_desc *desc = e->data;
-       int err;
-
-       desc->tfm = e->hash;
-       desc->flags = 0;
-
-       err = crypto_hash_init(desc);
-       if (err)
-               return err;
-
-       err = dst_trans_iter_in(bio, e, dst_hash_iterator);
-       if (err)
-               return err;
-
-       err = crypto_hash_final(desc, dst);
-       if (err)
-               return err;
-
-       return 0;
-}
-
-/*
- * Initialize/cleanup a crypto thread. The only thing it should
- * do is to allocate a pool of pages as temporary storage.
- * And to setup cipher and/or hash.
- */
-static void *dst_crypto_thread_init(void *data)
-{
-       struct dst_node *n = data;
-       struct dst_crypto_engine *e;
-       int err = -ENOMEM;
-
-       e = kzalloc(sizeof(struct dst_crypto_engine), GFP_KERNEL);
-       if (!e)
-               goto err_out_exit;
-       e->src = kcalloc(2 * n->max_pages, sizeof(struct scatterlist),
-                       GFP_KERNEL);
-       if (!e->src)
-               goto err_out_free;
-
-       e->dst = e->src + n->max_pages;
-
-       err = dst_crypto_engine_init(e, n);
-       if (err)
-               goto err_out_free_all;
-
-       return e;
-
-err_out_free_all:
-       kfree(e->src);
-err_out_free:
-       kfree(e);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-static void dst_crypto_thread_cleanup(void *private)
-{
-       struct dst_crypto_engine *e = private;
-
-       dst_crypto_engine_exit(e);
-       kfree(e->src);
-       kfree(e);
-}
-
-/*
- * Initialize crypto engine for given node: store keys, create pool
- * of threads, initialize each one.
- *
- * Each thread has unique ID, but 0 and 1 are reserved for receiving and
- * accepting threads (if export node), so IDs could start from 2, but starting
- * them from 10 allows easily understand what this thread is for.
- */
-int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl)
-{
-       void *key = (ctl + 1);
-       int err = -ENOMEM, i;
-       char name[32];
-
-       if (ctl->hash_keysize) {
-               n->hash_key = kmalloc(ctl->hash_keysize, GFP_KERNEL);
-               if (!n->hash_key)
-                       goto err_out_exit;
-               memcpy(n->hash_key, key, ctl->hash_keysize);
-       }
-
-       if (ctl->cipher_keysize) {
-               n->cipher_key = kmalloc(ctl->cipher_keysize, GFP_KERNEL);
-               if (!n->cipher_key)
-                       goto err_out_free_hash;
-               memcpy(n->cipher_key, key, ctl->cipher_keysize);
-       }
-       memcpy(&n->crypto, ctl, sizeof(struct dst_crypto_ctl));
-
-       for (i = 0; i < ctl->thread_num; ++i) {
-               snprintf(name, sizeof(name), "%s-crypto-%d", n->name, i);
-               /* Unique ids... */
-               err = thread_pool_add_worker(n->pool, name, i + 10,
-                       dst_crypto_thread_init, dst_crypto_thread_cleanup, n);
-               if (err)
-                       goto err_out_free_threads;
-       }
-
-       return 0;
-
-err_out_free_threads:
-       while (--i >= 0)
-               thread_pool_del_worker_id(n->pool, i+10);
-
-       if (ctl->cipher_keysize)
-               kfree(n->cipher_key);
-       ctl->cipher_keysize = 0;
-err_out_free_hash:
-       if (ctl->hash_keysize)
-               kfree(n->hash_key);
-       ctl->hash_keysize = 0;
-err_out_exit:
-       return err;
-}
-
-void dst_node_crypto_exit(struct dst_node *n)
-{
-       struct dst_crypto_ctl *ctl = &n->crypto;
-
-       if (ctl->cipher_algo[0] || ctl->hash_algo[0]) {
-               kfree(n->hash_key);
-               kfree(n->cipher_key);
-       }
-}
-
-/*
- * Thrad pool setup callback. Just stores a transaction in private data.
- */
-static int dst_trans_crypto_setup(void *crypto_engine, void *trans)
-{
-       struct dst_crypto_engine *e = crypto_engine;
-
-       e->private = trans;
-       return 0;
-}
-
-#if 0
-static void dst_dump_bio(struct bio *bio)
-{
-       u8 *p;
-       struct bio_vec *bv;
-       int i;
-
-       bio_for_each_segment(bv, bio, i) {
-               dprintk("%s: %llu/%u: size: %u, offset: %u, data: ",
-                               __func__, bio->bi_sector, bio->bi_size,
-                               bv->bv_len, bv->bv_offset);
-
-               p = kmap(bv->bv_page) + bv->bv_offset;
-               for (i = 0; i < bv->bv_len; ++i)
-                       printk(KERN_DEBUG "%02x ", p[i]);
-               kunmap(bv->bv_page);
-               printk("\n");
-       }
-}
-#endif
-
-/*
- * Encrypt/hash data and send it to the network.
- */
-static int dst_crypto_process_sending(struct dst_crypto_engine *e,
-               struct bio *bio, u8 *hash)
-{
-       int err;
-
-       if (e->cipher) {
-               err = dst_crypt(e, bio);
-               if (err)
-                       goto err_out_exit;
-       }
-
-       if (e->hash) {
-               err = dst_hash(e, bio, hash);
-               if (err)
-                       goto err_out_exit;
-
-#ifdef CONFIG_DST_DEBUG
-               {
-                       unsigned int i;
-
-                       /* dst_dump_bio(bio); */
-
-                       printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash: ",
-                               __func__, (u64)bio->bi_sector,
-                               bio->bi_size, bio_data_dir(bio));
-                       for (i = 0; i < crypto_hash_digestsize(e->hash); ++i)
-                                       printk("%02x ", hash[i]);
-                       printk("\n");
-               }
-#endif
-       }
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-/*
- * Check if received data is valid. Decipher if it is.
- */
-static int dst_crypto_process_receiving(struct dst_crypto_engine *e,
-               struct bio *bio, u8 *hash, u8 *recv_hash)
-{
-       int err;
-
-       if (e->hash) {
-               int mismatch;
-
-               err = dst_hash(e, bio, hash);
-               if (err)
-                       goto err_out_exit;
-
-               mismatch = !!memcmp(recv_hash, hash,
-                               crypto_hash_digestsize(e->hash));
-#ifdef CONFIG_DST_DEBUG
-               /* dst_dump_bio(bio); */
-
-               printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash mismatch: %d",
-                       __func__, (u64)bio->bi_sector, bio->bi_size,
-                       bio_data_dir(bio), mismatch);
-               if (mismatch) {
-                       unsigned int i;
-
-                       printk(", recv/calc: ");
-                       for (i = 0; i < crypto_hash_digestsize(e->hash); ++i)
-                               printk("%02x/%02x ", recv_hash[i], hash[i]);
-
-               }
-               printk("\n");
-#endif
-               err = -1;
-               if (mismatch)
-                       goto err_out_exit;
-       }
-
-       if (e->cipher) {
-               err = dst_crypt(e, bio);
-               if (err)
-                       goto err_out_exit;
-       }
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-/*
- * Thread pool callback to encrypt data and send it to the netowork.
- */
-static int dst_trans_crypto_action(void *crypto_engine, void *schedule_data)
-{
-       struct dst_crypto_engine *e = crypto_engine;
-       struct dst_trans *t = schedule_data;
-       struct bio *bio = t->bio;
-       int err;
-
-       dprintk("%s: t: %p, gen: %llu, cipher: %p, hash: %p.\n",
-                       __func__, t, t->gen, e->cipher, e->hash);
-
-       e->enc = t->enc;
-       e->iv = dst_gen_iv(t);
-
-       if (bio_data_dir(bio) == WRITE) {
-               err = dst_crypto_process_sending(e, bio, t->cmd.hash);
-               if (err)
-                       goto err_out_exit;
-
-               if (e->hash) {
-                       t->cmd.csize = crypto_hash_digestsize(e->hash);
-                       t->cmd.size += t->cmd.csize;
-               }
-
-               return dst_trans_send(t);
-       } else {
-               u8 *hash = e->data + e->size/2;
-
-               err = dst_crypto_process_receiving(e, bio, hash, t->cmd.hash);
-               if (err)
-                       goto err_out_exit;
-
-               dst_trans_remove(t);
-               dst_trans_put(t);
-       }
-
-       return 0;
-
-err_out_exit:
-       t->error = err;
-       dst_trans_put(t);
-       return err;
-}
-
-/*
- * Schedule crypto processing for given transaction.
- */
-int dst_trans_crypto(struct dst_trans *t)
-{
-       struct dst_node *n = t->n;
-       int err;
-
-       err = thread_pool_schedule(n->pool,
-               dst_trans_crypto_setup, dst_trans_crypto_action,
-               t, MAX_SCHEDULE_TIMEOUT);
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       dst_trans_put(t);
-       return err;
-}
-
-/*
- * Crypto machinery for the export node.
- */
-static int dst_export_crypto_setup(void *crypto_engine, void *bio)
-{
-       struct dst_crypto_engine *e = crypto_engine;
-
-       e->private = bio;
-       return 0;
-}
-
-static int dst_export_crypto_action(void *crypto_engine, void *schedule_data)
-{
-       struct dst_crypto_engine *e = crypto_engine;
-       struct bio *bio = schedule_data;
-       struct dst_export_priv *p = bio->bi_private;
-       int err;
-
-       dprintk("%s: e: %p, data: %p, bio: %llu/%u, dir: %lu.\n",
-                       __func__, e, e->data, (u64)bio->bi_sector,
-                       bio->bi_size, bio_data_dir(bio));
-
-       e->enc = (bio_data_dir(bio) == READ);
-       e->iv = p->cmd.id;
-
-       if (bio_data_dir(bio) == WRITE) {
-               u8 *hash = e->data + e->size/2;
-
-               err = dst_crypto_process_receiving(e, bio, hash, p->cmd.hash);
-               if (err)
-                       goto err_out_exit;
-
-               generic_make_request(bio);
-       } else {
-               err = dst_crypto_process_sending(e, bio, p->cmd.hash);
-               if (err)
-                       goto err_out_exit;
-
-               if (e->hash) {
-                       p->cmd.csize = crypto_hash_digestsize(e->hash);
-                       p->cmd.size += p->cmd.csize;
-               }
-
-               err = dst_export_send_bio(bio);
-       }
-       return 0;
-
-err_out_exit:
-       bio_put(bio);
-       return err;
-}
-
-int dst_export_crypto(struct dst_node *n, struct bio *bio)
-{
-       int err;
-
-       err = thread_pool_schedule(n->pool,
-               dst_export_crypto_setup, dst_export_crypto_action,
-               bio, MAX_SCHEDULE_TIMEOUT);
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       bio_put(bio);
-       return err;
-}
diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c
deleted file mode 100644 (file)
index c83ca7e..0000000
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/buffer_head.h>
-#include <linux/connector.h>
-#include <linux/dst.h>
-#include <linux/device.h>
-#include <linux/jhash.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/namei.h>
-#include <linux/slab.h>
-#include <linux/socket.h>
-
-#include <linux/in.h>
-#include <linux/in6.h>
-
-#include <net/sock.h>
-
-static int dst_major;
-
-static DEFINE_MUTEX(dst_hash_lock);
-static struct list_head *dst_hashtable;
-static unsigned int dst_hashtable_size = 128;
-module_param(dst_hashtable_size, uint, 0644);
-
-static char dst_name[] = "Dementianting goldfish";
-
-static DEFINE_IDR(dst_index_idr);
-static struct cb_id cn_dst_id = { CN_DST_IDX, CN_DST_VAL };
-
-/*
- * DST sysfs tree for device called 'storage':
- *
- * /sys/bus/dst/devices/storage/
- * /sys/bus/dst/devices/storage/type : 192.168.4.80:1025
- * /sys/bus/dst/devices/storage/size : 800
- * /sys/bus/dst/devices/storage/name : storage
- */
-
-static int dst_dev_match(struct device *dev, struct device_driver *drv)
-{
-       return 1;
-}
-
-static struct bus_type dst_dev_bus_type = {
-       .name           = "dst",
-       .match          = &dst_dev_match,
-};
-
-static void dst_node_release(struct device *dev)
-{
-       struct dst_info *info = container_of(dev, struct dst_info, device);
-
-       kfree(info);
-}
-
-static struct device dst_node_dev = {
-       .bus            = &dst_dev_bus_type,
-       .release        = &dst_node_release
-};
-
-/*
- * Setting size of the node after it was changed.
- */
-static void dst_node_set_size(struct dst_node *n)
-{
-       struct block_device *bdev;
-
-       set_capacity(n->disk, n->size >> 9);
-
-       bdev = bdget_disk(n->disk, 0);
-       if (bdev) {
-               mutex_lock(&bdev->bd_inode->i_mutex);
-               i_size_write(bdev->bd_inode, n->size);
-               mutex_unlock(&bdev->bd_inode->i_mutex);
-               bdput(bdev);
-       }
-}
-
-/*
- * Distributed storage request processing function.
- */
-static int dst_request(struct request_queue *q, struct bio *bio)
-{
-       struct dst_node *n = q->queuedata;
-       int err = -EIO;
-
-       if (bio_empty_barrier(bio) && !blk_queue_discard(q)) {
-               /*
-                * This is a dirty^Wnice hack, but if we complete this
-                * operation with -EOPNOTSUPP like intended, XFS
-                * will stuck and freeze the machine. This may be
-                * not particulary XFS problem though, but it is the
-                * only FS which sends empty barrier at umount time
-                * I worked with.
-                *
-                * Empty barriers are not allowed anyway, see 51fd77bd9f512
-                * for example, although later it was changed to
-                * bio_rw_flagged(bio, BIO_RW_DISCARD) only, which does not
-                * work in this case.
-                */
-               /* err = -EOPNOTSUPP; */
-               err = 0;
-               goto end_io;
-       }
-
-       bio_get(bio);
-
-       return dst_process_bio(n, bio);
-
-end_io:
-       bio_endio(bio, err);
-       return err;
-}
-
-/*
- * Open/close callbacks for appropriate block device.
- */
-static int dst_bdev_open(struct block_device *bdev, fmode_t mode)
-{
-       struct dst_node *n = bdev->bd_disk->private_data;
-
-       dst_node_get(n);
-       return 0;
-}
-
-static int dst_bdev_release(struct gendisk *disk, fmode_t mode)
-{
-       struct dst_node *n = disk->private_data;
-
-       dst_node_put(n);
-       return 0;
-}
-
-static struct block_device_operations dst_blk_ops = {
-       .open           = dst_bdev_open,
-       .release        = dst_bdev_release,
-       .owner          = THIS_MODULE,
-};
-
-/*
- * Block layer binding - disk is created when array is fully configured
- * by userspace request.
- */
-static int dst_node_create_disk(struct dst_node *n)
-{
-       int err = -ENOMEM;
-       u32 index = 0;
-
-       n->queue = blk_init_queue(NULL, NULL);
-       if (!n->queue)
-               goto err_out_exit;
-
-       n->queue->queuedata = n;
-       blk_queue_make_request(n->queue, dst_request);
-       blk_queue_max_phys_segments(n->queue, n->max_pages);
-       blk_queue_max_hw_segments(n->queue, n->max_pages);
-
-       err = -ENOMEM;
-       n->disk = alloc_disk(1);
-       if (!n->disk)
-               goto err_out_free_queue;
-
-       if (!(n->state->permissions & DST_PERM_WRITE)) {
-               printk(KERN_INFO "DST node %s attached read-only.\n", n->name);
-               set_disk_ro(n->disk, 1);
-       }
-
-       if (!idr_pre_get(&dst_index_idr, GFP_KERNEL))
-               goto err_out_put;
-
-       mutex_lock(&dst_hash_lock);
-       err = idr_get_new(&dst_index_idr, NULL, &index);
-       mutex_unlock(&dst_hash_lock);
-       if (err)
-               goto err_out_put;
-
-       n->disk->major = dst_major;
-       n->disk->first_minor = index;
-       n->disk->fops = &dst_blk_ops;
-       n->disk->queue = n->queue;
-       n->disk->private_data = n;
-       snprintf(n->disk->disk_name, sizeof(n->disk->disk_name),
-                       "dst-%s", n->name);
-
-       return 0;
-
-err_out_put:
-       put_disk(n->disk);
-err_out_free_queue:
-       blk_cleanup_queue(n->queue);
-err_out_exit:
-       return err;
-}
-
-/*
- * Sysfs machinery: show device's size.
- */
-static ssize_t dst_show_size(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct dst_info *info = container_of(dev, struct dst_info, device);
-
-       return sprintf(buf, "%llu\n", info->size);
-}
-
-/*
- * Show local exported device.
- */
-static ssize_t dst_show_local(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct dst_info *info = container_of(dev, struct dst_info, device);
-
-       return sprintf(buf, "%s\n", info->local);
-}
-
-/*
- * Shows type of the remote node - device major/minor number
- * for local nodes and address (af_inet ipv4/ipv6 only) for remote nodes.
- */
-static ssize_t dst_show_type(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct dst_info *info = container_of(dev, struct dst_info, device);
-       int family = info->net.addr.sa_family;
-
-       if (family == AF_INET) {
-               struct sockaddr_in *sin = (struct sockaddr_in *)&info->net.addr;
-               return sprintf(buf, "%u.%u.%u.%u:%d\n",
-                       NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port));
-       } else if (family == AF_INET6) {
-               struct sockaddr_in6 *sin = (struct sockaddr_in6 *)
-                               &info->net.addr;
-               return sprintf(buf,
-                       "%pi6:%d\n",
-                       &sin->sin6_addr, ntohs(sin->sin6_port));
-       } else {
-               int i, sz = PAGE_SIZE - 2; /* 0 symbol and '\n' below */
-               int size, addrlen = info->net.addr.sa_data_len;
-               unsigned char *a = (unsigned char *)&info->net.addr.sa_data;
-               char *buf_orig = buf;
-
-               size = snprintf(buf, sz, "family: %d, addrlen: %u, addr: ",
-                               family, addrlen);
-               sz -= size;
-               buf += size;
-
-               for (i = 0; i < addrlen; ++i) {
-                       if (sz < 3)
-                               break;
-
-                       size = snprintf(buf, sz, "%02x ", a[i]);
-                       sz -= size;
-                       buf += size;
-               }
-               buf += sprintf(buf, "\n");
-
-               return buf - buf_orig;
-       }
-       return 0;
-}
-
-static struct device_attribute dst_node_attrs[] = {
-       __ATTR(size, 0444, dst_show_size, NULL),
-       __ATTR(type, 0444, dst_show_type, NULL),
-       __ATTR(local, 0444, dst_show_local, NULL),
-};
-
-static int dst_create_node_attributes(struct dst_node *n)
-{
-       int err, i;
-
-       for (i = 0; i < ARRAY_SIZE(dst_node_attrs); ++i) {
-               err = device_create_file(&n->info->device,
-                               &dst_node_attrs[i]);
-               if (err)
-                       goto err_out_remove_all;
-       }
-       return 0;
-
-err_out_remove_all:
-       while (--i >= 0)
-               device_remove_file(&n->info->device,
-                               &dst_node_attrs[i]);
-
-       return err;
-}
-
-static void dst_remove_node_attributes(struct dst_node *n)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(dst_node_attrs); ++i)
-               device_remove_file(&n->info->device,
-                               &dst_node_attrs[i]);
-}
-
-/*
- * Sysfs cleanup and initialization.
- * Shows number of useful parameters.
- */
-static void dst_node_sysfs_exit(struct dst_node *n)
-{
-       if (n->info) {
-               dst_remove_node_attributes(n);
-               device_unregister(&n->info->device);
-               n->info = NULL;
-       }
-}
-
-static int dst_node_sysfs_init(struct dst_node *n)
-{
-       int err;
-
-       n->info = kzalloc(sizeof(struct dst_info), GFP_KERNEL);
-       if (!n->info)
-               return -ENOMEM;
-
-       memcpy(&n->info->device, &dst_node_dev, sizeof(struct device));
-       n->info->size = n->size;
-
-       dev_set_name(&n->info->device, "dst-%s", n->name);
-       err = device_register(&n->info->device);
-       if (err) {
-               dprintk(KERN_ERR "Failed to register node '%s', err: %d.\n",
-                               n->name, err);
-               goto err_out_exit;
-       }
-
-       dst_create_node_attributes(n);
-
-       return 0;
-
-err_out_exit:
-       kfree(n->info);
-       n->info = NULL;
-       return err;
-}
-
-/*
- * DST node hash tables machinery.
- */
-static inline unsigned int dst_hash(char *str, unsigned int size)
-{
-       return jhash(str, size, 0) % dst_hashtable_size;
-}
-
-static void dst_node_remove(struct dst_node *n)
-{
-       mutex_lock(&dst_hash_lock);
-       list_del_init(&n->node_entry);
-       mutex_unlock(&dst_hash_lock);
-}
-
-static void dst_node_add(struct dst_node *n)
-{
-       unsigned hash = dst_hash(n->name, sizeof(n->name));
-
-       mutex_lock(&dst_hash_lock);
-       list_add_tail(&n->node_entry, &dst_hashtable[hash]);
-       mutex_unlock(&dst_hash_lock);
-}
-
-/*
- * Cleaning node when it is about to be freed.
- * There are still users of the socket though,
- * so connection cleanup should be protected.
- */
-static void dst_node_cleanup(struct dst_node *n)
-{
-       struct dst_state *st = n->state;
-
-       if (!st)
-               return;
-
-       if (n->queue) {
-               blk_cleanup_queue(n->queue);
-
-               mutex_lock(&dst_hash_lock);
-               idr_remove(&dst_index_idr, n->disk->first_minor);
-               mutex_unlock(&dst_hash_lock);
-
-               put_disk(n->disk);
-       }
-
-       if (n->bdev) {
-               sync_blockdev(n->bdev);
-               close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE);
-       }
-
-       dst_state_lock(st);
-       st->need_exit = 1;
-       dst_state_exit_connected(st);
-       dst_state_unlock(st);
-
-       wake_up(&st->thread_wait);
-
-       dst_state_put(st);
-       n->state = NULL;
-}
-
-/*
- * Free security attributes attached to given node.
- */
-static void dst_security_exit(struct dst_node *n)
-{
-       struct dst_secure *s, *tmp;
-
-       list_for_each_entry_safe(s, tmp, &n->security_list, sec_entry) {
-               list_del(&s->sec_entry);
-               kfree(s);
-       }
-}
-
-/*
- * Free node when there are no more users.
- * Actually node has to be freed on behalf od userspace process,
- * since there are number of threads, which are embedded in the
- * node, so they can not exit and free node from there, that is
- * why there is a wakeup if reference counter is not equal to zero.
- */
-void dst_node_put(struct dst_node *n)
-{
-       if (unlikely(!n))
-               return;
-
-       dprintk("%s: n: %p, refcnt: %d.\n",
-                       __func__, n, atomic_read(&n->refcnt));
-
-       if (atomic_dec_and_test(&n->refcnt)) {
-               dst_node_remove(n);
-               n->trans_scan_timeout = 0;
-               dst_node_cleanup(n);
-               thread_pool_destroy(n->pool);
-               dst_node_sysfs_exit(n);
-               dst_node_crypto_exit(n);
-               dst_security_exit(n);
-               dst_node_trans_exit(n);
-
-               kfree(n);
-
-               dprintk("%s: freed n: %p.\n", __func__, n);
-       } else {
-               wake_up(&n->wait);
-       }
-}
-
-/*
- * Setting up export device: lookup by the name, get its size
- * and setup listening socket, which will accept clients, which
- * will submit IO for given storage.
- */
-static int dst_setup_export(struct dst_node *n, struct dst_ctl *ctl,
-               struct dst_export_ctl *le)
-{
-       int err;
-
-       snprintf(n->info->local, sizeof(n->info->local), "%s", le->device);
-
-       n->bdev = open_bdev_exclusive(le->device, FMODE_READ|FMODE_WRITE, NULL);
-       if (IS_ERR(n->bdev))
-               return PTR_ERR(n->bdev);
-
-       if (n->size != 0)
-               n->size = min_t(loff_t, n->bdev->bd_inode->i_size, n->size);
-       else
-               n->size = n->bdev->bd_inode->i_size;
-
-       n->info->size = n->size;
-       err = dst_node_init_listened(n, le);
-       if (err)
-               goto err_out_cleanup;
-
-       return 0;
-
-err_out_cleanup:
-       close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE);
-       n->bdev = NULL;
-
-       return err;
-}
-
-/* Empty thread pool callbacks for the network processing threads. */
-static inline void *dst_thread_network_init(void *data)
-{
-       dprintk("%s: data: %p.\n", __func__, data);
-       return data;
-}
-
-static inline void dst_thread_network_cleanup(void *data)
-{
-       dprintk("%s: data: %p.\n", __func__, data);
-}
-
-/*
- * Allocate DST node and initialize some of its parameters.
- */
-static struct dst_node *dst_alloc_node(struct dst_ctl *ctl,
-               int (*start)(struct dst_node *),
-               int num)
-{
-       struct dst_node *n;
-       int err;
-
-       n = kzalloc(sizeof(struct dst_node), GFP_KERNEL);
-       if (!n)
-               return NULL;
-
-       INIT_LIST_HEAD(&n->node_entry);
-
-       INIT_LIST_HEAD(&n->security_list);
-       mutex_init(&n->security_lock);
-
-       init_waitqueue_head(&n->wait);
-
-       n->trans_scan_timeout = msecs_to_jiffies(ctl->trans_scan_timeout);
-       if (!n->trans_scan_timeout)
-               n->trans_scan_timeout = HZ;
-
-       n->trans_max_retries = ctl->trans_max_retries;
-       if (!n->trans_max_retries)
-               n->trans_max_retries = 10;
-
-       /*
-        * Pretty much arbitrary default numbers.
-        * 32 matches maximum number of pages in bio originated from ext3 (31).
-        */
-       n->max_pages = ctl->max_pages;
-       if (!n->max_pages)
-               n->max_pages = 32;
-
-       if (n->max_pages > 1024)
-               n->max_pages = 1024;
-
-       n->start = start;
-       n->size = ctl->size;
-
-       atomic_set(&n->refcnt, 1);
-       atomic_long_set(&n->gen, 0);
-       snprintf(n->name, sizeof(n->name), "%s", ctl->name);
-
-       err = dst_node_sysfs_init(n);
-       if (err)
-               goto err_out_free;
-
-       n->pool = thread_pool_create(num, n->name, dst_thread_network_init,
-                       dst_thread_network_cleanup, n);
-       if (IS_ERR(n->pool)) {
-               err = PTR_ERR(n->pool);
-               goto err_out_sysfs_exit;
-       }
-
-       dprintk("%s: n: %p, name: %s.\n", __func__, n, n->name);
-
-       return n;
-
-err_out_sysfs_exit:
-       dst_node_sysfs_exit(n);
-err_out_free:
-       kfree(n);
-       return NULL;
-}
-
-/*
- * Starting a node, connected to the remote server:
- * register block device and initialize transaction mechanism.
- * In revers order though.
- *
- * It will autonegotiate some parameters with the remote node
- * and update local if needed.
- *
- * Transaction initialization should be the last thing before
- * starting the node, since transaction should include not only
- * block IO, but also crypto related data (if any), which are
- * initialized separately.
- */
-static int dst_start_remote(struct dst_node *n)
-{
-       int err;
-
-       err = dst_node_trans_init(n, sizeof(struct dst_trans));
-       if (err)
-               return err;
-
-       err = dst_node_create_disk(n);
-       if (err)
-               return err;
-
-       dst_node_set_size(n);
-       add_disk(n->disk);
-
-       dprintk("DST: started remote node '%s', minor: %d.\n",
-                       n->name, n->disk->first_minor);
-
-       return 0;
-}
-
-/*
- * Adding remote node and initialize connection.
- */
-static int dst_add_remote(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       int err;
-       struct dst_network_ctl *rctl = data;
-
-       if (n)
-               return -EEXIST;
-
-       if (size != sizeof(struct dst_network_ctl))
-               return -EINVAL;
-
-       n = dst_alloc_node(ctl, dst_start_remote, 1);
-       if (!n)
-               return -ENOMEM;
-
-       memcpy(&n->info->net, rctl, sizeof(struct dst_network_ctl));
-       err = dst_node_init_connected(n, rctl);
-       if (err)
-               goto err_out_free;
-
-       dst_node_add(n);
-
-       return 0;
-
-err_out_free:
-       dst_node_put(n);
-       return err;
-}
-
-/*
- * Adding export node: initializing block device and listening socket.
- */
-static int dst_add_export(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       int err;
-       struct dst_export_ctl *le = data;
-
-       if (n)
-               return -EEXIST;
-
-       if (size != sizeof(struct dst_export_ctl))
-               return -EINVAL;
-
-       n = dst_alloc_node(ctl, dst_start_export, 2);
-       if (!n)
-               return -EINVAL;
-
-       err = dst_setup_export(n, ctl, le);
-       if (err)
-               goto err_out_free;
-
-       dst_node_add(n);
-
-       return 0;
-
-err_out_free:
-       dst_node_put(n);
-       return err;
-}
-
-static int dst_node_remove_unload(struct dst_node *n)
-{
-       printk(KERN_INFO "STOPPED name: '%s', size: %llu.\n",
-                       n->name, n->size);
-
-       if (n->disk)
-               del_gendisk(n->disk);
-
-       dst_node_remove(n);
-       dst_node_sysfs_exit(n);
-
-       /*
-        * This is not a hack. Really.
-        * Node's reference counter allows to implement fine grained
-        * node freeing, but since all transactions (which hold node's
-        * reference counter) are processed in the dedicated thread,
-        * it is possible that reference will hit zero in that thread,
-        * so we will not be able to exit thread and cleanup the node.
-        *
-        * So, we remove disk, so no new activity is possible, and
-        * wait until all pending transaction are completed (either
-        * in receiving thread or by timeout in workqueue), in this
-        * case reference counter will be less or equal to 2 (once set in
-        * dst_alloc_node() and then in connector message parser;
-        * or when we force module unloading, and connector message
-        * parser does not hold a reference, in this case reference
-        * counter will be equal to 1),
-        * and subsequent dst_node_put() calls will free the node.
-        */
-       dprintk("%s: going to sleep with %d refcnt.\n",
-                       __func__, atomic_read(&n->refcnt));
-       wait_event(n->wait, atomic_read(&n->refcnt) <= 2);
-
-       dst_node_put(n);
-       return 0;
-}
-
-/*
- * Remove node from the hash table.
- */
-static int dst_del_node(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       if (!n)
-               return -ENODEV;
-
-       return dst_node_remove_unload(n);
-}
-
-/*
- * Initialize crypto processing for given node.
- */
-static int dst_crypto_init(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       struct dst_crypto_ctl *crypto = data;
-
-       if (!n)
-               return -ENODEV;
-
-       if (size != sizeof(struct dst_crypto_ctl) + crypto->hash_keysize +
-                       crypto->cipher_keysize)
-               return -EINVAL;
-
-       if (n->trans_cache)
-               return -EEXIST;
-
-       return dst_node_crypto_init(n, crypto);
-}
-
-/*
- * Security attributes for given node.
- */
-static int dst_security_init(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       struct dst_secure *s;
-
-       if (!n)
-               return -ENODEV;
-
-       if (size != sizeof(struct dst_secure_user))
-               return -EINVAL;
-
-       s = kmalloc(sizeof(struct dst_secure), GFP_KERNEL);
-       if (!s)
-               return -ENOMEM;
-
-       memcpy(&s->sec, data, size);
-
-       mutex_lock(&n->security_lock);
-       list_add_tail(&s->sec_entry, &n->security_list);
-       mutex_unlock(&n->security_lock);
-
-       return 0;
-}
-
-/*
- * Kill'em all!
- */
-static int dst_start_node(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       int err;
-
-       if (!n)
-               return -ENODEV;
-
-       if (n->trans_cache)
-               return 0;
-
-       err = n->start(n);
-       if (err)
-               return err;
-
-       printk(KERN_INFO "STARTED name: '%s', size: %llu.\n", n->name, n->size);
-       return 0;
-}
-
-typedef int (*dst_command_func)(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size);
-
-/*
- * List of userspace commands.
- */
-static dst_command_func dst_commands[] = {
-       [DST_ADD_REMOTE] = &dst_add_remote,
-       [DST_ADD_EXPORT] = &dst_add_export,
-       [DST_DEL_NODE] = &dst_del_node,
-       [DST_CRYPTO] = &dst_crypto_init,
-       [DST_SECURITY] = &dst_security_init,
-       [DST_START] = &dst_start_node,
-};
-
-/*
- * Configuration parser.
- */
-static void cn_dst_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
-{
-       struct dst_ctl *ctl;
-       int err;
-       struct dst_ctl_ack ack;
-       struct dst_node *n = NULL, *tmp;
-       unsigned int hash;
-
-       if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) {
-               err = -EPERM;
-               goto out;
-       }
-
-       if (msg->len < sizeof(struct dst_ctl)) {
-               err = -EBADMSG;
-               goto out;
-       }
-
-       ctl = (struct dst_ctl *)msg->data;
-
-       if (ctl->cmd >= DST_CMD_MAX) {
-               err = -EINVAL;
-               goto out;
-       }
-       hash = dst_hash(ctl->name, sizeof(ctl->name));
-
-       mutex_lock(&dst_hash_lock);
-       list_for_each_entry(tmp, &dst_hashtable[hash], node_entry) {
-               if (!memcmp(tmp->name, ctl->name, sizeof(tmp->name))) {
-                       n = tmp;
-                       dst_node_get(n);
-                       break;
-               }
-       }
-       mutex_unlock(&dst_hash_lock);
-
-       err = dst_commands[ctl->cmd](n, ctl, msg->data + sizeof(struct dst_ctl),
-                       msg->len - sizeof(struct dst_ctl));
-
-       dst_node_put(n);
-out:
-       memcpy(&ack.msg, msg, sizeof(struct cn_msg));
-
-       ack.msg.ack = msg->ack + 1;
-       ack.msg.len = sizeof(struct dst_ctl_ack) - sizeof(struct cn_msg);
-
-       ack.error = err;
-
-       cn_netlink_send(&ack.msg, 0, GFP_KERNEL);
-}
-
-/*
- * Global initialization: sysfs, hash table, block device registration,
- * connector and various caches.
- */
-static int __init dst_sysfs_init(void)
-{
-       return bus_register(&dst_dev_bus_type);
-}
-
-static void dst_sysfs_exit(void)
-{
-       bus_unregister(&dst_dev_bus_type);
-}
-
-static int __init dst_hashtable_init(void)
-{
-       unsigned int i;
-
-       dst_hashtable = kcalloc(dst_hashtable_size, sizeof(struct list_head),
-                       GFP_KERNEL);
-       if (!dst_hashtable)
-               return -ENOMEM;
-
-       for (i = 0; i < dst_hashtable_size; ++i)
-               INIT_LIST_HEAD(&dst_hashtable[i]);
-
-       return 0;
-}
-
-static void dst_hashtable_exit(void)
-{
-       unsigned int i;
-       struct dst_node *n, *tmp;
-
-       for (i = 0; i < dst_hashtable_size; ++i) {
-               list_for_each_entry_safe(n, tmp, &dst_hashtable[i], node_entry) {
-                       dst_node_remove_unload(n);
-               }
-       }
-
-       kfree(dst_hashtable);
-}
-
-static int __init dst_sys_init(void)
-{
-       int err = -ENOMEM;
-
-       err = dst_hashtable_init();
-       if (err)
-               goto err_out_exit;
-
-       err = dst_export_init();
-       if (err)
-               goto err_out_hashtable_exit;
-
-       err = register_blkdev(dst_major, DST_NAME);
-       if (err < 0)
-               goto err_out_export_exit;
-       if (err)
-               dst_major = err;
-
-       err = dst_sysfs_init();
-       if (err)
-               goto err_out_unregister;
-
-       err = cn_add_callback(&cn_dst_id, "DST", cn_dst_callback);
-       if (err)
-               goto err_out_sysfs_exit;
-
-       printk(KERN_INFO "Distributed storage, '%s' release.\n", dst_name);
-
-       return 0;
-
-err_out_sysfs_exit:
-       dst_sysfs_exit();
-err_out_unregister:
-       unregister_blkdev(dst_major, DST_NAME);
-err_out_export_exit:
-       dst_export_exit();
-err_out_hashtable_exit:
-       dst_hashtable_exit();
-err_out_exit:
-       return err;
-}
-
-static void __exit dst_sys_exit(void)
-{
-       cn_del_callback(&cn_dst_id);
-       unregister_blkdev(dst_major, DST_NAME);
-       dst_hashtable_exit();
-       dst_sysfs_exit();
-       dst_export_exit();
-}
-
-module_init(dst_sys_init);
-module_exit(dst_sys_exit);
-
-MODULE_DESCRIPTION("Distributed storage");
-MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/dst/export.c b/drivers/staging/dst/export.c
deleted file mode 100644 (file)
index c324230..0000000
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
-
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/dst.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/socket.h>
-
-#include <net/sock.h>
-
-/*
- * Export bioset is used for server block IO requests.
- */
-static struct bio_set *dst_bio_set;
-
-int __init dst_export_init(void)
-{
-       int err = -ENOMEM;
-
-       dst_bio_set = bioset_create(32, sizeof(struct dst_export_priv));
-       if (!dst_bio_set)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-void dst_export_exit(void)
-{
-       bioset_free(dst_bio_set);
-}
-
-/*
- * When client connects and autonegotiates with the server node,
- * its permissions are checked in a security attributes and sent
- * back.
- */
-static unsigned int dst_check_permissions(struct dst_state *main,
-               struct dst_state *st)
-{
-       struct dst_node *n = main->node;
-       struct dst_secure *sentry;
-       struct dst_secure_user *s;
-       struct saddr *sa = &st->ctl.addr;
-       unsigned int perm = 0;
-
-       mutex_lock(&n->security_lock);
-       list_for_each_entry(sentry, &n->security_list, sec_entry) {
-               s = &sentry->sec;
-
-               if (s->addr.sa_family != sa->sa_family)
-                       continue;
-
-               if (s->addr.sa_data_len != sa->sa_data_len)
-                       continue;
-
-               /*
-                * This '2' below is a port field. This may be very wrong to do
-                * in atalk for example though. If there will be any need
-                * to extent protocol to something else, I can create
-                * per-family helpers and use them instead of this memcmp.
-                */
-               if (memcmp(s->addr.sa_data + 2, sa->sa_data + 2,
-                                       sa->sa_data_len - 2))
-                       continue;
-
-               perm = s->permissions;
-       }
-       mutex_unlock(&n->security_lock);
-
-       return perm;
-}
-
-/*
- * Accept new client: allocate appropriate network state and check permissions.
- */
-static struct dst_state *dst_accept_client(struct dst_state *st)
-{
-       unsigned int revents = 0;
-       unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP;
-       unsigned int mask = err_mask | POLLIN;
-       struct dst_node *n = st->node;
-       int err = 0;
-       struct socket *sock = NULL;
-       struct dst_state *new;
-
-       while (!err && !sock) {
-               revents = dst_state_poll(st);
-
-               if (!(revents & mask)) {
-                       DEFINE_WAIT(wait);
-
-                       for (;;) {
-                               prepare_to_wait(&st->thread_wait,
-                                               &wait, TASK_INTERRUPTIBLE);
-                               if (!n->trans_scan_timeout || st->need_exit)
-                                       break;
-
-                               revents = dst_state_poll(st);
-
-                               if (revents & mask)
-                                       break;
-
-                               if (signal_pending(current))
-                                       break;
-
-                               /*
-                                * Magic HZ? Polling check above is not safe in
-                                * all cases (like socket reset in BH context),
-                                * so it is simpler just to postpone it to the
-                                * process context instead of implementing
-                                * special locking there.
-                                */
-                               schedule_timeout(HZ);
-                       }
-                       finish_wait(&st->thread_wait, &wait);
-               }
-
-               err = -ECONNRESET;
-               dst_state_lock(st);
-
-               dprintk("%s: st: %p, revents: %x [err: %d, in: %d].\n",
-                       __func__, st, revents, revents & err_mask,
-                       revents & POLLIN);
-
-               if (revents & err_mask) {
-                       dprintk("%s: revents: %x, socket: %p, err: %d.\n",
-                                       __func__, revents, st->socket, err);
-                       err = -ECONNRESET;
-               }
-
-               if (!n->trans_scan_timeout || st->need_exit)
-                       err = -ENODEV;
-
-               if (st->socket && (revents & POLLIN))
-                       err = kernel_accept(st->socket, &sock, 0);
-
-               dst_state_unlock(st);
-       }
-
-       if (err)
-               goto err_out_exit;
-
-       new = dst_state_alloc(st->node);
-       if (IS_ERR(new)) {
-               err = -ENOMEM;
-               goto err_out_release;
-       }
-       new->socket = sock;
-
-       new->ctl.addr.sa_data_len = sizeof(struct sockaddr);
-       err = kernel_getpeername(sock, (struct sockaddr *)&new->ctl.addr,
-                       (int *)&new->ctl.addr.sa_data_len);
-       if (err)
-               goto err_out_put;
-
-       new->permissions = dst_check_permissions(st, new);
-       if (new->permissions == 0) {
-               err = -EPERM;
-               dst_dump_addr(sock, (struct sockaddr *)&new->ctl.addr,
-                               "Client is not allowed to connect");
-               goto err_out_put;
-       }
-
-       err = dst_poll_init(new);
-       if (err)
-               goto err_out_put;
-
-       dst_dump_addr(sock, (struct sockaddr *)&new->ctl.addr,
-                       "Connected client");
-
-       return new;
-
-err_out_put:
-       dst_state_put(new);
-err_out_release:
-       sock_release(sock);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-/*
- * Each server's block request sometime finishes.
- * Usually it happens in hard irq context of the appropriate controller,
- * so to play good with all cases we just queue BIO into the queue
- * and wake up processing thread, which gets completed request and
- * send (encrypting if needed) it back to the client (if it was a read
- * request), or sends back reply that writing successfully completed.
- */
-static int dst_export_process_request_queue(struct dst_state *st)
-{
-       unsigned long flags;
-       struct dst_export_priv *p = NULL;
-       struct bio *bio;
-       int err = 0;
-
-       while (!list_empty(&st->request_list)) {
-               spin_lock_irqsave(&st->request_lock, flags);
-               if (!list_empty(&st->request_list)) {
-                       p = list_first_entry(&st->request_list,
-                               struct dst_export_priv, request_entry);
-                       list_del(&p->request_entry);
-               }
-               spin_unlock_irqrestore(&st->request_lock, flags);
-
-               if (!p)
-                       break;
-
-               bio = p->bio;
-
-               if (dst_need_crypto(st->node) && (bio_data_dir(bio) == READ))
-                       err = dst_export_crypto(st->node, bio);
-               else
-                       err = dst_export_send_bio(bio);
-
-               if (err)
-                       break;
-       }
-
-       return err;
-}
-
-/*
- * Cleanup export state.
- * It has to wait until all requests are finished,
- * and then free them all.
- */
-static void dst_state_cleanup_export(struct dst_state *st)
-{
-       struct dst_export_priv *p;
-       unsigned long flags;
-
-       /*
-        * This loop waits for all pending bios to be completed and freed.
-        */
-       while (atomic_read(&st->refcnt) > 1) {
-               dprintk("%s: st: %p, refcnt: %d, list_empty: %d.\n",
-                               __func__, st, atomic_read(&st->refcnt),
-                               list_empty(&st->request_list));
-               wait_event_timeout(st->thread_wait,
-                               (atomic_read(&st->refcnt) == 1) ||
-                               !list_empty(&st->request_list),
-                               HZ/2);
-
-               while (!list_empty(&st->request_list)) {
-                       p = NULL;
-                       spin_lock_irqsave(&st->request_lock, flags);
-                       if (!list_empty(&st->request_list)) {
-                               p = list_first_entry(&st->request_list,
-                                       struct dst_export_priv, request_entry);
-                               list_del(&p->request_entry);
-                       }
-                       spin_unlock_irqrestore(&st->request_lock, flags);
-
-                       if (p)
-                               bio_put(p->bio);
-
-                       dprintk("%s: st: %p, refcnt: %d, list_empty: %d, p: "
-                               "%p.\n", __func__, st, atomic_read(&st->refcnt),
-                               list_empty(&st->request_list), p);
-               }
-       }
-
-       dst_state_put(st);
-}
-
-/*
- * Client accepting thread.
- * Not only accepts new connection, but also schedules receiving thread
- * and performs request completion described above.
- */
-static int dst_accept(void *init_data, void *schedule_data)
-{
-       struct dst_state *main_st = schedule_data;
-       struct dst_node *n = init_data;
-       struct dst_state *st;
-       int err;
-
-       while (n->trans_scan_timeout && !main_st->need_exit) {
-               dprintk("%s: main_st: %p, n: %p.\n", __func__, main_st, n);
-               st = dst_accept_client(main_st);
-               if (IS_ERR(st))
-                       continue;
-
-               err = dst_state_schedule_receiver(st);
-               if (!err) {
-                       while (n->trans_scan_timeout) {
-                               err = wait_event_interruptible_timeout(st->thread_wait,
-                                       !list_empty(&st->request_list) ||
-                                       !n->trans_scan_timeout ||
-                                       st->need_exit,
-                                       HZ);
-
-                               if (!n->trans_scan_timeout || st->need_exit)
-                                       break;
-
-                               if (list_empty(&st->request_list))
-                                       continue;
-
-                               err = dst_export_process_request_queue(st);
-                               if (err)
-                                       break;
-                       }
-
-                       st->need_exit = 1;
-                       wake_up(&st->thread_wait);
-               }
-
-               dst_state_cleanup_export(st);
-       }
-
-       dprintk("%s: freeing listening socket st: %p.\n", __func__, main_st);
-
-       dst_state_lock(main_st);
-       dst_poll_exit(main_st);
-       dst_state_socket_release(main_st);
-       dst_state_unlock(main_st);
-       dst_state_put(main_st);
-       dprintk("%s: freed listening socket st: %p.\n", __func__, main_st);
-
-       return 0;
-}
-
-int dst_start_export(struct dst_node *n)
-{
-       if (list_empty(&n->security_list)) {
-               printk(KERN_ERR "You are trying to export node '%s' "
-                               "without security attributes.\nNo clients will "
-                               "be allowed to connect. Exiting.\n", n->name);
-               return -EINVAL;
-       }
-       return dst_node_trans_init(n, sizeof(struct dst_export_priv));
-}
-
-/*
- * Initialize listening state and schedule accepting thread.
- */
-int dst_node_init_listened(struct dst_node *n, struct dst_export_ctl *le)
-{
-       struct dst_state *st;
-       int err = -ENOMEM;
-       struct dst_network_ctl *ctl = &le->ctl;
-
-       memcpy(&n->info->net, ctl, sizeof(struct dst_network_ctl));
-
-       st = dst_state_alloc(n);
-       if (IS_ERR(st)) {
-               err = PTR_ERR(st);
-               goto err_out_exit;
-       }
-       memcpy(&st->ctl, ctl, sizeof(struct dst_network_ctl));
-
-       err = dst_state_socket_create(st);
-       if (err)
-               goto err_out_put;
-
-       st->socket->sk->sk_reuse = 1;
-
-       err = kernel_bind(st->socket, (struct sockaddr *)&ctl->addr,
-                       ctl->addr.sa_data_len);
-       if (err)
-               goto err_out_socket_release;
-
-       err = kernel_listen(st->socket, 1024);
-       if (err)
-               goto err_out_socket_release;
-       n->state = st;
-
-       err = dst_poll_init(st);
-       if (err)
-               goto err_out_socket_release;
-
-       dst_state_get(st);
-
-       err = thread_pool_schedule(n->pool, dst_thread_setup,
-                       dst_accept, st, MAX_SCHEDULE_TIMEOUT);
-       if (err)
-               goto err_out_poll_exit;
-
-       return 0;
-
-err_out_poll_exit:
-       dst_poll_exit(st);
-err_out_socket_release:
-       dst_state_socket_release(st);
-err_out_put:
-       dst_state_put(st);
-err_out_exit:
-       n->state = NULL;
-       return err;
-}
-
-/*
- * Free bio and related private data.
- * Also drop a reference counter for appropriate state,
- * which waits when there are no more block IOs in-flight.
- */
-static void dst_bio_destructor(struct bio *bio)
-{
-       struct bio_vec *bv;
-       struct dst_export_priv *priv = bio->bi_private;
-       int i;
-
-       bio_for_each_segment(bv, bio, i) {
-               if (!bv->bv_page)
-                       break;
-
-               __free_page(bv->bv_page);
-       }
-
-       if (priv)
-               dst_state_put(priv->state);
-       bio_free(bio, dst_bio_set);
-}
-
-/*
- * Block IO completion. Queue request to be sent back to
- * the client (or just confirmation).
- */
-static void dst_bio_end_io(struct bio *bio, int err)
-{
-       struct dst_export_priv *p = bio->bi_private;
-       struct dst_state *st = p->state;
-       unsigned long flags;
-
-       spin_lock_irqsave(&st->request_lock, flags);
-       list_add_tail(&p->request_entry, &st->request_list);
-       spin_unlock_irqrestore(&st->request_lock, flags);
-
-       wake_up(&st->thread_wait);
-}
-
-/*
- * Allocate read request for the server.
- */
-static int dst_export_read_request(struct bio *bio, unsigned int total_size)
-{
-       unsigned int size;
-       struct page *page;
-       int err;
-
-       while (total_size) {
-               err = -ENOMEM;
-               page = alloc_page(GFP_KERNEL);
-               if (!page)
-                       goto err_out_exit;
-
-               size = min_t(unsigned int, PAGE_SIZE, total_size);
-
-               err = bio_add_page(bio, page, size, 0);
-               dprintk("%s: bio: %llu/%u, size: %u, err: %d.\n",
-                               __func__, (u64)bio->bi_sector, bio->bi_size,
-                               size, err);
-               if (err <= 0)
-                       goto err_out_free_page;
-
-               total_size -= size;
-       }
-
-       return 0;
-
-err_out_free_page:
-       __free_page(page);
-err_out_exit:
-       return err;
-}
-
-/*
- * Allocate write request for the server.
- * Should not only get pages, but also read data from the network.
- */
-static int dst_export_write_request(struct dst_state *st,
-               struct bio *bio, unsigned int total_size)
-{
-       unsigned int size;
-       struct page *page;
-       void *data;
-       int err;
-
-       while (total_size) {
-               err = -ENOMEM;
-               page = alloc_page(GFP_KERNEL);
-               if (!page)
-                       goto err_out_exit;
-
-               data = kmap(page);
-               if (!data)
-                       goto err_out_free_page;
-
-               size = min_t(unsigned int, PAGE_SIZE, total_size);
-
-               err = dst_data_recv(st, data, size);
-               if (err)
-                       goto err_out_unmap_page;
-
-               err = bio_add_page(bio, page, size, 0);
-               if (err <= 0)
-                       goto err_out_unmap_page;
-
-               kunmap(page);
-
-               total_size -= size;
-       }
-
-       return 0;
-
-err_out_unmap_page:
-       kunmap(page);
-err_out_free_page:
-       __free_page(page);
-err_out_exit:
-       return err;
-}
-
-/*
- * Groovy, we've gotten an IO request from the client.
- * Allocate BIO from the bioset, private data from the mempool
- * and lots of pages for IO.
- */
-int dst_process_io(struct dst_state *st)
-{
-       struct dst_node *n = st->node;
-       struct dst_cmd *cmd = st->data;
-       struct bio *bio;
-       struct dst_export_priv *priv;
-       int err = -ENOMEM;
-
-       if (unlikely(!n->bdev)) {
-               err = -EINVAL;
-               goto err_out_exit;
-       }
-
-       bio = bio_alloc_bioset(GFP_KERNEL,
-                       PAGE_ALIGN(cmd->size) >> PAGE_SHIFT,
-                       dst_bio_set);
-       if (!bio)
-               goto err_out_exit;
-
-       priv = (struct dst_export_priv *)(((void *)bio) -
-                       sizeof (struct dst_export_priv));
-
-       priv->state = dst_state_get(st);
-       priv->bio = bio;
-
-       bio->bi_private = priv;
-       bio->bi_end_io = dst_bio_end_io;
-       bio->bi_destructor = dst_bio_destructor;
-       bio->bi_bdev = n->bdev;
-
-       /*
-        * Server side is only interested in two low bits:
-        * uptodate (set by itself actually) and rw block
-        */
-       bio->bi_flags |= cmd->flags & 3;
-
-       bio->bi_rw = cmd->rw;
-       bio->bi_size = 0;
-       bio->bi_sector = cmd->sector;
-
-       dst_bio_to_cmd(bio, &priv->cmd, DST_IO_RESPONSE, cmd->id);
-
-       priv->cmd.flags = 0;
-       priv->cmd.size = cmd->size;
-
-       if (bio_data_dir(bio) == WRITE) {
-               err = dst_recv_cdata(st, priv->cmd.hash);
-               if (err)
-                       goto err_out_free;
-
-               err = dst_export_write_request(st, bio, cmd->size);
-               if (err)
-                       goto err_out_free;
-
-               if (dst_need_crypto(n))
-                       return dst_export_crypto(n, bio);
-       } else {
-               err = dst_export_read_request(bio, cmd->size);
-               if (err)
-                       goto err_out_free;
-       }
-
-       dprintk("%s: bio: %llu/%u, rw: %lu, dir: %lu, flags: %lx, phys: %d.\n",
-                       __func__, (u64)bio->bi_sector, bio->bi_size,
-                       bio->bi_rw, bio_data_dir(bio),
-                       bio->bi_flags, bio->bi_phys_segments);
-
-       generic_make_request(bio);
-
-       return 0;
-
-err_out_free:
-       bio_put(bio);
-err_out_exit:
-       return err;
-}
-
-/*
- * Ok, block IO is ready, let's send it back to the client...
- */
-int dst_export_send_bio(struct bio *bio)
-{
-       struct dst_export_priv *p = bio->bi_private;
-       struct dst_state *st = p->state;
-       struct dst_cmd *cmd = &p->cmd;
-       int err;
-
-       dprintk("%s: id: %llu, bio: %llu/%u, csize: %u, flags: %lu, rw: %lu.\n",
-                       __func__, cmd->id, (u64)bio->bi_sector, bio->bi_size,
-                       cmd->csize, bio->bi_flags, bio->bi_rw);
-
-       dst_convert_cmd(cmd);
-
-       dst_state_lock(st);
-       if (!st->socket) {
-               err = -ECONNRESET;
-               goto err_out_unlock;
-       }
-
-       if (bio_data_dir(bio) == WRITE) {
-               /* ... or just confirmation that writing has completed. */
-               cmd->size = cmd->csize = 0;
-               err = dst_data_send_header(st->socket, cmd,
-                               sizeof(struct dst_cmd), 0);
-               if (err)
-                       goto err_out_unlock;
-       } else {
-               err = dst_send_bio(st, cmd, bio);
-               if (err)
-                       goto err_out_unlock;
-       }
-
-       dst_state_unlock(st);
-
-       bio_put(bio);
-       return 0;
-
-err_out_unlock:
-       dst_state_unlock(st);
-
-       bio_put(bio);
-       return err;
-}
diff --git a/drivers/staging/dst/state.c b/drivers/staging/dst/state.c
deleted file mode 100644 (file)
index 02a05e6..0000000
+++ /dev/null
@@ -1,844 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
-
-#include <linux/buffer_head.h>
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/connector.h>
-#include <linux/dst.h>
-#include <linux/device.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/socket.h>
-#include <linux/slab.h>
-
-#include <net/sock.h>
-
-/*
- * Polling machinery.
- */
-
-struct dst_poll_helper {
-       poll_table              pt;
-       struct dst_state        *st;
-};
-
-static int dst_queue_wake(wait_queue_t *wait, unsigned mode,
-               int sync, void *key)
-{
-       struct dst_state *st = container_of(wait, struct dst_state, wait);
-
-       wake_up(&st->thread_wait);
-       return 1;
-}
-
-static void dst_queue_func(struct file *file, wait_queue_head_t *whead,
-                                poll_table *pt)
-{
-       struct dst_state *st = container_of(pt, struct dst_poll_helper, pt)->st;
-
-       st->whead = whead;
-       init_waitqueue_func_entry(&st->wait, dst_queue_wake);
-       add_wait_queue(whead, &st->wait);
-}
-
-void dst_poll_exit(struct dst_state *st)
-{
-       if (st->whead) {
-               remove_wait_queue(st->whead, &st->wait);
-               st->whead = NULL;
-       }
-}
-
-int dst_poll_init(struct dst_state *st)
-{
-       struct dst_poll_helper ph;
-
-       ph.st = st;
-       init_poll_funcptr(&ph.pt, &dst_queue_func);
-
-       st->socket->ops->poll(NULL, st->socket, &ph.pt);
-       return 0;
-}
-
-/*
- * Header receiving function - may block.
- */
-static int dst_data_recv_header(struct socket *sock,
-               void *data, unsigned int size, int block)
-{
-       struct msghdr msg;
-       struct kvec iov;
-       int err;
-
-       iov.iov_base = data;
-       iov.iov_len = size;
-
-       msg.msg_iov = (struct iovec *)&iov;
-       msg.msg_iovlen = 1;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = (block) ? MSG_WAITALL : MSG_DONTWAIT;
-
-       err = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len,
-                       msg.msg_flags);
-       if (err != size)
-               return -1;
-
-       return 0;
-}
-
-/*
- * Header sending function - may block.
- */
-int dst_data_send_header(struct socket *sock,
-               void *data, unsigned int size, int more)
-{
-       struct msghdr msg;
-       struct kvec iov;
-       int err;
-
-       iov.iov_base = data;
-       iov.iov_len = size;
-
-       msg.msg_iov = (struct iovec *)&iov;
-       msg.msg_iovlen = 1;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = MSG_WAITALL | (more ? MSG_MORE : 0);
-
-       err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
-       if (err != size) {
-               dprintk("%s: size: %u, more: %d, err: %d.\n",
-                               __func__, size, more, err);
-               return -1;
-       }
-
-       return 0;
-}
-
-/*
- * Block autoconfiguration: request size of the storage and permissions.
- */
-static int dst_request_remote_config(struct dst_state *st)
-{
-       struct dst_node *n = st->node;
-       int err = -EINVAL;
-       struct dst_cmd *cmd = st->data;
-
-       memset(cmd, 0, sizeof(struct dst_cmd));
-       cmd->cmd = DST_CFG;
-
-       dst_convert_cmd(cmd);
-
-       err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0);
-       if (err)
-               goto out;
-
-       err = dst_data_recv_header(st->socket, cmd, sizeof(struct dst_cmd), 1);
-       if (err)
-               goto out;
-
-       dst_convert_cmd(cmd);
-
-       if (cmd->cmd != DST_CFG) {
-               err = -EINVAL;
-               dprintk("%s: checking result: cmd: %d, size reported: %llu.\n",
-                       __func__, cmd->cmd, cmd->sector);
-               goto out;
-       }
-
-       if (n->size != 0)
-               n->size = min_t(loff_t, n->size, cmd->sector);
-       else
-               n->size = cmd->sector;
-
-       n->info->size = n->size;
-       st->permissions = cmd->rw;
-
-out:
-       dprintk("%s: n: %p, err: %d, size: %llu, permission: %x.\n",
-                       __func__, n, err, n->size, st->permissions);
-       return err;
-}
-
-/*
- * Socket machinery.
- */
-
-#define DST_DEFAULT_TIMEO      20000
-
-int dst_state_socket_create(struct dst_state *st)
-{
-       int err;
-       struct socket *sock;
-       struct dst_network_ctl *ctl = &st->ctl;
-
-       err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &sock);
-       if (err < 0)
-               return err;
-
-       sock->sk->sk_sndtimeo = sock->sk->sk_rcvtimeo =
-               msecs_to_jiffies(DST_DEFAULT_TIMEO);
-       sock->sk->sk_allocation = GFP_NOIO;
-
-       st->socket = st->read_socket = sock;
-       return 0;
-}
-
-void dst_state_socket_release(struct dst_state *st)
-{
-       dprintk("%s: st: %p, socket: %p, n: %p.\n",
-                       __func__, st, st->socket, st->node);
-       if (st->socket) {
-               sock_release(st->socket);
-               st->socket = NULL;
-               st->read_socket = NULL;
-       }
-}
-
-void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str)
-{
-       if (sk->ops->family == AF_INET) {
-               struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-               printk(KERN_INFO "%s %u.%u.%u.%u:%d.\n", str,
-                       NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port));
-       } else if (sk->ops->family == AF_INET6) {
-               struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa;
-               printk(KERN_INFO "%s %pi6:%d",
-                       str, &sin->sin6_addr, ntohs(sin->sin6_port));
-       }
-}
-
-void dst_state_exit_connected(struct dst_state *st)
-{
-       if (st->socket) {
-               dst_poll_exit(st);
-               st->socket->ops->shutdown(st->socket, 2);
-
-               dst_dump_addr(st->socket, (struct sockaddr *)&st->ctl.addr,
-                               "Disconnected peer");
-               dst_state_socket_release(st);
-       }
-}
-
-static int dst_state_init_connected(struct dst_state *st)
-{
-       int err;
-       struct dst_network_ctl *ctl = &st->ctl;
-
-       err = dst_state_socket_create(st);
-       if (err)
-               goto err_out_exit;
-
-       err = kernel_connect(st->socket, (struct sockaddr *)&st->ctl.addr,
-                       st->ctl.addr.sa_data_len, 0);
-       if (err)
-               goto err_out_release;
-
-       err = dst_poll_init(st);
-       if (err)
-               goto err_out_release;
-
-       dst_dump_addr(st->socket, (struct sockaddr *)&ctl->addr,
-                       "Connected to peer");
-
-       return 0;
-
-err_out_release:
-       dst_state_socket_release(st);
-err_out_exit:
-       return err;
-}
-
-/*
- * State reset is used to reconnect to the remote peer.
- * May fail, but who cares, we will try again later.
- */
-static inline void dst_state_reset_nolock(struct dst_state *st)
-{
-       dst_state_exit_connected(st);
-       dst_state_init_connected(st);
-}
-
-static inline void dst_state_reset(struct dst_state *st)
-{
-       dst_state_lock(st);
-       dst_state_reset_nolock(st);
-       dst_state_unlock(st);
-}
-
-/*
- * Basic network sending/receiving functions.
- * Blocked mode is used.
- */
-static int dst_data_recv_raw(struct dst_state *st, void *buf, u64 size)
-{
-       struct msghdr msg;
-       struct kvec iov;
-       int err;
-
-       BUG_ON(!size);
-
-       iov.iov_base = buf;
-       iov.iov_len = size;
-
-       msg.msg_iov = (struct iovec *)&iov;
-       msg.msg_iovlen = 1;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = MSG_DONTWAIT;
-
-       err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len,
-                       msg.msg_flags);
-       if (err <= 0) {
-               dprintk("%s: failed to recv data: size: %llu, err: %d.\n",
-                               __func__, size, err);
-               if (err == 0)
-                       err = -ECONNRESET;
-
-               dst_state_exit_connected(st);
-       }
-
-       return err;
-}
-
-/*
- * Ping command to early detect failed nodes.
- */
-static int dst_send_ping(struct dst_state *st)
-{
-       struct dst_cmd *cmd = st->data;
-       int err = -ECONNRESET;
-
-       dst_state_lock(st);
-       if (st->socket) {
-               memset(cmd, 0, sizeof(struct dst_cmd));
-
-               cmd->cmd = __cpu_to_be32(DST_PING);
-
-               err = dst_data_send_header(st->socket, cmd,
-                               sizeof(struct dst_cmd), 0);
-       }
-       dprintk("%s: st: %p, socket: %p, err: %d.\n", __func__,
-                       st, st->socket, err);
-       dst_state_unlock(st);
-
-       return err;
-}
-
-/*
- * Receiving function, which should either return error or read
- * whole block request. If there was no traffic for a one second,
- * send a ping, since remote node may die.
- */
-int dst_data_recv(struct dst_state *st, void *data, unsigned int size)
-{
-       unsigned int revents = 0;
-       unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP;
-       unsigned int mask = err_mask | POLLIN;
-       struct dst_node *n = st->node;
-       int err = 0;
-
-       while (size && !err) {
-               revents = dst_state_poll(st);
-
-               if (!(revents & mask)) {
-                       DEFINE_WAIT(wait);
-
-                       for (;;) {
-                               prepare_to_wait(&st->thread_wait, &wait,
-                                               TASK_INTERRUPTIBLE);
-                               if (!n->trans_scan_timeout || st->need_exit)
-                                       break;
-
-                               revents = dst_state_poll(st);
-
-                               if (revents & mask)
-                                       break;
-
-                               if (signal_pending(current))
-                                       break;
-
-                               if (!schedule_timeout(HZ)) {
-                                       err = dst_send_ping(st);
-                                       if (err)
-                                               return err;
-                               }
-
-                               continue;
-                       }
-                       finish_wait(&st->thread_wait, &wait);
-               }
-
-               err = -ECONNRESET;
-               dst_state_lock(st);
-
-               if (st->socket && (st->read_socket == st->socket) &&
-                               (revents & POLLIN)) {
-                       err = dst_data_recv_raw(st, data, size);
-                       if (err > 0) {
-                               data += err;
-                               size -= err;
-                               err = 0;
-                       }
-               }
-
-               if (revents & err_mask || !st->socket) {
-                       dprintk("%s: revents: %x, socket: %p, size: %u, "
-                                       "err: %d.\n", __func__, revents,
-                                       st->socket, size, err);
-                       err = -ECONNRESET;
-               }
-
-               dst_state_unlock(st);
-
-               if (!n->trans_scan_timeout)
-                       err = -ENODEV;
-       }
-
-       return err;
-}
-
-/*
- * Send block autoconf reply.
- */
-static int dst_process_cfg(struct dst_state *st)
-{
-       struct dst_node *n = st->node;
-       struct dst_cmd *cmd = st->data;
-       int err;
-
-       cmd->sector = n->size;
-       cmd->rw = st->permissions;
-
-       dst_convert_cmd(cmd);
-
-       dst_state_lock(st);
-       err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0);
-       dst_state_unlock(st);
-
-       return err;
-}
-
-/*
- * Receive block IO from the network.
- */
-static int dst_recv_bio(struct dst_state *st, struct bio *bio,
-               unsigned int total_size)
-{
-       struct bio_vec *bv;
-       int i, err;
-       void *data;
-       unsigned int sz;
-
-       bio_for_each_segment(bv, bio, i) {
-               sz = min(total_size, bv->bv_len);
-
-               dprintk("%s: bio: %llu/%u, total: %u, len: %u, sz: %u, "
-                               "off: %u.\n", __func__, (u64)bio->bi_sector,
-                               bio->bi_size, total_size, bv->bv_len, sz,
-                               bv->bv_offset);
-
-               data = kmap(bv->bv_page) + bv->bv_offset;
-               err = dst_data_recv(st, data, sz);
-               kunmap(bv->bv_page);
-
-               bv->bv_len = sz;
-
-               if (err)
-                       return err;
-
-               total_size -= sz;
-               if (total_size == 0)
-                       break;
-       }
-
-       return 0;
-}
-
-/*
- * Our block IO has just completed and arrived: get it.
- */
-static int dst_process_io_response(struct dst_state *st)
-{
-       struct dst_node *n = st->node;
-       struct dst_cmd *cmd = st->data;
-       struct dst_trans *t;
-       int err = 0;
-       struct bio *bio;
-
-       mutex_lock(&n->trans_lock);
-       t = dst_trans_search(n, cmd->id);
-       mutex_unlock(&n->trans_lock);
-
-       if (!t)
-               goto err_out_exit;
-
-       bio = t->bio;
-
-       dprintk("%s: bio: %llu/%u, cmd_size: %u, csize: %u, dir: %lu.\n",
-               __func__, (u64)bio->bi_sector, bio->bi_size, cmd->size,
-               cmd->csize, bio_data_dir(bio));
-
-       if (bio_data_dir(bio) == READ) {
-               if (bio->bi_size != cmd->size - cmd->csize)
-                       goto err_out_exit;
-
-               if (dst_need_crypto(n)) {
-                       err = dst_recv_cdata(st, t->cmd.hash);
-                       if (err)
-                               goto err_out_exit;
-               }
-
-               err = dst_recv_bio(st, t->bio, bio->bi_size);
-               if (err)
-                       goto err_out_exit;
-
-               if (dst_need_crypto(n))
-                       return dst_trans_crypto(t);
-       } else {
-               err = -EBADMSG;
-               if (cmd->size || cmd->csize)
-                       goto err_out_exit;
-       }
-
-       dst_trans_remove(t);
-       dst_trans_put(t);
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-/*
- * Receive crypto data.
- */
-int dst_recv_cdata(struct dst_state *st, void *cdata)
-{
-       struct dst_cmd *cmd = st->data;
-       struct dst_node *n = st->node;
-       struct dst_crypto_ctl *c = &n->crypto;
-       int err;
-
-       if (cmd->csize != c->crypto_attached_size) {
-               dprintk("%s: cmd: cmd: %u, sector: %llu, size: %u, "
-                               "csize: %u != digest size %u.\n",
-                               __func__, cmd->cmd, cmd->sector, cmd->size,
-                               cmd->csize, c->crypto_attached_size);
-               err = -EINVAL;
-               goto err_out_exit;
-       }
-
-       err = dst_data_recv(st, cdata, cmd->csize);
-       if (err)
-               goto err_out_exit;
-
-       cmd->size -= cmd->csize;
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-/*
- * Receive the command and start its processing.
- */
-static int dst_recv_processing(struct dst_state *st)
-{
-       int err = -EINTR;
-       struct dst_cmd *cmd = st->data;
-
-       /*
-        * If socket will be reset after this statement, then
-        * dst_data_recv() will just fail and loop will
-        * start again, so it can be done without any locks.
-        *
-        * st->read_socket is needed to prevents state machine
-        * breaking between this data reading and subsequent one
-        * in protocol specific functions during connection reset.
-        * In case of reset we have to read next command and do
-        * not expect data for old command to magically appear in
-        * new connection.
-        */
-       st->read_socket = st->socket;
-       err = dst_data_recv(st, cmd, sizeof(struct dst_cmd));
-       if (err)
-               goto out_exit;
-
-       dst_convert_cmd(cmd);
-
-       dprintk("%s: cmd: %u, size: %u, csize: %u, id: %llu, "
-                       "sector: %llu, flags: %llx, rw: %llx.\n",
-                       __func__, cmd->cmd, cmd->size,
-                       cmd->csize, cmd->id, cmd->sector,
-                       cmd->flags, cmd->rw);
-
-       /*
-        * This should catch protocol breakage and random garbage
-        * instead of commands.
-        */
-       if (unlikely(cmd->csize > st->size - sizeof(struct dst_cmd))) {
-               err = -EBADMSG;
-               goto out_exit;
-       }
-
-       err = -EPROTO;
-       switch (cmd->cmd) {
-       case DST_IO_RESPONSE:
-               err = dst_process_io_response(st);
-               break;
-       case DST_IO:
-               err = dst_process_io(st);
-               break;
-       case DST_CFG:
-               err = dst_process_cfg(st);
-               break;
-       case DST_PING:
-               err = 0;
-               break;
-       default:
-               break;
-       }
-
-out_exit:
-       return err;
-}
-
-/*
- * Receiving thread. For the client node we should try to reconnect,
- * for accepted client we just drop the state and expect it to reconnect.
- */
-static int dst_recv(void *init_data, void *schedule_data)
-{
-       struct dst_state *st = schedule_data;
-       struct dst_node *n = init_data;
-       int err = 0;
-
-       dprintk("%s: start st: %p, n: %p, scan: %lu, need_exit: %d.\n",
-                       __func__, st, n, n->trans_scan_timeout, st->need_exit);
-
-       while (n->trans_scan_timeout && !st->need_exit) {
-               err = dst_recv_processing(st);
-               if (err < 0) {
-                       if (!st->ctl.type)
-                               break;
-
-                       if (!n->trans_scan_timeout || st->need_exit)
-                               break;
-
-                       dst_state_reset(st);
-                       msleep(1000);
-               }
-       }
-
-       st->need_exit = 1;
-       wake_up(&st->thread_wait);
-
-       dprintk("%s: freeing receiving socket st: %p.\n", __func__, st);
-       dst_state_lock(st);
-       dst_state_exit_connected(st);
-       dst_state_unlock(st);
-       dst_state_put(st);
-
-       dprintk("%s: freed receiving socket st: %p.\n", __func__, st);
-
-       return err;
-}
-
-/*
- * Network state dies here and borns couple of lines below.
- * This object is the main network state processing engine:
- * sending, receiving, reconnections, all network related
- * tasks are handled on behalf of the state.
- */
-static void dst_state_free(struct dst_state *st)
-{
-       dprintk("%s: st: %p.\n", __func__, st);
-       if (st->cleanup)
-               st->cleanup(st);
-       kfree(st->data);
-       kfree(st);
-}
-
-struct dst_state *dst_state_alloc(struct dst_node *n)
-{
-       struct dst_state *st;
-       int err = -ENOMEM;
-
-       st = kzalloc(sizeof(struct dst_state), GFP_KERNEL);
-       if (!st)
-               goto err_out_exit;
-
-       st->node = n;
-       st->need_exit = 0;
-
-       st->size = PAGE_SIZE;
-       st->data = kmalloc(st->size, GFP_KERNEL);
-       if (!st->data)
-               goto err_out_free;
-
-       spin_lock_init(&st->request_lock);
-       INIT_LIST_HEAD(&st->request_list);
-
-       mutex_init(&st->state_lock);
-       init_waitqueue_head(&st->thread_wait);
-
-       /*
-        * One for processing thread, another one for node itself.
-        */
-       atomic_set(&st->refcnt, 2);
-
-       dprintk("%s: st: %p, n: %p.\n", __func__, st, st->node);
-
-       return st;
-
-err_out_free:
-       kfree(st);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-int dst_state_schedule_receiver(struct dst_state *st)
-{
-       return thread_pool_schedule_private(st->node->pool, dst_thread_setup,
-                       dst_recv, st, MAX_SCHEDULE_TIMEOUT, st->node);
-}
-
-/*
- * Initialize client's connection to the remote peer: allocate state,
- * connect and perform block IO autoconfiguration.
- */
-int dst_node_init_connected(struct dst_node *n, struct dst_network_ctl *r)
-{
-       struct dst_state *st;
-       int err = -ENOMEM;
-
-       st = dst_state_alloc(n);
-       if (IS_ERR(st)) {
-               err = PTR_ERR(st);
-               goto err_out_exit;
-       }
-       memcpy(&st->ctl, r, sizeof(struct dst_network_ctl));
-
-       err = dst_state_init_connected(st);
-       if (err)
-               goto err_out_free_data;
-
-       err = dst_request_remote_config(st);
-       if (err)
-               goto err_out_exit_connected;
-       n->state = st;
-
-       err = dst_state_schedule_receiver(st);
-       if (err)
-               goto err_out_exit_connected;
-
-       return 0;
-
-err_out_exit_connected:
-       dst_state_exit_connected(st);
-err_out_free_data:
-       dst_state_free(st);
-err_out_exit:
-       n->state = NULL;
-       return err;
-}
-
-void dst_state_put(struct dst_state *st)
-{
-       dprintk("%s: st: %p, refcnt: %d.\n",
-                       __func__, st, atomic_read(&st->refcnt));
-       if (atomic_dec_and_test(&st->refcnt))
-               dst_state_free(st);
-}
-
-/*
- * Send block IO to the network one by one using zero-copy ->sendpage().
- */
-int dst_send_bio(struct dst_state *st, struct dst_cmd *cmd, struct bio *bio)
-{
-       struct bio_vec *bv;
-       struct dst_crypto_ctl *c = &st->node->crypto;
-       int err, i = 0;
-       int flags = MSG_WAITALL;
-
-       err = dst_data_send_header(st->socket, cmd,
-               sizeof(struct dst_cmd) + c->crypto_attached_size, bio->bi_vcnt);
-       if (err)
-               goto err_out_exit;
-
-       bio_for_each_segment(bv, bio, i) {
-               if (i < bio->bi_vcnt - 1)
-                       flags |= MSG_MORE;
-
-               err = kernel_sendpage(st->socket, bv->bv_page, bv->bv_offset,
-                               bv->bv_len, flags);
-               if (err <= 0)
-                       goto err_out_exit;
-       }
-
-       return 0;
-
-err_out_exit:
-       dprintk("%s: %d/%d, flags: %x, err: %d.\n",
-                       __func__, i, bio->bi_vcnt, flags, err);
-       return err;
-}
-
-/*
- * Send transaction to the remote peer.
- */
-int dst_trans_send(struct dst_trans *t)
-{
-       int err;
-       struct dst_state *st = t->n->state;
-       struct bio *bio = t->bio;
-
-       dst_convert_cmd(&t->cmd);
-
-       dst_state_lock(st);
-       if (!st->socket) {
-               err = dst_state_init_connected(st);
-               if (err)
-                       goto err_out_unlock;
-       }
-
-       if (bio_data_dir(bio) == WRITE) {
-               err = dst_send_bio(st, &t->cmd, t->bio);
-       } else {
-               err = dst_data_send_header(st->socket, &t->cmd,
-                               sizeof(struct dst_cmd), 0);
-       }
-       if (err)
-               goto err_out_reset;
-
-       dst_state_unlock(st);
-       return 0;
-
-err_out_reset:
-       dst_state_reset_nolock(st);
-err_out_unlock:
-       dst_state_unlock(st);
-
-       return err;
-}
diff --git a/drivers/staging/dst/thread_pool.c b/drivers/staging/dst/thread_pool.c
deleted file mode 100644 (file)
index 29a82b2..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/dst.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-
-/*
- * Thread pool abstraction allows to schedule a work to be performed
- * on behalf of kernel thread. One does not operate with threads itself,
- * instead user provides setup and cleanup callbacks for thread pool itself,
- * and action and cleanup callbacks for each submitted work.
- *
- * Each worker has private data initialized at creation time and data,
- * provided by user at scheduling time.
- *
- * When action is being performed, thread can not be used by other users,
- * instead they will sleep until there is free thread to pick their work.
- */
-struct thread_pool_worker {
-       struct list_head        worker_entry;
-
-       struct task_struct      *thread;
-
-       struct thread_pool      *pool;
-
-       int                     error;
-       int                     has_data;
-       int                     need_exit;
-       unsigned int            id;
-
-       wait_queue_head_t       wait;
-
-       void                    *private;
-       void                    *schedule_data;
-
-       int                     (*action)(void *private, void *schedule_data);
-       void                    (*cleanup)(void *private);
-};
-
-static void thread_pool_exit_worker(struct thread_pool_worker *w)
-{
-       kthread_stop(w->thread);
-
-       w->cleanup(w->private);
-       kfree(w);
-}
-
-/*
- * Called to mark thread as ready and allow users to schedule new work.
- */
-static void thread_pool_worker_make_ready(struct thread_pool_worker *w)
-{
-       struct thread_pool *p = w->pool;
-
-       mutex_lock(&p->thread_lock);
-
-       if (!w->need_exit) {
-               list_move_tail(&w->worker_entry, &p->ready_list);
-               w->has_data = 0;
-               mutex_unlock(&p->thread_lock);
-
-               wake_up(&p->wait);
-       } else {
-               p->thread_num--;
-               list_del(&w->worker_entry);
-               mutex_unlock(&p->thread_lock);
-
-               thread_pool_exit_worker(w);
-       }
-}
-
-/*
- * Thread action loop: waits until there is new work.
- */
-static int thread_pool_worker_func(void *data)
-{
-       struct thread_pool_worker *w = data;
-
-       while (!kthread_should_stop()) {
-               wait_event_interruptible(w->wait,
-                       kthread_should_stop() || w->has_data);
-
-               if (kthread_should_stop())
-                       break;
-
-               if (!w->has_data)
-                       continue;
-
-               w->action(w->private, w->schedule_data);
-               thread_pool_worker_make_ready(w);
-       }
-
-       return 0;
-}
-
-/*
- * Remove single worker without specifying which one.
- */
-void thread_pool_del_worker(struct thread_pool *p)
-{
-       struct thread_pool_worker *w = NULL;
-
-       while (!w && p->thread_num) {
-               wait_event(p->wait, !list_empty(&p->ready_list) ||
-                               !p->thread_num);
-
-               dprintk("%s: locking list_empty: %d, thread_num: %d.\n",
-                               __func__, list_empty(&p->ready_list),
-                               p->thread_num);
-
-               mutex_lock(&p->thread_lock);
-               if (!list_empty(&p->ready_list)) {
-                       w = list_first_entry(&p->ready_list,
-                                       struct thread_pool_worker,
-                                       worker_entry);
-
-                       dprintk("%s: deleting w: %p, thread_num: %d, "
-                                       "list: %p [%p.%p].\n", __func__,
-                                       w, p->thread_num, &p->ready_list,
-                                       p->ready_list.prev, p->ready_list.next);
-
-                       p->thread_num--;
-                       list_del(&w->worker_entry);
-               }
-               mutex_unlock(&p->thread_lock);
-       }
-
-       if (w)
-               thread_pool_exit_worker(w);
-       dprintk("%s: deleted w: %p, thread_num: %d.\n",
-                       __func__, w, p->thread_num);
-}
-
-/*
- * Remove a worker with given ID.
- */
-void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id)
-{
-       struct thread_pool_worker *w;
-       int found = 0;
-
-       mutex_lock(&p->thread_lock);
-       list_for_each_entry(w, &p->ready_list, worker_entry) {
-               if (w->id == id) {
-                       found = 1;
-                       p->thread_num--;
-                       list_del(&w->worker_entry);
-                       break;
-               }
-       }
-
-       if (!found) {
-               list_for_each_entry(w, &p->active_list, worker_entry) {
-                       if (w->id == id) {
-                               w->need_exit = 1;
-                               break;
-                       }
-               }
-       }
-       mutex_unlock(&p->thread_lock);
-
-       if (found)
-               thread_pool_exit_worker(w);
-}
-
-/*
- * Add new worker thread with given parameters.
- * If initialization callback fails, return error.
- */
-int thread_pool_add_worker(struct thread_pool *p,
-               char *name,
-               unsigned int id,
-               void *(*init)(void *private),
-               void (*cleanup)(void *private),
-               void *private)
-{
-       struct thread_pool_worker *w;
-       int err = -ENOMEM;
-
-       w = kzalloc(sizeof(struct thread_pool_worker), GFP_KERNEL);
-       if (!w)
-               goto err_out_exit;
-
-       w->pool = p;
-       init_waitqueue_head(&w->wait);
-       w->cleanup = cleanup;
-       w->id = id;
-
-       w->thread = kthread_run(thread_pool_worker_func, w, "%s", name);
-       if (IS_ERR(w->thread)) {
-               err = PTR_ERR(w->thread);
-               goto err_out_free;
-       }
-
-       w->private = init(private);
-       if (IS_ERR(w->private)) {
-               err = PTR_ERR(w->private);
-               goto err_out_stop_thread;
-       }
-
-       mutex_lock(&p->thread_lock);
-       list_add_tail(&w->worker_entry, &p->ready_list);
-       p->thread_num++;
-       mutex_unlock(&p->thread_lock);
-
-       return 0;
-
-err_out_stop_thread:
-       kthread_stop(w->thread);
-err_out_free:
-       kfree(w);
-err_out_exit:
-       return err;
-}
-
-/*
- * Destroy the whole pool.
- */
-void thread_pool_destroy(struct thread_pool *p)
-{
-       while (p->thread_num) {
-               dprintk("%s: num: %d.\n", __func__, p->thread_num);
-               thread_pool_del_worker(p);
-       }
-
-       kfree(p);
-}
-
-/*
- * Create a pool with given number of threads.
- * They will have sequential IDs started from zero.
- */
-struct thread_pool *thread_pool_create(int num, char *name,
-               void *(*init)(void *private),
-               void (*cleanup)(void *private),
-               void *private)
-{
-       struct thread_pool_worker *w, *tmp;
-       struct thread_pool *p;
-       int err = -ENOMEM;
-       int i;
-
-       p = kzalloc(sizeof(struct thread_pool), GFP_KERNEL);
-       if (!p)
-               goto err_out_exit;
-
-       init_waitqueue_head(&p->wait);
-       mutex_init(&p->thread_lock);
-       INIT_LIST_HEAD(&p->ready_list);
-       INIT_LIST_HEAD(&p->active_list);
-       p->thread_num = 0;
-
-       for (i = 0; i < num; ++i) {
-               err = thread_pool_add_worker(p, name, i, init,
-                               cleanup, private);
-               if (err)
-                       goto err_out_free_all;
-       }
-
-       return p;
-
-err_out_free_all:
-       list_for_each_entry_safe(w, tmp, &p->ready_list, worker_entry) {
-               list_del(&w->worker_entry);
-               thread_pool_exit_worker(w);
-       }
-       kfree(p);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-/*
- * Schedule execution of the action on a given thread,
- * provided ID pointer has to match previously stored
- * private data.
- */
-int thread_pool_schedule_private(struct thread_pool *p,
-               int (*setup)(void *private, void *data),
-               int (*action)(void *private, void *data),
-               void *data, long timeout, void *id)
-{
-       struct thread_pool_worker *w, *tmp, *worker = NULL;
-       int err = 0;
-
-       while (!worker && !err) {
-               timeout = wait_event_interruptible_timeout(p->wait,
-                               !list_empty(&p->ready_list),
-                               timeout);
-
-               if (!timeout) {
-                       err = -ETIMEDOUT;
-                       break;
-               }
-
-               worker = NULL;
-               mutex_lock(&p->thread_lock);
-               list_for_each_entry_safe(w, tmp, &p->ready_list, worker_entry) {
-                       if (id && id != w->private)
-                               continue;
-
-                       worker = w;
-
-                       list_move_tail(&w->worker_entry, &p->active_list);
-
-                       err = setup(w->private, data);
-                       if (!err) {
-                               w->schedule_data = data;
-                               w->action = action;
-                               w->has_data = 1;
-                               wake_up(&w->wait);
-                       } else {
-                               list_move_tail(&w->worker_entry,
-                                               &p->ready_list);
-                       }
-
-                       break;
-               }
-               mutex_unlock(&p->thread_lock);
-       }
-
-       return err;
-}
-
-/*
- * Schedule execution on arbitrary thread from the pool.
- */
-int thread_pool_schedule(struct thread_pool *p,
-               int (*setup)(void *private, void *data),
-               int (*action)(void *private, void *data),
-               void *data, long timeout)
-{
-       return thread_pool_schedule_private(p, setup,
-                       action, data, timeout, NULL);
-}
diff --git a/drivers/staging/dst/trans.c b/drivers/staging/dst/trans.c
deleted file mode 100644 (file)
index 1c36a6b..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
-
-#include <linux/bio.h>
-#include <linux/dst.h>
-#include <linux/slab.h>
-#include <linux/mempool.h>
-
-/*
- * Transaction memory pool size.
- */
-static int dst_mempool_num = 32;
-module_param(dst_mempool_num, int, 0644);
-
-/*
- * Transaction tree management.
- */
-static inline int dst_trans_cmp(dst_gen_t gen, dst_gen_t new)
-{
-       if (gen < new)
-               return 1;
-       if (gen > new)
-               return -1;
-       return 0;
-}
-
-struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen)
-{
-       struct rb_root *root = &node->trans_root;
-       struct rb_node *n = root->rb_node;
-       struct dst_trans *t, *ret = NULL;
-       int cmp;
-
-       while (n) {
-               t = rb_entry(n, struct dst_trans, trans_entry);
-
-               cmp = dst_trans_cmp(t->gen, gen);
-               if (cmp < 0)
-                       n = n->rb_left;
-               else if (cmp > 0)
-                       n = n->rb_right;
-               else {
-                       ret = t;
-                       break;
-               }
-       }
-
-       dprintk("%s: %s transaction: id: %llu.\n", __func__,
-                       (ret) ? "found" : "not found", gen);
-
-       return ret;
-}
-
-static int dst_trans_insert(struct dst_trans *new)
-{
-       struct rb_root *root = &new->n->trans_root;
-       struct rb_node **n = &root->rb_node, *parent = NULL;
-       struct dst_trans *ret = NULL, *t;
-       int cmp;
-
-       while (*n) {
-               parent = *n;
-
-               t = rb_entry(parent, struct dst_trans, trans_entry);
-
-               cmp = dst_trans_cmp(t->gen, new->gen);
-               if (cmp < 0)
-                       n = &parent->rb_left;
-               else if (cmp > 0)
-                       n = &parent->rb_right;
-               else {
-                       ret = t;
-                       break;
-               }
-       }
-
-       new->send_time = jiffies;
-       if (ret) {
-               printk(KERN_DEBUG "%s: exist: old: gen: %llu, bio: %llu/%u, "
-                       "send_time: %lu, new: gen: %llu, bio: %llu/%u, "
-                       "send_time: %lu.\n", __func__,
-                       ret->gen, (u64)ret->bio->bi_sector,
-                       ret->bio->bi_size, ret->send_time,
-                       new->gen, (u64)new->bio->bi_sector,
-                       new->bio->bi_size, new->send_time);
-               return -EEXIST;
-       }
-
-       rb_link_node(&new->trans_entry, parent, n);
-       rb_insert_color(&new->trans_entry, root);
-
-       dprintk("%s: inserted: gen: %llu, bio: %llu/%u, send_time: %lu.\n",
-               __func__, new->gen, (u64)new->bio->bi_sector,
-               new->bio->bi_size, new->send_time);
-
-       return 0;
-}
-
-int dst_trans_remove_nolock(struct dst_trans *t)
-{
-       struct dst_node *n = t->n;
-
-       if (t->trans_entry.rb_parent_color) {
-               rb_erase(&t->trans_entry, &n->trans_root);
-               t->trans_entry.rb_parent_color = 0;
-       }
-       return 0;
-}
-
-int dst_trans_remove(struct dst_trans *t)
-{
-       int ret;
-       struct dst_node *n = t->n;
-
-       mutex_lock(&n->trans_lock);
-       ret = dst_trans_remove_nolock(t);
-       mutex_unlock(&n->trans_lock);
-
-       return ret;
-}
-
-/*
- * When transaction is completed and there are no more users,
- * we complete appriate block IO request with given error status.
- */
-void dst_trans_put(struct dst_trans *t)
-{
-       if (atomic_dec_and_test(&t->refcnt)) {
-               struct bio *bio = t->bio;
-
-               dprintk("%s: completed t: %p, gen: %llu, bio: %p.\n",
-                               __func__, t, t->gen, bio);
-
-               bio_endio(bio, t->error);
-               bio_put(bio);
-
-               dst_node_put(t->n);
-               mempool_free(t, t->n->trans_pool);
-       }
-}
-
-/*
- * Process given block IO request: allocate transaction, insert it into the tree
- * and send/schedule crypto processing.
- */
-int dst_process_bio(struct dst_node *n, struct bio *bio)
-{
-       struct dst_trans *t;
-       int err = -ENOMEM;
-
-       t = mempool_alloc(n->trans_pool, GFP_NOFS);
-       if (!t)
-               goto err_out_exit;
-
-       t->n = dst_node_get(n);
-       t->bio = bio;
-       t->error = 0;
-       t->retries = 0;
-       atomic_set(&t->refcnt, 1);
-       t->gen = atomic_long_inc_return(&n->gen);
-
-       t->enc = bio_data_dir(bio);
-       dst_bio_to_cmd(bio, &t->cmd, DST_IO, t->gen);
-
-       mutex_lock(&n->trans_lock);
-       err = dst_trans_insert(t);
-       mutex_unlock(&n->trans_lock);
-       if (err)
-               goto err_out_free;
-
-       dprintk("%s: gen: %llu, bio: %llu/%u, dir/enc: %d, need_crypto: %d.\n",
-                       __func__, t->gen, (u64)bio->bi_sector,
-                       bio->bi_size, t->enc, dst_need_crypto(n));
-
-       if (dst_need_crypto(n) && t->enc)
-               dst_trans_crypto(t);
-       else
-               dst_trans_send(t);
-
-       return 0;
-
-err_out_free:
-       dst_node_put(n);
-       mempool_free(t, n->trans_pool);
-err_out_exit:
-       bio_endio(bio, err);
-       bio_put(bio);
-       return err;
-}
-
-/*
- * Scan for timeout/stale transactions.
- * Each transaction is being resent multiple times before error completion.
- */
-static void dst_trans_scan(struct work_struct *work)
-{
-       struct dst_node *n = container_of(work, struct dst_node,
-                       trans_work.work);
-       struct rb_node *rb_node;
-       struct dst_trans *t;
-       unsigned long timeout = n->trans_scan_timeout;
-       int num = 10 * n->trans_max_retries;
-
-       mutex_lock(&n->trans_lock);
-
-       for (rb_node = rb_first(&n->trans_root); rb_node; ) {
-               t = rb_entry(rb_node, struct dst_trans, trans_entry);
-
-               if (timeout && time_after(t->send_time + timeout, jiffies)
-                               && t->retries == 0)
-                       break;
-#if 0
-               dprintk("%s: t: %p, gen: %llu, n: %s, retries: %u, max: %u.\n",
-                       __func__, t, t->gen, n->name,
-                       t->retries, n->trans_max_retries);
-#endif
-               if (--num == 0)
-                       break;
-
-               dst_trans_get(t);
-
-               rb_node = rb_next(rb_node);
-
-               if (timeout && (++t->retries < n->trans_max_retries)) {
-                       dst_trans_send(t);
-               } else {
-                       t->error = -ETIMEDOUT;
-                       dst_trans_remove_nolock(t);
-                       dst_trans_put(t);
-               }
-
-               dst_trans_put(t);
-       }
-
-       mutex_unlock(&n->trans_lock);
-
-       /*
-        * If no timeout specified then system is in the middle of exiting
-        * process, so no need to reschedule scanning process again.
-        */
-       if (timeout) {
-               if (!num)
-                       timeout = HZ;
-               schedule_delayed_work(&n->trans_work, timeout);
-       }
-}
-
-/*
- * Flush all transactions and mark them as timed out.
- * Destroy transaction pools.
- */
-void dst_node_trans_exit(struct dst_node *n)
-{
-       struct dst_trans *t;
-       struct rb_node *rb_node;
-
-       if (!n->trans_cache)
-               return;
-
-       dprintk("%s: n: %p, cancelling the work.\n", __func__, n);
-       cancel_delayed_work_sync(&n->trans_work);
-       flush_scheduled_work();
-       dprintk("%s: n: %p, work has been cancelled.\n", __func__, n);
-
-       for (rb_node = rb_first(&n->trans_root); rb_node; ) {
-               t = rb_entry(rb_node, struct dst_trans, trans_entry);
-
-               dprintk("%s: t: %p, gen: %llu, n: %s.\n",
-                       __func__, t, t->gen, n->name);
-
-               rb_node = rb_next(rb_node);
-
-               t->error = -ETIMEDOUT;
-               dst_trans_remove_nolock(t);
-               dst_trans_put(t);
-       }
-
-       mempool_destroy(n->trans_pool);
-       kmem_cache_destroy(n->trans_cache);
-}
-
-/*
- * Initialize transaction storage for given node.
- * Transaction stores not only control information,
- * but also network command and crypto data (if needed)
- * to reduce number of allocations. Thus transaction size
- * differs from node to node.
- */
-int dst_node_trans_init(struct dst_node *n, unsigned int size)
-{
-       /*
-        * We need this, since node with given name can be dropped from the
-        * hash table, but be still alive, so subsequent creation of the node
-        * with the same name may collide with existing cache name.
-        */
-
-       snprintf(n->cache_name, sizeof(n->cache_name), "%s-%p", n->name, n);
-
-       n->trans_cache = kmem_cache_create(n->cache_name,
-                       size + n->crypto.crypto_attached_size,
-                       0, 0, NULL);
-       if (!n->trans_cache)
-               goto err_out_exit;
-
-       n->trans_pool = mempool_create_slab_pool(dst_mempool_num,
-                       n->trans_cache);
-       if (!n->trans_pool)
-               goto err_out_cache_destroy;
-
-       mutex_init(&n->trans_lock);
-       n->trans_root = RB_ROOT;
-
-       INIT_DELAYED_WORK(&n->trans_work, dst_trans_scan);
-       schedule_delayed_work(&n->trans_work, n->trans_scan_timeout);
-
-       dprintk("%s: n: %p, size: %u, crypto: %u.\n",
-               __func__, n, size, n->crypto.crypto_attached_size);
-
-       return 0;
-
-err_out_cache_destroy:
-       kmem_cache_destroy(n->trans_cache);
-err_out_exit:
-       return -ENOMEM;
-}
index 3abe7c9..3defa01 100644 (file)
@@ -47,7 +47,7 @@ config PANEL_PROFILE
 config PANEL_KEYPAD
        depends on PANEL && PANEL_PROFILE="0"
        int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)"
-       range 0 4
+       range 0 3
        default 0
        ---help---
          This enables and configures a keypad connected to the parallel port.
index f98a524..95c93e8 100644 (file)
@@ -378,7 +378,7 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
 
 #ifdef CONFIG_PANEL_LCD_CHARSET
 #undef DEFAULT_LCD_CHARSET
-#define DEFAULT_LCD_CHARSET
+#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET
 #endif
 
 #endif /* DEFAULT_PROFILE == 0 */
index 6c5b261..aacd25b 100644 (file)
@@ -722,8 +722,6 @@ static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry)
                if (inode->i_nlink)
                        inode_dec_link_count(inode);
        }
-       dprintk("%s: inode: %p, lock: %ld, unhashed: %d.\n",
-               __func__, pi, inode->i_state & I_LOCK, hlist_unhashed(&inode->i_hash));
 
        return err;
 }
index bac40d6..8d64e28 100644 (file)
@@ -1,6 +1,5 @@
 TODO:
        - Add support for swap notifiers
-       - Remove CONFIG_ARM hack
 
 Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
 Nitin Gupta <ngupta@vflare.org>
index b839f05..989fac5 100644 (file)
@@ -222,28 +222,6 @@ out:
        return ret;
 }
 
-static void ramzswap_flush_dcache_page(struct page *page)
-{
-#ifdef CONFIG_ARM
-       int flag = 0;
-       /*
-        * Ugly hack to get flush_dcache_page() work on ARM.
-        * page_mapping(page) == NULL after clearing this swap cache flag.
-        * Without clearing this flag, flush_dcache_page() will simply set
-        * "PG_dcache_dirty" bit and return.
-        */
-       if (PageSwapCache(page)) {
-               flag = 1;
-               ClearPageSwapCache(page);
-       }
-#endif
-       flush_dcache_page(page);
-#ifdef CONFIG_ARM
-       if (flag)
-               SetPageSwapCache(page);
-#endif
-}
-
 void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
                        struct ramzswap_ioctl_stats *s)
 {
@@ -655,7 +633,7 @@ static int handle_zero_page(struct bio *bio)
        memset(user_mem, 0, PAGE_SIZE);
        kunmap_atomic(user_mem, KM_USER0);
 
-       ramzswap_flush_dcache_page(page);
+       flush_dcache_page(page);
 
        set_bit(BIO_UPTODATE, &bio->bi_flags);
        bio_endio(bio, 0);
@@ -679,7 +657,7 @@ static int handle_uncompressed_page(struct ramzswap *rzs, struct bio *bio)
        kunmap_atomic(user_mem, KM_USER0);
        kunmap_atomic(cmem, KM_USER1);
 
-       ramzswap_flush_dcache_page(page);
+       flush_dcache_page(page);
 
        set_bit(BIO_UPTODATE, &bio->bi_flags);
        bio_endio(bio, 0);
@@ -779,7 +757,7 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio)
                goto out;
        }
 
-       ramzswap_flush_dcache_page(page);
+       flush_dcache_page(page);
 
        set_bit(BIO_UPTODATE, &bio->bi_flags);
        bio_endio(bio, 0);
index 3222c22..0d490c1 100644 (file)
@@ -1318,13 +1318,13 @@ extern int ieee80211_encrypt_fragment(
        struct sk_buff *frag,
        int hdr_len);
 
-extern int ieee80211_xmit(struct sk_buff *skb,
+extern int ieee80211_rtl_xmit(struct sk_buff *skb,
                          struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                             struct ieee80211_hdr_4addr *header,
@@ -1376,8 +1376,8 @@ extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
@@ -1385,7 +1385,7 @@ extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct
 extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
 extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
 extern void SendDisassociation(struct ieee80211_device *ieee,u8* asSta,u8 asRsn);
-extern void ieee80211_start_scan(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_start_scan(struct ieee80211_device *ieee);
 
 //Add for RF power on power off by lizhaoming 080512
 extern void SendDisassociation(struct ieee80211_device *ieee,
index f882dd8..9128c18 100644 (file)
@@ -469,7 +469,7 @@ drop:
 /* All received frames are sent to this function. @skb contains the frame in
  * IEEE 802.11 format, i.e., in the format it was sent over air.
  * This function is called only as a tasklet (software IRQ). */
-int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                 struct ieee80211_rx_stats *rx_stats)
 {
        struct net_device *dev = ieee->dev;
index 1fe19c3..c7c645a 100644 (file)
@@ -689,7 +689,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee)
 }
 
 /* called with ieee->lock held */
-void ieee80211_start_scan(struct ieee80211_device *ieee)
+void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
 {
        if(IS_DOT11D_ENABLE(ieee) )
        {
@@ -1196,7 +1196,7 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee)
        }
 }
 
-void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
+void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
 {
        u8 *c;
        struct sk_buff *skb;
@@ -1898,7 +1898,7 @@ associate_complete:
 
                                                                ieee80211_associate_step2(ieee);
                                                        }else{
-                                                               ieee80211_auth_challenge(ieee, challenge, chlen);
+                                                               ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
                                                        }
                                                }else{
                                                        ieee->softmac_stats.rx_auth_rs_err++;
@@ -2047,7 +2047,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee)
 
 }
 
-void ieee80211_wake_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
 {
 
        unsigned long flags;
@@ -2089,7 +2089,7 @@ exit :
 }
 
 
-void ieee80211_stop_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
 {
        //unsigned long flags;
        //spin_lock_irqsave(&ieee->lock,flags);
@@ -2301,7 +2301,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
 //#else
        if (ieee->state == IEEE80211_NOLINK){
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
 //#endif
        spin_unlock_irqrestore(&ieee->lock, flags);
@@ -2357,7 +2357,7 @@ void ieee80211_associate_retry_wq(struct work_struct *work)
        if(ieee->state == IEEE80211_NOLINK){
                ieee->beinretry = false;
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
        //YJ,add,080828, notify os here
        if(ieee->state == IEEE80211_NOLINK)
index dde1f2e..69bd021 100644 (file)
@@ -304,7 +304,7 @@ ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network)
 }
 
 /* SKBs are added to the ieee->tx_queue. */
-int ieee80211_xmit(struct sk_buff *skb,
+int ieee80211_rtl_xmit(struct sk_buff *skb,
                   struct net_device *dev)
 {
        struct ieee80211_device *ieee = netdev_priv(dev);
index 57c62b0..e0f13ef 100644 (file)
@@ -1811,7 +1811,7 @@ void rtl8180_rx(struct net_device *dev)
                        if(priv->rx_skb->len > 4)
                                skb_trim(priv->rx_skb,priv->rx_skb->len-4);
 #ifndef RX_DONT_PASS_UL
-                       if(!ieee80211_rx(priv->ieee80211,
+                       if(!ieee80211_rtl_rx(priv->ieee80211,
                                         priv->rx_skb, &stats)){
 #endif // RX_DONT_PASS_UL
 
@@ -1917,11 +1917,11 @@ rate)
        if (!check_nic_enought_desc(dev, priority)){
                DMESGW("Error: no descriptor left by previous TX (avail %d) ",
                        get_curr_tx_free_desc(dev, priority));
-               ieee80211_stop_queue(priv->ieee80211);
+               ieee80211_rtl_stop_queue(priv->ieee80211);
        }
        rtl8180_tx(dev, skb->data, skb->len, priority, morefrag,0,rate);
        if (!check_nic_enought_desc(dev, priority))
-               ieee80211_stop_queue(priv->ieee80211);
+               ieee80211_rtl_stop_queue(priv->ieee80211);
 
        spin_unlock_irqrestore(&priv->tx_lock,flags);
 }
@@ -3680,7 +3680,7 @@ static const struct net_device_ops rtl8180_netdev_ops = {
        .ndo_set_mac_address    = r8180_set_mac_adr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
-       .ndo_start_xmit         = ieee80211_xmit,
+       .ndo_start_xmit         = ieee80211_rtl_xmit,
 };
 
 static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
@@ -3900,7 +3900,7 @@ void rtl8180_try_wake_queue(struct net_device *dev, int pri)
        spin_unlock_irqrestore(&priv->tx_lock,flags);
 
        if(enough_desc)
-               ieee80211_wake_queue(priv->ieee80211);
+               ieee80211_rtl_wake_queue(priv->ieee80211);
 }
 
 void rtl8180_tx_isr(struct net_device *dev, int pri,short error)
index 536cb6e..124cde3 100644 (file)
@@ -377,7 +377,7 @@ static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
        //      queue_work(priv->ieee80211->wq, &priv->ieee80211->wx_sync_scan_wq);
                //printk("start scan============================>\n");
                ieee80211_softmac_ips_scan_syncro(priv->ieee80211);
-//ieee80211_start_scan(priv->ieee80211);
+//ieee80211_rtl_start_scan(priv->ieee80211);
                /* intentionally forget to up sem */
 //                     up(&priv->ieee80211->wx_sem);
                        ret = 0;
index 97137dd..3ba9e9e 100644 (file)
@@ -303,8 +303,8 @@ enum        _ReasonCode{
 #define ieee80211_rx_mgt               ieee80211_rx_mgt_rsl
 
 #define ieee80211_get_beacon           ieee80211_get_beacon_rsl
-#define ieee80211_wake_queue           ieee80211_wake_queue_rsl
-#define ieee80211_stop_queue           ieee80211_stop_queue_rsl
+#define ieee80211_rtl_wake_queue               ieee80211_rtl_wake_queue_rsl
+#define ieee80211_rtl_stop_queue               ieee80211_rtl_stop_queue_rsl
 #define ieee80211_reset_queue          ieee80211_reset_queue_rsl
 #define ieee80211_softmac_stop_protocol        ieee80211_softmac_stop_protocol_rsl
 #define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl
@@ -2435,13 +2435,13 @@ extern int ieee80211_encrypt_fragment(
        struct sk_buff *frag,
        int hdr_len);
 
-extern int ieee80211_xmit(struct sk_buff *skb,
+extern int ieee80211_rtl_xmit(struct sk_buff *skb,
                          struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                             struct ieee80211_hdr_4addr *header,
@@ -2502,8 +2502,8 @@ extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
index 83c8452..aa76390 100644 (file)
@@ -333,8 +333,8 @@ enum        _ReasonCode{
 #define ieee80211_rx_mgt               ieee80211_rx_mgt_rsl
 
 #define ieee80211_get_beacon           ieee80211_get_beacon_rsl
-#define ieee80211_wake_queue           ieee80211_wake_queue_rsl
-#define ieee80211_stop_queue           ieee80211_stop_queue_rsl
+#define ieee80211_rtl_wake_queue               ieee80211_rtl_wake_queue_rsl
+#define ieee80211_rtl_stop_queue               ieee80211_rtl_stop_queue_rsl
 #define ieee80211_reset_queue          ieee80211_reset_queue_rsl
 #define ieee80211_softmac_stop_protocol        ieee80211_softmac_stop_protocol_rsl
 #define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl
@@ -2546,13 +2546,13 @@ extern int ieee80211_encrypt_fragment(
        struct sk_buff *frag,
        int hdr_len);
 
-extern int ieee80211_xmit(struct sk_buff *skb,
+extern int ieee80211_rtl_xmit(struct sk_buff *skb,
                          struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                             struct ieee80211_hdr_4addr *header,
@@ -2613,8 +2613,8 @@ extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
index 2644155..f43a7db 100644 (file)
@@ -119,7 +119,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
        ieee = (struct ieee80211_device *)dev->priv;
 #endif
 #if 0
-       dev->hard_start_xmit = ieee80211_xmit;
+       dev->hard_start_xmit = ieee80211_rtl_xmit;
 #endif
 
        memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv);
@@ -333,7 +333,7 @@ extern void ieee80211_crypto_ccmp_exit(void);
 extern int ieee80211_crypto_wep_init(void);
 extern void ieee80211_crypto_wep_exit(void);
 
-int __init ieee80211_init(void)
+int __init ieee80211_rtl_init(void)
 {
        struct proc_dir_entry *e;
        int retval;
@@ -389,7 +389,7 @@ int __init ieee80211_init(void)
        return 0;
 }
 
-void __exit ieee80211_exit(void)
+void __exit ieee80211_rtl_exit(void)
 {
        if (ieee80211_proc) {
                remove_proc_entry("debug_level", ieee80211_proc);
@@ -412,8 +412,8 @@ module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "debug output mask");
 
 
-//module_exit(ieee80211_exit);
-//module_init(ieee80211_init);
+//module_exit(ieee80211_rtl_exit);
+//module_init(ieee80211_rtl_init);
 #endif
 #endif
 
index 5dc478b..06d9171 100644 (file)
@@ -923,7 +923,7 @@ u8 parse_subframe(struct sk_buff *skb,
 /* All received frames are sent to this function. @skb contains the frame in
  * IEEE 802.11 format, i.e., in the format it was sent over air.
  * This function is called only as a tasklet (software IRQ). */
-int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                 struct ieee80211_rx_stats *rx_stats)
 {
        struct net_device *dev = ieee->dev;
index 593d228..6d1ddec 100644 (file)
@@ -684,7 +684,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee)
 }
 
 /* called with ieee->lock held */
-void ieee80211_start_scan(struct ieee80211_device *ieee)
+void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
 {
 #ifdef ENABLE_DOT11D
        if(IS_DOT11D_ENABLE(ieee) )
@@ -1430,7 +1430,7 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee)
        }
 }
 
-void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
+void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
 {
        u8 *c;
        struct sk_buff *skb;
@@ -2262,7 +2262,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 
                                                                ieee80211_associate_step2(ieee);
                                                        }else{
-                                                               ieee80211_auth_challenge(ieee, challenge, chlen);
+                                                               ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
                                                        }
                                                }else{
                                                        ieee->softmac_stats.rx_auth_rs_err++;
@@ -2376,7 +2376,7 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *
                         * to check it any more.
                         * */
                        //printk("error:no descriptor left@queue_index %d\n", queue_index);
-                       //ieee80211_stop_queue(ieee);
+                       //ieee80211_rtl_stop_queue(ieee);
 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
                        skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
 #else
@@ -2440,7 +2440,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee)
 
 }
 
-void ieee80211_wake_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
 {
 
        unsigned long flags;
@@ -2481,7 +2481,7 @@ exit :
 }
 
 
-void ieee80211_stop_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
 {
        //unsigned long flags;
        //spin_lock_irqsave(&ieee->lock,flags);
@@ -2706,7 +2706,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
 
        if (ieee->state == IEEE80211_NOLINK){
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
        spin_unlock_irqrestore(&ieee->lock, flags);
 }
@@ -2775,7 +2775,7 @@ void ieee80211_associate_retry_wq(struct ieee80211_device *ieee)
        {
                ieee->is_roaming= false;
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
        spin_unlock_irqrestore(&ieee->lock, flags);
 
@@ -3497,8 +3497,8 @@ void notify_wx_assoc_event(struct ieee80211_device *ieee)
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 //EXPORT_SYMBOL(ieee80211_get_beacon);
-//EXPORT_SYMBOL(ieee80211_wake_queue);
-//EXPORT_SYMBOL(ieee80211_stop_queue);
+//EXPORT_SYMBOL(ieee80211_rtl_wake_queue);
+//EXPORT_SYMBOL(ieee80211_rtl_stop_queue);
 //EXPORT_SYMBOL(ieee80211_reset_queue);
 //EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
 //EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
@@ -3518,8 +3518,8 @@ void notify_wx_assoc_event(struct ieee80211_device *ieee)
 //EXPORT_SYMBOL(ieee80211_start_scan_syncro);
 #else
 EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon);
-EXPORT_SYMBOL_NOVERS(ieee80211_wake_queue);
-EXPORT_SYMBOL_NOVERS(ieee80211_stop_queue);
+EXPORT_SYMBOL_NOVERS(ieee80211_rtl_wake_queue);
+EXPORT_SYMBOL_NOVERS(ieee80211_rtl_stop_queue);
 EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue);
 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol);
 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
index 103b33c..798fb41 100644 (file)
@@ -604,7 +604,7 @@ void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u
        }
 }
 
-int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
+int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
        struct ieee80211_device *ieee = netdev_priv(dev);
index 4e34a1f..3441b72 100644 (file)
@@ -976,7 +976,7 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
        {
                if (len != ie[1]+2)
                {
-                       printk("len:%d, ie:%d\n", len, ie[1]);
+                       printk("len:%zu, ie:%d\n", len, ie[1]);
                        return -EINVAL;
                }
                buf = kmalloc(len, GFP_KERNEL);
index 98b3bb6..e41e8a0 100644 (file)
@@ -382,7 +382,7 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 9));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 9));
                return -1;
        }
 
@@ -481,7 +481,7 @@ int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 9));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 9));
                return -1;
        }
        rsp = ( struct ieee80211_hdr_3addr*)skb->data;
@@ -611,7 +611,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 6));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 6));
                return -1;
        }
 
index ff8fe7e..0ca5d8b 100644 (file)
@@ -5795,7 +5795,7 @@ static void rtl8192_rx(struct net_device *dev)
                 stats.fragoffset = 0;
                 stats.ntotalfrag = 1;
 
-                if(!ieee80211_rx(priv->ieee80211, skb, &stats)){
+                if(!ieee80211_rtl_rx(priv->ieee80211, skb, &stats)){
                     dev_kfree_skb_any(skb);
                 } else {
                     priv->stats.rxok++;
@@ -5837,7 +5837,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
        .ndo_do_ioctl =                 rtl8192_ioctl,
        .ndo_set_multicast_list =       r8192_set_multicast,
        .ndo_set_mac_address =          r8192_set_mac_adr,
-       .ndo_start_xmit =               ieee80211_xmit,
+       .ndo_start_xmit =               ieee80211_rtl_xmit,
 };
 
 /****************************************************************************
@@ -6121,14 +6121,14 @@ static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev)
        RT_TRACE(COMP_DOWN, "wlan driver removed\n");
 }
 
-extern int ieee80211_init(void);
-extern void ieee80211_exit(void);
+extern int ieee80211_rtl_init(void);
+extern void ieee80211_rtl_exit(void);
 
 static int __init rtl8192_pci_module_init(void)
 {
        int retval;
 
-       retval = ieee80211_init();
+       retval = ieee80211_rtl_init();
        if (retval)
                return retval;
 
@@ -6153,7 +6153,7 @@ static void __exit rtl8192_pci_module_exit(void)
 
        RT_TRACE(COMP_DOWN, "Exiting");
        rtl8192_proc_module_remove();
-       ieee80211_exit();
+       ieee80211_rtl_exit();
 }
 
 //warning message WB
@@ -6313,7 +6313,7 @@ void rtl8192_try_wake_queue(struct net_device *dev, int pri)
         spin_unlock_irqrestore(&priv->tx_lock,flags);
 
        if(enough_desc)
-               ieee80211_wake_queue(priv->ieee80211);
+               ieee80211_rtl_wake_queue(priv->ieee80211);
 #endif
 }
 
index f22d024..9a4c858 100644 (file)
@@ -1721,13 +1721,13 @@ extern int ieee80211_encrypt_fragment(
        struct sk_buff *frag,
        int hdr_len);
 
-extern int rtl8192_ieee80211_xmit(struct sk_buff *skb,
+extern int rtl8192_ieee80211_rtl_xmit(struct sk_buff *skb,
                          struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                             struct ieee80211_hdr_4addr *header,
@@ -1783,8 +1783,8 @@ extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
index ac223ce..fecfa12 100644 (file)
@@ -208,7 +208,7 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
  *
  * Responsible for handling management control frames
  *
- * Called by ieee80211_rx */
+ * Called by ieee80211_rtl_rx */
 static inline int
 ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats, u16 type,
@@ -289,7 +289,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
        return 0;
 }
 
-/* Called only as a tasklet (software IRQ), by ieee80211_rx */
+/* Called only as a tasklet (software IRQ), by ieee80211_rtl_rx */
 static inline int
 ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
                           struct ieee80211_crypt_data *crypt)
@@ -858,7 +858,7 @@ u8 parse_subframe(struct sk_buff *skb,
 /* All received frames are sent to this function. @skb contains the frame in
  * IEEE 802.11 format, i.e., in the format it was sent over air.
  * This function is called only as a tasklet (software IRQ). */
-int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                 struct ieee80211_rx_stats *rx_stats)
 {
        struct net_device *dev = ieee->dev;
index 203c0a5..95d4f84 100644 (file)
@@ -610,7 +610,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee)
 }
 
 /* called with ieee->lock held */
-void ieee80211_start_scan(struct ieee80211_device *ieee)
+void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
 {
        if(IS_DOT11D_ENABLE(ieee) )
        {
@@ -1281,7 +1281,7 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee)
        }
 }
 
-void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
+void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
 {
        u8 *c;
        struct sk_buff *skb;
@@ -2054,7 +2054,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 
                                                                ieee80211_associate_step2(ieee);
                                                        }else{
-                                                               ieee80211_auth_challenge(ieee, challenge, chlen);
+                                                               ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
                                                        }
                                                }else{
                                                        ieee->softmac_stats.rx_auth_rs_err++;
@@ -2162,7 +2162,7 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *
                         * to check it any more.
                         * */
                        //printk("error:no descriptor left@queue_index %d, %d, %d\n", queue_index, skb_queue_len(&ieee->skb_waitQ[queue_index]), ieee->check_nic_enough_desc(ieee->dev,queue_index));
-                       //ieee80211_stop_queue(ieee);
+                       //ieee80211_rtl_stop_queue(ieee);
                        skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
                }else{
                        ieee->softmac_data_hard_start_xmit(
@@ -2222,7 +2222,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee)
 
 }
 
-void ieee80211_wake_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
 {
 
        unsigned long flags;
@@ -2263,7 +2263,7 @@ exit :
 }
 
 
-void ieee80211_stop_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
 {
        //unsigned long flags;
        //spin_lock_irqsave(&ieee->lock,flags);
@@ -2479,7 +2479,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
 
        if (ieee->state == IEEE80211_NOLINK){
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
        spin_unlock_irqrestore(&ieee->lock, flags);
 }
@@ -2552,7 +2552,7 @@ void ieee80211_associate_retry_wq(struct work_struct *work)
        if(ieee->state == IEEE80211_NOLINK)
        {
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
        spin_unlock_irqrestore(&ieee->lock, flags);
 
index 60621d6..4d54e1e 100644 (file)
@@ -604,7 +604,7 @@ void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u
        }
 }
 
-int rtl8192_ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
+int rtl8192_ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ieee80211_device *ieee = netdev_priv(dev);
        struct ieee80211_txb *txb = NULL;
index 66274d7..ccb9d5b 100644 (file)
@@ -126,6 +126,8 @@ static struct usb_device_id rtl8192_usb_id_tbl[] = {
        {USB_DEVICE(0x2001, 0x3301)},
        /* Zinwell */
        {USB_DEVICE(0x5a57, 0x0290)},
+       /* Guillemot */
+       {USB_DEVICE(0x06f8, 0xe031)},
        //92SU
        {USB_DEVICE(0x0bda, 0x8172)},
        {}
@@ -1501,7 +1503,7 @@ static void rtl8192_rx_isr(struct urb *urb)
         urb->context = skb;
         skb_queue_tail(&priv->rx_queue, skb);
         err = usb_submit_urb(urb, GFP_ATOMIC);
-       if(err && err != EPERM)
+       if(err && err != -EPERM)
                printk("can not submit rxurb, err is %x,URB status is %x\n",err,urb->status);
 }
 
@@ -7155,7 +7157,7 @@ void rtl8192SU_rx_nomal(struct sk_buff* skb)
                        unicast_packet = true;
                }
 
-               if(!ieee80211_rx(priv->ieee80211,skb, &stats)) {
+               if(!ieee80211_rtl_rx(priv->ieee80211,skb, &stats)) {
                        dev_kfree_skb_any(skb);
                } else {
                //      priv->stats.rxoktotal++;  //YJ,test,090108
@@ -7426,7 +7428,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
        .ndo_set_mac_address    = r8192_set_mac_adr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
-       .ndo_start_xmit         = rtl8192_ieee80211_xmit,
+       .ndo_start_xmit         = rtl8192_ieee80211_rtl_xmit,
 };
 
 static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
@@ -7619,7 +7621,7 @@ void rtl8192_try_wake_queue(struct net_device *dev, int pri)
         spin_unlock_irqrestore(&priv->tx_lock,flags);
 
        if(enough_desc)
-               ieee80211_wake_queue(priv->ieee80211);
+               ieee80211_rtl_wake_queue(priv->ieee80211);
 }
 
 void EnableHWSecurityConfig8192(struct net_device *dev)
index d397f1d..5f12d62 100644 (file)
@@ -845,7 +845,7 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
        {
                if (len != ie[1]+2)
                {
-                       printk("len:%d, ie:%d\n", len, ie[1]);
+                       printk("len:%zu, ie:%d\n", len, ie[1]);
                        return -EINVAL;
                }
                buf = kmalloc(len, GFP_KERNEL);
index 26af43b..512a57a 100644 (file)
@@ -340,7 +340,7 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 9));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 9));
                return -1;
        }
 
@@ -439,7 +439,7 @@ int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 9));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 9));
                return -1;
        }
        rsp = ( struct ieee80211_hdr_3addr*)skb->data;
@@ -569,7 +569,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 6));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 6));
                return -1;
        }
 
diff --git a/drivers/staging/sm7xx/Kconfig b/drivers/staging/sm7xx/Kconfig
new file mode 100644 (file)
index 0000000..204dbfc
--- /dev/null
@@ -0,0 +1,15 @@
+config FB_SM7XX
+       tristate "Silicon Motion SM7XX Frame Buffer Support"
+       depends on FB
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         Frame Buffer driver for the Silicon Motion SM7XX serial graphic card.
+
+config FB_SM7XX_ACCEL
+       bool "Siliconmotion Acceleration functions (EXPERIMENTAL)"
+       depends on FB_SM7XX && EXPERIMENTAL
+       help
+         This will compile the Trident frame buffer device with
+         acceleration functions.
diff --git a/drivers/staging/sm7xx/Makefile b/drivers/staging/sm7xx/Makefile
new file mode 100644 (file)
index 0000000..f43cb91
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_FB_SM7XX) += sm7xx.o
+
+sm7xx-y := smtcfb.o
diff --git a/drivers/staging/sm7xx/TODO b/drivers/staging/sm7xx/TODO
new file mode 100644 (file)
index 0000000..1f61f5e
--- /dev/null
@@ -0,0 +1,10 @@
+TODO:
+- Dual head support
+- use kernel coding style
+- checkpatch.pl clean
+- refine the code and remove unused code
+- use kernel framebuffer mode setting instead of hard code
+- move it to drivers/video/sm7xx/ or make it be drivers/video/sm7xxfb.c
+
+Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and
+Teddy Wang <teddy.wang@siliconmotion.com.cn>.
diff --git a/drivers/staging/sm7xx/smtc2d.c b/drivers/staging/sm7xx/smtc2d.c
new file mode 100644 (file)
index 0000000..133b86c
--- /dev/null
@@ -0,0 +1,979 @@
+/*
+ * Silicon Motion SM7XX 2D drawing engine functions.
+ *
+ * Copyright (C) 2006 Silicon Motion Technology Corp.
+ * Author: Boyod boyod.yang@siliconmotion.com.cn
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ *  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.
+ *
+ * Version 0.10.26192.21.01
+ *     - Add PowerPC support
+ *     - Add 2D support for Lynx -
+ * Verified on 2.6.19.2
+ *     Boyod.yang  <boyod.yang@siliconmotion.com.cn>
+ */
+
+unsigned char smtc_de_busy;
+
+void SMTC_write2Dreg(unsigned long nOffset, unsigned long nData)
+{
+       writel(nData, smtc_2DBaseAddress + nOffset);
+}
+
+unsigned long SMTC_read2Dreg(unsigned long nOffset)
+{
+       return readl(smtc_2DBaseAddress + nOffset);
+}
+
+void SMTC_write2Ddataport(unsigned long nOffset, unsigned long nData)
+{
+       writel(nData, smtc_2Ddataport + nOffset);
+}
+
+/**********************************************************************
+ *
+ * deInit
+ *
+ * Purpose
+ *    Drawing engine initialization.
+ *
+ **********************************************************************/
+
+void deInit(unsigned int nModeWidth, unsigned int nModeHeight,
+               unsigned int bpp)
+{
+       /* Get current power configuration. */
+       unsigned char clock;
+       clock = smtc_seqr(0x21);
+
+       /* initialize global 'mutex lock' variable */
+       smtc_de_busy = 0;
+
+       /* Enable 2D Drawing Engine */
+       smtc_seqw(0x21, clock & 0xF8);
+
+       SMTC_write2Dreg(DE_CLIP_TL,
+                       FIELD_VALUE(0, DE_CLIP_TL, TOP, 0) |
+                       FIELD_SET(0, DE_CLIP_TL, STATUS, DISABLE) |
+                       FIELD_SET(0, DE_CLIP_TL, INHIBIT, OUTSIDE) |
+                       FIELD_VALUE(0, DE_CLIP_TL, LEFT, 0));
+
+       if (bpp >= 24) {
+               SMTC_write2Dreg(DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                           nModeWidth * 3) | FIELD_VALUE(0,
+                                                                 DE_PITCH,
+                                                                 SOURCE,
+                                                                 nModeWidth
+                                                                 * 3));
+       } else {
+               SMTC_write2Dreg(DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                           nModeWidth) | FIELD_VALUE(0,
+                                                             DE_PITCH,
+                                                             SOURCE,
+                                                             nModeWidth));
+       }
+
+       SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                                   nModeWidth) | FIELD_VALUE(0,
+                                                             DE_WINDOW_WIDTH,
+                                                             SOURCE,
+                                                             nModeWidth));
+
+       switch (bpp) {
+       case 8:
+               SMTC_write2Dreg(DE_STRETCH_FORMAT,
+                               FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
+                                         NORMAL) | FIELD_VALUE(0,
+                                                       DE_STRETCH_FORMAT,
+                                                       PATTERN_Y,
+                                                       0) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
+                                   0) | FIELD_SET(0, DE_STRETCH_FORMAT,
+                                                  PIXEL_FORMAT,
+                                                  8) | FIELD_SET(0,
+                                                         DE_STRETCH_FORMAT,
+                                                         ADDRESSING,
+                                                         XY) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT,
+                                       SOURCE_HEIGHT, 3));
+               break;
+       case 24:
+               SMTC_write2Dreg(DE_STRETCH_FORMAT,
+                               FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
+                                         NORMAL) | FIELD_VALUE(0,
+                                                       DE_STRETCH_FORMAT,
+                                                       PATTERN_Y,
+                                                       0) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
+                                   0) | FIELD_SET(0, DE_STRETCH_FORMAT,
+                                                          PIXEL_FORMAT,
+                                                          24) | FIELD_SET(0,
+                                                          DE_STRETCH_FORMAT,
+                                                          ADDRESSING,
+                                                          XY) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT,
+                                       SOURCE_HEIGHT, 3));
+               break;
+       case 16:
+       default:
+               SMTC_write2Dreg(DE_STRETCH_FORMAT,
+                               FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
+                                         NORMAL) | FIELD_VALUE(0,
+                                                       DE_STRETCH_FORMAT,
+                                                       PATTERN_Y,
+                                                       0) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
+                                   0) | FIELD_SET(0, DE_STRETCH_FORMAT,
+                                                          PIXEL_FORMAT,
+                                                          16) | FIELD_SET(0,
+                                                          DE_STRETCH_FORMAT,
+                                                          ADDRESSING,
+                                                          XY) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT,
+                                       SOURCE_HEIGHT, 3));
+               break;
+       }
+
+       SMTC_write2Dreg(DE_MASKS,
+                       FIELD_VALUE(0, DE_MASKS, BYTE_MASK, 0xFFFF) |
+                       FIELD_VALUE(0, DE_MASKS, BIT_MASK, 0xFFFF));
+       SMTC_write2Dreg(DE_COLOR_COMPARE_MASK,
+                       FIELD_VALUE(0, DE_COLOR_COMPARE_MASK, MASKS, \
+                               0xFFFFFF));
+       SMTC_write2Dreg(DE_COLOR_COMPARE,
+                       FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, 0xFFFFFF));
+}
+
+void deVerticalLine(unsigned long dst_base,
+                   unsigned long dst_pitch,
+                   unsigned long nX,
+                   unsigned long nY,
+                   unsigned long dst_height, unsigned long nColor)
+{
+       deWaitForNotBusy();
+
+       SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                       FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+                                   dst_base));
+
+       SMTC_write2Dreg(DE_PITCH,
+                       FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
+                       FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
+
+       SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                           dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH,
+                                                    SOURCE,
+                                                    dst_pitch));
+
+       SMTC_write2Dreg(DE_FOREGROUND,
+                       FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+       SMTC_write2Dreg(DE_DESTINATION,
+                       FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_DESTINATION, X, nX) |
+                       FIELD_VALUE(0, DE_DESTINATION, Y, nY));
+
+       SMTC_write2Dreg(DE_DIMENSION,
+                       FIELD_VALUE(0, DE_DIMENSION, X, 1) |
+                       FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
+
+       SMTC_write2Dreg(DE_CONTROL,
+                       FIELD_SET(0, DE_CONTROL, STATUS, START) |
+                       FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
+                       FIELD_SET(0, DE_CONTROL, MAJOR, Y) |
+                       FIELD_SET(0, DE_CONTROL, STEP_X, NEGATIVE) |
+                       FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) |
+                       FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
+                       FIELD_SET(0, DE_CONTROL, COMMAND, SHORT_STROKE) |
+                       FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+                       FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
+
+       smtc_de_busy = 1;
+}
+
+void deHorizontalLine(unsigned long dst_base,
+                     unsigned long dst_pitch,
+                     unsigned long nX,
+                     unsigned long nY,
+                     unsigned long dst_width, unsigned long nColor)
+{
+       deWaitForNotBusy();
+
+       SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                       FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+                                   dst_base));
+
+       SMTC_write2Dreg(DE_PITCH,
+                       FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
+                       FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
+
+       SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                           dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH,
+                                                    SOURCE,
+                                                    dst_pitch));
+       SMTC_write2Dreg(DE_FOREGROUND,
+                       FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+       SMTC_write2Dreg(DE_DESTINATION,
+                       FIELD_SET(0, DE_DESTINATION, WRAP,
+                         DISABLE) | FIELD_VALUE(0, DE_DESTINATION, X,
+                                                nX) | FIELD_VALUE(0,
+                                                          DE_DESTINATION,
+                                                          Y,
+                                                          nY));
+       SMTC_write2Dreg(DE_DIMENSION,
+                       FIELD_VALUE(0, DE_DIMENSION, X,
+                           dst_width) | FIELD_VALUE(0, DE_DIMENSION,
+                                                    Y_ET, 1));
+       SMTC_write2Dreg(DE_CONTROL,
+               FIELD_SET(0, DE_CONTROL, STATUS, START) | FIELD_SET(0,
+                                                           DE_CONTROL,
+                                                           DIRECTION,
+                                                           RIGHT_TO_LEFT)
+               | FIELD_SET(0, DE_CONTROL, MAJOR, X) | FIELD_SET(0,
+                                                        DE_CONTROL,
+                                                        STEP_X,
+                                                        POSITIVE)
+               | FIELD_SET(0, DE_CONTROL, STEP_Y,
+                           NEGATIVE) | FIELD_SET(0, DE_CONTROL,
+                                                 LAST_PIXEL,
+                                                 OFF) | FIELD_SET(0,
+                                                          DE_CONTROL,
+                                                          COMMAND,
+                                                          SHORT_STROKE)
+               | FIELD_SET(0, DE_CONTROL, ROP_SELECT,
+                           ROP2) | FIELD_VALUE(0, DE_CONTROL, ROP,
+                                               0x0C));
+
+       smtc_de_busy = 1;
+}
+
+void deLine(unsigned long dst_base,
+           unsigned long dst_pitch,
+           unsigned long nX1,
+           unsigned long nY1,
+           unsigned long nX2, unsigned long nY2, unsigned long nColor)
+{
+       unsigned long nCommand =
+           FIELD_SET(0, DE_CONTROL, STATUS, START) |
+           FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
+           FIELD_SET(0, DE_CONTROL, MAJOR, X) |
+           FIELD_SET(0, DE_CONTROL, STEP_X, POSITIVE) |
+           FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) |
+           FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
+           FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+           FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C);
+       unsigned long DeltaX;
+       unsigned long DeltaY;
+
+       /* Calculate delta X */
+       if (nX1 <= nX2)
+               DeltaX = nX2 - nX1;
+       else {
+               DeltaX = nX1 - nX2;
+               nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_X, NEGATIVE);
+       }
+
+       /* Calculate delta Y */
+       if (nY1 <= nY2)
+               DeltaY = nY2 - nY1;
+       else {
+               DeltaY = nY1 - nY2;
+               nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_Y, NEGATIVE);
+       }
+
+       /* Determine the major axis */
+       if (DeltaX < DeltaY)
+               nCommand = FIELD_SET(nCommand, DE_CONTROL, MAJOR, Y);
+
+       /* Vertical line? */
+       if (nX1 == nX2)
+               deVerticalLine(dst_base, dst_pitch, nX1, nY1, DeltaY, nColor);
+
+       /* Horizontal line? */
+       else if (nY1 == nY2)
+               deHorizontalLine(dst_base, dst_pitch, nX1, nY1, \
+                               DeltaX, nColor);
+
+       /* Diagonal line? */
+       else if (DeltaX == DeltaY) {
+               deWaitForNotBusy();
+
+               SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                               FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE,
+                                           ADDRESS, dst_base));
+
+               SMTC_write2Dreg(DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_PITCH,
+                                                            SOURCE,
+                                                            dst_pitch));
+
+               SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                               FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_WINDOW_WIDTH,
+                                                            SOURCE,
+                                                            dst_pitch));
+
+               SMTC_write2Dreg(DE_FOREGROUND,
+                               FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+               SMTC_write2Dreg(DE_DESTINATION,
+                               FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                               FIELD_VALUE(0, DE_DESTINATION, X, 1) |
+                               FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
+
+               SMTC_write2Dreg(DE_DIMENSION,
+                               FIELD_VALUE(0, DE_DIMENSION, X, 1) |
+                               FIELD_VALUE(0, DE_DIMENSION, Y_ET, DeltaX));
+
+               SMTC_write2Dreg(DE_CONTROL,
+                               FIELD_SET(nCommand, DE_CONTROL, COMMAND,
+                                         SHORT_STROKE));
+       }
+
+       /* Generic line */
+       else {
+               unsigned int k1, k2, et, w;
+               if (DeltaX < DeltaY) {
+                       k1 = 2 * DeltaX;
+                       et = k1 - DeltaY;
+                       k2 = et - DeltaY;
+                       w = DeltaY + 1;
+               } else {
+                       k1 = 2 * DeltaY;
+                       et = k1 - DeltaX;
+                       k2 = et - DeltaX;
+                       w = DeltaX + 1;
+               }
+
+               deWaitForNotBusy();
+
+               SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                               FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE,
+                                           ADDRESS, dst_base));
+
+               SMTC_write2Dreg(DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_PITCH,
+                                                            SOURCE,
+                                                            dst_pitch));
+
+               SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                               FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_WINDOW_WIDTH,
+                                                            SOURCE,
+                                                            dst_pitch));
+
+               SMTC_write2Dreg(DE_FOREGROUND,
+                               FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+               SMTC_write2Dreg(DE_SOURCE,
+                               FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+                               FIELD_VALUE(0, DE_SOURCE, X_K1, k1) |
+                               FIELD_VALUE(0, DE_SOURCE, Y_K2, k2));
+
+               SMTC_write2Dreg(DE_DESTINATION,
+                               FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                               FIELD_VALUE(0, DE_DESTINATION, X, nX1) |
+                               FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
+
+               SMTC_write2Dreg(DE_DIMENSION,
+                               FIELD_VALUE(0, DE_DIMENSION, X, w) |
+                               FIELD_VALUE(0, DE_DIMENSION, Y_ET, et));
+
+               SMTC_write2Dreg(DE_CONTROL,
+                               FIELD_SET(nCommand, DE_CONTROL, COMMAND,
+                                         LINE_DRAW));
+       }
+
+       smtc_de_busy = 1;
+}
+
+void deFillRect(unsigned long dst_base,
+               unsigned long dst_pitch,
+               unsigned long dst_X,
+               unsigned long dst_Y,
+               unsigned long dst_width,
+               unsigned long dst_height, unsigned long nColor)
+{
+       deWaitForNotBusy();
+
+       SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                       FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+                                   dst_base));
+
+       if (dst_pitch) {
+               SMTC_write2Dreg(DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_PITCH,
+                                                            SOURCE,
+                                                            dst_pitch));
+
+               SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                               FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_WINDOW_WIDTH,
+                                                            SOURCE,
+                                                            dst_pitch));
+       }
+
+       SMTC_write2Dreg(DE_FOREGROUND,
+                       FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+       SMTC_write2Dreg(DE_DESTINATION,
+                       FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_DESTINATION, X, dst_X) |
+                       FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y));
+
+       SMTC_write2Dreg(DE_DIMENSION,
+                       FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
+                       FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
+
+       SMTC_write2Dreg(DE_CONTROL,
+                       FIELD_SET(0, DE_CONTROL, STATUS, START) |
+                       FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
+                       FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
+                       FIELD_SET(0, DE_CONTROL, COMMAND, RECTANGLE_FILL) |
+                       FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+                       FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
+
+       smtc_de_busy = 1;
+}
+
+/**********************************************************************
+ *
+ * deRotatePattern
+ *
+ * Purpose
+ *    Rotate the given pattern if necessary
+ *
+ * Parameters
+ *    [in]
+ *        pPattern  - Pointer to DE_SURFACE structure containing
+ *                    pattern attributes
+ *        patternX  - X position (0-7) of pattern origin
+ *        patternY  - Y position (0-7) of pattern origin
+ *
+ *    [out]
+ *        pattern_dstaddr - Pointer to pre-allocated buffer containing
+ *        rotated pattern
+ *
+ **********************************************************************/
+void deRotatePattern(unsigned char *pattern_dstaddr,
+                    unsigned long pattern_src_addr,
+                    unsigned long pattern_BPP,
+                    unsigned long pattern_stride, int patternX, int patternY)
+{
+       unsigned int i;
+       unsigned long pattern[PATTERN_WIDTH * PATTERN_HEIGHT];
+       unsigned int x, y;
+       unsigned char *pjPatByte;
+
+       if (pattern_dstaddr != NULL) {
+               deWaitForNotBusy();
+
+               if (patternX || patternY) {
+                       /* Rotate pattern */
+                       pjPatByte = (unsigned char *)pattern;
+
+                       switch (pattern_BPP) {
+                       case 8:
+                               {
+                                       for (y = 0; y < 8; y++) {
+                                               unsigned char *pjBuffer =
+                                                   pattern_dstaddr +
+                                                   ((patternY + y) & 7) * 8;
+                                               for (x = 0; x < 8; x++) {
+                                                       pjBuffer[(patternX +
+                                                                 x) & 7] =
+                                                           pjPatByte[x];
+                                               }
+                                               pjPatByte += pattern_stride;
+                                       }
+                                       break;
+                               }
+
+                       case 16:
+                               {
+                                       for (y = 0; y < 8; y++) {
+                                               unsigned short *pjBuffer =
+                                                   (unsigned short *)
+                                                   pattern_dstaddr +
+                                                   ((patternY + y) & 7) * 8;
+                                               for (x = 0; x < 8; x++) {
+                                                       pjBuffer[(patternX +
+                                                                 x) & 7] =
+                                                           ((unsigned short *)
+                                                            pjPatByte)[x];
+                                               }
+                                               pjPatByte += pattern_stride;
+                                       }
+                                       break;
+                               }
+
+                       case 32:
+                               {
+                                       for (y = 0; y < 8; y++) {
+                                               unsigned long *pjBuffer =
+                                                   (unsigned long *)
+                                                   pattern_dstaddr +
+                                                   ((patternY + y) & 7) * 8;
+                                               for (x = 0; x < 8; x++) {
+                                                       pjBuffer[(patternX +
+                                                                 x) & 7] =
+                                                           ((unsigned long *)
+                                                            pjPatByte)[x];
+                                               }
+                                               pjPatByte += pattern_stride;
+                                       }
+                                       break;
+                               }
+                       }
+               } else {
+                       /*Don't rotate,just copy pattern into pattern_dstaddr*/
+                       for (i = 0; i < (pattern_BPP * 2); i++) {
+                               ((unsigned long *)pattern_dstaddr)[i] =
+                                   pattern[i];
+                       }
+               }
+
+       }
+}
+
+/**********************************************************************
+ *
+ * deCopy
+ *
+ * Purpose
+ *    Copy a rectangular area of the source surface to a destination surface
+ *
+ * Remarks
+ *    Source bitmap must have the same color depth (BPP) as the destination
+ *    bitmap.
+ *
+**********************************************************************/
+void deCopy(unsigned long dst_base,
+           unsigned long dst_pitch,
+           unsigned long dst_BPP,
+           unsigned long dst_X,
+           unsigned long dst_Y,
+           unsigned long dst_width,
+           unsigned long dst_height,
+           unsigned long src_base,
+           unsigned long src_pitch,
+           unsigned long src_X,
+           unsigned long src_Y, pTransparent pTransp, unsigned char nROP2)
+{
+       unsigned long nDirection = 0;
+       unsigned long nTransparent = 0;
+       /* Direction of ROP2 operation:
+        * 1 = Left to Right,
+        * (-1) = Right to Left
+        */
+       unsigned long opSign = 1;
+       /* xWidth is in pixels */
+       unsigned long xWidth = 192 / (dst_BPP / 8);
+       unsigned long de_ctrl = 0;
+
+       deWaitForNotBusy();
+
+       SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                       FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+                                   dst_base));
+
+       SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE,
+                       FIELD_VALUE(0, DE_WINDOW_SOURCE_BASE, ADDRESS,
+                                   src_base));
+
+       if (dst_pitch && src_pitch) {
+               SMTC_write2Dreg(DE_PITCH,
+                       FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                   dst_pitch) | FIELD_VALUE(0,
+                                                    DE_PITCH,
+                                                    SOURCE,
+                                                    src_pitch));
+
+               SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                                   dst_pitch) | FIELD_VALUE(0,
+                                                    DE_WINDOW_WIDTH,
+                                                    SOURCE,
+                                                    src_pitch));
+       }
+
+       /* Set transparent bits if necessary */
+       if (pTransp != NULL) {
+               nTransparent =
+                   pTransp->match | pTransp->select | pTransp->control;
+
+               /* Set color compare register */
+               SMTC_write2Dreg(DE_COLOR_COMPARE,
+                               FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR,
+                                           pTransp->color));
+       }
+
+       /* Determine direction of operation */
+       if (src_Y < dst_Y) {
+               /* +----------+
+                  |S         |
+                  |          +----------+
+                  |          |      |   |
+                  |          |      |   |
+                  +---|------+      |
+                  |               D |
+                  +----------+ */
+
+               nDirection = BOTTOM_TO_TOP;
+       } else if (src_Y > dst_Y) {
+               /* +----------+
+                  |D         |
+                  |          +----------+
+                  |          |      |   |
+                  |          |      |   |
+                  +---|------+      |
+                  |               S |
+                  +----------+ */
+
+               nDirection = TOP_TO_BOTTOM;
+       } else {
+               /* src_Y == dst_Y */
+
+               if (src_X <= dst_X) {
+                       /* +------+---+------+
+                          |S     |   |     D|
+                          |      |   |      |
+                          |      |   |      |
+                          |      |   |      |
+                          +------+---+------+ */
+
+                       nDirection = RIGHT_TO_LEFT;
+               } else {
+                       /* src_X > dst_X */
+
+                       /* +------+---+------+
+                          |D     |   |     S|
+                          |      |   |      |
+                          |      |   |      |
+                          |      |   |      |
+                          +------+---+------+ */
+
+                       nDirection = LEFT_TO_RIGHT;
+               }
+       }
+
+       if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
+               src_X += dst_width - 1;
+               src_Y += dst_height - 1;
+               dst_X += dst_width - 1;
+               dst_Y += dst_height - 1;
+               opSign = (-1);
+       }
+
+       if (dst_BPP >= 24) {
+               src_X *= 3;
+               src_Y *= 3;
+               dst_X *= 3;
+               dst_Y *= 3;
+               dst_width *= 3;
+               if ((nDirection == BOTTOM_TO_TOP)
+                   || (nDirection == RIGHT_TO_LEFT)) {
+                       src_X += 2;
+                       dst_X += 2;
+               }
+       }
+
+       /* Workaround for 192 byte hw bug */
+       if ((nROP2 != 0x0C) && ((dst_width * (dst_BPP / 8)) >= 192)) {
+               /*
+                * Perform the ROP2 operation in chunks of (xWidth *
+                * dst_height)
+                */
+               while (1) {
+                       deWaitForNotBusy();
+
+                       SMTC_write2Dreg(DE_SOURCE,
+                               FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+                               FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) |
+                               FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y));
+
+                       SMTC_write2Dreg(DE_DESTINATION,
+                               FIELD_SET(0, DE_DESTINATION, WRAP,
+                                 DISABLE) | FIELD_VALUE(0,
+                                                        DE_DESTINATION,
+                                                        X,
+                                                        dst_X)
+                       | FIELD_VALUE(0, DE_DESTINATION, Y,
+                                                     dst_Y));
+
+                       SMTC_write2Dreg(DE_DIMENSION,
+                               FIELD_VALUE(0, DE_DIMENSION, X,
+                                   xWidth) | FIELD_VALUE(0,
+                                                         DE_DIMENSION,
+                                                         Y_ET,
+                                                         dst_height));
+
+                       de_ctrl =
+                           FIELD_VALUE(0, DE_CONTROL, ROP,
+                               nROP2) | nTransparent | FIELD_SET(0,
+                                                         DE_CONTROL,
+                                                         ROP_SELECT,
+                                                         ROP2)
+                           | FIELD_SET(0, DE_CONTROL, COMMAND,
+                               BITBLT) | ((nDirection ==
+                                           1) ? FIELD_SET(0,
+                                                  DE_CONTROL,
+                                                  DIRECTION,
+                                                  RIGHT_TO_LEFT)
+                                          : FIELD_SET(0, DE_CONTROL,
+                                              DIRECTION,
+                                              LEFT_TO_RIGHT)) |
+                           FIELD_SET(0, DE_CONTROL, STATUS, START);
+
+                       SMTC_write2Dreg(DE_CONTROL, de_ctrl);
+
+                       src_X += (opSign * xWidth);
+                       dst_X += (opSign * xWidth);
+                       dst_width -= xWidth;
+
+                       if (dst_width <= 0) {
+                               /* ROP2 operation is complete */
+                               break;
+                       }
+
+                       if (xWidth > dst_width)
+                               xWidth = dst_width;
+               }
+       } else {
+               deWaitForNotBusy();
+               SMTC_write2Dreg(DE_SOURCE,
+                       FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) |
+                       FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y));
+
+               SMTC_write2Dreg(DE_DESTINATION,
+                       FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_DESTINATION, X, dst_X) |
+                       FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y));
+
+               SMTC_write2Dreg(DE_DIMENSION,
+                       FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
+                       FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
+
+               de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, nROP2) |
+                   nTransparent |
+                   FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+                   FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
+                   ((nDirection == 1) ? FIELD_SET(0, DE_CONTROL, DIRECTION,
+                                                  RIGHT_TO_LEFT)
+                    : FIELD_SET(0, DE_CONTROL, DIRECTION,
+                                LEFT_TO_RIGHT)) | FIELD_SET(0, DE_CONTROL,
+                                                            STATUS, START);
+               SMTC_write2Dreg(DE_CONTROL, de_ctrl);
+       }
+
+       smtc_de_busy = 1;
+}
+
+/*
+ * This function sets the pixel format that will apply to the 2D Engine.
+ */
+void deSetPixelFormat(unsigned long bpp)
+{
+       unsigned long de_format;
+
+       de_format = SMTC_read2Dreg(DE_STRETCH_FORMAT);
+
+       switch (bpp) {
+       case 8:
+               de_format =
+                   FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 8);
+               break;
+       default:
+       case 16:
+               de_format =
+                   FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 16);
+               break;
+       case 32:
+               de_format =
+                   FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 32);
+               break;
+       }
+
+       SMTC_write2Dreg(DE_STRETCH_FORMAT, de_format);
+}
+
+/*
+ * System memory to Video memory monochrome expansion.
+ *
+ * Source is monochrome image in system memory.  This function expands the
+ * monochrome data to color image in video memory.
+ */
+
+long deSystemMem2VideoMemMonoBlt(const char *pSrcbuf,
+                                long srcDelta,
+                                unsigned long startBit,
+                                unsigned long dBase,
+                                unsigned long dPitch,
+                                unsigned long bpp,
+                                unsigned long dx, unsigned long dy,
+                                unsigned long width, unsigned long height,
+                                unsigned long fColor,
+                                unsigned long bColor,
+                                unsigned long rop2) {
+       unsigned long bytePerPixel;
+       unsigned long ulBytesPerScan;
+       unsigned long ul4BytesPerScan;
+       unsigned long ulBytesRemain;
+       unsigned long de_ctrl = 0;
+       unsigned char ajRemain[4];
+       long i, j;
+
+       bytePerPixel = bpp / 8;
+
+       /* Just make sure the start bit is within legal range */
+       startBit &= 7;
+
+       ulBytesPerScan = (width + startBit + 7) / 8;
+       ul4BytesPerScan = ulBytesPerScan & ~3;
+       ulBytesRemain = ulBytesPerScan & 3;
+
+       if (smtc_de_busy)
+               deWaitForNotBusy();
+
+       /*
+        * 2D Source Base.  Use 0 for HOST Blt.
+        */
+
+       SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE, 0);
+
+       /*
+        * 2D Destination Base.
+        *
+        * It is an address offset (128 bit aligned) from the beginning of
+        * frame buffer.
+        */
+
+       SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, dBase);
+
+       if (dPitch) {
+
+               /*
+                * Program pitch (distance between the 1st points of two
+                * adjacent lines).
+                *
+                * Note that input pitch is BYTE value, but the 2D Pitch
+                * register uses pixel values. Need Byte to pixel convertion.
+                */
+
+               SMTC_write2Dreg(DE_PITCH,
+                       FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                           dPitch /
+                           bytePerPixel) | FIELD_VALUE(0,
+                                                       DE_PITCH,
+                                                       SOURCE,
+                                                       dPitch /
+                                                       bytePerPixel));
+
+               /* Screen Window width in Pixels.
+                *
+                * 2D engine uses this value to calculate the linear address in
+                * frame buffer for a given point.
+                */
+
+               SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                           (dPitch /
+                            bytePerPixel)) | FIELD_VALUE(0,
+                                                         DE_WINDOW_WIDTH,
+                                                         SOURCE,
+                                                         (dPitch
+                                                          /
+                                                          bytePerPixel)));
+       }
+       /* Note: For 2D Source in Host Write, only X_K1 field is needed, and
+        * Y_K2 field is not used. For mono bitmap, use startBit for X_K1.
+        */
+
+       SMTC_write2Dreg(DE_SOURCE,
+                       FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_SOURCE, X_K1, startBit) |
+                       FIELD_VALUE(0, DE_SOURCE, Y_K2, 0));
+
+       SMTC_write2Dreg(DE_DESTINATION,
+                       FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_DESTINATION, X, dx) |
+                       FIELD_VALUE(0, DE_DESTINATION, Y, dy));
+
+       SMTC_write2Dreg(DE_DIMENSION,
+                       FIELD_VALUE(0, DE_DIMENSION, X, width) |
+                       FIELD_VALUE(0, DE_DIMENSION, Y_ET, height));
+
+       SMTC_write2Dreg(DE_FOREGROUND, fColor);
+       SMTC_write2Dreg(DE_BACKGROUND, bColor);
+
+       if (bpp)
+               deSetPixelFormat(bpp);
+       /* Set the pixel format of the destination */
+
+       de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
+           FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+           FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) |
+           FIELD_SET(0, DE_CONTROL, HOST, MONO) |
+           FIELD_SET(0, DE_CONTROL, STATUS, START);
+
+       SMTC_write2Dreg(DE_CONTROL, de_ctrl | deGetTransparency());
+
+       /* Write MONO data (line by line) to 2D Engine data port */
+       for (i = 0; i < height; i++) {
+               /* For each line, send the data in chunks of 4 bytes */
+               for (j = 0; j < (ul4BytesPerScan / 4); j++)
+                       SMTC_write2Ddataport(0,
+                                            *(unsigned long *)(pSrcbuf +
+                                                               (j * 4)));
+
+               if (ulBytesRemain) {
+                       memcpy(ajRemain, pSrcbuf + ul4BytesPerScan,
+                              ulBytesRemain);
+                       SMTC_write2Ddataport(0, *(unsigned long *)ajRemain);
+               }
+
+               pSrcbuf += srcDelta;
+       }
+       smtc_de_busy = 1;
+
+       return 0;
+}
+
+/*
+ * This function gets the transparency status from DE_CONTROL register.
+ * It returns a double word with the transparent fields properly set,
+ * while other fields are 0.
+ */
+unsigned long deGetTransparency(void)
+{
+       unsigned long de_ctrl;
+
+       de_ctrl = SMTC_read2Dreg(DE_CONTROL);
+
+       de_ctrl &=
+           FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
+           FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT) |
+           FIELD_MASK(DE_CONTROL_TRANSPARENCY);
+
+       return de_ctrl;
+}
diff --git a/drivers/staging/sm7xx/smtc2d.h b/drivers/staging/sm7xx/smtc2d.h
new file mode 100644 (file)
index 0000000..38d0c33
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+ * Silicon Motion SM712 2D drawing engine functions.
+ *
+ * Copyright (C) 2006 Silicon Motion Technology Corp.
+ * Author: Ge Wang, gewang@siliconmotion.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ *  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 NULL
+#define NULL    0
+#endif
+
+/* Internal macros */
+
+#define _F_START(f)            (0 ? f)
+#define _F_END(f)              (1 ? f)
+#define _F_SIZE(f)             (1 + _F_END(f) - _F_START(f))
+#define _F_MASK(f)             (((1ULL << _F_SIZE(f)) - 1) << _F_START(f))
+#define _F_NORMALIZE(v, f)     (((v) & _F_MASK(f)) >> _F_START(f))
+#define _F_DENORMALIZE(v, f)   (((v) << _F_START(f)) & _F_MASK(f))
+
+/* Global macros */
+
+#define FIELD_GET(x, reg, field) \
+( \
+    _F_NORMALIZE((x), reg ## _ ## field) \
+)
+
+#define FIELD_SET(x, reg, field, value) \
+( \
+    (x & ~_F_MASK(reg ## _ ## field)) \
+    | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
+)
+
+#define FIELD_VALUE(x, reg, field, value) \
+( \
+    (x & ~_F_MASK(reg ## _ ## field)) \
+    | _F_DENORMALIZE(value, reg ## _ ## field) \
+)
+
+#define FIELD_CLEAR(reg, field) \
+( \
+    ~_F_MASK(reg ## _ ## field) \
+)
+
+/* Field Macros                        */
+
+#define FIELD_START(field)     (0 ? field)
+#define FIELD_END(field)       (1 ? field)
+#define FIELD_SIZE(field) \
+       (1 + FIELD_END(field) - FIELD_START(field))
+
+#define FIELD_MASK(field) \
+       (((1 << (FIELD_SIZE(field)-1)) \
+       | ((1 << (FIELD_SIZE(field)-1)) - 1)) \
+       << FIELD_START(field))
+
+#define FIELD_NORMALIZE(reg, field) \
+       (((reg) & FIELD_MASK(field)) >> FIELD_START(field))
+
+#define FIELD_DENORMALIZE(field, value) \
+       (((value) << FIELD_START(field)) & FIELD_MASK(field))
+
+#define FIELD_INIT(reg, field, value) \
+       FIELD_DENORMALIZE(reg ## _ ## field, \
+               reg ## _ ## field ## _ ## value)
+
+#define FIELD_INIT_VAL(reg, field, value) \
+       (FIELD_DENORMALIZE(reg ## _ ## field, value))
+
+#define FIELD_VAL_SET(x, r, f, v) ({ \
+       x = (x & ~FIELD_MASK(r ## _ ## f)) \
+       | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v) \
+})
+
+#define RGB(r, g, b)   ((unsigned long)(((r) << 16) | ((g) << 8) | (b)))
+
+/* Transparent info definition */
+typedef struct {
+       unsigned long match;    /* Matching pixel is OPAQUE/TRANSPARENT */
+       unsigned long select;   /* Transparency controlled by SRC/DST */
+       unsigned long control;  /* ENABLE/DISABLE transparency */
+       unsigned long color;    /* Transparent color */
+} Transparent, *pTransparent;
+
+#define PIXEL_DEPTH_1_BP       0       /* 1 bit per pixel */
+#define PIXEL_DEPTH_8_BPP      1       /* 8 bits per pixel */
+#define PIXEL_DEPTH_16_BPP     2       /* 16 bits per pixel */
+#define PIXEL_DEPTH_32_BPP     3       /* 32 bits per pixel */
+#define PIXEL_DEPTH_YUV422     8       /* 16 bits per pixel YUV422 */
+#define PIXEL_DEPTH_YUV420     9       /* 16 bits per pixel YUV420 */
+
+#define PATTERN_WIDTH          8
+#define PATTERN_HEIGHT         8
+
+#define        TOP_TO_BOTTOM           0
+#define        BOTTOM_TO_TOP           1
+#define RIGHT_TO_LEFT          BOTTOM_TO_TOP
+#define LEFT_TO_RIGHT          TOP_TO_BOTTOM
+
+/* Constants used in Transparent structure */
+#define MATCH_OPAQUE           0x00000000
+#define MATCH_TRANSPARENT      0x00000400
+#define SOURCE                 0x00000000
+#define DESTINATION            0x00000200
+
+/* 2D registers. */
+
+#define        DE_SOURCE                       0x000000
+#define        DE_SOURCE_WRAP                  31 : 31
+#define        DE_SOURCE_WRAP_DISABLE          0
+#define        DE_SOURCE_WRAP_ENABLE           1
+#define        DE_SOURCE_X_K1                  29 : 16
+#define        DE_SOURCE_Y_K2                  15 : 0
+
+#define        DE_DESTINATION                  0x000004
+#define        DE_DESTINATION_WRAP             31 : 31
+#define        DE_DESTINATION_WRAP_DISABLE     0
+#define        DE_DESTINATION_WRAP_ENABLE      1
+#define        DE_DESTINATION_X                28 : 16
+#define        DE_DESTINATION_Y                15 : 0
+
+#define        DE_DIMENSION                    0x000008
+#define        DE_DIMENSION_X                  28 : 16
+#define        DE_DIMENSION_Y_ET               15 : 0
+
+#define        DE_CONTROL                      0x00000C
+#define        DE_CONTROL_STATUS               31 : 31
+#define        DE_CONTROL_STATUS_STOP          0
+#define        DE_CONTROL_STATUS_START         1
+#define        DE_CONTROL_PATTERN              30 : 30
+#define        DE_CONTROL_PATTERN_MONO         0
+#define        DE_CONTROL_PATTERN_COLOR        1
+#define        DE_CONTROL_UPDATE_DESTINATION_X         29 : 29
+#define        DE_CONTROL_UPDATE_DESTINATION_X_DISABLE 0
+#define        DE_CONTROL_UPDATE_DESTINATION_X_ENABLE  1
+#define        DE_CONTROL_QUICK_START                  28 : 28
+#define        DE_CONTROL_QUICK_START_DISABLE          0
+#define        DE_CONTROL_QUICK_START_ENABLE           1
+#define        DE_CONTROL_DIRECTION                    27 : 27
+#define        DE_CONTROL_DIRECTION_LEFT_TO_RIGHT      0
+#define        DE_CONTROL_DIRECTION_RIGHT_TO_LEFT      1
+#define        DE_CONTROL_MAJOR                        26 : 26
+#define        DE_CONTROL_MAJOR_X                      0
+#define        DE_CONTROL_MAJOR_Y                      1
+#define        DE_CONTROL_STEP_X                       25 : 25
+#define        DE_CONTROL_STEP_X_POSITIVE              1
+#define        DE_CONTROL_STEP_X_NEGATIVE              0
+#define        DE_CONTROL_STEP_Y                       24 : 24
+#define        DE_CONTROL_STEP_Y_POSITIVE              1
+#define        DE_CONTROL_STEP_Y_NEGATIVE              0
+#define        DE_CONTROL_STRETCH                      23 : 23
+#define        DE_CONTROL_STRETCH_DISABLE              0
+#define        DE_CONTROL_STRETCH_ENABLE               1
+#define        DE_CONTROL_HOST                         22 : 22
+#define        DE_CONTROL_HOST_COLOR                   0
+#define        DE_CONTROL_HOST_MONO                    1
+#define        DE_CONTROL_LAST_PIXEL                   21 : 21
+#define        DE_CONTROL_LAST_PIXEL_OFF               0
+#define        DE_CONTROL_LAST_PIXEL_ON                1
+#define        DE_CONTROL_COMMAND                      20 : 16
+#define        DE_CONTROL_COMMAND_BITBLT               0
+#define        DE_CONTROL_COMMAND_RECTANGLE_FILL       1
+#define        DE_CONTROL_COMMAND_DE_TILE              2
+#define        DE_CONTROL_COMMAND_TRAPEZOID_FILL       3
+#define        DE_CONTROL_COMMAND_ALPHA_BLEND          4
+#define        DE_CONTROL_COMMAND_RLE_STRIP            5
+#define        DE_CONTROL_COMMAND_SHORT_STROKE         6
+#define        DE_CONTROL_COMMAND_LINE_DRAW            7
+#define        DE_CONTROL_COMMAND_HOST_WRITE           8
+#define        DE_CONTROL_COMMAND_HOST_READ            9
+#define        DE_CONTROL_COMMAND_HOST_WRITE_BOTTOM_UP 10
+#define        DE_CONTROL_COMMAND_ROTATE               11
+#define        DE_CONTROL_COMMAND_FONT                 12
+#define        DE_CONTROL_COMMAND_TEXTURE_LOAD         15
+#define        DE_CONTROL_ROP_SELECT                   15 : 15
+#define        DE_CONTROL_ROP_SELECT_ROP3              0
+#define        DE_CONTROL_ROP_SELECT_ROP2              1
+#define        DE_CONTROL_ROP2_SOURCE                  14 : 14
+#define        DE_CONTROL_ROP2_SOURCE_BITMAP           0
+#define        DE_CONTROL_ROP2_SOURCE_PATTERN          1
+#define        DE_CONTROL_MONO_DATA                    13 : 12
+#define        DE_CONTROL_MONO_DATA_NOT_PACKED         0
+#define        DE_CONTROL_MONO_DATA_8_PACKED           1
+#define        DE_CONTROL_MONO_DATA_16_PACKED          2
+#define        DE_CONTROL_MONO_DATA_32_PACKED          3
+#define        DE_CONTROL_REPEAT_ROTATE                11 : 11
+#define        DE_CONTROL_REPEAT_ROTATE_DISABLE        0
+#define        DE_CONTROL_REPEAT_ROTATE_ENABLE         1
+#define        DE_CONTROL_TRANSPARENCY_MATCH           10 : 10
+#define        DE_CONTROL_TRANSPARENCY_MATCH_OPAQUE            0
+#define        DE_CONTROL_TRANSPARENCY_MATCH_TRANSPARENT       1
+#define        DE_CONTROL_TRANSPARENCY_SELECT                  9 : 9
+#define        DE_CONTROL_TRANSPARENCY_SELECT_SOURCE           0
+#define        DE_CONTROL_TRANSPARENCY_SELECT_DESTINATION      1
+#define        DE_CONTROL_TRANSPARENCY                         8 : 8
+#define        DE_CONTROL_TRANSPARENCY_DISABLE                 0
+#define        DE_CONTROL_TRANSPARENCY_ENABLE                  1
+#define        DE_CONTROL_ROP                                  7 : 0
+
+/* Pseudo fields. */
+
+#define        DE_CONTROL_SHORT_STROKE_DIR                     27 : 24
+#define        DE_CONTROL_SHORT_STROKE_DIR_225                 0
+#define        DE_CONTROL_SHORT_STROKE_DIR_135                 1
+#define        DE_CONTROL_SHORT_STROKE_DIR_315                 2
+#define        DE_CONTROL_SHORT_STROKE_DIR_45                  3
+#define        DE_CONTROL_SHORT_STROKE_DIR_270                 4
+#define        DE_CONTROL_SHORT_STROKE_DIR_90                  5
+#define        DE_CONTROL_SHORT_STROKE_DIR_180                 8
+#define        DE_CONTROL_SHORT_STROKE_DIR_0                   10
+#define        DE_CONTROL_ROTATION                             25 : 24
+#define        DE_CONTROL_ROTATION_0                           0
+#define        DE_CONTROL_ROTATION_270                         1
+#define        DE_CONTROL_ROTATION_90                          2
+#define        DE_CONTROL_ROTATION_180                         3
+
+#define        DE_PITCH                                        0x000010
+#define        DE_PITCH_DESTINATION                            28 : 16
+#define        DE_PITCH_SOURCE                                 12 : 0
+
+#define        DE_FOREGROUND                                   0x000014
+#define        DE_FOREGROUND_COLOR                             31 : 0
+
+#define        DE_BACKGROUND                                   0x000018
+#define        DE_BACKGROUND_COLOR                             31 : 0
+
+#define        DE_STRETCH_FORMAT                               0x00001C
+#define        DE_STRETCH_FORMAT_PATTERN_XY                    30 : 30
+#define        DE_STRETCH_FORMAT_PATTERN_XY_NORMAL             0
+#define        DE_STRETCH_FORMAT_PATTERN_XY_OVERWRITE          1
+#define        DE_STRETCH_FORMAT_PATTERN_Y                     29 : 27
+#define        DE_STRETCH_FORMAT_PATTERN_X                     25 : 23
+#define        DE_STRETCH_FORMAT_PIXEL_FORMAT                  21 : 20
+#define        DE_STRETCH_FORMAT_PIXEL_FORMAT_8                0
+#define        DE_STRETCH_FORMAT_PIXEL_FORMAT_16               1
+#define        DE_STRETCH_FORMAT_PIXEL_FORMAT_24               3
+#define        DE_STRETCH_FORMAT_PIXEL_FORMAT_32               2
+#define        DE_STRETCH_FORMAT_ADDRESSING                    19 : 16
+#define        DE_STRETCH_FORMAT_ADDRESSING_XY                 0
+#define        DE_STRETCH_FORMAT_ADDRESSING_LINEAR             15
+#define        DE_STRETCH_FORMAT_SOURCE_HEIGHT                 11 : 0
+
+#define        DE_COLOR_COMPARE                                0x000020
+#define        DE_COLOR_COMPARE_COLOR                          23 : 0
+
+#define        DE_COLOR_COMPARE_MASK                           0x000024
+#define        DE_COLOR_COMPARE_MASK_MASKS                     23 : 0
+
+#define        DE_MASKS                                        0x000028
+#define        DE_MASKS_BYTE_MASK                              31 : 16
+#define        DE_MASKS_BIT_MASK                               15 : 0
+
+#define        DE_CLIP_TL                                      0x00002C
+#define        DE_CLIP_TL_TOP                                  31 : 16
+#define        DE_CLIP_TL_STATUS                               13 : 13
+#define        DE_CLIP_TL_STATUS_DISABLE                       0
+#define        DE_CLIP_TL_STATUS_ENABLE                        1
+#define        DE_CLIP_TL_INHIBIT                              12 : 12
+#define        DE_CLIP_TL_INHIBIT_OUTSIDE                      0
+#define        DE_CLIP_TL_INHIBIT_INSIDE                       1
+#define        DE_CLIP_TL_LEFT                                 11 : 0
+
+#define        DE_CLIP_BR                                      0x000030
+#define        DE_CLIP_BR_BOTTOM                               31 : 16
+#define        DE_CLIP_BR_RIGHT                                12 : 0
+
+#define        DE_MONO_PATTERN_LOW                             0x000034
+#define        DE_MONO_PATTERN_LOW_PATTERN                     31 : 0
+
+#define        DE_MONO_PATTERN_HIGH                            0x000038
+#define        DE_MONO_PATTERN_HIGH_PATTERN                    31 : 0
+
+#define        DE_WINDOW_WIDTH                                 0x00003C
+#define        DE_WINDOW_WIDTH_DESTINATION                     28 : 16
+#define        DE_WINDOW_WIDTH_SOURCE                          12 : 0
+
+#define        DE_WINDOW_SOURCE_BASE                           0x000040
+#define        DE_WINDOW_SOURCE_BASE_EXT                       27 : 27
+#define        DE_WINDOW_SOURCE_BASE_EXT_LOCAL                 0
+#define        DE_WINDOW_SOURCE_BASE_EXT_EXTERNAL              1
+#define        DE_WINDOW_SOURCE_BASE_CS                        26 : 26
+#define        DE_WINDOW_SOURCE_BASE_CS_0                      0
+#define        DE_WINDOW_SOURCE_BASE_CS_1                      1
+#define        DE_WINDOW_SOURCE_BASE_ADDRESS                   25 : 0
+
+#define        DE_WINDOW_DESTINATION_BASE                      0x000044
+#define        DE_WINDOW_DESTINATION_BASE_EXT                  27 : 27
+#define        DE_WINDOW_DESTINATION_BASE_EXT_LOCAL            0
+#define        DE_WINDOW_DESTINATION_BASE_EXT_EXTERNAL         1
+#define        DE_WINDOW_DESTINATION_BASE_CS                   26 : 26
+#define        DE_WINDOW_DESTINATION_BASE_CS_0                 0
+#define        DE_WINDOW_DESTINATION_BASE_CS_1                 1
+#define        DE_WINDOW_DESTINATION_BASE_ADDRESS              25 : 0
+
+#define        DE_ALPHA                                        0x000048
+#define        DE_ALPHA_VALUE                                  7 : 0
+
+#define        DE_WRAP                                         0x00004C
+#define        DE_WRAP_X                                       31 : 16
+#define        DE_WRAP_Y                                       15 : 0
+
+#define        DE_STATUS                                       0x000050
+#define        DE_STATUS_CSC                                   1 : 1
+#define        DE_STATUS_CSC_CLEAR                             0
+#define        DE_STATUS_CSC_NOT_ACTIVE                        0
+#define        DE_STATUS_CSC_ACTIVE                            1
+#define        DE_STATUS_2D                                    0 : 0
+#define        DE_STATUS_2D_CLEAR                              0
+#define        DE_STATUS_2D_NOT_ACTIVE                         0
+#define        DE_STATUS_2D_ACTIVE                             1
+
+/* Color Space Conversion registers. */
+
+#define        CSC_Y_SOURCE_BASE                               0x0000C8
+#define        CSC_Y_SOURCE_BASE_EXT                           27 : 27
+#define        CSC_Y_SOURCE_BASE_EXT_LOCAL                     0
+#define        CSC_Y_SOURCE_BASE_EXT_EXTERNAL                  1
+#define        CSC_Y_SOURCE_BASE_CS                            26 : 26
+#define        CSC_Y_SOURCE_BASE_CS_0                          0
+#define        CSC_Y_SOURCE_BASE_CS_1                          1
+#define        CSC_Y_SOURCE_BASE_ADDRESS                       25 : 0
+
+#define        CSC_CONSTANTS                                   0x0000CC
+#define        CSC_CONSTANTS_Y                                 31 : 24
+#define        CSC_CONSTANTS_R                                 23 : 16
+#define        CSC_CONSTANTS_G                                 15 : 8
+#define        CSC_CONSTANTS_B                                 7 : 0
+
+#define        CSC_Y_SOURCE_X                                  0x0000D0
+#define        CSC_Y_SOURCE_X_INTEGER                          26 : 16
+#define        CSC_Y_SOURCE_X_FRACTION                         15 : 3
+
+#define        CSC_Y_SOURCE_Y                                  0x0000D4
+#define        CSC_Y_SOURCE_Y_INTEGER                          27 : 16
+#define        CSC_Y_SOURCE_Y_FRACTION                         15 : 3
+
+#define        CSC_U_SOURCE_BASE                               0x0000D8
+#define        CSC_U_SOURCE_BASE_EXT                           27 : 27
+#define        CSC_U_SOURCE_BASE_EXT_LOCAL                     0
+#define        CSC_U_SOURCE_BASE_EXT_EXTERNAL                  1
+#define        CSC_U_SOURCE_BASE_CS                            26 : 26
+#define        CSC_U_SOURCE_BASE_CS_0                          0
+#define        CSC_U_SOURCE_BASE_CS_1                          1
+#define        CSC_U_SOURCE_BASE_ADDRESS                       25 : 0
+
+#define        CSC_V_SOURCE_BASE                               0x0000DC
+#define        CSC_V_SOURCE_BASE_EXT                           27 : 27
+#define        CSC_V_SOURCE_BASE_EXT_LOCAL                     0
+#define        CSC_V_SOURCE_BASE_EXT_EXTERNAL                  1
+#define        CSC_V_SOURCE_BASE_CS                            26 : 26
+#define        CSC_V_SOURCE_BASE_CS_0                          0
+#define        CSC_V_SOURCE_BASE_CS_1                          1
+#define        CSC_V_SOURCE_BASE_ADDRESS                       25 : 0
+
+#define        CSC_SOURCE_DIMENSION                            0x0000E0
+#define        CSC_SOURCE_DIMENSION_X                          31 : 16
+#define        CSC_SOURCE_DIMENSION_Y                          15 : 0
+
+#define        CSC_SOURCE_PITCH                                0x0000E4
+#define        CSC_SOURCE_PITCH_Y                              31 : 16
+#define        CSC_SOURCE_PITCH_UV                             15 : 0
+
+#define        CSC_DESTINATION                                 0x0000E8
+#define        CSC_DESTINATION_WRAP                            31 : 31
+#define        CSC_DESTINATION_WRAP_DISABLE                    0
+#define        CSC_DESTINATION_WRAP_ENABLE                     1
+#define        CSC_DESTINATION_X                               27 : 16
+#define        CSC_DESTINATION_Y                               11 : 0
+
+#define        CSC_DESTINATION_DIMENSION                       0x0000EC
+#define        CSC_DESTINATION_DIMENSION_X                     31 : 16
+#define        CSC_DESTINATION_DIMENSION_Y                     15 : 0
+
+#define        CSC_DESTINATION_PITCH                           0x0000F0
+#define        CSC_DESTINATION_PITCH_X                         31 : 16
+#define        CSC_DESTINATION_PITCH_Y                         15 : 0
+
+#define        CSC_SCALE_FACTOR                                0x0000F4
+#define        CSC_SCALE_FACTOR_HORIZONTAL                     31 : 16
+#define        CSC_SCALE_FACTOR_VERTICAL                       15 : 0
+
+#define        CSC_DESTINATION_BASE                            0x0000F8
+#define        CSC_DESTINATION_BASE_EXT                        27 : 27
+#define        CSC_DESTINATION_BASE_EXT_LOCAL                  0
+#define        CSC_DESTINATION_BASE_EXT_EXTERNAL               1
+#define        CSC_DESTINATION_BASE_CS                         26 : 26
+#define        CSC_DESTINATION_BASE_CS_0                       0
+#define        CSC_DESTINATION_BASE_CS_1                       1
+#define        CSC_DESTINATION_BASE_ADDRESS                    25 : 0
+
+#define        CSC_CONTROL                                     0x0000FC
+#define        CSC_CONTROL_STATUS                              31 : 31
+#define        CSC_CONTROL_STATUS_STOP                         0
+#define        CSC_CONTROL_STATUS_START                        1
+#define        CSC_CONTROL_SOURCE_FORMAT                       30 : 28
+#define        CSC_CONTROL_SOURCE_FORMAT_YUV422                0
+#define        CSC_CONTROL_SOURCE_FORMAT_YUV420I               1
+#define        CSC_CONTROL_SOURCE_FORMAT_YUV420                2
+#define        CSC_CONTROL_SOURCE_FORMAT_YVU9                  3
+#define        CSC_CONTROL_SOURCE_FORMAT_IYU1                  4
+#define        CSC_CONTROL_SOURCE_FORMAT_IYU2                  5
+#define        CSC_CONTROL_SOURCE_FORMAT_RGB565                6
+#define        CSC_CONTROL_SOURCE_FORMAT_RGB8888               7
+#define        CSC_CONTROL_DESTINATION_FORMAT                  27 : 26
+#define        CSC_CONTROL_DESTINATION_FORMAT_RGB565           0
+#define        CSC_CONTROL_DESTINATION_FORMAT_RGB8888          1
+#define        CSC_CONTROL_HORIZONTAL_FILTER                   25 : 25
+#define        CSC_CONTROL_HORIZONTAL_FILTER_DISABLE           0
+#define        CSC_CONTROL_HORIZONTAL_FILTER_ENABLE            1
+#define        CSC_CONTROL_VERTICAL_FILTER                     24 : 24
+#define        CSC_CONTROL_VERTICAL_FILTER_DISABLE             0
+#define        CSC_CONTROL_VERTICAL_FILTER_ENABLE              1
+#define        CSC_CONTROL_BYTE_ORDER                          23 : 23
+#define        CSC_CONTROL_BYTE_ORDER_YUYV                     0
+#define        CSC_CONTROL_BYTE_ORDER_UYVY                     1
+
+#define        DE_DATA_PORT_501                                0x110000
+#define        DE_DATA_PORT_712                                0x400000
+#define        DE_DATA_PORT_722                                0x6000
+
+/* point to virtual Memory Map IO starting address */
+extern char *smtc_RegBaseAddress;
+/* point to virtual video memory starting address */
+extern char *smtc_VRAMBaseAddress;
+extern unsigned char smtc_de_busy;
+
+extern unsigned long memRead32(unsigned long nOffset);
+extern void memWrite32(unsigned long nOffset, unsigned long nData);
+extern unsigned long SMTC_read2Dreg(unsigned long nOffset);
+
+/* 2D functions */
+extern void deInit(unsigned int nModeWidth, unsigned int nModeHeight,
+                  unsigned int bpp);
+
+extern void deWaitForNotBusy(void);
+
+extern void deVerticalLine(unsigned long dst_base,
+       unsigned long dst_pitch,
+       unsigned long nX,
+       unsigned long nY,
+       unsigned long dst_height,
+       unsigned long nColor);
+
+extern void deHorizontalLine(unsigned long dst_base,
+       unsigned long dst_pitch,
+       unsigned long nX,
+       unsigned long nY,
+       unsigned long dst_width,
+       unsigned long nColor);
+
+extern void deLine(unsigned long dst_base,
+       unsigned long dst_pitch,
+       unsigned long nX1,
+       unsigned long nY1,
+       unsigned long nX2,
+       unsigned long nY2,
+       unsigned long nColor);
+
+extern void deFillRect(unsigned long dst_base,
+       unsigned long dst_pitch,
+       unsigned long dst_X,
+       unsigned long dst_Y,
+       unsigned long dst_width,
+       unsigned long dst_height,
+       unsigned long nColor);
+
+extern void deRotatePattern(unsigned char *pattern_dstaddr,
+       unsigned long pattern_src_addr,
+       unsigned long pattern_BPP,
+       unsigned long pattern_stride,
+       int     patternX,
+       int     patternY);
+
+extern void deCopy(unsigned long dst_base,
+       unsigned long dst_pitch,
+       unsigned long dst_BPP,
+       unsigned long dst_X,
+       unsigned long dst_Y,
+       unsigned long dst_width,
+       unsigned long dst_height,
+       unsigned long src_base,
+       unsigned long src_pitch,
+       unsigned long src_X,
+       unsigned long src_Y,
+       pTransparent    pTransp,
+       unsigned char nROP2);
+
+/*
+ * System memory to Video memory monochrome expansion.
+ *
+ * Source is monochrome image in system memory.  This function expands the
+ * monochrome data to color image in video memory.
+ *
+ * @pSrcbuf: pointer to start of source buffer in system memory
+ * @srcDelta: Pitch value (in bytes) of the source buffer, +ive means top
+ *             down and -ive mean button up
+ * @startBit: Mono data can start at any bit in a byte, this value should
+ *             be 0 to 7
+ * @dBase: Address of destination :  offset in frame buffer
+ * @dPitch: Pitch value of destination surface in BYTE
+ * @bpp: Color depth of destination surface
+ * @dx, dy: Starting coordinate of destination surface
+ * @width, height: width and height of rectange in pixel value
+ * @fColor,bColor: Foreground, Background color (corresponding to a 1, 0 in
+ *     the monochrome data)
+ * @rop2: ROP value
+ */
+
+extern long deSystemMem2VideoMemMonoBlt(
+       const char *pSrcbuf,
+       long srcDelta,
+       unsigned long startBit,
+       unsigned long dBase,
+       unsigned long dPitch,
+       unsigned long bpp,
+       unsigned long dx, unsigned long dy,
+       unsigned long width, unsigned long height,
+       unsigned long fColor,
+       unsigned long bColor,
+       unsigned long rop2);
+
+extern unsigned long deGetTransparency(void);
+extern void deSetPixelFormat(unsigned long bpp);
diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c
new file mode 100644 (file)
index 0000000..161dbc9
--- /dev/null
@@ -0,0 +1,1253 @@
+/*
+ * Silicon Motion SM7XX frame buffer device
+ *
+ * Copyright (C) 2006 Silicon Motion Technology Corp.
+ * Authors: Ge Wang, gewang@siliconmotion.com
+ *         Boyod boyod.yang@siliconmotion.com.cn
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ *  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.
+ *
+ * Version 0.10.26192.21.01
+ *     - Add PowerPC/Big endian support
+ *     - Add 2D support for Lynx
+ *     - Verified on2.6.19.2  Boyod.yang <boyod.yang@siliconmotion.com.cn>
+ *
+ * Version 0.09.2621.00.01
+ *     - Only support Linux Kernel's version 2.6.21.
+ *     Boyod.yang  <boyod.yang@siliconmotion.com.cn>
+ *
+ * Version 0.09
+ *     - Only support Linux Kernel's version 2.6.12.
+ *     Boyod.yang <boyod.yang@siliconmotion.com.cn>
+ */
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include <linux/io.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/console.h>
+#include <linux/screen_info.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+struct screen_info smtc_screen_info;
+
+#include "smtcfb.h"
+#include "smtc2d.h"
+
+#ifdef DEBUG
+#define smdbg(format, arg...)  printk(KERN_DEBUG format , ## arg)
+#else
+#define smdbg(format, arg...)
+#endif
+
+/*
+* Private structure
+*/
+struct smtcfb_info {
+       /*
+        * The following is a pointer to be passed into the
+        * functions below.  The modules outside the main
+        * voyager.c driver have no knowledge as to what
+        * is within this structure.
+        */
+       struct fb_info fb;
+       struct display_switch *dispsw;
+       struct pci_dev *dev;
+       signed int currcon;
+
+       struct {
+               u8 red, green, blue;
+       } palette[NR_RGB];
+
+       u_int palette_size;
+};
+
+struct par_info {
+       /*
+        * Hardware
+        */
+       u16 chipID;
+       unsigned char __iomem *m_pMMIO;
+       char __iomem *m_pLFB;
+       char *m_pDPR;
+       char *m_pVPR;
+       char *m_pCPR;
+
+       u_int width;
+       u_int height;
+       u_int hz;
+       u_long BaseAddressInVRAM;
+       u8 chipRevID;
+};
+
+struct vesa_mode_table {
+       char mode_index[6];
+       u16 lfb_width;
+       u16 lfb_height;
+       u16 lfb_depth;
+};
+
+static struct vesa_mode_table vesa_mode[] = {
+       {"0x301", 640,  480,  8},
+       {"0x303", 800,  600,  8},
+       {"0x305", 1024, 768,    8},
+       {"0x307", 1280, 1024, 8},
+
+       {"0x311", 640,  480,  16},
+       {"0x314", 800,  600,  16},
+       {"0x317", 1024, 768,    16},
+       {"0x31A", 1280, 1024, 16},
+
+       {"0x312", 640,  480,  24},
+       {"0x315", 800,  600,  24},
+       {"0x318", 1024, 768,    24},
+       {"0x31B", 1280, 1024, 24},
+};
+
+char __iomem *smtc_RegBaseAddress;     /* Memory Map IO starting address */
+char __iomem *smtc_VRAMBaseAddress;    /* video memory starting address */
+
+char *smtc_2DBaseAddress;      /* 2D engine starting address */
+char *smtc_2Ddataport;         /* 2D data port offset */
+short smtc_2Dacceleration;
+
+static u32 colreg[17];
+static struct par_info hw;     /* hardware information */
+
+u16 smtc_ChipIDs[] = {
+       0x710,
+       0x712,
+       0x720
+};
+
+#define numSMTCchipIDs (sizeof(smtc_ChipIDs) / sizeof(u16))
+
+void deWaitForNotBusy(void)
+{
+       unsigned long i = 0x1000000;
+       while (i--) {
+               if ((smtc_seqr(0x16) & 0x18) == 0x10)
+                       break;
+       }
+       smtc_de_busy = 0;
+}
+
+static void sm712_set_timing(struct smtcfb_info *sfb,
+                            struct par_info *ppar_info)
+{
+       int i = 0, j = 0;
+       u32 m_nScreenStride;
+
+       smdbg("\nppar_info->width = %d ppar_info->height = %d"
+                       "sfb->fb.var.bits_per_pixel = %d ppar_info->hz = %d\n",
+                       ppar_info->width, ppar_info->height,
+                       sfb->fb.var.bits_per_pixel, ppar_info->hz);
+
+       for (j = 0; j < numVGAModes; j++) {
+               if (VGAMode[j].mmSizeX == ppar_info->width &&
+                   VGAMode[j].mmSizeY == ppar_info->height &&
+                   VGAMode[j].bpp == sfb->fb.var.bits_per_pixel &&
+                   VGAMode[j].hz == ppar_info->hz) {
+
+                       smdbg("\nVGAMode[j].mmSizeX  = %d VGAMode[j].mmSizeY ="
+                                       "%d VGAMode[j].bpp = %d"
+                                       "VGAMode[j].hz=%d\n",
+                                       VGAMode[j].mmSizeX, VGAMode[j].mmSizeY,
+                                       VGAMode[j].bpp, VGAMode[j].hz);
+
+                       smdbg("VGAMode index=%d\n", j);
+
+                       smtc_mmiowb(0x0, 0x3c6);
+
+                       smtc_seqw(0, 0x1);
+
+                       smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2);
+
+                       /* init SEQ register SR00 - SR04 */
+                       for (i = 0; i < SIZE_SR00_SR04; i++)
+                               smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]);
+
+                       /* init SEQ register SR10 - SR24 */
+                       for (i = 0; i < SIZE_SR10_SR24; i++)
+                               smtc_seqw(i + 0x10,
+                                         VGAMode[j].Init_SR10_SR24[i]);
+
+                       /* init SEQ register SR30 - SR75 */
+                       for (i = 0; i < SIZE_SR30_SR75; i++)
+                               if (((i + 0x30) != 0x62) \
+                                       && ((i + 0x30) != 0x6a) \
+                                       && ((i + 0x30) != 0x6b))
+                                       smtc_seqw(i + 0x30,
+                                               VGAMode[j].Init_SR30_SR75[i]);
+
+                       /* init SEQ register SR80 - SR93 */
+                       for (i = 0; i < SIZE_SR80_SR93; i++)
+                               smtc_seqw(i + 0x80,
+                                         VGAMode[j].Init_SR80_SR93[i]);
+
+                       /* init SEQ register SRA0 - SRAF */
+                       for (i = 0; i < SIZE_SRA0_SRAF; i++)
+                               smtc_seqw(i + 0xa0,
+                                         VGAMode[j].Init_SRA0_SRAF[i]);
+
+                       /* init Graphic register GR00 - GR08 */
+                       for (i = 0; i < SIZE_GR00_GR08; i++)
+                               smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]);
+
+                       /* init Attribute register AR00 - AR14 */
+                       for (i = 0; i < SIZE_AR00_AR14; i++)
+                               smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]);
+
+                       /* init CRTC register CR00 - CR18 */
+                       for (i = 0; i < SIZE_CR00_CR18; i++)
+                               smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]);
+
+                       /* init CRTC register CR30 - CR4D */
+                       for (i = 0; i < SIZE_CR30_CR4D; i++)
+                               smtc_crtcw(i + 0x30,
+                                          VGAMode[j].Init_CR30_CR4D[i]);
+
+                       /* init CRTC register CR90 - CRA7 */
+                       for (i = 0; i < SIZE_CR90_CRA7; i++)
+                               smtc_crtcw(i + 0x90,
+                                          VGAMode[j].Init_CR90_CRA7[i]);
+               }
+       }
+       smtc_mmiowb(0x67, 0x3c2);
+
+       /* set VPR registers */
+       writel(0x0, ppar_info->m_pVPR + 0x0C);
+       writel(0x0, ppar_info->m_pVPR + 0x40);
+
+       /* set data width */
+       m_nScreenStride =
+               (ppar_info->width * sfb->fb.var.bits_per_pixel) / 64;
+       switch (sfb->fb.var.bits_per_pixel) {
+       case 8:
+               writel(0x0, ppar_info->m_pVPR + 0x0);
+               break;
+       case 16:
+               writel(0x00020000, ppar_info->m_pVPR + 0x0);
+               break;
+       case 24:
+               writel(0x00040000, ppar_info->m_pVPR + 0x0);
+               break;
+       case 32:
+               writel(0x00030000, ppar_info->m_pVPR + 0x0);
+               break;
+       }
+       writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride),
+              ppar_info->m_pVPR + 0x10);
+
+}
+
+static void sm712_setpalette(int regno, unsigned red, unsigned green,
+                            unsigned blue, struct fb_info *info)
+{
+       struct par_info *cur_par = (struct par_info *)info->par;
+
+       if (cur_par->BaseAddressInVRAM)
+               /*
+                * second display palette for dual head. Enable CRT RAM, 6-bit
+                * RAM
+                */
+               smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x20);
+       else
+               /* primary display palette. Enable LCD RAM only, 6-bit RAM */
+               smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
+       smtc_mmiowb(regno, dac_reg);
+       smtc_mmiowb(red >> 10, dac_val);
+       smtc_mmiowb(green >> 10, dac_val);
+       smtc_mmiowb(blue >> 10, dac_val);
+}
+
+static void smtc_set_timing(struct smtcfb_info *sfb, struct par_info
+               *ppar_info)
+{
+       switch (ppar_info->chipID) {
+       case 0x710:
+       case 0x712:
+       case 0x720:
+               sm712_set_timing(sfb, ppar_info);
+               break;
+       }
+}
+
+static struct fb_var_screeninfo smtcfb_var = {
+       .xres = 1024,
+       .yres = 600,
+       .xres_virtual = 1024,
+       .yres_virtual = 600,
+       .bits_per_pixel = 16,
+       .red = {16, 8, 0},
+       .green = {8, 8, 0},
+       .blue = {0, 8, 0},
+       .activate = FB_ACTIVATE_NOW,
+       .height = -1,
+       .width = -1,
+       .vmode = FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo smtcfb_fix = {
+       .id = "sm712fb",
+       .type = FB_TYPE_PACKED_PIXELS,
+       .visual = FB_VISUAL_TRUECOLOR,
+       .line_length = 800 * 3,
+       .accel = FB_ACCEL_SMI_LYNX,
+};
+
+/* chan_to_field
+ *
+ * convert a colour value into a field position
+ *
+ * from pxafb.c
+ */
+
+static inline unsigned int chan_to_field(unsigned int chan,
+                                        struct fb_bitfield *bf)
+{
+       chan &= 0xffff;
+       chan >>= 16 - bf->length;
+       return chan << bf->offset;
+}
+
+static int smtcfb_blank(int blank_mode, struct fb_info *info)
+{
+       /* clear DPMS setting */
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               /* Screen On: HSync: On, VSync : On */
+               smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
+               smtc_seqw(0x6a, 0x16);
+               smtc_seqw(0x6b, 0x02);
+               smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
+               smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
+               smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
+               smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
+               smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
+               break;
+       case FB_BLANK_NORMAL:
+               /* Screen Off: HSync: On, VSync : On   Soft blank */
+               smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
+               smtc_seqw(0x6a, 0x16);
+               smtc_seqw(0x6b, 0x02);
+               smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
+               smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
+               smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
+               smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
+               break;
+       case FB_BLANK_VSYNC_SUSPEND:
+               /* Screen On: HSync: On, VSync : Off */
+               smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
+               smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
+               smtc_seqw(0x6a, 0x0c);
+               smtc_seqw(0x6b, 0x02);
+               smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
+               smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
+               smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
+               smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
+               smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
+               smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
+               break;
+       case FB_BLANK_HSYNC_SUSPEND:
+               /* Screen On: HSync: Off, VSync : On */
+               smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
+               smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
+               smtc_seqw(0x6a, 0x0c);
+               smtc_seqw(0x6b, 0x02);
+               smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
+               smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
+               smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
+               smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
+               smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
+               smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
+               break;
+       case FB_BLANK_POWERDOWN:
+               /* Screen On: HSync: Off, VSync : Off */
+               smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
+               smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
+               smtc_seqw(0x6a, 0x0c);
+               smtc_seqw(0x6b, 0x02);
+               smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
+               smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
+               smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
+               smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
+               smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
+               smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green,
+                         unsigned blue, unsigned trans, struct fb_info *info)
+{
+       struct smtcfb_info *sfb = (struct smtcfb_info *)info;
+       u32 val;
+
+       if (regno > 255)
+               return 1;
+
+       switch (sfb->fb.fix.visual) {
+       case FB_VISUAL_DIRECTCOLOR:
+       case FB_VISUAL_TRUECOLOR:
+               /*
+                * 16/32 bit true-colour, use pseuo-palette for 16 base color
+                */
+               if (regno < 16) {
+                       if (sfb->fb.var.bits_per_pixel == 16) {
+                               u32 *pal = sfb->fb.pseudo_palette;
+                               val = chan_to_field(red, &sfb->fb.var.red);
+                               val |= chan_to_field(green, \
+                                               &sfb->fb.var.green);
+                               val |= chan_to_field(blue, &sfb->fb.var.blue);
+#ifdef __BIG_ENDIAN
+                               pal[regno] =
+                                   ((red & 0xf800) >> 8) |
+                                   ((green & 0xe000) >> 13) |
+                                   ((green & 0x1c00) << 3) |
+                                   ((blue & 0xf800) >> 3);
+#else
+                               pal[regno] = val;
+#endif
+                       } else {
+                               u32 *pal = sfb->fb.pseudo_palette;
+                               val = chan_to_field(red, &sfb->fb.var.red);
+                               val |= chan_to_field(green, \
+                                               &sfb->fb.var.green);
+                               val |= chan_to_field(blue, &sfb->fb.var.blue);
+#ifdef __BIG_ENDIAN
+                               val =
+                                   (val & 0xff00ff00 >> 8) |
+                                   (val & 0x00ff00ff << 8);
+#endif
+                               pal[regno] = val;
+                       }
+               }
+               break;
+
+       case FB_VISUAL_PSEUDOCOLOR:
+               /* color depth 8 bit */
+               sm712_setpalette(regno, red, green, blue, info);
+               break;
+
+       default:
+               return 1;       /* unknown type */
+       }
+
+       return 0;
+
+}
+
+#ifdef __BIG_ENDIAN
+static ssize_t smtcfb_read(struct fb_info *info, char __user * buf, size_t
+                               count, loff_t *ppos)
+{
+       unsigned long p = *ppos;
+
+       u32 *buffer, *dst;
+       u32 __iomem *src;
+       int c, i, cnt = 0, err = 0;
+       unsigned long total_size;
+
+       if (!info || !info->screen_base)
+               return -ENODEV;
+
+       if (info->state != FBINFO_STATE_RUNNING)
+               return -EPERM;
+
+       total_size = info->screen_size;
+
+       if (total_size == 0)
+               total_size = info->fix.smem_len;
+
+       if (p >= total_size)
+               return 0;
+
+       if (count >= total_size)
+               count = total_size;
+
+       if (count + p > total_size)
+               count = total_size - p;
+
+       buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       src = (u32 __iomem *) (info->screen_base + p);
+
+       if (info->fbops->fb_sync)
+               info->fbops->fb_sync(info);
+
+       while (count) {
+               c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+               dst = buffer;
+               for (i = c >> 2; i--;) {
+                       *dst = fb_readl(src++);
+                       *dst =
+                           (*dst & 0xff00ff00 >> 8) |
+                           (*dst & 0x00ff00ff << 8);
+                       dst++;
+               }
+               if (c & 3) {
+                       u8 *dst8 = (u8 *) dst;
+                       u8 __iomem *src8 = (u8 __iomem *) src;
+
+                       for (i = c & 3; i--;) {
+                               if (i & 1) {
+                                       *dst8++ = fb_readb(++src8);
+                               } else {
+                                       *dst8++ = fb_readb(--src8);
+                                       src8 += 2;
+                               }
+                       }
+                       src = (u32 __iomem *) src8;
+               }
+
+               if (copy_to_user(buf, buffer, c)) {
+                       err = -EFAULT;
+                       break;
+               }
+               *ppos += c;
+               buf += c;
+               cnt += c;
+               count -= c;
+       }
+
+       kfree(buffer);
+
+       return (err) ? err : cnt;
+}
+
+static ssize_t
+smtcfb_write(struct fb_info *info, const char __user *buf, size_t count,
+            loff_t *ppos)
+{
+       unsigned long p = *ppos;
+
+       u32 *buffer, *src;
+       u32 __iomem *dst;
+       int c, i, cnt = 0, err = 0;
+       unsigned long total_size;
+
+       if (!info || !info->screen_base)
+               return -ENODEV;
+
+       if (info->state != FBINFO_STATE_RUNNING)
+               return -EPERM;
+
+       total_size = info->screen_size;
+
+       if (total_size == 0)
+               total_size = info->fix.smem_len;
+
+       if (p > total_size)
+               return -EFBIG;
+
+       if (count > total_size) {
+               err = -EFBIG;
+               count = total_size;
+       }
+
+       if (count + p > total_size) {
+               if (!err)
+                       err = -ENOSPC;
+
+               count = total_size - p;
+       }
+
+       buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       dst = (u32 __iomem *) (info->screen_base + p);
+
+       if (info->fbops->fb_sync)
+               info->fbops->fb_sync(info);
+
+       while (count) {
+               c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+               src = buffer;
+
+               if (copy_from_user(src, buf, c)) {
+                       err = -EFAULT;
+                       break;
+               }
+
+               for (i = c >> 2; i--;) {
+                       fb_writel((*src & 0xff00ff00 >> 8) |
+                                 (*src & 0x00ff00ff << 8), dst++);
+                       src++;
+               }
+               if (c & 3) {
+                       u8 *src8 = (u8 *) src;
+                       u8 __iomem *dst8 = (u8 __iomem *) dst;
+
+                       for (i = c & 3; i--;) {
+                               if (i & 1) {
+                                       fb_writeb(*src8++, ++dst8);
+                               } else {
+                                       fb_writeb(*src8++, --dst8);
+                                       dst8 += 2;
+                               }
+                       }
+                       dst = (u32 __iomem *) dst8;
+               }
+
+               *ppos += c;
+               buf += c;
+               cnt += c;
+               count -= c;
+       }
+
+       kfree(buffer);
+
+       return (cnt) ? cnt : err;
+}
+#endif /* ! __BIG_ENDIAN */
+
+#include "smtc2d.c"
+
+void smtcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+       struct par_info *p = (struct par_info *)info->par;
+
+       if (smtc_2Dacceleration) {
+               if (!area->width || !area->height)
+                       return;
+
+               deCopy(p->BaseAddressInVRAM, 0, info->var.bits_per_pixel,
+                      area->dx, area->dy, area->width, area->height,
+                      p->BaseAddressInVRAM, 0, area->sx, area->sy, 0, 0xC);
+
+       } else
+               cfb_copyarea(info, area);
+}
+
+void smtcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+       struct par_info *p = (struct par_info *)info->par;
+
+       if (smtc_2Dacceleration) {
+               if (!rect->width || !rect->height)
+                       return;
+               if (info->var.bits_per_pixel >= 24)
+                       deFillRect(p->BaseAddressInVRAM, 0, rect->dx * 3,
+                                  rect->dy * 3, rect->width * 3, rect->height,
+                                  rect->color);
+               else
+                       deFillRect(p->BaseAddressInVRAM, 0, rect->dx, rect->dy,
+                                  rect->width, rect->height, rect->color);
+       } else
+               cfb_fillrect(info, rect);
+}
+
+void smtcfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       struct par_info *p = (struct par_info *)info->par;
+       u32 bg_col = 0, fg_col = 0;
+
+       if ((smtc_2Dacceleration) && (image->depth == 1)) {
+               if (smtc_de_busy)
+                       deWaitForNotBusy();
+
+               switch (info->var.bits_per_pixel) {
+               case 8:
+                       bg_col = image->bg_color;
+                       fg_col = image->fg_color;
+                       break;
+               case 16:
+                       bg_col =
+                           ((u32 *) (info->pseudo_palette))[image->bg_color];
+                       fg_col =
+                           ((u32 *) (info->pseudo_palette))[image->fg_color];
+                       break;
+               case 32:
+                       bg_col =
+                           ((u32 *) (info->pseudo_palette))[image->bg_color];
+                       fg_col =
+                           ((u32 *) (info->pseudo_palette))[image->fg_color];
+                       break;
+               }
+
+               deSystemMem2VideoMemMonoBlt(
+                       image->data,
+                       image->width / 8,
+                       0,
+                       p->BaseAddressInVRAM,
+                       0,
+                       0,
+                       image->dx, image->dy,
+                       image->width, image->height,
+                       fg_col, bg_col,
+                       0x0C);
+
+       } else
+               cfb_imageblit(info, image);
+}
+
+static struct fb_ops smtcfb_ops = {
+       .owner = THIS_MODULE,
+       .fb_setcolreg = smtc_setcolreg,
+       .fb_blank = smtcfb_blank,
+       .fb_fillrect = smtcfb_fillrect,
+       .fb_imageblit = smtcfb_imageblit,
+       .fb_copyarea = smtcfb_copyarea,
+#ifdef __BIG_ENDIAN
+       .fb_read = smtcfb_read,
+       .fb_write = smtcfb_write,
+#endif
+
+};
+
+void smtcfb_setmode(struct smtcfb_info *sfb)
+{
+       switch (sfb->fb.var.bits_per_pixel) {
+       case 32:
+               sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+               sfb->fb.fix.line_length = sfb->fb.var.xres * 4;
+               sfb->fb.var.red.length = 8;
+               sfb->fb.var.green.length = 8;
+               sfb->fb.var.blue.length = 8;
+               sfb->fb.var.red.offset = 16;
+               sfb->fb.var.green.offset = 8;
+               sfb->fb.var.blue.offset = 0;
+
+               break;
+       case 8:
+               sfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+               sfb->fb.fix.line_length = sfb->fb.var.xres;
+               sfb->fb.var.red.offset = 5;
+               sfb->fb.var.red.length = 3;
+               sfb->fb.var.green.offset = 2;
+               sfb->fb.var.green.length = 3;
+               sfb->fb.var.blue.offset = 0;
+               sfb->fb.var.blue.length = 2;
+               break;
+       case 24:
+               sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+               sfb->fb.fix.line_length = sfb->fb.var.xres * 3;
+               sfb->fb.var.red.length = 8;
+               sfb->fb.var.green.length = 8;
+               sfb->fb.var.blue.length = 8;
+
+               sfb->fb.var.red.offset = 16;
+               sfb->fb.var.green.offset = 8;
+               sfb->fb.var.blue.offset = 0;
+
+               break;
+       case 16:
+       default:
+               sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+               sfb->fb.fix.line_length = sfb->fb.var.xres * 2;
+
+               sfb->fb.var.red.length = 5;
+               sfb->fb.var.green.length = 6;
+               sfb->fb.var.blue.length = 5;
+
+               sfb->fb.var.red.offset = 11;
+               sfb->fb.var.green.offset = 5;
+               sfb->fb.var.blue.offset = 0;
+
+               break;
+       }
+
+       hw.width = sfb->fb.var.xres;
+       hw.height = sfb->fb.var.yres;
+       hw.hz = 60;
+       smtc_set_timing(sfb, &hw);
+       if (smtc_2Dacceleration) {
+               printk("2D acceleration enabled!\n");
+               /* Init smtc drawing engine */
+               deInit(sfb->fb.var.xres, sfb->fb.var.yres,
+                               sfb->fb.var.bits_per_pixel);
+       }
+}
+
+/*
+ * Alloc struct smtcfb_info and assign the default value
+ */
+static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *dev,
+                                                       char *name)
+{
+       struct smtcfb_info *sfb;
+
+       sfb = kmalloc(sizeof(struct smtcfb_info), GFP_KERNEL);
+
+       if (!sfb)
+               return NULL;
+
+       memset(sfb, 0, sizeof(struct smtcfb_info));
+
+       sfb->currcon = -1;
+       sfb->dev = dev;
+
+       /*** Init sfb->fb with default value ***/
+       sfb->fb.flags = FBINFO_FLAG_DEFAULT;
+       sfb->fb.fbops = &smtcfb_ops;
+       sfb->fb.var = smtcfb_var;
+       sfb->fb.fix = smtcfb_fix;
+
+       strcpy(sfb->fb.fix.id, name);
+
+       sfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
+       sfb->fb.fix.type_aux = 0;
+       sfb->fb.fix.xpanstep = 0;
+       sfb->fb.fix.ypanstep = 0;
+       sfb->fb.fix.ywrapstep = 0;
+       sfb->fb.fix.accel = FB_ACCEL_SMI_LYNX;
+
+       sfb->fb.var.nonstd = 0;
+       sfb->fb.var.activate = FB_ACTIVATE_NOW;
+       sfb->fb.var.height = -1;
+       sfb->fb.var.width = -1;
+       /* text mode acceleration */
+       sfb->fb.var.accel_flags = FB_ACCELF_TEXT;
+       sfb->fb.var.vmode = FB_VMODE_NONINTERLACED;
+       sfb->fb.par = &hw;
+       sfb->fb.pseudo_palette = colreg;
+
+       return sfb;
+}
+
+/*
+ * Unmap in the memory mapped IO registers
+ */
+
+static void smtc_unmap_mmio(struct smtcfb_info *sfb)
+{
+       if (sfb && smtc_RegBaseAddress)
+               smtc_RegBaseAddress = NULL;
+}
+
+/*
+ * Map in the screen memory
+ */
+
+static int smtc_map_smem(struct smtcfb_info *sfb,
+               struct pci_dev *dev, u_long smem_len)
+{
+       if (sfb->fb.var.bits_per_pixel == 32) {
+#ifdef __BIG_ENDIAN
+               sfb->fb.fix.smem_start = pci_resource_start(dev, 0)
+                       + 0x800000;
+#else
+               sfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+#endif
+       } else {
+               sfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+       }
+
+       sfb->fb.fix.smem_len = smem_len;
+
+       sfb->fb.screen_base = smtc_VRAMBaseAddress;
+
+       if (!sfb->fb.screen_base) {
+               printk(KERN_INFO "%s: unable to map screen memory\n",
+                               sfb->fb.fix.id);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/*
+ * Unmap in the screen memory
+ *
+ */
+static void smtc_unmap_smem(struct smtcfb_info *sfb)
+{
+       if (sfb && sfb->fb.screen_base) {
+               iounmap(sfb->fb.screen_base);
+               sfb->fb.screen_base = NULL;
+       }
+}
+
+/*
+ * We need to wake up the LynxEM+, and make sure its in linear memory mode.
+ */
+static inline void sm7xx_init_hw(void)
+{
+       outb_p(0x18, 0x3c4);
+       outb_p(0x11, 0x3c5);
+}
+
+static void smtc_free_fb_info(struct smtcfb_info *sfb)
+{
+       if (sfb) {
+               fb_alloc_cmap(&sfb->fb.cmap, 0, 0);
+               kfree(sfb);
+       }
+}
+
+/*
+ *     sm712vga_setup - process command line options, get vga parameter
+ *     @options: string of options
+ *     Returns zero.
+ *
+ */
+static int __init __maybe_unused sm712vga_setup(char *options)
+{
+       int index;
+
+       if (!options || !*options) {
+               smdbg("\n No vga parameter\n");
+               return -EINVAL;
+       }
+
+       smtc_screen_info.lfb_width = 0;
+       smtc_screen_info.lfb_height = 0;
+       smtc_screen_info.lfb_depth = 0;
+
+       smdbg("\nsm712vga_setup = %s\n", options);
+
+       for (index = 0;
+            index < (sizeof(vesa_mode) / sizeof(struct vesa_mode_table));
+            index++) {
+               if (strstr(options, vesa_mode[index].mode_index)) {
+                       smtc_screen_info.lfb_width = vesa_mode[index].lfb_width;
+                       smtc_screen_info.lfb_height =
+                                       vesa_mode[index].lfb_height;
+                       smtc_screen_info.lfb_depth = vesa_mode[index].lfb_depth;
+                       return 0;
+               }
+       }
+
+       return -1;
+}
+__setup("vga=", sm712vga_setup);
+
+/* Jason (08/13/2009)
+ * Original init function changed to probe method to be used by pci_drv
+ * process used to detect chips replaced with kernel process in pci_drv
+ */
+static int __init smtcfb_pci_probe(struct pci_dev *pdev,
+                                  const struct pci_device_id *ent)
+{
+       struct smtcfb_info *sfb;
+       u_long smem_size = 0x00800000;  /* default 8MB */
+       char name[16];
+       int err;
+       unsigned long pFramebufferPhysical;
+
+       printk(KERN_INFO
+               "Silicon Motion display driver " SMTC_LINUX_FB_VERSION "\n");
+
+       err = pci_enable_device(pdev);  /* enable SMTC chip */
+
+       if (err)
+               return err;
+       err = -ENOMEM;
+
+       hw.chipID = ent->device;
+       sprintf(name, "sm%Xfb", hw.chipID);
+
+       sfb = smtc_alloc_fb_info(pdev, name);
+
+       if (!sfb)
+               goto failed;
+       /* Jason (08/13/2009)
+        * Store fb_info to be further used when suspending and resuming
+        */
+       pci_set_drvdata(pdev, sfb);
+
+       sm7xx_init_hw();
+
+       /*get mode parameter from smtc_screen_info */
+       if (smtc_screen_info.lfb_width != 0) {
+               sfb->fb.var.xres = smtc_screen_info.lfb_width;
+               sfb->fb.var.yres = smtc_screen_info.lfb_height;
+               sfb->fb.var.bits_per_pixel = smtc_screen_info.lfb_depth;
+       } else {
+               /* default resolution 1024x600 16bit mode */
+               sfb->fb.var.xres = SCREEN_X_RES;
+               sfb->fb.var.yres = SCREEN_Y_RES;
+               sfb->fb.var.bits_per_pixel = SCREEN_BPP;
+       }
+
+#ifdef __BIG_ENDIAN
+       if (sfb->fb.var.bits_per_pixel == 24)
+               sfb->fb.var.bits_per_pixel = (smtc_screen_info.lfb_depth = 32);
+#endif
+       /* Map address and memory detection */
+       pFramebufferPhysical = pci_resource_start(pdev, 0);
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &hw.chipRevID);
+
+       switch (hw.chipID) {
+       case 0x710:
+       case 0x712:
+               sfb->fb.fix.mmio_start = pFramebufferPhysical + 0x00400000;
+               sfb->fb.fix.mmio_len = 0x00400000;
+               smem_size = SM712_VIDEOMEMORYSIZE;
+#ifdef __BIG_ENDIAN
+               hw.m_pLFB = (smtc_VRAMBaseAddress =
+                   ioremap(pFramebufferPhysical, 0x00c00000));
+#else
+               hw.m_pLFB = (smtc_VRAMBaseAddress =
+                   ioremap(pFramebufferPhysical, 0x00800000));
+#endif
+               hw.m_pMMIO = (smtc_RegBaseAddress =
+                   smtc_VRAMBaseAddress + 0x00700000);
+               smtc_2DBaseAddress = (hw.m_pDPR =
+                   smtc_VRAMBaseAddress + 0x00408000);
+               smtc_2Ddataport = smtc_VRAMBaseAddress + DE_DATA_PORT_712;
+               hw.m_pVPR = hw.m_pLFB + 0x0040c000;
+#ifdef __BIG_ENDIAN
+               if (sfb->fb.var.bits_per_pixel == 32) {
+                       smtc_VRAMBaseAddress += 0x800000;
+                       hw.m_pLFB += 0x800000;
+                       printk(KERN_INFO
+                               "\nsmtc_VRAMBaseAddress=%p hw.m_pLFB=%p\n",
+                                       smtc_VRAMBaseAddress, hw.m_pLFB);
+               }
+#endif
+               if (!smtc_RegBaseAddress) {
+                       printk(KERN_INFO
+                               "%s: unable to map memory mapped IO\n",
+                               sfb->fb.fix.id);
+                       return -ENOMEM;
+               }
+
+               /* set MCLK = 14.31818 * (0x16 / 0x2) */
+               smtc_seqw(0x6a, 0x16);
+               smtc_seqw(0x6b, 0x02);
+               smtc_seqw(0x62, 0x3e);
+               /* enable PCI burst */
+               smtc_seqw(0x17, 0x20);
+               /* enable word swap */
+#ifdef __BIG_ENDIAN
+               if (sfb->fb.var.bits_per_pixel == 32)
+                       smtc_seqw(0x17, 0x30);
+#endif
+#ifdef CONFIG_FB_SM7XX_ACCEL
+               smtc_2Dacceleration = 1;
+#endif
+               break;
+       case 0x720:
+               sfb->fb.fix.mmio_start = pFramebufferPhysical;
+               sfb->fb.fix.mmio_len = 0x00200000;
+               smem_size = SM722_VIDEOMEMORYSIZE;
+               smtc_2DBaseAddress = (hw.m_pDPR =
+                   ioremap(pFramebufferPhysical, 0x00a00000));
+               hw.m_pLFB = (smtc_VRAMBaseAddress =
+                   smtc_2DBaseAddress + 0x00200000);
+               hw.m_pMMIO = (smtc_RegBaseAddress =
+                   smtc_2DBaseAddress + 0x000c0000);
+               smtc_2Ddataport = smtc_2DBaseAddress + DE_DATA_PORT_722;
+               hw.m_pVPR = smtc_2DBaseAddress + 0x800;
+
+               smtc_seqw(0x62, 0xff);
+               smtc_seqw(0x6a, 0x0d);
+               smtc_seqw(0x6b, 0x02);
+               smtc_2Dacceleration = 0;
+               break;
+       default:
+               printk(KERN_INFO
+               "No valid Silicon Motion display chip was detected!\n");
+
+               smtc_free_fb_info(sfb);
+               return err;
+       }
+
+       /* can support 32 bpp */
+       if (15 == sfb->fb.var.bits_per_pixel)
+               sfb->fb.var.bits_per_pixel = 16;
+
+       sfb->fb.var.xres_virtual = sfb->fb.var.xres;
+       sfb->fb.var.yres_virtual = sfb->fb.var.yres;
+       err = smtc_map_smem(sfb, pdev, smem_size);
+       if (err)
+               goto failed;
+
+       smtcfb_setmode(sfb);
+       /* Primary display starting from 0 postion */
+       hw.BaseAddressInVRAM = 0;
+       sfb->fb.par = &hw;
+
+       err = register_framebuffer(&sfb->fb);
+       if (err < 0)
+               goto failed;
+
+       printk(KERN_INFO "Silicon Motion SM%X Rev%X primary display mode"
+                       "%dx%d-%d Init Complete.\n", hw.chipID, hw.chipRevID,
+                       sfb->fb.var.xres, sfb->fb.var.yres,
+                       sfb->fb.var.bits_per_pixel);
+
+       return 0;
+
+ failed:
+       printk(KERN_INFO "Silicon Motion, Inc.  primary display init fail\n");
+
+       smtc_unmap_smem(sfb);
+       smtc_unmap_mmio(sfb);
+       smtc_free_fb_info(sfb);
+
+       return err;
+}
+
+
+/* Jason (08/11/2009) PCI_DRV wrapper essential structs */
+static struct pci_device_id smtcfb_pci_table[] = {
+       {0x126f, 0x710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x126f, 0x712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x126f, 0x720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0,}
+};
+
+
+/* Jason (08/14/2009)
+ * do some clean up when the driver module is removed
+ */
+static void __devexit smtcfb_pci_remove(struct pci_dev *pdev)
+{
+       struct smtcfb_info *sfb;
+
+       sfb = pci_get_drvdata(pdev);
+       pci_set_drvdata(pdev, NULL);
+       smtc_unmap_smem(sfb);
+       smtc_unmap_mmio(sfb);
+       unregister_framebuffer(&sfb->fb);
+       smtc_free_fb_info(sfb);
+}
+
+/* Jason (08/14/2009)
+ * suspend function, called when the suspend event is triggered
+ */
+static int __maybe_unused smtcfb_suspend(struct pci_dev *pdev, pm_message_t msg)
+{
+       struct smtcfb_info *sfb;
+       int retv;
+
+       sfb = pci_get_drvdata(pdev);
+
+       /* set the hw in sleep mode use externel clock and self memory refresh
+        * so that we can turn off internal PLLs later on
+        */
+       smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
+       smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
+
+       switch (msg.event) {
+       case PM_EVENT_FREEZE:
+       case PM_EVENT_PRETHAW:
+               pdev->dev.power.power_state = msg;
+               return 0;
+       }
+
+       /* when doing suspend, call fb apis and pci apis */
+       if (msg.event == PM_EVENT_SUSPEND) {
+               acquire_console_sem();
+               fb_set_suspend(&sfb->fb, 1);
+               release_console_sem();
+               retv = pci_save_state(pdev);
+               pci_disable_device(pdev);
+               retv = pci_choose_state(pdev, msg);
+               retv = pci_set_power_state(pdev, retv);
+       }
+
+       pdev->dev.power.power_state = msg;
+
+       /* additionaly turn off all function blocks including internal PLLs */
+       smtc_seqw(0x21, 0xff);
+
+       return 0;
+}
+
+static int __maybe_unused smtcfb_resume(struct pci_dev *pdev)
+{
+       struct smtcfb_info *sfb;
+       int retv;
+
+       sfb = pci_get_drvdata(pdev);
+
+       /* when resuming, restore pci data and fb cursor */
+       if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) {
+               retv = pci_set_power_state(pdev, PCI_D0);
+               retv = pci_restore_state(pdev);
+               if (pci_enable_device(pdev))
+                       return -1;
+               pci_set_master(pdev);
+       }
+
+       /* reinit hardware */
+       sm7xx_init_hw();
+       switch (hw.chipID) {
+       case 0x710:
+       case 0x712:
+               /* set MCLK = 14.31818 *  (0x16 / 0x2) */
+               smtc_seqw(0x6a, 0x16);
+               smtc_seqw(0x6b, 0x02);
+               smtc_seqw(0x62, 0x3e);
+               /* enable PCI burst */
+               smtc_seqw(0x17, 0x20);
+#ifdef __BIG_ENDIAN
+               if (sfb->fb.var.bits_per_pixel == 32)
+                       smtc_seqw(0x17, 0x30);
+#endif
+               break;
+       case 0x720:
+               smtc_seqw(0x62, 0xff);
+               smtc_seqw(0x6a, 0x0d);
+               smtc_seqw(0x6b, 0x02);
+               break;
+       }
+
+       smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
+       smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
+
+       smtcfb_setmode(sfb);
+
+       acquire_console_sem();
+       fb_set_suspend(&sfb->fb, 0);
+       release_console_sem();
+
+       return 0;
+}
+
+/* Jason (08/13/2009)
+ * pci_driver struct used to wrap the original driver
+ * so that it can be registered into the kernel and
+ * the proper method would be called when suspending and resuming
+ */
+static struct pci_driver smtcfb_driver = {
+       .name = "smtcfb",
+       .id_table = smtcfb_pci_table,
+       .probe = smtcfb_pci_probe,
+       .remove = __devexit_p(smtcfb_pci_remove),
+#ifdef CONFIG_PM
+       .suspend = smtcfb_suspend,
+       .resume = smtcfb_resume,
+#endif
+};
+
+static int __init smtcfb_init(void)
+{
+       return pci_register_driver(&smtcfb_driver);
+}
+
+static void __exit smtcfb_exit(void)
+{
+       pci_unregister_driver(&smtcfb_driver);
+}
+
+module_init(smtcfb_init);
+module_exit(smtcfb_exit);
+
+MODULE_AUTHOR("Siliconmotion ");
+MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/sm7xx/smtcfb.h b/drivers/staging/sm7xx/smtcfb.h
new file mode 100644 (file)
index 0000000..7f2c341
--- /dev/null
@@ -0,0 +1,793 @@
+/*
+ * Silicon Motion SM712 frame buffer device
+ *
+ * Copyright (C) 2006 Silicon Motion Technology Corp.
+ * Authors:    Ge Wang, gewang@siliconmotion.com
+ *             Boyod boyod.yang@siliconmotion.com.cn
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ *  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.
+ */
+
+#define SMTC_LINUX_FB_VERSION  "version 0.11.2619.21.01 July 27, 2008"
+
+#define NR_PALETTE        256
+#define NR_RGB            2
+
+#define FB_ACCEL_SMI_LYNX 88
+
+#ifdef __BIG_ENDIAN
+#define PC_VGA            0
+#else
+#define PC_VGA            1
+#endif
+
+#define SCREEN_X_RES      1024
+#define SCREEN_Y_RES      600
+#define SCREEN_BPP        16
+
+#ifndef FIELD_OFFSET
+#define FIELD_OFSFET(type, field) \
+       ((unsigned long) (PUCHAR) & (((type *)0)->field))
+#endif
+
+/*Assume SM712 graphics chip has 4MB VRAM */
+#define SM712_VIDEOMEMORYSIZE    0x00400000
+/*Assume SM722 graphics chip has 8MB VRAM */
+#define SM722_VIDEOMEMORYSIZE    0x00800000
+
+#define dac_reg        (0x3c8)
+#define dac_val        (0x3c9)
+
+extern char *smtc_RegBaseAddress;
+#define smtc_mmiowb(dat, reg)  writeb(dat, smtc_RegBaseAddress + reg)
+#define smtc_mmioww(dat, reg)  writew(dat, smtc_RegBaseAddress + reg)
+#define smtc_mmiowl(dat, reg)  writel(dat, smtc_RegBaseAddress + reg)
+
+#define smtc_mmiorb(reg)       readb(smtc_RegBaseAddress + reg)
+#define smtc_mmiorw(reg)       readw(smtc_RegBaseAddress + reg)
+#define smtc_mmiorl(reg)       readl(smtc_RegBaseAddress + reg)
+
+#define SIZE_SR00_SR04      (0x04 - 0x00 + 1)
+#define SIZE_SR10_SR24      (0x24 - 0x10 + 1)
+#define SIZE_SR30_SR75      (0x75 - 0x30 + 1)
+#define SIZE_SR80_SR93      (0x93 - 0x80 + 1)
+#define SIZE_SRA0_SRAF      (0xAF - 0xA0 + 1)
+#define SIZE_GR00_GR08      (0x08 - 0x00 + 1)
+#define SIZE_AR00_AR14      (0x14 - 0x00 + 1)
+#define SIZE_CR00_CR18      (0x18 - 0x00 + 1)
+#define SIZE_CR30_CR4D      (0x4D - 0x30 + 1)
+#define SIZE_CR90_CRA7      (0xA7 - 0x90 + 1)
+#define SIZE_VPR               (0x6C + 1)
+#define SIZE_DPR               (0x44 + 1)
+
+static inline void smtc_crtcw(int reg, int val)
+{
+       smtc_mmiowb(reg, 0x3d4);
+       smtc_mmiowb(val, 0x3d5);
+}
+
+static inline unsigned int smtc_crtcr(int reg)
+{
+       smtc_mmiowb(reg, 0x3d4);
+       return smtc_mmiorb(0x3d5);
+}
+
+static inline void smtc_grphw(int reg, int val)
+{
+       smtc_mmiowb(reg, 0x3ce);
+       smtc_mmiowb(val, 0x3cf);
+}
+
+static inline unsigned int smtc_grphr(int reg)
+{
+       smtc_mmiowb(reg, 0x3ce);
+       return smtc_mmiorb(0x3cf);
+}
+
+static inline void smtc_attrw(int reg, int val)
+{
+       smtc_mmiorb(0x3da);
+       smtc_mmiowb(reg, 0x3c0);
+       smtc_mmiorb(0x3c1);
+       smtc_mmiowb(val, 0x3c0);
+}
+
+static inline void smtc_seqw(int reg, int val)
+{
+       smtc_mmiowb(reg, 0x3c4);
+       smtc_mmiowb(val, 0x3c5);
+}
+
+static inline unsigned int smtc_seqr(int reg)
+{
+       smtc_mmiowb(reg, 0x3c4);
+       return smtc_mmiorb(0x3c5);
+}
+
+/* The next structure holds all information relevant for a specific video mode.
+ */
+
+struct ModeInit {
+       int mmSizeX;
+       int mmSizeY;
+       int bpp;
+       int hz;
+       unsigned char Init_MISC;
+       unsigned char Init_SR00_SR04[SIZE_SR00_SR04];
+       unsigned char Init_SR10_SR24[SIZE_SR10_SR24];
+       unsigned char Init_SR30_SR75[SIZE_SR30_SR75];
+       unsigned char Init_SR80_SR93[SIZE_SR80_SR93];
+       unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF];
+       unsigned char Init_GR00_GR08[SIZE_GR00_GR08];
+       unsigned char Init_AR00_AR14[SIZE_AR00_AR14];
+       unsigned char Init_CR00_CR18[SIZE_CR00_CR18];
+       unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D];
+       unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7];
+};
+
+/**********************************************************************
+                        SM712 Mode table.
+ **********************************************************************/
+struct ModeInit VGAMode[] = {
+       {
+        /*  mode#0: 640 x 480  16Bpp  60Hz */
+        640, 480, 16, 60,
+        /*  Init_MISC */
+        0xE3,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x00, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x30, 0x02, 0x01, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
+         0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
+         0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
+         0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
+         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
+         0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
+         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
+         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
+         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
+         0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+         0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
+         0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
+         0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
+         },
+        },
+       {
+        /*  mode#1: 640 x 480  24Bpp  60Hz */
+        640, 480, 24, 60,
+        /*  Init_MISC */
+        0xE3,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x00, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x30, 0x02, 0x01, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
+         0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
+         0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
+         0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
+         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
+         0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
+         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
+         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
+         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
+         0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+         0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
+         0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
+         0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
+         },
+        },
+       {
+        /*  mode#0: 640 x 480  32Bpp  60Hz */
+        640, 480, 32, 60,
+        /*  Init_MISC */
+        0xE3,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x00, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x30, 0x02, 0x01, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
+         0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
+         0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
+         0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
+         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
+         0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
+         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
+         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
+         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
+         0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+         0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
+         0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
+         0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
+         },
+        },
+
+       {                       /*  mode#2: 800 x 600  16Bpp  60Hz */
+        800, 600, 16, 60,
+        /*  Init_MISC */
+        0x2B,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x03, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+         0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x30, 0x02, 0x01, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
+         0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
+         0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
+         0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
+         0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
+         0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
+         0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
+         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
+         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
+         0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+         0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+         0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
+         0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
+         },
+        },
+       {                       /*  mode#3: 800 x 600  24Bpp  60Hz */
+        800, 600, 24, 60,
+        0x2B,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x03, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x30, 0x02, 0x01, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
+         0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
+         0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
+         0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
+         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
+         0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
+         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
+         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
+         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
+         0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+         0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+         0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
+         0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
+         },
+        },
+       {                       /*  mode#7: 800 x 600  32Bpp  60Hz */
+        800, 600, 32, 60,
+        /*  Init_MISC */
+        0x2B,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x03, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+         0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x30, 0x02, 0x01, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
+         0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
+         0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
+         0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
+         0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
+         0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
+         0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
+         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
+         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
+         0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+         0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+         0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
+         0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
+         },
+        },
+       /* We use 1024x768 table to light 1024x600 panel for lemote */
+       {                       /*  mode#4: 1024 x 600  16Bpp  60Hz  */
+        1024, 600, 16, 60,
+        /*  Init_MISC */
+        0xEB,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x00, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20,
+         0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x30, 0x02, 0x00, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22,
+         0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22,
+         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+         0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22,
+         0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02,
+         0x04, 0x45, 0x3F, 0x30, 0x40, 0x20,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
+         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+         0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+         0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00,
+         0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+         },
+        },
+       {                       /*  mode#5: 1024 x 768  24Bpp  60Hz */
+        1024, 768, 24, 60,
+        /*  Init_MISC */
+        0xEB,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x03, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
+         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x30, 0x02, 0x01, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
+         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
+         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
+         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
+         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
+         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+         0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+         0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
+         0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+         },
+        },
+       {                       /*  mode#4: 1024 x 768  32Bpp  60Hz */
+        1024, 768, 32, 60,
+        /*  Init_MISC */
+        0xEB,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x03, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
+         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x32, 0x02, 0x01, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
+         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
+         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
+         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
+         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
+         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+         0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+         0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
+         0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+         },
+        },
+       {                       /*  mode#6: 320 x 240  16Bpp  60Hz */
+        320, 240, 16, 60,
+        /*  Init_MISC */
+        0xEB,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x03, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
+         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x32, 0x02, 0x01, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
+         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
+         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
+         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
+         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
+         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+         0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+         0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
+         0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+         },
+        },
+
+       {                       /*  mode#8: 320 x 240  32Bpp  60Hz */
+        320, 240, 32, 60,
+        /*  Init_MISC */
+        0xEB,
+        {                      /*  Init_SR0_SR4 */
+         0x03, 0x01, 0x0F, 0x03, 0x0E,
+         },
+        {                      /*  Init_SR10_SR24 */
+         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
+         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0xC4, 0x32, 0x02, 0x01, 0x01,
+         },
+        {                      /*  Init_SR30_SR75 */
+         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
+         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
+         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
+         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
+         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+         0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
+         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
+         },
+        {                      /*  Init_SR80_SR93 */
+         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
+         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
+         0x00, 0x00, 0x00, 0x00,
+         },
+        {                      /*  Init_SRA0_SRAF */
+         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+         },
+        {                      /*  Init_GR00_GR08 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+         0xFF,
+         },
+        {                      /*  Init_AR00_AR14 */
+         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+         0x41, 0x00, 0x0F, 0x00, 0x00,
+         },
+        {                      /*  Init_CR00_CR18 */
+         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+         0xFF,
+         },
+        {                      /*  Init_CR30_CR4D */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+         0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+         0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
+         0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
+         },
+        {                      /*  Init_CR90_CRA7 */
+         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+         },
+        },
+};
+
+#define numVGAModes            (sizeof(VGAMode) / sizeof(struct ModeInit))
index 825bbc4..061e730 100644 (file)
@@ -1,6 +1,6 @@
 config VT6655
    tristate "VIA Technologies VT6655 support"
-   depends on PCI
+   depends on PCI && WLAN
    select WIRELESS_EXT
    select WEXT_PRIV
    ---help---
index 87bcd26..1055b52 100644 (file)
@@ -1,6 +1,6 @@
 config VT6656
        tristate "VIA Technologies VT6656 support"
-       depends on USB
+       depends on USB && WLAN
        select WIRELESS_EXT
        select WEXT_PRIV
        ---help---
index 7d76a7f..aaa70ed 100644 (file)
@@ -439,7 +439,7 @@ void free_chunks(imgchunk_t *fchunk, unsigned int *nfchunks)
                }
        }
        *nfchunks = 0;
-       memset(fchunk, 0, sizeof(fchunk));
+       memset(fchunk, 0, sizeof(*fchunk));
 
 }
 
index 473aa1a..be3c9b8 100644 (file)
@@ -44,5 +44,3 @@ obj-y                         += early/
 
 obj-$(CONFIG_USB_ATM)          += atm/
 obj-$(CONFIG_USB_SPEEDTOUCH)   += atm/
-
-obj-$(CONFIG_USB_ULPI)         += otg/
index 6dac3b8..0495fa6 100644 (file)
@@ -1597,7 +1597,9 @@ rescan:
 }
 
 /**
- * Check whether a new bandwidth setting exceeds the bus bandwidth.
+ * usb_hcd_alloc_bandwidth - check whether a new bandwidth setting exceeds
+ *                             the bus bandwidth
+ * @udev: target &usb_device
  * @new_config: new configuration to install
  * @cur_alt: the current alternate interface setting
  * @new_alt: alternate interface setting that is being installed
index 06af970..0cec6ca 100644 (file)
@@ -1658,12 +1658,12 @@ static inline void announce_device(struct usb_device *udev) { }
 #endif
 
 /**
- * usb_configure_device_otg - FIXME (usbcore-internal)
+ * usb_enumerate_device_otg - FIXME (usbcore-internal)
  * @udev: newly addressed device (in ADDRESS state)
  *
- * Do configuration for On-The-Go devices
+ * Finish enumeration for On-The-Go devices
  */
-static int usb_configure_device_otg(struct usb_device *udev)
+static int usb_enumerate_device_otg(struct usb_device *udev)
 {
        int err = 0;
 
@@ -1734,7 +1734,7 @@ fail:
 
 
 /**
- * usb_configure_device - Detect and probe device intfs/otg (usbcore-internal)
+ * usb_enumerate_device - Read device configs/intfs/otg (usbcore-internal)
  * @udev: newly addressed device (in ADDRESS state)
  *
  * This is only called by usb_new_device() and usb_authorize_device()
@@ -1745,7 +1745,7 @@ fail:
  * the string descriptors, as they will be errored out by the device
  * until it has been authorized.
  */
-static int usb_configure_device(struct usb_device *udev)
+static int usb_enumerate_device(struct usb_device *udev)
 {
        int err;
 
@@ -1769,7 +1769,7 @@ static int usb_configure_device(struct usb_device *udev)
                                                      udev->descriptor.iManufacturer);
                udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
        }
-       err = usb_configure_device_otg(udev);
+       err = usb_enumerate_device_otg(udev);
 fail:
        return err;
 }
@@ -1779,8 +1779,8 @@ fail:
  * usb_new_device - perform initial device setup (usbcore-internal)
  * @udev: newly addressed device (in ADDRESS state)
  *
- * This is called with devices which have been enumerated, but not yet
- * configured.  The device descriptor is available, but not descriptors
+ * This is called with devices which have been detected but not fully
+ * enumerated.  The device descriptor is available, but not descriptors
  * for any device configuration.  The caller must have locked either
  * the parent hub (if udev is a normal device) or else the
  * usb_bus_list_lock (if udev is a root hub).  The parent's pointer to
@@ -1803,8 +1803,8 @@ int usb_new_device(struct usb_device *udev)
        if (udev->parent)
                usb_autoresume_device(udev->parent);
 
-       usb_detect_quirks(udev);                /* Determine quirks */
-       err = usb_configure_device(udev);       /* detect & probe dev/intfs */
+       usb_detect_quirks(udev);
+       err = usb_enumerate_device(udev);       /* Read descriptors */
        if (err < 0)
                goto fail;
        dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n",
@@ -1849,21 +1849,23 @@ fail:
  */
 int usb_deauthorize_device(struct usb_device *usb_dev)
 {
-       unsigned cnt;
        usb_lock_device(usb_dev);
        if (usb_dev->authorized == 0)
                goto out_unauthorized;
+
        usb_dev->authorized = 0;
        usb_set_configuration(usb_dev, -1);
+
+       kfree(usb_dev->product);
        usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
+       kfree(usb_dev->manufacturer);
        usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
+       kfree(usb_dev->serial);
        usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
-       kfree(usb_dev->config);
-       usb_dev->config = NULL;
-       for (cnt = 0; cnt < usb_dev->descriptor.bNumConfigurations; cnt++)
-               kfree(usb_dev->rawdescriptors[cnt]);
+
+       usb_destroy_configuration(usb_dev);
        usb_dev->descriptor.bNumConfigurations = 0;
-       kfree(usb_dev->rawdescriptors);
+
 out_unauthorized:
        usb_unlock_device(usb_dev);
        return 0;
@@ -1873,15 +1875,11 @@ out_unauthorized:
 int usb_authorize_device(struct usb_device *usb_dev)
 {
        int result = 0, c;
+
        usb_lock_device(usb_dev);
        if (usb_dev->authorized == 1)
                goto out_authorized;
-       kfree(usb_dev->product);
-       usb_dev->product = NULL;
-       kfree(usb_dev->manufacturer);
-       usb_dev->manufacturer = NULL;
-       kfree(usb_dev->serial);
-       usb_dev->serial = NULL;
+
        result = usb_autoresume_device(usb_dev);
        if (result < 0) {
                dev_err(&usb_dev->dev,
@@ -1894,10 +1892,18 @@ int usb_authorize_device(struct usb_device *usb_dev)
                        "authorization: %d\n", result);
                goto error_device_descriptor;
        }
+
+       kfree(usb_dev->product);
+       usb_dev->product = NULL;
+       kfree(usb_dev->manufacturer);
+       usb_dev->manufacturer = NULL;
+       kfree(usb_dev->serial);
+       usb_dev->serial = NULL;
+
        usb_dev->authorized = 1;
-       result = usb_configure_device(usb_dev);
+       result = usb_enumerate_device(usb_dev);
        if (result < 0)
-               goto error_configure;
+               goto error_enumerate;
        /* Choose and set the configuration.  This registers the interfaces
         * with the driver core and lets interface drivers bind to them.
         */
@@ -1912,8 +1918,10 @@ int usb_authorize_device(struct usb_device *usb_dev)
                }
        }
        dev_info(&usb_dev->dev, "authorized to connect\n");
-error_configure:
+
+error_enumerate:
 error_device_descriptor:
+       usb_autosuspend_device(usb_dev);
 error_autoresume:
 out_authorized:
        usb_unlock_device(usb_dev);     // complements locktree
index 1547700..485edf9 100644 (file)
@@ -82,9 +82,13 @@ static ssize_t  show_##name(struct device *dev,                              \
                struct device_attribute *attr, char *buf)               \
 {                                                                      \
        struct usb_device *udev;                                        \
+       int retval;                                                     \
                                                                        \
        udev = to_usb_device(dev);                                      \
-       return sprintf(buf, "%s\n", udev->name);                        \
+       usb_lock_device(udev);                                          \
+       retval = sprintf(buf, "%s\n", udev->name);                      \
+       usb_unlock_device(udev);                                        \
+       return retval;                                                  \
 }                                                                      \
 static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
 
index 2fb4204..0daff0d 100644 (file)
@@ -66,9 +66,9 @@ MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
 /**
  * usb_find_alt_setting() - Given a configuration, find the alternate setting
  * for the given interface.
- * @config - the configuration to search (not necessarily the current config).
- * @iface_num - interface number to search in
- * @alt_num - alternate interface setting number to search for.
+ * @config: the configuration to search (not necessarily the current config).
+ * @iface_num: interface number to search in
+ * @alt_num: alternate interface setting number to search for.
  *
  * Search the configuration's interface cache for the given alt setting.
  */
index 1206a26..2958a12 100644 (file)
@@ -613,7 +613,7 @@ err:
 }
 EXPORT_SYMBOL_GPL(dbgp_external_startup);
 
-static int __init ehci_reset_port(int port)
+static int ehci_reset_port(int port)
 {
        u32 portsc;
        u32 delay_time, delay;
index 58f2203..a62af7b 100644 (file)
@@ -158,6 +158,7 @@ fail:
 
 static int __exit audio_unbind(struct usb_composite_dev *cdev)
 {
+       gaudio_cleanup();
        return 0;
 }
 
index c43c89f..df77f61 100644 (file)
@@ -56,13 +56,16 @@ static struct usb_interface_descriptor ac_interface_desc __initdata = {
 DECLARE_UAC_AC_HEADER_DESCRIPTOR(2);
 
 #define UAC_DT_AC_HEADER_LENGTH        UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)
+/* 1 input terminal, 1 output terminal and 1 feature unit */
+#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \
+       + UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0))
 /* B.3.2  Class-Specific AC Interface Descriptor */
 static struct uac_ac_header_descriptor_2 ac_header_desc = {
        .bLength =              UAC_DT_AC_HEADER_LENGTH,
        .bDescriptorType =      USB_DT_CS_INTERFACE,
        .bDescriptorSubtype =   UAC_HEADER,
        .bcdADC =               __constant_cpu_to_le16(0x0100),
-       .wTotalLength =         __constant_cpu_to_le16(UAC_DT_AC_HEADER_LENGTH),
+       .wTotalLength =         __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH),
        .bInCollection =        F_AUDIO_NUM_INTERFACES,
        .baInterfaceNr = {
                [0] =           F_AUDIO_AC_INTERFACE,
@@ -252,12 +255,12 @@ static struct f_audio_buf *f_audio_buffer_alloc(int buf_size)
 
        copy_buf = kzalloc(sizeof *copy_buf, GFP_ATOMIC);
        if (!copy_buf)
-               return (struct f_audio_buf *)-ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        copy_buf->buf = kzalloc(buf_size, GFP_ATOMIC);
        if (!copy_buf->buf) {
                kfree(copy_buf);
-               return (struct f_audio_buf *)-ENOMEM;
+               return ERR_PTR(-ENOMEM);
        }
 
        return copy_buf;
@@ -332,7 +335,7 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
                list_add_tail(&copy_buf->list, &audio->play_queue);
                schedule_work(&audio->playback_work);
                copy_buf = f_audio_buffer_alloc(audio_buf_size);
-               if (copy_buf < 0)
+               if (IS_ERR(copy_buf))
                        return -ENOMEM;
        }
 
@@ -576,6 +579,8 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                        usb_ep_enable(out_ep, audio->out_desc);
                        out_ep->driver_data = audio;
                        audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
+                       if (IS_ERR(audio->copy_buf))
+                               return -ENOMEM;
 
                        /*
                         * allocate a bunch of read buffers
@@ -787,7 +792,7 @@ int __init audio_bind_config(struct usb_configuration *c)
        return status;
 
 add_fail:
-       gaudio_cleanup(&audio->card);
+       gaudio_cleanup();
 setup_fail:
        kfree(audio);
        return status;
index 8252595..35e0930 100644 (file)
@@ -288,6 +288,7 @@ static int gaudio_close_snd_dev(struct gaudio *gau)
        return 0;
 }
 
+static struct gaudio *the_card;
 /**
  * gaudio_setup - setup ALSA interface and preparing for USB transfer
  *
@@ -303,6 +304,9 @@ int __init gaudio_setup(struct gaudio *card)
        if (ret)
                ERROR(card, "we need at least one control device\n");
 
+       if (!the_card)
+               the_card = card;
+
        return ret;
 
 }
@@ -312,9 +316,11 @@ int __init gaudio_setup(struct gaudio *card)
  *
  * This is called to free all resources allocated by @gaudio_setup().
  */
-void gaudio_cleanup(struct gaudio *card)
+void gaudio_cleanup(void)
 {
-       if (card)
-               gaudio_close_snd_dev(card);
+       if (the_card) {
+               gaudio_close_snd_dev(the_card);
+               the_card = NULL;
+       }
 }
 
index cc8d159..08ffce3 100644 (file)
@@ -51,6 +51,6 @@ struct gaudio {
 };
 
 int gaudio_setup(struct gaudio *card);
-void gaudio_cleanup(struct gaudio *card);
+void gaudio_cleanup(void);
 
 #endif /* __U_AUDIO_H */
index 00a2985..ff43747 100644 (file)
@@ -37,7 +37,7 @@ static void recycle_frame(struct fhci_usb *usb, struct packet *pkt)
        pkt->info = 0;
        pkt->priv_data = NULL;
 
-       cq_put(usb->ep0->empty_frame_Q, pkt);
+       cq_put(&usb->ep0->empty_frame_Q, pkt);
 }
 
 /* confirm submitted packet */
@@ -57,7 +57,7 @@ void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt)
                if ((td->data + td->actual_len) && trans_len)
                        memcpy(td->data + td->actual_len, pkt->data,
                               trans_len);
-               cq_put(usb->ep0->dummy_packets_Q, pkt->data);
+               cq_put(&usb->ep0->dummy_packets_Q, pkt->data);
        }
 
        recycle_frame(usb, pkt);
@@ -213,7 +213,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td)
        }
 
        /* update frame object fields before transmitting */
-       pkt = cq_get(usb->ep0->empty_frame_Q);
+       pkt = cq_get(&usb->ep0->empty_frame_Q);
        if (!pkt) {
                fhci_dbg(usb->fhci, "there is no empty frame\n");
                return -1;
@@ -222,7 +222,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td)
 
        pkt->info = 0;
        if (data == NULL) {
-               data = cq_get(usb->ep0->dummy_packets_Q);
+               data = cq_get(&usb->ep0->dummy_packets_Q);
                BUG_ON(!data);
                pkt->info = PKT_DUMMY_PACKET;
        }
@@ -246,7 +246,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td)
                list_del_init(&td->frame_lh);
                td->status = USB_TD_OK;
                if (pkt->info & PKT_DUMMY_PACKET)
-                       cq_put(usb->ep0->dummy_packets_Q, pkt->data);
+                       cq_put(&usb->ep0->dummy_packets_Q, pkt->data);
                recycle_frame(usb, pkt);
                usb->actual_frame->total_bytes -= (len + PROTOCOL_OVERHEAD);
                fhci_err(usb->fhci, "host transaction failed\n");
index b403322..d224ab4 100644 (file)
@@ -106,33 +106,33 @@ void fhci_ep0_free(struct fhci_usb *usb)
                        cpm_muram_free(cpm_muram_offset(ep->td_base));
 
                if (ep->conf_frame_Q) {
-                       size = cq_howmany(ep->conf_frame_Q);
+                       size = cq_howmany(&ep->conf_frame_Q);
                        for (; size; size--) {
-                               struct packet *pkt = cq_get(ep->conf_frame_Q);
+                               struct packet *pkt = cq_get(&ep->conf_frame_Q);
 
                                kfree(pkt);
                        }
-                       cq_delete(ep->conf_frame_Q);
+                       cq_delete(&ep->conf_frame_Q);
                }
 
                if (ep->empty_frame_Q) {
-                       size = cq_howmany(ep->empty_frame_Q);
+                       size = cq_howmany(&ep->empty_frame_Q);
                        for (; size; size--) {
-                               struct packet *pkt = cq_get(ep->empty_frame_Q);
+                               struct packet *pkt = cq_get(&ep->empty_frame_Q);
 
                                kfree(pkt);
                        }
-                       cq_delete(ep->empty_frame_Q);
+                       cq_delete(&ep->empty_frame_Q);
                }
 
                if (ep->dummy_packets_Q) {
-                       size = cq_howmany(ep->dummy_packets_Q);
+                       size = cq_howmany(&ep->dummy_packets_Q);
                        for (; size; size--) {
-                               u8 *buff = cq_get(ep->dummy_packets_Q);
+                               u8 *buff = cq_get(&ep->dummy_packets_Q);
 
                                kfree(buff);
                        }
-                       cq_delete(ep->dummy_packets_Q);
+                       cq_delete(&ep->dummy_packets_Q);
                }
 
                kfree(ep);
@@ -175,10 +175,9 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem,
        ep->td_base = cpm_muram_addr(ep_offset);
 
        /* zero all queue pointers */
-       ep->conf_frame_Q = cq_new(ring_len + 2);
-       ep->empty_frame_Q = cq_new(ring_len + 2);
-       ep->dummy_packets_Q = cq_new(ring_len + 2);
-       if (!ep->conf_frame_Q || !ep->empty_frame_Q || !ep->dummy_packets_Q) {
+       if (cq_new(&ep->conf_frame_Q, ring_len + 2) ||
+           cq_new(&ep->empty_frame_Q, ring_len + 2) ||
+           cq_new(&ep->dummy_packets_Q, ring_len + 2)) {
                err_for = "frame_queues";
                goto err;
        }
@@ -199,8 +198,8 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem,
                        err_for = "buffer";
                        goto err;
                }
-               cq_put(ep->empty_frame_Q, pkt);
-               cq_put(ep->dummy_packets_Q, buff);
+               cq_put(&ep->empty_frame_Q, pkt);
+               cq_put(&ep->dummy_packets_Q, buff);
        }
 
        /* we put the endpoint parameter RAM right behind the TD ring */
@@ -319,7 +318,7 @@ static void fhci_td_transaction_confirm(struct fhci_usb *usb)
                if ((buf == DUMMY2_BD_BUFFER) && !(td_status & ~TD_W))
                        continue;
 
-               pkt = cq_get(ep->conf_frame_Q);
+               pkt = cq_get(&ep->conf_frame_Q);
                if (!pkt)
                        fhci_err(usb->fhci, "no frame to confirm\n");
 
@@ -460,9 +459,9 @@ u32 fhci_host_transaction(struct fhci_usb *usb,
                out_be16(&td->length, pkt->len);
 
        /* put the frame to the confirmation queue */
-       cq_put(ep->conf_frame_Q, pkt);
+       cq_put(&ep->conf_frame_Q, pkt);
 
-       if (cq_howmany(ep->conf_frame_Q) == 1)
+       if (cq_howmany(&ep->conf_frame_Q) == 1)
                out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO);
 
        return 0;
index 7116284..72dae1c 100644 (file)
@@ -423,9 +423,9 @@ struct endpoint {
        struct usb_td __iomem *td_base; /* first TD in the ring */
        struct usb_td __iomem *conf_td; /* next TD for confirm after transac */
        struct usb_td __iomem *empty_td;/* next TD for new transaction req. */
-       struct kfifo *empty_frame_Q;  /* Empty frames list to use */
-       struct kfifo *conf_frame_Q;   /* frames passed to TDs,waiting for tx */
-       struct kfifo *dummy_packets_Q;/* dummy packets for the CRC overun */
+       struct kfifo empty_frame_Q;  /* Empty frames list to use */
+       struct kfifo conf_frame_Q;   /* frames passed to TDs,waiting for tx */
+       struct kfifo dummy_packets_Q;/* dummy packets for the CRC overun */
 
        bool already_pushed_dummy_bd;
 };
@@ -493,9 +493,9 @@ static inline struct usb_hcd *fhci_to_hcd(struct fhci_hcd *fhci)
 }
 
 /* fifo of pointers */
-static inline struct kfifo *cq_new(int size)
+static inline int cq_new(struct kfifo *fifo, int size)
 {
-       return kfifo_alloc(size * sizeof(void *), GFP_KERNEL, NULL);
+       return kfifo_alloc(fifo, size * sizeof(void *), GFP_KERNEL);
 }
 
 static inline void cq_delete(struct kfifo *kfifo)
@@ -505,19 +505,19 @@ static inline void cq_delete(struct kfifo *kfifo)
 
 static inline unsigned int cq_howmany(struct kfifo *kfifo)
 {
-       return __kfifo_len(kfifo) / sizeof(void *);
+       return kfifo_len(kfifo) / sizeof(void *);
 }
 
 static inline int cq_put(struct kfifo *kfifo, void *p)
 {
-       return __kfifo_put(kfifo, (void *)&p, sizeof(p));
+       return kfifo_in(kfifo, (void *)&p, sizeof(p));
 }
 
 static inline void *cq_get(struct kfifo *kfifo)
 {
        void *p = NULL;
 
-       __kfifo_get(kfifo, (void *)&p, sizeof(p));
+       kfifo_out(kfifo, (void *)&p, sizeof(p));
        return p;
 }
 
index 1d8e39a..1eb9e41 100644 (file)
@@ -60,6 +60,7 @@
 static struct usb_device_id appledisplay_table [] = {
        { APPLEDISPLAY_DEVICE(0x9218) },
        { APPLEDISPLAY_DEVICE(0x9219) },
+       { APPLEDISPLAY_DEVICE(0x921c) },
        { APPLEDISPLAY_DEVICE(0x921d) },
 
        /* Terminating entry */
@@ -72,8 +73,8 @@ struct appledisplay {
        struct usb_device *udev;        /* usb device */
        struct urb *urb;                /* usb request block */
        struct backlight_device *bd;    /* backlight device */
-       char *urbdata;                  /* interrupt URB data buffer */
-       char *msgdata;                  /* control message data buffer */
+       u8 *urbdata;                    /* interrupt URB data buffer */
+       u8 *msgdata;                    /* control message data buffer */
 
        struct delayed_work work;
        int button_pressed;
index 602ee05..59860b3 100644 (file)
@@ -167,7 +167,7 @@ static int emi62_load_firmware (struct usb_device *dev)
                        err("%s - error loading firmware: error = %d", __func__, err);
                        goto wraperr;
                }
-       } while (i > 0);
+       } while (rec);
 
        /* Assert reset (stop the CPU in the EMI) */
        err = emi62_set_reset(dev,1);
index fe4934d..ad26e65 100644 (file)
@@ -29,6 +29,8 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
 {
        void __iomem *fifo = hw_ep->fifo;
        void __iomem *epio = hw_ep->regs;
+       u8 epnum = hw_ep->epnum;
+       u16 dma_reg = 0;
 
        prefetch((u8 *)src);
 
@@ -39,67 +41,113 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
 
        dump_fifo_data(src, len);
 
-       if (unlikely((unsigned long)src & 0x01))
-               outsw_8((unsigned long)fifo, src,
-                       len & 0x01 ? (len >> 1) + 1 : len >> 1);
-       else
-               outsw((unsigned long)fifo, src,
-                       len & 0x01 ? (len >> 1) + 1 : len >> 1);
-}
+       if (!ANOMALY_05000380 && epnum != 0) {
+               flush_dcache_range((unsigned int)src,
+                       (unsigned int)(src + len));
+
+               /* Setup DMA address register */
+               dma_reg = (u16) ((u32) src & 0xFFFF);
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg);
+               SSYNC();
+
+               dma_reg = (u16) (((u32) src >> 16) & 0xFFFF);
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg);
+               SSYNC();
+
+               /* Setup DMA count register */
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len);
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0);
+               SSYNC();
+
+               /* Enable the DMA */
+               dma_reg = (epnum << 4) | DMA_ENA | INT_ENA | DIRECTION;
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg);
+               SSYNC();
+
+               /* Wait for compelete */
+               while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum)))
+                       cpu_relax();
+
+               /* acknowledge dma interrupt */
+               bfin_write_USB_DMA_INTERRUPT(1 << epnum);
+               SSYNC();
+
+               /* Reset DMA */
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0);
+               SSYNC();
+       } else {
+               SSYNC();
+
+               if (unlikely((unsigned long)src & 0x01))
+                       outsw_8((unsigned long)fifo, src,
+                               len & 0x01 ? (len >> 1) + 1 : len >> 1);
+               else
+                       outsw((unsigned long)fifo, src,
+                               len & 0x01 ? (len >> 1) + 1 : len >> 1);
 
+       }
+}
 /*
  * Unload an endpoint's FIFO
  */
 void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
 {
        void __iomem *fifo = hw_ep->fifo;
-
-#ifdef CONFIG_BF52x
        u8 epnum = hw_ep->epnum;
        u16 dma_reg = 0;
 
-       invalidate_dcache_range((unsigned int)dst,
-               (unsigned int)(dst + len));
+       if (ANOMALY_05000467 && epnum != 0) {
 
-       /* Setup DMA address register */
-       dma_reg = (u16) ((u32) dst & 0xFFFF);
-       bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg);
-       SSYNC();
+               invalidate_dcache_range((unsigned int)dst,
+                       (unsigned int)(dst + len));
 
-       dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF);
-       bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg);
-       SSYNC();
+               /* Setup DMA address register */
+               dma_reg = (u16) ((u32) dst & 0xFFFF);
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg);
+               SSYNC();
 
-       /* Setup DMA count register */
-       bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len);
-       bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0);
-       SSYNC();
+               dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF);
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg);
+               SSYNC();
 
-       /* Enable the DMA */
-       dma_reg = (epnum << 4) | DMA_ENA | INT_ENA;
-       bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg);
-       SSYNC();
+               /* Setup DMA count register */
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len);
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0);
+               SSYNC();
 
-       /* Wait for compelete */
-       while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum)))
-               cpu_relax();
+               /* Enable the DMA */
+               dma_reg = (epnum << 4) | DMA_ENA | INT_ENA;
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg);
+               SSYNC();
 
-       /* acknowledge dma interrupt */
-       bfin_write_USB_DMA_INTERRUPT(1 << epnum);
-       SSYNC();
+               /* Wait for compelete */
+               while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum)))
+                       cpu_relax();
 
-       /* Reset DMA */
-       bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0);
-       SSYNC();
-#else
-       if (unlikely((unsigned long)dst & 0x01))
-               insw_8((unsigned long)fifo, dst,
-                       len & 0x01 ? (len >> 1) + 1 : len >> 1);
-       else
-               insw((unsigned long)fifo, dst,
-                       len & 0x01 ? (len >> 1) + 1 : len >> 1);
-#endif
+               /* acknowledge dma interrupt */
+               bfin_write_USB_DMA_INTERRUPT(1 << epnum);
+               SSYNC();
 
+               /* Reset DMA */
+               bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0);
+               SSYNC();
+       } else {
+               SSYNC();
+               /* Read the last byte of packet with odd size from address fifo + 4
+                * to trigger 1 byte access to EP0 FIFO.
+                */
+               if (len == 1)
+                       *dst = (u8)inw((unsigned long)fifo + 4);
+               else {
+                       if (unlikely((unsigned long)dst & 0x01))
+                               insw_8((unsigned long)fifo, dst, len >> 1);
+                       else
+                               insw((unsigned long)fifo, dst, len >> 1);
+
+                       if (len & 0x01)
+                               *(dst + len - 1) = (u8)inw((unsigned long)fifo + 4);
+               }
+       }
        DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
                        'R', hw_ep->epnum, fifo, len, dst);
 
index 10b7d75..bd9352a 100644 (file)
@@ -69,7 +69,6 @@ static void dump_fifo_data(u8 *buf, u16 len)
 #define dump_fifo_data(buf, len)       do {} while (0)
 #endif
 
-#ifdef CONFIG_BF52x
 
 #define USB_DMA_BASE           USB_DMA_INTERRUPT
 #define USB_DMAx_CTRL          0x04
@@ -79,7 +78,6 @@ static void dump_fifo_data(u8 *buf, u16 len)
 #define USB_DMAx_COUNT_HIGH    0x14
 
 #define USB_DMA_REG(ep, reg)   (USB_DMA_BASE + 0x20 * ep + reg)
-#endif
 
 /* Almost 1 second */
 #define TIMER_DELAY    (1 * HZ)
index ef2332a..a44a450 100644 (file)
@@ -1154,8 +1154,11 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
        struct musb_hw_ep       *hw_ep = NULL;
        u32                     rx, tx;
        int                     i, index;
+       unsigned long           flags;
 
        cppi = container_of(musb->dma_controller, struct cppi, controller);
+       if (cppi->irq)
+               spin_lock_irqsave(&musb->lock, flags);
 
        tibase = musb->ctrl_base;
 
@@ -1285,6 +1288,9 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
        /* write to CPPI EOI register to re-enable interrupts */
        musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0);
 
+       if (cppi->irq)
+               spin_unlock_irqrestore(&musb->lock, flags);
+
        return IRQ_HANDLED;
 }
 
index e16ff60..6691381 100644 (file)
@@ -42,7 +42,7 @@
 #include "musb_core.h"
 
 #ifdef CONFIG_MACH_DAVINCI_EVM
-#define GPIO_nVBUS_DRV         144
+#define GPIO_nVBUS_DRV         160
 #endif
 
 #include "davinci.h"
index bfe08f4..5eb9318 100644 (file)
@@ -1319,7 +1319,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
 #endif
        u8 reg;
        char *type;
-       char aInfo[78], aRevision[32], aDate[12];
+       char aInfo[90], aRevision[32], aDate[12];
        void __iomem    *mbase = musb->mregs;
        int             status = 0;
        int             i;
@@ -1521,6 +1521,14 @@ irqreturn_t musb_interrupt(struct musb *musb)
                (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
                musb->int_usb, musb->int_tx, musb->int_rx);
 
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+       if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
+               if (!musb->gadget_driver) {
+                       DBG(5, "No gadget driver loaded\n");
+                       return IRQ_HANDLED;
+               }
+#endif
+
        /* the core can interrupt us for multiple reasons; docs have
         * a generic interrupt flowchart to follow
         */
@@ -2139,7 +2147,7 @@ static int __init musb_probe(struct platform_device *pdev)
        return musb_init_controller(dev, irq, base);
 }
 
-static int __devexit musb_remove(struct platform_device *pdev)
+static int __exit musb_remove(struct platform_device *pdev)
 {
        struct musb     *musb = dev_to_musb(&pdev->dev);
        void __iomem    *ctrl_base = musb->ctrl_base;
@@ -2231,7 +2239,7 @@ static struct platform_driver musb_driver = {
                .owner          = THIS_MODULE,
                .pm             = MUSB_DEV_PM_OPS,
        },
-       .remove         = __devexit_p(musb_remove),
+       .remove         = __exit_p(musb_remove),
        .shutdown       = musb_shutdown,
 };
 
index c49b9ba..cbcf14a 100644 (file)
@@ -309,7 +309,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
                        size_t request_size;
 
                        /* setup DMA, then program endpoint CSR */
-                       request_size = min(request->length,
+                       request_size = min_t(size_t, request->length,
                                                musb_ep->dma->max_len);
                        if (request_size < musb_ep->packet_sz)
                                musb_ep->dma->desired_mode = 0;
@@ -319,7 +319,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
                        use_dma = use_dma && c->channel_program(
                                        musb_ep->dma, musb_ep->packet_sz,
                                        musb_ep->dma->desired_mode,
-                                       request->dma, request_size);
+                                       request->dma + request->actual, request_size);
                        if (use_dma) {
                                if (musb_ep->dma->desired_mode == 0) {
                                        /*
@@ -515,12 +515,12 @@ void musb_g_tx(struct musb *musb, u8 epnum)
                        if (csr & MUSB_TXCSR_FIFONOTEMPTY)
                                return;
 
-                       if (!musb_ep->desc) {
+                       request = musb_ep->desc ? next_request(musb_ep) : NULL;
+                       if (!request) {
                                DBG(4, "%s idle now\n",
                                        musb_ep->end_point.name);
                                return;
-                       } else
-                               request = next_request(musb_ep);
+                       }
                }
 
                txstate(musb, to_musb_request(request));
@@ -746,6 +746,8 @@ void musb_g_rx(struct musb *musb, u8 epnum)
        musb_ep_select(mbase, epnum);
 
        request = next_request(musb_ep);
+       if (!request)
+               return;
 
        csr = musb_readw(epio, MUSB_RXCSR);
        dma = is_dma_capable() ? musb_ep->dma : NULL;
@@ -1731,6 +1733,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
                spin_lock_irqsave(&musb->lock, flags);
 
                otg_set_peripheral(musb->xceiv, &musb->g);
+               musb->xceiv->state = OTG_STATE_B_IDLE;
                musb->is_active = 1;
 
                /* FIXME this ignores the softconnect flag.  Drivers are
index 8fba3f1..53d0645 100644 (file)
@@ -664,7 +664,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
                        musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
                        break;
                default:
-                       ERR("SetupEnd came in a wrong ep0stage %s",
+                       ERR("SetupEnd came in a wrong ep0stage %s\n",
                            decode_ep0stage(musb->ep0_state));
                }
                csr = musb_readw(regs, MUSB_CSR0);
@@ -787,12 +787,18 @@ setup:
                                handled = service_zero_data_request(
                                                musb, &setup);
 
+                               /*
+                                * We're expecting no data in any case, so
+                                * always set the DATAEND bit -- doing this
+                                * here helps avoid SetupEnd interrupt coming
+                                * in the idle stage when we're stalling...
+                                */
+                               musb->ackpend |= MUSB_CSR0_P_DATAEND;
+
                                /* status stage might be immediate */
-                               if (handled > 0) {
-                                       musb->ackpend |= MUSB_CSR0_P_DATAEND;
+                               if (handled > 0)
                                        musb->ep0_state =
                                                MUSB_EP0_STAGE_STATUSIN;
-                               }
                                break;
 
                        /* sequence #1 (IN to host), includes GET_STATUS
index d54460a..78a2097 100644 (file)
@@ -843,7 +843,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
 
 static struct platform_device *otg_dev;
 
-static int otg_init(struct isp1301 *isp)
+static int isp1301_otg_init(struct isp1301 *isp)
 {
        u32 l;
 
@@ -1275,7 +1275,7 @@ static int __exit isp1301_remove(struct i2c_client *i2c)
 static int isp1301_otg_enable(struct isp1301 *isp)
 {
        power_up(isp);
-       otg_init(isp);
+       isp1301_otg_init(isp);
 
        /* NOTE:  since we don't change this, this provides
         * a few more interrupts than are strictly needed.
index f99498f..216f187 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/serial.h>
 #include <linux/usb/serial.h>
 #include "ftdi_sio.h"
+#include "ftdi_sio_ids.h"
 
 /*
  * Version Information
index 4586a24..b0e0d64 100644 (file)
@@ -1,7 +1,10 @@
 /*
- * Definitions for the FTDI USB Single Port Serial Converter -
+ * Driver definitions for the FTDI USB Single Port Serial Converter -
  * known as FTDI_SIO (Serial Input/Output application of the chipset)
  *
+ * For USB vendor/product IDs (VID/PID), please see ftdi_sio_ids.h
+ *
+ *
  * The example I have is known as the USC-1000 which is available from
  * http://www.dse.co.nz - cat no XH4214 It looks similar to this:
  * http://www.dansdata.com/usbser.htm but I can't be sure There are other
  * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the
  * FTDI_SIO implementation.
  *
- * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
- * from Rudolf Gugler
- *
- */
-
-#define FTDI_VID       0x0403  /* Vendor Id */
-#define FTDI_SIO_PID   0x8372  /* Product Id SIO application of 8U100AX  */
-#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
-#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
-#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
-#define FTDI_232RL_PID  0xFBFA  /* Product ID for FT232RL */
-#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
-#define FTDI_RELAIS_PID        0xFA10  /* Relais device from Rudolf Gugler */
-#define FTDI_NF_RIC_VID        0x0DCD  /* Vendor Id */
-#define FTDI_NF_RIC_PID        0x0001  /* Product Id */
-#define FTDI_USBX_707_PID 0xF857       /* ADSTech IR Blaster USBX-707 */
-
-/* Larsen and Brusgaard AltiTrack/USBtrack  */
-#define LARSENBRUSGAARD_VID            0x0FD8
-#define LB_ALTITRACK_PID               0x0001
-
-/* www.canusb.com Lawicel CANUSB device */
-#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */
-
-/* AlphaMicro Components AMC-232USB01 device */
-#define FTDI_AMC232_PID 0xFF00 /* Product Id */
-
-/* www.candapter.com Ewert Energy Systems CANdapter device */
-#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
-
-/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
-/* the VID is the standard ftdi vid (FTDI_VID) */
-#define FTDI_SCS_DEVICE_0_PID 0xD010    /* SCS PTC-IIusb */
-#define FTDI_SCS_DEVICE_1_PID 0xD011    /* SCS Tracker / DSP TNC */
-#define FTDI_SCS_DEVICE_2_PID 0xD012
-#define FTDI_SCS_DEVICE_3_PID 0xD013
-#define FTDI_SCS_DEVICE_4_PID 0xD014
-#define FTDI_SCS_DEVICE_5_PID 0xD015
-#define FTDI_SCS_DEVICE_6_PID 0xD016
-#define FTDI_SCS_DEVICE_7_PID 0xD017
-
-/* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */
-#define FTDI_ACTZWAVE_PID      0xF2D0
-
-
-/* www.starting-point-systems.com ÂµChameleon device */
-#define FTDI_MICRO_CHAMELEON_PID       0xCAA0  /* Product Id */
-
-/* www.irtrans.de device */
-#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
-
-
-/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */
-#define FTDI_TTUSB_PID 0xFF20 /* Product Id */
-
-/* iPlus device */
-#define FTDI_IPLUS_PID 0xD070 /* Product Id */
-#define FTDI_IPLUS2_PID 0xD071 /* Product Id */
-
-/* DMX4ALL DMX Interfaces */
-#define FTDI_DMX4ALL 0xC850
-
-/* OpenDCC (www.opendcc.de) product id */
-#define FTDI_OPENDCC_PID       0xBFD8
-#define FTDI_OPENDCC_SNIFFER_PID       0xBFD9
-#define FTDI_OPENDCC_THROTTLE_PID      0xBFDA
-#define FTDI_OPENDCC_GATEWAY_PID       0xBFDB
-
-/* Sprog II (Andrew Crosland's SprogII DCC interface) */
-#define FTDI_SPROG_II          0xF0C8
-
-/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
-/* they use the ftdi chipset for the USB interface and the vendor id is the same */
-#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */
-#define FTDI_XF_634_PID 0xFC09 /* 634: 20x4 Character Display */
-#define FTDI_XF_547_PID 0xFC0A /* 547: Two line Display */
-#define FTDI_XF_633_PID 0xFC0B /* 633: 16x2 Character Display with Keys */
-#define FTDI_XF_631_PID 0xFC0C /* 631: 20x2 Character Display */
-#define FTDI_XF_635_PID 0xFC0D /* 635: 20x4 Character Display */
-#define FTDI_XF_640_PID 0xFC0E /* 640: Two line Display */
-#define FTDI_XF_642_PID 0xFC0F /* 642: Two line Display */
-
-/* Video Networks Limited / Homechoice in the UK use an ftdi-based device for their 1Mb */
-/* broadband internet service.  The following PID is exhibited by the usb device supplied */
-/* (the VID is the standard ftdi vid (FTDI_VID) */
-#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */
-
-/*
- * PCDJ use ftdi based dj-controllers.  The following PID is for their DAC-2 device
- * http://www.pcdjhardware.com/DAC2.asp (PID sent by Wouter Paesen)
- * (the VID is the standard ftdi vid (FTDI_VID) */
-#define FTDI_PCDJ_DAC2_PID 0xFA88
-
-/*
- * The following are the values for the Matrix Orbital LCD displays,
- * which are the FT232BM ( similar to the 8U232AM )
- */
-#define FTDI_MTXORB_0_PID      0xFA00  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_1_PID      0xFA01  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_2_PID      0xFA02  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_3_PID      0xFA03  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_4_PID      0xFA04  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_5_PID      0xFA05  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_6_PID      0xFA06  /* Matrix Orbital Product Id */
-
-/* OOCDlink by Joern Kaipf <joernk@web.de>
- * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */
-#define FTDI_OOCDLINK_PID      0xbaf8  /* Amontec JTAGkey */
-
-/*
- * The following are the values for the Matrix Orbital FTDI Range
- * Anything in this range will use an FT232RL.
- */
-#define MTXORB_VID                     0x1B3D
-#define MTXORB_FTDI_RANGE_0100_PID     0x0100
-#define MTXORB_FTDI_RANGE_0101_PID     0x0101
-#define MTXORB_FTDI_RANGE_0102_PID     0x0102
-#define MTXORB_FTDI_RANGE_0103_PID     0x0103
-#define MTXORB_FTDI_RANGE_0104_PID     0x0104
-#define MTXORB_FTDI_RANGE_0105_PID     0x0105
-#define MTXORB_FTDI_RANGE_0106_PID     0x0106
-#define MTXORB_FTDI_RANGE_0107_PID     0x0107
-#define MTXORB_FTDI_RANGE_0108_PID     0x0108
-#define MTXORB_FTDI_RANGE_0109_PID     0x0109
-#define MTXORB_FTDI_RANGE_010A_PID     0x010A
-#define MTXORB_FTDI_RANGE_010B_PID     0x010B
-#define MTXORB_FTDI_RANGE_010C_PID     0x010C
-#define MTXORB_FTDI_RANGE_010D_PID     0x010D
-#define MTXORB_FTDI_RANGE_010E_PID     0x010E
-#define MTXORB_FTDI_RANGE_010F_PID     0x010F
-#define MTXORB_FTDI_RANGE_0110_PID     0x0110
-#define MTXORB_FTDI_RANGE_0111_PID     0x0111
-#define MTXORB_FTDI_RANGE_0112_PID     0x0112
-#define MTXORB_FTDI_RANGE_0113_PID     0x0113
-#define MTXORB_FTDI_RANGE_0114_PID     0x0114
-#define MTXORB_FTDI_RANGE_0115_PID     0x0115
-#define MTXORB_FTDI_RANGE_0116_PID     0x0116
-#define MTXORB_FTDI_RANGE_0117_PID     0x0117
-#define MTXORB_FTDI_RANGE_0118_PID     0x0118
-#define MTXORB_FTDI_RANGE_0119_PID     0x0119
-#define MTXORB_FTDI_RANGE_011A_PID     0x011A
-#define MTXORB_FTDI_RANGE_011B_PID     0x011B
-#define MTXORB_FTDI_RANGE_011C_PID     0x011C
-#define MTXORB_FTDI_RANGE_011D_PID     0x011D
-#define MTXORB_FTDI_RANGE_011E_PID     0x011E
-#define MTXORB_FTDI_RANGE_011F_PID     0x011F
-#define MTXORB_FTDI_RANGE_0120_PID     0x0120
-#define MTXORB_FTDI_RANGE_0121_PID     0x0121
-#define MTXORB_FTDI_RANGE_0122_PID     0x0122
-#define MTXORB_FTDI_RANGE_0123_PID     0x0123
-#define MTXORB_FTDI_RANGE_0124_PID     0x0124
-#define MTXORB_FTDI_RANGE_0125_PID     0x0125
-#define MTXORB_FTDI_RANGE_0126_PID     0x0126
-#define MTXORB_FTDI_RANGE_0127_PID     0x0127
-#define MTXORB_FTDI_RANGE_0128_PID     0x0128
-#define MTXORB_FTDI_RANGE_0129_PID     0x0129
-#define MTXORB_FTDI_RANGE_012A_PID     0x012A
-#define MTXORB_FTDI_RANGE_012B_PID     0x012B
-#define MTXORB_FTDI_RANGE_012C_PID     0x012C
-#define MTXORB_FTDI_RANGE_012D_PID     0x012D
-#define MTXORB_FTDI_RANGE_012E_PID     0x012E
-#define MTXORB_FTDI_RANGE_012F_PID     0x012F
-#define MTXORB_FTDI_RANGE_0130_PID     0x0130
-#define MTXORB_FTDI_RANGE_0131_PID     0x0131
-#define MTXORB_FTDI_RANGE_0132_PID     0x0132
-#define MTXORB_FTDI_RANGE_0133_PID     0x0133
-#define MTXORB_FTDI_RANGE_0134_PID     0x0134
-#define MTXORB_FTDI_RANGE_0135_PID     0x0135
-#define MTXORB_FTDI_RANGE_0136_PID     0x0136
-#define MTXORB_FTDI_RANGE_0137_PID     0x0137
-#define MTXORB_FTDI_RANGE_0138_PID     0x0138
-#define MTXORB_FTDI_RANGE_0139_PID     0x0139
-#define MTXORB_FTDI_RANGE_013A_PID     0x013A
-#define MTXORB_FTDI_RANGE_013B_PID     0x013B
-#define MTXORB_FTDI_RANGE_013C_PID     0x013C
-#define MTXORB_FTDI_RANGE_013D_PID     0x013D
-#define MTXORB_FTDI_RANGE_013E_PID     0x013E
-#define MTXORB_FTDI_RANGE_013F_PID     0x013F
-#define MTXORB_FTDI_RANGE_0140_PID     0x0140
-#define MTXORB_FTDI_RANGE_0141_PID     0x0141
-#define MTXORB_FTDI_RANGE_0142_PID     0x0142
-#define MTXORB_FTDI_RANGE_0143_PID     0x0143
-#define MTXORB_FTDI_RANGE_0144_PID     0x0144
-#define MTXORB_FTDI_RANGE_0145_PID     0x0145
-#define MTXORB_FTDI_RANGE_0146_PID     0x0146
-#define MTXORB_FTDI_RANGE_0147_PID     0x0147
-#define MTXORB_FTDI_RANGE_0148_PID     0x0148
-#define MTXORB_FTDI_RANGE_0149_PID     0x0149
-#define MTXORB_FTDI_RANGE_014A_PID     0x014A
-#define MTXORB_FTDI_RANGE_014B_PID     0x014B
-#define MTXORB_FTDI_RANGE_014C_PID     0x014C
-#define MTXORB_FTDI_RANGE_014D_PID     0x014D
-#define MTXORB_FTDI_RANGE_014E_PID     0x014E
-#define MTXORB_FTDI_RANGE_014F_PID     0x014F
-#define MTXORB_FTDI_RANGE_0150_PID     0x0150
-#define MTXORB_FTDI_RANGE_0151_PID     0x0151
-#define MTXORB_FTDI_RANGE_0152_PID     0x0152
-#define MTXORB_FTDI_RANGE_0153_PID     0x0153
-#define MTXORB_FTDI_RANGE_0154_PID     0x0154
-#define MTXORB_FTDI_RANGE_0155_PID     0x0155
-#define MTXORB_FTDI_RANGE_0156_PID     0x0156
-#define MTXORB_FTDI_RANGE_0157_PID     0x0157
-#define MTXORB_FTDI_RANGE_0158_PID     0x0158
-#define MTXORB_FTDI_RANGE_0159_PID     0x0159
-#define MTXORB_FTDI_RANGE_015A_PID     0x015A
-#define MTXORB_FTDI_RANGE_015B_PID     0x015B
-#define MTXORB_FTDI_RANGE_015C_PID     0x015C
-#define MTXORB_FTDI_RANGE_015D_PID     0x015D
-#define MTXORB_FTDI_RANGE_015E_PID     0x015E
-#define MTXORB_FTDI_RANGE_015F_PID     0x015F
-#define MTXORB_FTDI_RANGE_0160_PID     0x0160
-#define MTXORB_FTDI_RANGE_0161_PID     0x0161
-#define MTXORB_FTDI_RANGE_0162_PID     0x0162
-#define MTXORB_FTDI_RANGE_0163_PID     0x0163
-#define MTXORB_FTDI_RANGE_0164_PID     0x0164
-#define MTXORB_FTDI_RANGE_0165_PID     0x0165
-#define MTXORB_FTDI_RANGE_0166_PID     0x0166
-#define MTXORB_FTDI_RANGE_0167_PID     0x0167
-#define MTXORB_FTDI_RANGE_0168_PID     0x0168
-#define MTXORB_FTDI_RANGE_0169_PID     0x0169
-#define MTXORB_FTDI_RANGE_016A_PID     0x016A
-#define MTXORB_FTDI_RANGE_016B_PID     0x016B
-#define MTXORB_FTDI_RANGE_016C_PID     0x016C
-#define MTXORB_FTDI_RANGE_016D_PID     0x016D
-#define MTXORB_FTDI_RANGE_016E_PID     0x016E
-#define MTXORB_FTDI_RANGE_016F_PID     0x016F
-#define MTXORB_FTDI_RANGE_0170_PID     0x0170
-#define MTXORB_FTDI_RANGE_0171_PID     0x0171
-#define MTXORB_FTDI_RANGE_0172_PID     0x0172
-#define MTXORB_FTDI_RANGE_0173_PID     0x0173
-#define MTXORB_FTDI_RANGE_0174_PID     0x0174
-#define MTXORB_FTDI_RANGE_0175_PID     0x0175
-#define MTXORB_FTDI_RANGE_0176_PID     0x0176
-#define MTXORB_FTDI_RANGE_0177_PID     0x0177
-#define MTXORB_FTDI_RANGE_0178_PID     0x0178
-#define MTXORB_FTDI_RANGE_0179_PID     0x0179
-#define MTXORB_FTDI_RANGE_017A_PID     0x017A
-#define MTXORB_FTDI_RANGE_017B_PID     0x017B
-#define MTXORB_FTDI_RANGE_017C_PID     0x017C
-#define MTXORB_FTDI_RANGE_017D_PID     0x017D
-#define MTXORB_FTDI_RANGE_017E_PID     0x017E
-#define MTXORB_FTDI_RANGE_017F_PID     0x017F
-#define MTXORB_FTDI_RANGE_0180_PID     0x0180
-#define MTXORB_FTDI_RANGE_0181_PID     0x0181
-#define MTXORB_FTDI_RANGE_0182_PID     0x0182
-#define MTXORB_FTDI_RANGE_0183_PID     0x0183
-#define MTXORB_FTDI_RANGE_0184_PID     0x0184
-#define MTXORB_FTDI_RANGE_0185_PID     0x0185
-#define MTXORB_FTDI_RANGE_0186_PID     0x0186
-#define MTXORB_FTDI_RANGE_0187_PID     0x0187
-#define MTXORB_FTDI_RANGE_0188_PID     0x0188
-#define MTXORB_FTDI_RANGE_0189_PID     0x0189
-#define MTXORB_FTDI_RANGE_018A_PID     0x018A
-#define MTXORB_FTDI_RANGE_018B_PID     0x018B
-#define MTXORB_FTDI_RANGE_018C_PID     0x018C
-#define MTXORB_FTDI_RANGE_018D_PID     0x018D
-#define MTXORB_FTDI_RANGE_018E_PID     0x018E
-#define MTXORB_FTDI_RANGE_018F_PID     0x018F
-#define MTXORB_FTDI_RANGE_0190_PID     0x0190
-#define MTXORB_FTDI_RANGE_0191_PID     0x0191
-#define MTXORB_FTDI_RANGE_0192_PID     0x0192
-#define MTXORB_FTDI_RANGE_0193_PID     0x0193
-#define MTXORB_FTDI_RANGE_0194_PID     0x0194
-#define MTXORB_FTDI_RANGE_0195_PID     0x0195
-#define MTXORB_FTDI_RANGE_0196_PID     0x0196
-#define MTXORB_FTDI_RANGE_0197_PID     0x0197
-#define MTXORB_FTDI_RANGE_0198_PID     0x0198
-#define MTXORB_FTDI_RANGE_0199_PID     0x0199
-#define MTXORB_FTDI_RANGE_019A_PID     0x019A
-#define MTXORB_FTDI_RANGE_019B_PID     0x019B
-#define MTXORB_FTDI_RANGE_019C_PID     0x019C
-#define MTXORB_FTDI_RANGE_019D_PID     0x019D
-#define MTXORB_FTDI_RANGE_019E_PID     0x019E
-#define MTXORB_FTDI_RANGE_019F_PID     0x019F
-#define MTXORB_FTDI_RANGE_01A0_PID     0x01A0
-#define MTXORB_FTDI_RANGE_01A1_PID     0x01A1
-#define MTXORB_FTDI_RANGE_01A2_PID     0x01A2
-#define MTXORB_FTDI_RANGE_01A3_PID     0x01A3
-#define MTXORB_FTDI_RANGE_01A4_PID     0x01A4
-#define MTXORB_FTDI_RANGE_01A5_PID     0x01A5
-#define MTXORB_FTDI_RANGE_01A6_PID     0x01A6
-#define MTXORB_FTDI_RANGE_01A7_PID     0x01A7
-#define MTXORB_FTDI_RANGE_01A8_PID     0x01A8
-#define MTXORB_FTDI_RANGE_01A9_PID     0x01A9
-#define MTXORB_FTDI_RANGE_01AA_PID     0x01AA
-#define MTXORB_FTDI_RANGE_01AB_PID     0x01AB
-#define MTXORB_FTDI_RANGE_01AC_PID     0x01AC
-#define MTXORB_FTDI_RANGE_01AD_PID     0x01AD
-#define MTXORB_FTDI_RANGE_01AE_PID     0x01AE
-#define MTXORB_FTDI_RANGE_01AF_PID     0x01AF
-#define MTXORB_FTDI_RANGE_01B0_PID     0x01B0
-#define MTXORB_FTDI_RANGE_01B1_PID     0x01B1
-#define MTXORB_FTDI_RANGE_01B2_PID     0x01B2
-#define MTXORB_FTDI_RANGE_01B3_PID     0x01B3
-#define MTXORB_FTDI_RANGE_01B4_PID     0x01B4
-#define MTXORB_FTDI_RANGE_01B5_PID     0x01B5
-#define MTXORB_FTDI_RANGE_01B6_PID     0x01B6
-#define MTXORB_FTDI_RANGE_01B7_PID     0x01B7
-#define MTXORB_FTDI_RANGE_01B8_PID     0x01B8
-#define MTXORB_FTDI_RANGE_01B9_PID     0x01B9
-#define MTXORB_FTDI_RANGE_01BA_PID     0x01BA
-#define MTXORB_FTDI_RANGE_01BB_PID     0x01BB
-#define MTXORB_FTDI_RANGE_01BC_PID     0x01BC
-#define MTXORB_FTDI_RANGE_01BD_PID     0x01BD
-#define MTXORB_FTDI_RANGE_01BE_PID     0x01BE
-#define MTXORB_FTDI_RANGE_01BF_PID     0x01BF
-#define MTXORB_FTDI_RANGE_01C0_PID     0x01C0
-#define MTXORB_FTDI_RANGE_01C1_PID     0x01C1
-#define MTXORB_FTDI_RANGE_01C2_PID     0x01C2
-#define MTXORB_FTDI_RANGE_01C3_PID     0x01C3
-#define MTXORB_FTDI_RANGE_01C4_PID     0x01C4
-#define MTXORB_FTDI_RANGE_01C5_PID     0x01C5
-#define MTXORB_FTDI_RANGE_01C6_PID     0x01C6
-#define MTXORB_FTDI_RANGE_01C7_PID     0x01C7
-#define MTXORB_FTDI_RANGE_01C8_PID     0x01C8
-#define MTXORB_FTDI_RANGE_01C9_PID     0x01C9
-#define MTXORB_FTDI_RANGE_01CA_PID     0x01CA
-#define MTXORB_FTDI_RANGE_01CB_PID     0x01CB
-#define MTXORB_FTDI_RANGE_01CC_PID     0x01CC
-#define MTXORB_FTDI_RANGE_01CD_PID     0x01CD
-#define MTXORB_FTDI_RANGE_01CE_PID     0x01CE
-#define MTXORB_FTDI_RANGE_01CF_PID     0x01CF
-#define MTXORB_FTDI_RANGE_01D0_PID     0x01D0
-#define MTXORB_FTDI_RANGE_01D1_PID     0x01D1
-#define MTXORB_FTDI_RANGE_01D2_PID     0x01D2
-#define MTXORB_FTDI_RANGE_01D3_PID     0x01D3
-#define MTXORB_FTDI_RANGE_01D4_PID     0x01D4
-#define MTXORB_FTDI_RANGE_01D5_PID     0x01D5
-#define MTXORB_FTDI_RANGE_01D6_PID     0x01D6
-#define MTXORB_FTDI_RANGE_01D7_PID     0x01D7
-#define MTXORB_FTDI_RANGE_01D8_PID     0x01D8
-#define MTXORB_FTDI_RANGE_01D9_PID     0x01D9
-#define MTXORB_FTDI_RANGE_01DA_PID     0x01DA
-#define MTXORB_FTDI_RANGE_01DB_PID     0x01DB
-#define MTXORB_FTDI_RANGE_01DC_PID     0x01DC
-#define MTXORB_FTDI_RANGE_01DD_PID     0x01DD
-#define MTXORB_FTDI_RANGE_01DE_PID     0x01DE
-#define MTXORB_FTDI_RANGE_01DF_PID     0x01DF
-#define MTXORB_FTDI_RANGE_01E0_PID     0x01E0
-#define MTXORB_FTDI_RANGE_01E1_PID     0x01E1
-#define MTXORB_FTDI_RANGE_01E2_PID     0x01E2
-#define MTXORB_FTDI_RANGE_01E3_PID     0x01E3
-#define MTXORB_FTDI_RANGE_01E4_PID     0x01E4
-#define MTXORB_FTDI_RANGE_01E5_PID     0x01E5
-#define MTXORB_FTDI_RANGE_01E6_PID     0x01E6
-#define MTXORB_FTDI_RANGE_01E7_PID     0x01E7
-#define MTXORB_FTDI_RANGE_01E8_PID     0x01E8
-#define MTXORB_FTDI_RANGE_01E9_PID     0x01E9
-#define MTXORB_FTDI_RANGE_01EA_PID     0x01EA
-#define MTXORB_FTDI_RANGE_01EB_PID     0x01EB
-#define MTXORB_FTDI_RANGE_01EC_PID     0x01EC
-#define MTXORB_FTDI_RANGE_01ED_PID     0x01ED
-#define MTXORB_FTDI_RANGE_01EE_PID     0x01EE
-#define MTXORB_FTDI_RANGE_01EF_PID     0x01EF
-#define MTXORB_FTDI_RANGE_01F0_PID     0x01F0
-#define MTXORB_FTDI_RANGE_01F1_PID     0x01F1
-#define MTXORB_FTDI_RANGE_01F2_PID     0x01F2
-#define MTXORB_FTDI_RANGE_01F3_PID     0x01F3
-#define MTXORB_FTDI_RANGE_01F4_PID     0x01F4
-#define MTXORB_FTDI_RANGE_01F5_PID     0x01F5
-#define MTXORB_FTDI_RANGE_01F6_PID     0x01F6
-#define MTXORB_FTDI_RANGE_01F7_PID     0x01F7
-#define MTXORB_FTDI_RANGE_01F8_PID     0x01F8
-#define MTXORB_FTDI_RANGE_01F9_PID     0x01F9
-#define MTXORB_FTDI_RANGE_01FA_PID     0x01FA
-#define MTXORB_FTDI_RANGE_01FB_PID     0x01FB
-#define MTXORB_FTDI_RANGE_01FC_PID     0x01FC
-#define MTXORB_FTDI_RANGE_01FD_PID     0x01FD
-#define MTXORB_FTDI_RANGE_01FE_PID     0x01FE
-#define MTXORB_FTDI_RANGE_01FF_PID     0x01FF
-
-
-
-/* Interbiometrics USB I/O Board */
-/* Developed for Interbiometrics by Rudolf Gugler */
-#define INTERBIOMETRICS_VID              0x1209
-#define INTERBIOMETRICS_IOBOARD_PID      0x1002
-#define INTERBIOMETRICS_MINI_IOBOARD_PID 0x1006
-
-/*
- * The following are the values for the Perle Systems
- * UltraPort USB serial converters
- */
-#define FTDI_PERLE_ULTRAPORT_PID 0xF0C0        /* Perle UltraPort Product Id */
-
-/*
- * The following are the values for the Sealevel SeaLINK+ adapters.
- * (Original list sent by Tuan Hoang.  Ian Abbott renamed the macros and
- * removed some PIDs that don't seem to match any existing products.)
- */
-#define SEALEVEL_VID           0x0c52  /* Sealevel Vendor ID */
-#define SEALEVEL_2101_PID      0x2101  /* SeaLINK+232 (2101/2105) */
-#define SEALEVEL_2102_PID      0x2102  /* SeaLINK+485 (2102) */
-#define SEALEVEL_2103_PID      0x2103  /* SeaLINK+232I (2103) */
-#define SEALEVEL_2104_PID      0x2104  /* SeaLINK+485I (2104) */
-#define SEALEVEL_2106_PID      0x9020  /* SeaLINK+422 (2106) */
-#define SEALEVEL_2201_1_PID    0x2211  /* SeaPORT+2/232 (2201) Port 1 */
-#define SEALEVEL_2201_2_PID    0x2221  /* SeaPORT+2/232 (2201) Port 2 */
-#define SEALEVEL_2202_1_PID    0x2212  /* SeaPORT+2/485 (2202) Port 1 */
-#define SEALEVEL_2202_2_PID    0x2222  /* SeaPORT+2/485 (2202) Port 2 */
-#define SEALEVEL_2203_1_PID    0x2213  /* SeaPORT+2 (2203) Port 1 */
-#define SEALEVEL_2203_2_PID    0x2223  /* SeaPORT+2 (2203) Port 2 */
-#define SEALEVEL_2401_1_PID    0x2411  /* SeaPORT+4/232 (2401) Port 1 */
-#define SEALEVEL_2401_2_PID    0x2421  /* SeaPORT+4/232 (2401) Port 2 */
-#define SEALEVEL_2401_3_PID    0x2431  /* SeaPORT+4/232 (2401) Port 3 */
-#define SEALEVEL_2401_4_PID    0x2441  /* SeaPORT+4/232 (2401) Port 4 */
-#define SEALEVEL_2402_1_PID    0x2412  /* SeaPORT+4/485 (2402) Port 1 */
-#define SEALEVEL_2402_2_PID    0x2422  /* SeaPORT+4/485 (2402) Port 2 */
-#define SEALEVEL_2402_3_PID    0x2432  /* SeaPORT+4/485 (2402) Port 3 */
-#define SEALEVEL_2402_4_PID    0x2442  /* SeaPORT+4/485 (2402) Port 4 */
-#define SEALEVEL_2403_1_PID    0x2413  /* SeaPORT+4 (2403) Port 1 */
-#define SEALEVEL_2403_2_PID    0x2423  /* SeaPORT+4 (2403) Port 2 */
-#define SEALEVEL_2403_3_PID    0x2433  /* SeaPORT+4 (2403) Port 3 */
-#define SEALEVEL_2403_4_PID    0x2443  /* SeaPORT+4 (2403) Port 4 */
-#define SEALEVEL_2801_1_PID    0X2811  /* SeaLINK+8/232 (2801) Port 1 */
-#define SEALEVEL_2801_2_PID    0X2821  /* SeaLINK+8/232 (2801) Port 2 */
-#define SEALEVEL_2801_3_PID    0X2831  /* SeaLINK+8/232 (2801) Port 3 */
-#define SEALEVEL_2801_4_PID    0X2841  /* SeaLINK+8/232 (2801) Port 4 */
-#define SEALEVEL_2801_5_PID    0X2851  /* SeaLINK+8/232 (2801) Port 5 */
-#define SEALEVEL_2801_6_PID    0X2861  /* SeaLINK+8/232 (2801) Port 6 */
-#define SEALEVEL_2801_7_PID    0X2871  /* SeaLINK+8/232 (2801) Port 7 */
-#define SEALEVEL_2801_8_PID    0X2881  /* SeaLINK+8/232 (2801) Port 8 */
-#define SEALEVEL_2802_1_PID    0X2812  /* SeaLINK+8/485 (2802) Port 1 */
-#define SEALEVEL_2802_2_PID    0X2822  /* SeaLINK+8/485 (2802) Port 2 */
-#define SEALEVEL_2802_3_PID    0X2832  /* SeaLINK+8/485 (2802) Port 3 */
-#define SEALEVEL_2802_4_PID    0X2842  /* SeaLINK+8/485 (2802) Port 4 */
-#define SEALEVEL_2802_5_PID    0X2852  /* SeaLINK+8/485 (2802) Port 5 */
-#define SEALEVEL_2802_6_PID    0X2862  /* SeaLINK+8/485 (2802) Port 6 */
-#define SEALEVEL_2802_7_PID    0X2872  /* SeaLINK+8/485 (2802) Port 7 */
-#define SEALEVEL_2802_8_PID    0X2882  /* SeaLINK+8/485 (2802) Port 8 */
-#define SEALEVEL_2803_1_PID    0X2813  /* SeaLINK+8 (2803) Port 1 */
-#define SEALEVEL_2803_2_PID    0X2823  /* SeaLINK+8 (2803) Port 2 */
-#define SEALEVEL_2803_3_PID    0X2833  /* SeaLINK+8 (2803) Port 3 */
-#define SEALEVEL_2803_4_PID    0X2843  /* SeaLINK+8 (2803) Port 4 */
-#define SEALEVEL_2803_5_PID    0X2853  /* SeaLINK+8 (2803) Port 5 */
-#define SEALEVEL_2803_6_PID    0X2863  /* SeaLINK+8 (2803) Port 6 */
-#define SEALEVEL_2803_7_PID    0X2873  /* SeaLINK+8 (2803) Port 7 */
-#define SEALEVEL_2803_8_PID    0X2883  /* SeaLINK+8 (2803) Port 8 */
-
-/*
- * The following are the values for two KOBIL chipcard terminals.
- */
-#define KOBIL_VID              0x0d46  /* KOBIL Vendor ID */
-#define KOBIL_CONV_B1_PID      0x2020  /* KOBIL Konverter for B1 */
-#define KOBIL_CONV_KAAN_PID    0x2021  /* KOBIL_Konverter for KAAN */
-
-/*
- * Icom ID-1 digital transceiver
- */
-
-#define ICOM_ID1_VID            0x0C26
-#define ICOM_ID1_PID            0x0004
-
-/*
- * ASK.fr devices
- */
-#define FTDI_ASK_RDR400_PID    0xC991  /* ASK RDR 400 series card reader */
-
-/*
- * FTDI USB UART chips used in construction projects from the
- * Elektor Electronics magazine (http://elektor-electronics.co.uk)
- */
-#define ELEKTOR_VID            0x0C7D
-#define ELEKTOR_FT323R_PID     0x0005  /* RFID-Reader, issue 09-2006 */
-
-/*
- * DSS-20 Sync Station for Sony Ericsson P800
- */
-#define FTDI_DSS20_PID          0xFC82
-
-/*
- * Home Electronics (www.home-electro.com) USB gadgets
- */
-#define FTDI_HE_TIRA1_PID      0xFA78  /* Tira-1 IR transceiver */
-
-/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */
-/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
-#define FTDI_USB_UIRT_PID      0xF850  /* Product Id */
-
-/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */
-
-#define FTDI_TNC_X_PID         0xEBE0
-
-/*
- * ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
- * All of these devices use FTDI's vendor ID (0x0403).
- *
- * The previously included PID for the UO 100 module was incorrect.
- * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58).
- *
- * Armin Laeuger originally sent the PID for the UM 100 module.
- */
-#define FTDI_R2000KU_TRUE_RNG  0xFB80  /* R2000KU TRUE RNG */
-#define FTDI_ELV_UR100_PID     0xFB58  /* USB-RS232-Umsetzer (UR 100) */
-#define FTDI_ELV_UM100_PID     0xFB5A  /* USB-Modul UM 100 */
-#define FTDI_ELV_UO100_PID     0xFB5B  /* USB-Modul UO 100 */
-#define FTDI_ELV_ALC8500_PID   0xF06E  /* ALC 8500 Expert */
-/* Additional ELV PIDs that default to using the FTDI D2XX drivers on
- * MS Windows, rather than the FTDI Virtual Com Port drivers.
- * Maybe these will be easier to use with the libftdi/libusb user-space
- * drivers, or possibly the Comedi drivers in some cases. */
-#define FTDI_ELV_CLI7000_PID   0xFB59  /* Computer-Light-Interface (CLI 7000) */
-#define FTDI_ELV_PPS7330_PID   0xFB5C  /* Processor-Power-Supply (PPS 7330) */
-#define FTDI_ELV_TFM100_PID    0xFB5D  /* Temperartur-Feuchte Messgeraet (TFM 100) */
-#define FTDI_ELV_UDF77_PID     0xFB5E  /* USB DCF Funkurh (UDF 77) */
-#define FTDI_ELV_UIO88_PID     0xFB5F  /* USB-I/O Interface (UIO 88) */
-#define FTDI_ELV_UAD8_PID      0xF068  /* USB-AD-Wandler (UAD 8) */
-#define FTDI_ELV_UDA7_PID      0xF069  /* USB-DA-Wandler (UDA 7) */
-#define FTDI_ELV_USI2_PID      0xF06A  /* USB-Schrittmotoren-Interface (USI 2) */
-#define FTDI_ELV_T1100_PID     0xF06B  /* Thermometer (T 1100) */
-#define FTDI_ELV_PCD200_PID    0xF06C  /* PC-Datenlogger (PCD 200) */
-#define FTDI_ELV_ULA200_PID    0xF06D  /* USB-LCD-Ansteuerung (ULA 200) */
-#define FTDI_ELV_FHZ1000PC_PID 0xF06F  /* FHZ 1000 PC */
-#define FTDI_ELV_CSI8_PID      0xE0F0  /* Computer-Schalt-Interface (CSI 8) */
-#define FTDI_ELV_EM1000DL_PID  0xE0F1  /* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */
-#define FTDI_ELV_PCK100_PID    0xE0F2  /* PC-Kabeltester (PCK 100) */
-#define FTDI_ELV_RFP500_PID    0xE0F3  /* HF-Leistungsmesser (RFP 500) */
-#define FTDI_ELV_FS20SIG_PID   0xE0F4  /* Signalgeber (FS 20 SIG) */
-#define FTDI_ELV_WS300PC_PID   0xE0F6  /* PC-Wetterstation (WS 300 PC) */
-#define FTDI_ELV_FHZ1300PC_PID 0xE0E8  /* FHZ 1300 PC */
-#define FTDI_ELV_WS500_PID     0xE0E9  /* PC-Wetterstation (WS 500) */
-#define FTDI_ELV_HS485_PID     0xE0EA  /* USB to RS-485 adapter */
-#define FTDI_ELV_EM1010PC_PID  0xE0EF  /* Engery monitor EM 1010 PC */
-#define FTDI_PHI_FISCO_PID      0xE40B  /* PHI Fisco USB to Serial cable */
-
-/*
- * Definitions for ID TECH (www.idt-net.com) devices
- */
-#define IDTECH_VID             0x0ACD  /* ID TECH Vendor ID */
-#define IDTECH_IDT1221U_PID    0x0300  /* IDT1221U USB to RS-232 adapter */
-
-/*
- * Definitions for Omnidirectional Control Technology, Inc. devices
- */
-#define OCT_VID                        0x0B39  /* OCT vendor ID */
-/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */
-/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */
-/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */
-#define OCT_US101_PID          0x0421  /* OCT US101 USB to RS-232 */
-
-/* an infrared receiver for user access control with IR tags */
-#define FTDI_PIEGROUP_PID      0xF208  /* Product Id */
-
-/*
- * Definitions for Artemis astronomical USB based cameras
- * Check it at http://www.artemisccd.co.uk/
- */
-#define FTDI_ARTEMIS_PID       0xDF28  /* All Artemis Cameras */
-
-/*
- * Definitions for ATIK Instruments astronomical USB based cameras
- * Check it at http://www.atik-instruments.com/
- */
-#define FTDI_ATIK_ATK16_PID    0xDF30  /* ATIK ATK-16 Grayscale Camera */
-#define FTDI_ATIK_ATK16C_PID   0xDF32  /* ATIK ATK-16C Colour Camera */
-#define FTDI_ATIK_ATK16HR_PID  0xDF31  /* ATIK ATK-16HR Grayscale Camera */
-#define FTDI_ATIK_ATK16HRC_PID 0xDF33  /* ATIK ATK-16HRC Colour Camera */
-#define FTDI_ATIK_ATK16IC_PID   0xDF35  /* ATIK ATK-16IC Grayscale Camera */
-
-/*
- * Protego product ids
- */
-#define PROTEGO_SPECIAL_1      0xFC70  /* special/unknown device */
-#define PROTEGO_R2X0           0xFC71  /* R200-USB TRNG unit (R210, R220, and R230) */
-#define PROTEGO_SPECIAL_3      0xFC72  /* special/unknown device */
-#define PROTEGO_SPECIAL_4      0xFC73  /* special/unknown device */
-
-/*
- * Gude Analog- und Digitalsysteme GmbH
- */
-#define FTDI_GUDEADS_E808_PID    0xE808
-#define FTDI_GUDEADS_E809_PID    0xE809
-#define FTDI_GUDEADS_E80A_PID    0xE80A
-#define FTDI_GUDEADS_E80B_PID    0xE80B
-#define FTDI_GUDEADS_E80C_PID    0xE80C
-#define FTDI_GUDEADS_E80D_PID    0xE80D
-#define FTDI_GUDEADS_E80E_PID    0xE80E
-#define FTDI_GUDEADS_E80F_PID    0xE80F
-#define FTDI_GUDEADS_E888_PID    0xE888  /* Expert ISDN Control USB */
-#define FTDI_GUDEADS_E889_PID    0xE889  /* USB RS-232 OptoBridge */
-#define FTDI_GUDEADS_E88A_PID    0xE88A
-#define FTDI_GUDEADS_E88B_PID    0xE88B
-#define FTDI_GUDEADS_E88C_PID    0xE88C
-#define FTDI_GUDEADS_E88D_PID    0xE88D
-#define FTDI_GUDEADS_E88E_PID    0xE88E
-#define FTDI_GUDEADS_E88F_PID    0xE88F
-
-/*
- * Linx Technologies product ids
- */
-#define LINX_SDMUSBQSS_PID     0xF448  /* Linx SDM-USB-QS-S */
-#define LINX_MASTERDEVEL2_PID   0xF449   /* Linx Master Development 2.0 */
-#define LINX_FUTURE_0_PID   0xF44A   /* Linx future device */
-#define LINX_FUTURE_1_PID   0xF44B   /* Linx future device */
-#define LINX_FUTURE_2_PID   0xF44C   /* Linx future device */
-
-/* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */
-/* unit for PIC16's/PIC18's */
-#define FTDI_CCSICDU20_0_PID    0xF9D0
-#define FTDI_CCSICDU40_1_PID    0xF9D1
-#define FTDI_CCSMACHX_2_PID     0xF9D2
-#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3
-#define FTDI_CCSICDU64_4_PID    0xF9D4
-#define FTDI_CCSPRIME8_5_PID    0xF9D5
-
-/* Inside Accesso contactless reader (http://www.insidefr.com) */
-#define INSIDE_ACCESSO         0xFAD0
-
-/*
- * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI
- */
-#define INTREPID_VID           0x093C
-#define INTREPID_VALUECAN_PID  0x0601
-#define INTREPID_NEOVI_PID     0x0701
-
-/*
- * Falcom Wireless Communications GmbH
- */
-#define FALCOM_VID             0x0F94  /* Vendor Id */
-#define FALCOM_TWIST_PID       0x0001  /* Falcom Twist USB GPRS modem */
-#define FALCOM_SAMBA_PID       0x0005  /* Falcom Samba USB GPRS modem */
-
-/*
- * SUUNTO product ids
- */
-#define FTDI_SUUNTO_SPORTS_PID 0xF680  /* Suunto Sports instrument */
-
-/*
- * Oceanic product ids
- */
-#define FTDI_OCEANIC_PID       0xF460  /* Oceanic dive instrument */
-
-/*
- * TTi (Thurlby Thandar Instruments)
- */
-#define TTI_VID                        0x103E  /* Vendor Id */
-#define TTI_QL355P_PID         0x03E8  /* TTi QL355P power supply */
-
-/*
- * Definitions for B&B Electronics products.
- */
-#define BANDB_VID              0x0856  /* B&B Electronics Vendor ID */
-#define BANDB_USOTL4_PID       0xAC01  /* USOTL4 Isolated RS-485 Converter */
-#define BANDB_USTL4_PID                0xAC02  /* USTL4 RS-485 Converter */
-#define BANDB_USO9ML2_PID      0xAC03  /* USO9ML2 Isolated RS-232 Converter */
-#define BANDB_USOPTL4_PID      0xAC11
-#define BANDB_USPTL4_PID       0xAC12
-#define BANDB_USO9ML2DR_2_PID  0xAC16
-#define BANDB_USO9ML2DR_PID    0xAC17
-#define BANDB_USOPTL4DR2_PID   0xAC18  /* USOPTL4R-2 2-port Isolated RS-232 Converter */
-#define BANDB_USOPTL4DR_PID    0xAC19
-#define BANDB_485USB9F_2W_PID  0xAC25
-#define BANDB_485USB9F_4W_PID  0xAC26
-#define BANDB_232USB9M_PID     0xAC27
-#define BANDB_485USBTB_2W_PID  0xAC33
-#define BANDB_485USBTB_4W_PID  0xAC34
-#define BANDB_TTL5USB9M_PID    0xAC49
-#define BANDB_TTL3USB9M_PID    0xAC50
-#define BANDB_ZZ_PROG1_USB_PID 0xBA02
-
-/*
- * RM Michaelides CANview USB (http://www.rmcan.com)
- * CAN fieldbus interface adapter, added by port GmbH www.port.de)
- * Ian Abbott changed the macro names for consistency.
- */
-#define FTDI_RM_CANVIEW_PID    0xfd60  /* Product Id */
-
-/*
- * EVER Eco Pro UPS (http://www.ever.com.pl/)
- */
-
-#define        EVER_ECO_PRO_CDS        0xe520  /* RS-232 converter */
-
-/*
- * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485,
- * USB-TTY activ, USB-TTY passiv.  Some PIDs are used by several devices
- * and I'm not entirely sure which are used by which.
- */
-#define FTDI_4N_GALAXY_DE_1_PID        0xF3C0
-#define FTDI_4N_GALAXY_DE_2_PID        0xF3C1
-
-/*
- * Mobility Electronics products.
- */
-#define MOBILITY_VID                   0x1342
-#define MOBILITY_USB_SERIAL_PID                0x0202  /* EasiDock USB 200 serial */
-
-/*
- * microHAM product IDs (http://www.microham.com).
- * Submitted by Justin Burket (KL1RL) <zorton@jtan.com>
- * and Mike Studer (K6EEP) <k6eep@hamsoftware.org>.
- * Ian Abbott <abbotti@mev.co.uk> added a few more from the driver INF file.
- */
-#define FTDI_MHAM_KW_PID 0xEEE8                /* USB-KW interface */
-#define FTDI_MHAM_YS_PID 0xEEE9                /* USB-YS interface */
-#define FTDI_MHAM_Y6_PID 0xEEEA                /* USB-Y6 interface */
-#define FTDI_MHAM_Y8_PID 0xEEEB                /* USB-Y8 interface */
-#define FTDI_MHAM_IC_PID 0xEEEC                /* USB-IC interface */
-#define FTDI_MHAM_DB9_PID 0xEEED       /* USB-DB9 interface */
-#define FTDI_MHAM_RS232_PID 0xEEEE     /* USB-RS232 interface */
-#define FTDI_MHAM_Y9_PID 0xEEEF                /* USB-Y9 interface */
-
-/*
- * Active Robots product ids.
- */
-#define FTDI_ACTIVE_ROBOTS_PID 0xE548  /* USB comms board */
-
-/*
- * Xsens Technologies BV products (http://www.xsens.com).
- */
-#define XSENS_CONVERTER_0_PID  0xD388
-#define XSENS_CONVERTER_1_PID  0xD389
-#define XSENS_CONVERTER_2_PID  0xD38A
-#define XSENS_CONVERTER_3_PID  0xD38B
-#define XSENS_CONVERTER_4_PID  0xD38C
-#define XSENS_CONVERTER_5_PID  0xD38D
-#define XSENS_CONVERTER_6_PID  0xD38E
-#define XSENS_CONVERTER_7_PID  0xD38F
-
-/*
- * Teratronik product ids.
- * Submitted by O. Wölfelschneider.
- */
-#define FTDI_TERATRONIK_VCP_PID         0xEC88 /* Teratronik device (preferring VCP driver on windows) */
-#define FTDI_TERATRONIK_D2XX_PID 0xEC89        /* Teratronik device (preferring D2XX driver on windows) */
-
-/*
- * Evolution Robotics products (http://www.evolution.com/).
- * Submitted by Shawn M. Lavelle.
- */
-#define EVOLUTION_VID          0xDEEE  /* Vendor ID */
-#define EVOLUTION_ER1_PID      0x0300  /* ER1 Control Module */
-#define EVO_8U232AM_PID        0x02FF  /* Evolution robotics RCM2 (FT232AM)*/
-#define EVO_HYBRID_PID         0x0302  /* Evolution robotics RCM4 PID (FT232BM)*/
-#define EVO_RCM4_PID           0x0303  /* Evolution robotics RCM4 PID */
-
-/* Pyramid Computer GmbH */
-#define FTDI_PYRAMID_PID       0xE6C8  /* Pyramid Appliance Display */
-
-/*
- * NDI (www.ndigital.com) product ids
- */
-#define FTDI_NDI_HUC_PID               0xDA70  /* NDI Host USB Converter */
-#define FTDI_NDI_SPECTRA_SCU_PID       0xDA71  /* NDI Spectra SCU */
-#define FTDI_NDI_FUTURE_2_PID          0xDA72  /* NDI future device #2 */
-#define FTDI_NDI_FUTURE_3_PID          0xDA73  /* NDI future device #3 */
-#define FTDI_NDI_AURORA_SCU_PID                0xDA74  /* NDI Aurora SCU */
-
-/*
- * Posiflex inc retail equipment (http://www.posiflex.com.tw)
- */
-#define POSIFLEX_VID           0x0d3a  /* Vendor ID */
-#define POSIFLEX_PP7000_PID    0x0300  /* PP-7000II thermal printer */
-
-/*
- * Westrex International devices submitted by Cory Lee
- */
-#define FTDI_WESTREX_MODEL_777_PID     0xDC00  /* Model 777 */
-#define FTDI_WESTREX_MODEL_8900F_PID   0xDC01  /* Model 8900F */
-
-/*
- * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
- */
-#define FTDI_RRCIRKITS_LOCOBUFFER_PID  0xc7d0  /* LocoBuffer USB */
-
-/*
- * Eclo (http://www.eclo.pt/) product IDs.
- * PID 0xEA90 submitted by Martin Grill.
- */
-#define FTDI_ECLO_COM_1WIRE_PID        0xEA90  /* COM to 1-Wire USB adaptor */
-
-/*
- * Papouch products (http://www.papouch.com/)
- * Submitted by Folkert van Heusden
- */
-
-#define PAPOUCH_VID                    0x5050  /* Vendor ID */
-#define PAPOUCH_TMU_PID                        0x0400  /* TMU USB Thermometer */
-#define PAPOUCH_QUIDO4x4_PID           0x0900  /* Quido 4/4 Module */
-
-/*
- * ACG Identification Technologies GmbH products (http://www.acg.de/).
- * Submitted by anton -at- goto10 -dot- org.
  */
-#define FTDI_ACG_HFDUAL_PID            0xDD20  /* HF Dual ISO Reader (RFID) */
-
-/*
- * Yost Engineering, Inc. products (www.yostengineering.com).
- * PID 0xE050 submitted by Aaron Prose.
- */
-#define FTDI_YEI_SERVOCENTER31_PID     0xE050  /* YEI ServoCenter3.1 USB */
-
-/*
- * ThorLabs USB motor drivers
- */
-#define FTDI_THORLABS_PID              0xfaf0 /* ThorLabs USB motor drivers */
-
-/*
- * Testo products (http://www.testo.com/)
- * Submitted by Colin Leroy
- */
-#define TESTO_VID                      0x128D
-#define TESTO_USB_INTERFACE_PID                0x0001
-
-/*
- * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com.
- */
-#define FTDI_GAMMA_SCOUT_PID           0xD678  /* Gamma Scout online */
-
-/*
- * Tactrix OpenPort (ECU) devices.
- * OpenPort 1.3M submitted by Donour Sizemore.
- * OpenPort 1.3S and 1.3U submitted by Ian Abbott.
- */
-#define FTDI_TACTRIX_OPENPORT_13M_PID  0xCC48  /* OpenPort 1.3 Mitsubishi */
-#define FTDI_TACTRIX_OPENPORT_13S_PID  0xCC49  /* OpenPort 1.3 Subaru */
-#define FTDI_TACTRIX_OPENPORT_13U_PID  0xCC4A  /* OpenPort 1.3 Universal */
-
-/*
- * Telldus Technologies
- */
-#define TELLDUS_VID                    0x1781  /* Vendor ID */
-#define TELLDUS_TELLSTICK_PID          0x0C30  /* RF control dongle 433 MHz using FT232RL */
-
-/*
- * IBS elektronik product ids
- * Submitted by Thomas Schleusener
- */
-#define FTDI_IBS_US485_PID     0xff38  /* IBS US485 (USB<-->RS422/485 interface) */
-#define FTDI_IBS_PICPRO_PID    0xff39  /* IBS PIC-Programmer */
-#define FTDI_IBS_PCMCIA_PID    0xff3a  /* IBS Card reader for PCMCIA SRAM-cards */
-#define FTDI_IBS_PK1_PID       0xff3b  /* IBS PK1 - Particel counter */
-#define FTDI_IBS_RS232MON_PID  0xff3c  /* IBS RS232 - Monitor */
-#define FTDI_IBS_APP70_PID     0xff3d  /* APP 70 (dust monitoring system) */
-#define FTDI_IBS_PEDO_PID      0xff3e  /* IBS PEDO-Modem (RF modem 868.35 MHz) */
-#define FTDI_IBS_PROD_PID      0xff3f  /* future device */
-
-/*
- *  MaxStream devices  www.maxstream.net
- */
-#define FTDI_MAXSTREAM_PID     0xEE18  /* Xbee PKG-U Module */
-
-/* Olimex */
-#define OLIMEX_VID                     0x15BA
-#define OLIMEX_ARM_USB_OCD_PID         0x0003
-
-/* Luminary Micro Stellaris Boards, VID = FTDI_VID */
-/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */
-#define LMI_LM3S_DEVEL_BOARD_PID       0xbcd8
-#define LMI_LM3S_EVAL_BOARD_PID                0xbcd9
-
-/* www.elsterelectricity.com Elster Unicom III Optical Probe */
-#define FTDI_ELSTER_UNICOM_PID         0xE700 /* Product Id */
-
-/*
- * The Mobility Lab (TML)
- * Submitted by Pierre Castella
- */
-#define TML_VID                        0x1B91  /* Vendor ID */
-#define TML_USB_SERIAL_PID     0x0064  /* USB - Serial Converter */
-
-/* Propox devices */
-#define FTDI_PROPOX_JTAGCABLEII_PID    0xD738
-
-/* Rig Expert Ukraine devices */
-#define FTDI_REU_TINY_PID              0xED22  /* RigExpert Tiny */
-
-/* Domintell products  http://www.domintell.com */
-#define FTDI_DOMINTELL_DGQG_PID        0xEF50  /* Master */
-#define FTDI_DOMINTELL_DUSB_PID        0xEF51  /* DUSB01 module */
-
-/* Alti-2 products  http://www.alti-2.com */
-#define ALTI2_VID      0x1BC9
-#define ALTI2_N3_PID   0x6001  /* Neptune 3 */
 
 /* Commands */
 #define FTDI_SIO_RESET                 0 /* Reset the port */
 #define INTERFACE_C            3
 #define INTERFACE_D            4
 
-/*
- * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3
- * Submitted by Harald Welte <laforge@openmoko.org>
- */
-#define        FIC_VID                 0x1457
-#define        FIC_NEO1973_DEBUG_PID   0x5118
-
-/*
- * RATOC REX-USB60F
- */
-#define RATOC_VENDOR_ID                0x0584
-#define RATOC_PRODUCT_ID_USB60F        0xb020
-
-/*
- * DIEBOLD BCS SE923
- */
-#define DIEBOLD_BCS_SE923_PID  0xfb99
-
-/*
- * Atmel STK541
- */
-#define ATMEL_VID              0x03eb /* Vendor ID */
-#define STK541_PID             0x2109 /* Zigbee Controller */
-
-/*
- * Dresden Elektronic Sensor Terminal Board
- */
-#define DE_VID                 0x1cf1 /* Vendor ID */
-#define STB_PID                        0x0001 /* Sensor Terminal Board */
-#define WHT_PID                        0x0004 /* Wireless Handheld Terminal */
-
-/*
- * Blackfin gnICE JTAG
- * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice
- */
-#define ADI_VID                0x0456
-#define ADI_GNICE_PID          0xF000
-#define ADI_GNICEPLUS_PID      0xF001
-
-/*
- * JETI SPECTROMETER SPECBOS 1201
- * http://www.jeti.com/products/sys/scb/scb1201.php
- */
-#define JETI_VID               0x0c6c
-#define JETI_SPC1201_PID       0x04b2
-
-/*
- * Marvell SheevaPlug
- */
-#define MARVELL_VID            0x9e88
-#define MARVELL_SHEEVAPLUG_PID 0x9e8f
-
-#define FTDI_TURTELIZER_PID    0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */
-
-/*
- * GN Otometrics (http://www.otometrics.com)
- * Submitted by Ville Sundberg.
- */
-#define GN_OTOMETRICS_VID      0x0c33  /* Vendor ID */
-#define AURICAL_USB_PID                0x0010  /* Aurical USB Audiometer */
-
-/*
- * Bayer Ascensia Contour blood glucose meter USB-converter cable.
- * http://winglucofacts.com/cables/
- */
-#define BAYER_VID                      0x1A79
-#define BAYER_CONTOUR_CABLE_PID        0x6001
-
-/*
- * Marvell OpenRD Base, Client
- * http://www.open-rd.org
- * OpenRD Base, Client use VID 0x0403
- */
-#define MARVELL_OPENRD_PID     0x9e90
-
-/*
- * Hameg HO820 and HO870 interface (using VID 0x0403)
- */
-#define        HAMEG_HO820_PID         0xed74
-#define        HAMEG_HO870_PID         0xed71
 
 /*
  *   BmRequestType:  1100 0000b
@@ -1504,4 +554,3 @@ typedef enum {
  * B2..7       Length of message - (not including Byte 0)
  *
  */
-
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
new file mode 100644 (file)
index 0000000..da92b49
--- /dev/null
@@ -0,0 +1,986 @@
+/*
+ * vendor/product IDs (VID/PID) of devices using FTDI USB serial converters.
+ * Please keep numerically sorted within individual areas, thanks!
+ *
+ * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
+ * from Rudolf Gugler
+ *
+ */
+
+
+/**********************************/
+/***** devices using FTDI VID *****/
+/**********************************/
+
+
+#define FTDI_VID       0x0403  /* Vendor Id */
+
+
+/*** "original" FTDI device PIDs ***/
+
+#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
+#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
+#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
+#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
+#define FTDI_SIO_PID   0x8372  /* Product Id SIO application of 8U100AX  */
+#define FTDI_232RL_PID  0xFBFA  /* Product ID for FT232RL */
+
+
+/*** third-party PIDs (using FTDI_VID) ***/
+
+/*
+ * Marvell OpenRD Base, Client
+ * http://www.open-rd.org
+ * OpenRD Base, Client use VID 0x0403
+ */
+#define MARVELL_OPENRD_PID     0x9e90
+
+/* www.candapter.com Ewert Energy Systems CANdapter device */
+#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
+
+/* OOCDlink by Joern Kaipf <joernk@web.de>
+ * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */
+#define FTDI_OOCDLINK_PID      0xbaf8  /* Amontec JTAGkey */
+
+/* Luminary Micro Stellaris Boards, VID = FTDI_VID */
+/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */
+#define LMI_LM3S_DEVEL_BOARD_PID       0xbcd8
+#define LMI_LM3S_EVAL_BOARD_PID                0xbcd9
+
+#define FTDI_TURTELIZER_PID    0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */
+
+/* OpenDCC (www.opendcc.de) product id */
+#define FTDI_OPENDCC_PID       0xBFD8
+#define FTDI_OPENDCC_SNIFFER_PID       0xBFD9
+#define FTDI_OPENDCC_THROTTLE_PID      0xBFDA
+#define FTDI_OPENDCC_GATEWAY_PID       0xBFDB
+
+/*
+ * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
+ */
+#define FTDI_RRCIRKITS_LOCOBUFFER_PID  0xc7d0  /* LocoBuffer USB */
+
+/* DMX4ALL DMX Interfaces */
+#define FTDI_DMX4ALL 0xC850
+
+/*
+ * ASK.fr devices
+ */
+#define FTDI_ASK_RDR400_PID    0xC991  /* ASK RDR 400 series card reader */
+
+/* www.starting-point-systems.com ÂµChameleon device */
+#define FTDI_MICRO_CHAMELEON_PID       0xCAA0  /* Product Id */
+
+/*
+ * Tactrix OpenPort (ECU) devices.
+ * OpenPort 1.3M submitted by Donour Sizemore.
+ * OpenPort 1.3S and 1.3U submitted by Ian Abbott.
+ */
+#define FTDI_TACTRIX_OPENPORT_13M_PID  0xCC48  /* OpenPort 1.3 Mitsubishi */
+#define FTDI_TACTRIX_OPENPORT_13S_PID  0xCC49  /* OpenPort 1.3 Subaru */
+#define FTDI_TACTRIX_OPENPORT_13U_PID  0xCC4A  /* OpenPort 1.3 Universal */
+
+/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
+/* the VID is the standard ftdi vid (FTDI_VID) */
+#define FTDI_SCS_DEVICE_0_PID 0xD010    /* SCS PTC-IIusb */
+#define FTDI_SCS_DEVICE_1_PID 0xD011    /* SCS Tracker / DSP TNC */
+#define FTDI_SCS_DEVICE_2_PID 0xD012
+#define FTDI_SCS_DEVICE_3_PID 0xD013
+#define FTDI_SCS_DEVICE_4_PID 0xD014
+#define FTDI_SCS_DEVICE_5_PID 0xD015
+#define FTDI_SCS_DEVICE_6_PID 0xD016
+#define FTDI_SCS_DEVICE_7_PID 0xD017
+
+/* iPlus device */
+#define FTDI_IPLUS_PID 0xD070 /* Product Id */
+#define FTDI_IPLUS2_PID 0xD071 /* Product Id */
+
+/*
+ * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com.
+ */
+#define FTDI_GAMMA_SCOUT_PID           0xD678  /* Gamma Scout online */
+
+/* Propox devices */
+#define FTDI_PROPOX_JTAGCABLEII_PID    0xD738
+
+/*
+ * Xsens Technologies BV products (http://www.xsens.com).
+ */
+#define XSENS_CONVERTER_0_PID  0xD388
+#define XSENS_CONVERTER_1_PID  0xD389
+#define XSENS_CONVERTER_2_PID  0xD38A
+#define XSENS_CONVERTER_3_PID  0xD38B
+#define XSENS_CONVERTER_4_PID  0xD38C
+#define XSENS_CONVERTER_5_PID  0xD38D
+#define XSENS_CONVERTER_6_PID  0xD38E
+#define XSENS_CONVERTER_7_PID  0xD38F
+
+/*
+ * NDI (www.ndigital.com) product ids
+ */
+#define FTDI_NDI_HUC_PID               0xDA70  /* NDI Host USB Converter */
+#define FTDI_NDI_SPECTRA_SCU_PID       0xDA71  /* NDI Spectra SCU */
+#define FTDI_NDI_FUTURE_2_PID          0xDA72  /* NDI future device #2 */
+#define FTDI_NDI_FUTURE_3_PID          0xDA73  /* NDI future device #3 */
+#define FTDI_NDI_AURORA_SCU_PID                0xDA74  /* NDI Aurora SCU */
+
+/*
+ * Westrex International devices submitted by Cory Lee
+ */
+#define FTDI_WESTREX_MODEL_777_PID     0xDC00  /* Model 777 */
+#define FTDI_WESTREX_MODEL_8900F_PID   0xDC01  /* Model 8900F */
+
+/*
+ * ACG Identification Technologies GmbH products (http://www.acg.de/).
+ * Submitted by anton -at- goto10 -dot- org.
+ */
+#define FTDI_ACG_HFDUAL_PID            0xDD20  /* HF Dual ISO Reader (RFID) */
+
+/*
+ * Definitions for Artemis astronomical USB based cameras
+ * Check it at http://www.artemisccd.co.uk/
+ */
+#define FTDI_ARTEMIS_PID       0xDF28  /* All Artemis Cameras */
+
+/*
+ * Definitions for ATIK Instruments astronomical USB based cameras
+ * Check it at http://www.atik-instruments.com/
+ */
+#define FTDI_ATIK_ATK16_PID    0xDF30  /* ATIK ATK-16 Grayscale Camera */
+#define FTDI_ATIK_ATK16C_PID   0xDF32  /* ATIK ATK-16C Colour Camera */
+#define FTDI_ATIK_ATK16HR_PID  0xDF31  /* ATIK ATK-16HR Grayscale Camera */
+#define FTDI_ATIK_ATK16HRC_PID 0xDF33  /* ATIK ATK-16HRC Colour Camera */
+#define FTDI_ATIK_ATK16IC_PID   0xDF35  /* ATIK ATK-16IC Grayscale Camera */
+
+/*
+ * Yost Engineering, Inc. products (www.yostengineering.com).
+ * PID 0xE050 submitted by Aaron Prose.
+ */
+#define FTDI_YEI_SERVOCENTER31_PID     0xE050  /* YEI ServoCenter3.1 USB */
+
+/*
+ * ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
+ * All of these devices use FTDI's vendor ID (0x0403).
+ *
+ * The previously included PID for the UO 100 module was incorrect.
+ * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58).
+ *
+ * Armin Laeuger originally sent the PID for the UM 100 module.
+ */
+#define FTDI_ELV_FHZ1300PC_PID 0xE0E8  /* FHZ 1300 PC */
+#define FTDI_ELV_WS500_PID     0xE0E9  /* PC-Wetterstation (WS 500) */
+#define FTDI_ELV_HS485_PID     0xE0EA  /* USB to RS-485 adapter */
+#define FTDI_ELV_EM1010PC_PID  0xE0EF  /* Engery monitor EM 1010 PC */
+#define FTDI_ELV_CSI8_PID      0xE0F0  /* Computer-Schalt-Interface (CSI 8) */
+#define FTDI_ELV_EM1000DL_PID  0xE0F1  /* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */
+#define FTDI_ELV_PCK100_PID    0xE0F2  /* PC-Kabeltester (PCK 100) */
+#define FTDI_ELV_RFP500_PID    0xE0F3  /* HF-Leistungsmesser (RFP 500) */
+#define FTDI_ELV_FS20SIG_PID   0xE0F4  /* Signalgeber (FS 20 SIG) */
+#define FTDI_ELV_WS300PC_PID   0xE0F6  /* PC-Wetterstation (WS 300 PC) */
+#define FTDI_PHI_FISCO_PID      0xE40B  /* PHI Fisco USB to Serial cable */
+#define FTDI_ELV_UAD8_PID      0xF068  /* USB-AD-Wandler (UAD 8) */
+#define FTDI_ELV_UDA7_PID      0xF069  /* USB-DA-Wandler (UDA 7) */
+#define FTDI_ELV_USI2_PID      0xF06A  /* USB-Schrittmotoren-Interface (USI 2) */
+#define FTDI_ELV_T1100_PID     0xF06B  /* Thermometer (T 1100) */
+#define FTDI_ELV_PCD200_PID    0xF06C  /* PC-Datenlogger (PCD 200) */
+#define FTDI_ELV_ULA200_PID    0xF06D  /* USB-LCD-Ansteuerung (ULA 200) */
+#define FTDI_ELV_ALC8500_PID   0xF06E  /* ALC 8500 Expert */
+#define FTDI_ELV_FHZ1000PC_PID 0xF06F  /* FHZ 1000 PC */
+#define FTDI_ELV_UR100_PID     0xFB58  /* USB-RS232-Umsetzer (UR 100) */
+#define FTDI_ELV_UM100_PID     0xFB5A  /* USB-Modul UM 100 */
+#define FTDI_ELV_UO100_PID     0xFB5B  /* USB-Modul UO 100 */
+/* Additional ELV PIDs that default to using the FTDI D2XX drivers on
+ * MS Windows, rather than the FTDI Virtual Com Port drivers.
+ * Maybe these will be easier to use with the libftdi/libusb user-space
+ * drivers, or possibly the Comedi drivers in some cases. */
+#define FTDI_ELV_CLI7000_PID   0xFB59  /* Computer-Light-Interface (CLI 7000) */
+#define FTDI_ELV_PPS7330_PID   0xFB5C  /* Processor-Power-Supply (PPS 7330) */
+#define FTDI_ELV_TFM100_PID    0xFB5D  /* Temperartur-Feuchte Messgeraet (TFM 100) */
+#define FTDI_ELV_UDF77_PID     0xFB5E  /* USB DCF Funkurh (UDF 77) */
+#define FTDI_ELV_UIO88_PID     0xFB5F  /* USB-I/O Interface (UIO 88) */
+
+/*
+ * EVER Eco Pro UPS (http://www.ever.com.pl/)
+ */
+
+#define        EVER_ECO_PRO_CDS        0xe520  /* RS-232 converter */
+
+/*
+ * Active Robots product ids.
+ */
+#define FTDI_ACTIVE_ROBOTS_PID 0xE548  /* USB comms board */
+
+/* Pyramid Computer GmbH */
+#define FTDI_PYRAMID_PID       0xE6C8  /* Pyramid Appliance Display */
+
+/* www.elsterelectricity.com Elster Unicom III Optical Probe */
+#define FTDI_ELSTER_UNICOM_PID         0xE700 /* Product Id */
+
+/*
+ * Gude Analog- und Digitalsysteme GmbH
+ */
+#define FTDI_GUDEADS_E808_PID    0xE808
+#define FTDI_GUDEADS_E809_PID    0xE809
+#define FTDI_GUDEADS_E80A_PID    0xE80A
+#define FTDI_GUDEADS_E80B_PID    0xE80B
+#define FTDI_GUDEADS_E80C_PID    0xE80C
+#define FTDI_GUDEADS_E80D_PID    0xE80D
+#define FTDI_GUDEADS_E80E_PID    0xE80E
+#define FTDI_GUDEADS_E80F_PID    0xE80F
+#define FTDI_GUDEADS_E888_PID    0xE888  /* Expert ISDN Control USB */
+#define FTDI_GUDEADS_E889_PID    0xE889  /* USB RS-232 OptoBridge */
+#define FTDI_GUDEADS_E88A_PID    0xE88A
+#define FTDI_GUDEADS_E88B_PID    0xE88B
+#define FTDI_GUDEADS_E88C_PID    0xE88C
+#define FTDI_GUDEADS_E88D_PID    0xE88D
+#define FTDI_GUDEADS_E88E_PID    0xE88E
+#define FTDI_GUDEADS_E88F_PID    0xE88F
+
+/*
+ * Eclo (http://www.eclo.pt/) product IDs.
+ * PID 0xEA90 submitted by Martin Grill.
+ */
+#define FTDI_ECLO_COM_1WIRE_PID        0xEA90  /* COM to 1-Wire USB adaptor */
+
+/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */
+#define FTDI_TNC_X_PID         0xEBE0
+
+/*
+ * Teratronik product ids.
+ * Submitted by O. Wölfelschneider.
+ */
+#define FTDI_TERATRONIK_VCP_PID         0xEC88 /* Teratronik device (preferring VCP driver on windows) */
+#define FTDI_TERATRONIK_D2XX_PID 0xEC89        /* Teratronik device (preferring D2XX driver on windows) */
+
+/* Rig Expert Ukraine devices */
+#define FTDI_REU_TINY_PID              0xED22  /* RigExpert Tiny */
+
+/*
+ * Hameg HO820 and HO870 interface (using VID 0x0403)
+ */
+#define        HAMEG_HO820_PID         0xed74
+#define        HAMEG_HO870_PID         0xed71
+
+/*
+ *  MaxStream devices  www.maxstream.net
+ */
+#define FTDI_MAXSTREAM_PID     0xEE18  /* Xbee PKG-U Module */
+
+/*
+ * microHAM product IDs (http://www.microham.com).
+ * Submitted by Justin Burket (KL1RL) <zorton@jtan.com>
+ * and Mike Studer (K6EEP) <k6eep@hamsoftware.org>.
+ * Ian Abbott <abbotti@mev.co.uk> added a few more from the driver INF file.
+ */
+#define FTDI_MHAM_KW_PID 0xEEE8                /* USB-KW interface */
+#define FTDI_MHAM_YS_PID 0xEEE9                /* USB-YS interface */
+#define FTDI_MHAM_Y6_PID 0xEEEA                /* USB-Y6 interface */
+#define FTDI_MHAM_Y8_PID 0xEEEB                /* USB-Y8 interface */
+#define FTDI_MHAM_IC_PID 0xEEEC                /* USB-IC interface */
+#define FTDI_MHAM_DB9_PID 0xEEED       /* USB-DB9 interface */
+#define FTDI_MHAM_RS232_PID 0xEEEE     /* USB-RS232 interface */
+#define FTDI_MHAM_Y9_PID 0xEEEF                /* USB-Y9 interface */
+
+/* Domintell products  http://www.domintell.com */
+#define FTDI_DOMINTELL_DGQG_PID        0xEF50  /* Master */
+#define FTDI_DOMINTELL_DUSB_PID        0xEF51  /* DUSB01 module */
+
+/*
+ * The following are the values for the Perle Systems
+ * UltraPort USB serial converters
+ */
+#define FTDI_PERLE_ULTRAPORT_PID 0xF0C0        /* Perle UltraPort Product Id */
+
+/* Sprog II (Andrew Crosland's SprogII DCC interface) */
+#define FTDI_SPROG_II          0xF0C8
+
+/* an infrared receiver for user access control with IR tags */
+#define FTDI_PIEGROUP_PID      0xF208  /* Product Id */
+
+/* ACT Solutions HomePro ZWave interface
+   (http://www.act-solutions.com/HomePro.htm) */
+#define FTDI_ACTZWAVE_PID      0xF2D0
+
+/*
+ * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485,
+ * USB-TTY activ, USB-TTY passiv.  Some PIDs are used by several devices
+ * and I'm not entirely sure which are used by which.
+ */
+#define FTDI_4N_GALAXY_DE_1_PID        0xF3C0
+#define FTDI_4N_GALAXY_DE_2_PID        0xF3C1
+
+/*
+ * Linx Technologies product ids
+ */
+#define LINX_SDMUSBQSS_PID     0xF448  /* Linx SDM-USB-QS-S */
+#define LINX_MASTERDEVEL2_PID   0xF449   /* Linx Master Development 2.0 */
+#define LINX_FUTURE_0_PID   0xF44A   /* Linx future device */
+#define LINX_FUTURE_1_PID   0xF44B   /* Linx future device */
+#define LINX_FUTURE_2_PID   0xF44C   /* Linx future device */
+
+/*
+ * Oceanic product ids
+ */
+#define FTDI_OCEANIC_PID       0xF460  /* Oceanic dive instrument */
+
+/*
+ * SUUNTO product ids
+ */
+#define FTDI_SUUNTO_SPORTS_PID 0xF680  /* Suunto Sports instrument */
+
+/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */
+/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
+#define FTDI_USB_UIRT_PID      0xF850  /* Product Id */
+
+/* CCS Inc. ICDU/ICDU40 product ID -
+ * the FT232BM is used in an in-circuit-debugger unit for PIC16's/PIC18's */
+#define FTDI_CCSICDU20_0_PID    0xF9D0
+#define FTDI_CCSICDU40_1_PID    0xF9D1
+#define FTDI_CCSMACHX_2_PID     0xF9D2
+#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3
+#define FTDI_CCSICDU64_4_PID    0xF9D4
+#define FTDI_CCSPRIME8_5_PID    0xF9D5
+
+/*
+ * The following are the values for the Matrix Orbital LCD displays,
+ * which are the FT232BM ( similar to the 8U232AM )
+ */
+#define FTDI_MTXORB_0_PID      0xFA00  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_1_PID      0xFA01  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_2_PID      0xFA02  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_3_PID      0xFA03  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_4_PID      0xFA04  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_5_PID      0xFA05  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_6_PID      0xFA06  /* Matrix Orbital Product Id */
+
+/*
+ * Home Electronics (www.home-electro.com) USB gadgets
+ */
+#define FTDI_HE_TIRA1_PID      0xFA78  /* Tira-1 IR transceiver */
+
+/* Inside Accesso contactless reader (http://www.insidefr.com) */
+#define INSIDE_ACCESSO         0xFAD0
+
+/*
+ * ThorLabs USB motor drivers
+ */
+#define FTDI_THORLABS_PID              0xfaf0 /* ThorLabs USB motor drivers */
+
+/*
+ * Protego product ids
+ */
+#define PROTEGO_SPECIAL_1      0xFC70  /* special/unknown device */
+#define PROTEGO_R2X0           0xFC71  /* R200-USB TRNG unit (R210, R220, and R230) */
+#define PROTEGO_SPECIAL_3      0xFC72  /* special/unknown device */
+#define PROTEGO_SPECIAL_4      0xFC73  /* special/unknown device */
+
+/*
+ * DSS-20 Sync Station for Sony Ericsson P800
+ */
+#define FTDI_DSS20_PID          0xFC82
+
+/* www.irtrans.de device */
+#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
+
+/*
+ * RM Michaelides CANview USB (http://www.rmcan.com) (FTDI_VID)
+ * CAN fieldbus interface adapter, added by port GmbH www.port.de)
+ * Ian Abbott changed the macro names for consistency.
+ */
+#define FTDI_RM_CANVIEW_PID    0xfd60  /* Product Id */
+/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */
+#define FTDI_TTUSB_PID 0xFF20 /* Product Id */
+
+#define FTDI_USBX_707_PID 0xF857       /* ADSTech IR Blaster USBX-707 (FTDI_VID) */
+
+#define FTDI_RELAIS_PID        0xFA10  /* Relais device from Rudolf Gugler */
+
+/*
+ * PCDJ use ftdi based dj-controllers. The following PID is
+ * for their DAC-2 device http://www.pcdjhardware.com/DAC2.asp
+ * (the VID is the standard ftdi vid (FTDI_VID), PID sent by Wouter Paesen)
+ */
+#define FTDI_PCDJ_DAC2_PID 0xFA88
+
+#define FTDI_R2000KU_TRUE_RNG  0xFB80  /* R2000KU TRUE RNG (FTDI_VID) */
+
+/*
+ * DIEBOLD BCS SE923 (FTDI_VID)
+ */
+#define DIEBOLD_BCS_SE923_PID  0xfb99
+
+/* www.crystalfontz.com devices
+ * - thanx for providing free devices for evaluation !
+ * they use the ftdi chipset for the USB interface
+ * and the vendor id is the same
+ */
+#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */
+#define FTDI_XF_634_PID 0xFC09 /* 634: 20x4 Character Display */
+#define FTDI_XF_547_PID 0xFC0A /* 547: Two line Display */
+#define FTDI_XF_633_PID 0xFC0B /* 633: 16x2 Character Display with Keys */
+#define FTDI_XF_631_PID 0xFC0C /* 631: 20x2 Character Display */
+#define FTDI_XF_635_PID 0xFC0D /* 635: 20x4 Character Display */
+#define FTDI_XF_640_PID 0xFC0E /* 640: Two line Display */
+#define FTDI_XF_642_PID 0xFC0F /* 642: Two line Display */
+
+/*
+ * Video Networks Limited / Homechoice in the UK use an ftdi-based device
+ * for their 1Mb broadband internet service.  The following PID is exhibited
+ * by the usb device supplied (the VID is the standard ftdi vid (FTDI_VID)
+ */
+#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */
+
+/* AlphaMicro Components AMC-232USB01 device (FTDI_VID) */
+#define FTDI_AMC232_PID 0xFF00 /* Product Id */
+
+/*
+ * IBS elektronik product ids (FTDI_VID)
+ * Submitted by Thomas Schleusener
+ */
+#define FTDI_IBS_US485_PID     0xff38  /* IBS US485 (USB<-->RS422/485 interface) */
+#define FTDI_IBS_PICPRO_PID    0xff39  /* IBS PIC-Programmer */
+#define FTDI_IBS_PCMCIA_PID    0xff3a  /* IBS Card reader for PCMCIA SRAM-cards */
+#define FTDI_IBS_PK1_PID       0xff3b  /* IBS PK1 - Particel counter */
+#define FTDI_IBS_RS232MON_PID  0xff3c  /* IBS RS232 - Monitor */
+#define FTDI_IBS_APP70_PID     0xff3d  /* APP 70 (dust monitoring system) */
+#define FTDI_IBS_PEDO_PID      0xff3e  /* IBS PEDO-Modem (RF modem 868.35 MHz) */
+#define FTDI_IBS_PROD_PID      0xff3f  /* future device */
+/* www.canusb.com Lawicel CANUSB device (FTDI_VID) */
+#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */
+
+
+
+/********************************/
+/** third-party VID/PID combos **/
+/********************************/
+
+
+
+/*
+ * Atmel STK541
+ */
+#define ATMEL_VID              0x03eb /* Vendor ID */
+#define STK541_PID             0x2109 /* Zigbee Controller */
+
+/*
+ * Blackfin gnICE JTAG
+ * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice
+ */
+#define ADI_VID                0x0456
+#define ADI_GNICE_PID          0xF000
+#define ADI_GNICEPLUS_PID      0xF001
+
+/*
+ * RATOC REX-USB60F
+ */
+#define RATOC_VENDOR_ID                0x0584
+#define RATOC_PRODUCT_ID_USB60F        0xb020
+
+/*
+ * Definitions for B&B Electronics products.
+ */
+#define BANDB_VID              0x0856  /* B&B Electronics Vendor ID */
+#define BANDB_USOTL4_PID       0xAC01  /* USOTL4 Isolated RS-485 Converter */
+#define BANDB_USTL4_PID                0xAC02  /* USTL4 RS-485 Converter */
+#define BANDB_USO9ML2_PID      0xAC03  /* USO9ML2 Isolated RS-232 Converter */
+#define BANDB_USOPTL4_PID      0xAC11
+#define BANDB_USPTL4_PID       0xAC12
+#define BANDB_USO9ML2DR_2_PID  0xAC16
+#define BANDB_USO9ML2DR_PID    0xAC17
+#define BANDB_USOPTL4DR2_PID   0xAC18  /* USOPTL4R-2 2-port Isolated RS-232 Converter */
+#define BANDB_USOPTL4DR_PID    0xAC19
+#define BANDB_485USB9F_2W_PID  0xAC25
+#define BANDB_485USB9F_4W_PID  0xAC26
+#define BANDB_232USB9M_PID     0xAC27
+#define BANDB_485USBTB_2W_PID  0xAC33
+#define BANDB_485USBTB_4W_PID  0xAC34
+#define BANDB_TTL5USB9M_PID    0xAC49
+#define BANDB_TTL3USB9M_PID    0xAC50
+#define BANDB_ZZ_PROG1_USB_PID 0xBA02
+
+/*
+ * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI
+ */
+#define INTREPID_VID           0x093C
+#define INTREPID_VALUECAN_PID  0x0601
+#define INTREPID_NEOVI_PID     0x0701
+
+/*
+ * Definitions for ID TECH (www.idt-net.com) devices
+ */
+#define IDTECH_VID             0x0ACD  /* ID TECH Vendor ID */
+#define IDTECH_IDT1221U_PID    0x0300  /* IDT1221U USB to RS-232 adapter */
+
+/*
+ * Definitions for Omnidirectional Control Technology, Inc. devices
+ */
+#define OCT_VID                        0x0B39  /* OCT vendor ID */
+/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */
+/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */
+/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */
+#define OCT_US101_PID          0x0421  /* OCT US101 USB to RS-232 */
+
+/*
+ * Icom ID-1 digital transceiver
+ */
+
+#define ICOM_ID1_VID            0x0C26
+#define ICOM_ID1_PID            0x0004
+
+/*
+ * GN Otometrics (http://www.otometrics.com)
+ * Submitted by Ville Sundberg.
+ */
+#define GN_OTOMETRICS_VID      0x0c33  /* Vendor ID */
+#define AURICAL_USB_PID                0x0010  /* Aurical USB Audiometer */
+
+/*
+ * The following are the values for the Sealevel SeaLINK+ adapters.
+ * (Original list sent by Tuan Hoang.  Ian Abbott renamed the macros and
+ * removed some PIDs that don't seem to match any existing products.)
+ */
+#define SEALEVEL_VID           0x0c52  /* Sealevel Vendor ID */
+#define SEALEVEL_2101_PID      0x2101  /* SeaLINK+232 (2101/2105) */
+#define SEALEVEL_2102_PID      0x2102  /* SeaLINK+485 (2102) */
+#define SEALEVEL_2103_PID      0x2103  /* SeaLINK+232I (2103) */
+#define SEALEVEL_2104_PID      0x2104  /* SeaLINK+485I (2104) */
+#define SEALEVEL_2106_PID      0x9020  /* SeaLINK+422 (2106) */
+#define SEALEVEL_2201_1_PID    0x2211  /* SeaPORT+2/232 (2201) Port 1 */
+#define SEALEVEL_2201_2_PID    0x2221  /* SeaPORT+2/232 (2201) Port 2 */
+#define SEALEVEL_2202_1_PID    0x2212  /* SeaPORT+2/485 (2202) Port 1 */
+#define SEALEVEL_2202_2_PID    0x2222  /* SeaPORT+2/485 (2202) Port 2 */
+#define SEALEVEL_2203_1_PID    0x2213  /* SeaPORT+2 (2203) Port 1 */
+#define SEALEVEL_2203_2_PID    0x2223  /* SeaPORT+2 (2203) Port 2 */
+#define SEALEVEL_2401_1_PID    0x2411  /* SeaPORT+4/232 (2401) Port 1 */
+#define SEALEVEL_2401_2_PID    0x2421  /* SeaPORT+4/232 (2401) Port 2 */
+#define SEALEVEL_2401_3_PID    0x2431  /* SeaPORT+4/232 (2401) Port 3 */
+#define SEALEVEL_2401_4_PID    0x2441  /* SeaPORT+4/232 (2401) Port 4 */
+#define SEALEVEL_2402_1_PID    0x2412  /* SeaPORT+4/485 (2402) Port 1 */
+#define SEALEVEL_2402_2_PID    0x2422  /* SeaPORT+4/485 (2402) Port 2 */
+#define SEALEVEL_2402_3_PID    0x2432  /* SeaPORT+4/485 (2402) Port 3 */
+#define SEALEVEL_2402_4_PID    0x2442  /* SeaPORT+4/485 (2402) Port 4 */
+#define SEALEVEL_2403_1_PID    0x2413  /* SeaPORT+4 (2403) Port 1 */
+#define SEALEVEL_2403_2_PID    0x2423  /* SeaPORT+4 (2403) Port 2 */
+#define SEALEVEL_2403_3_PID    0x2433  /* SeaPORT+4 (2403) Port 3 */
+#define SEALEVEL_2403_4_PID    0x2443  /* SeaPORT+4 (2403) Port 4 */
+#define SEALEVEL_2801_1_PID    0X2811  /* SeaLINK+8/232 (2801) Port 1 */
+#define SEALEVEL_2801_2_PID    0X2821  /* SeaLINK+8/232 (2801) Port 2 */
+#define SEALEVEL_2801_3_PID    0X2831  /* SeaLINK+8/232 (2801) Port 3 */
+#define SEALEVEL_2801_4_PID    0X2841  /* SeaLINK+8/232 (2801) Port 4 */
+#define SEALEVEL_2801_5_PID    0X2851  /* SeaLINK+8/232 (2801) Port 5 */
+#define SEALEVEL_2801_6_PID    0X2861  /* SeaLINK+8/232 (2801) Port 6 */
+#define SEALEVEL_2801_7_PID    0X2871  /* SeaLINK+8/232 (2801) Port 7 */
+#define SEALEVEL_2801_8_PID    0X2881  /* SeaLINK+8/232 (2801) Port 8 */
+#define SEALEVEL_2802_1_PID    0X2812  /* SeaLINK+8/485 (2802) Port 1 */
+#define SEALEVEL_2802_2_PID    0X2822  /* SeaLINK+8/485 (2802) Port 2 */
+#define SEALEVEL_2802_3_PID    0X2832  /* SeaLINK+8/485 (2802) Port 3 */
+#define SEALEVEL_2802_4_PID    0X2842  /* SeaLINK+8/485 (2802) Port 4 */
+#define SEALEVEL_2802_5_PID    0X2852  /* SeaLINK+8/485 (2802) Port 5 */
+#define SEALEVEL_2802_6_PID    0X2862  /* SeaLINK+8/485 (2802) Port 6 */
+#define SEALEVEL_2802_7_PID    0X2872  /* SeaLINK+8/485 (2802) Port 7 */
+#define SEALEVEL_2802_8_PID    0X2882  /* SeaLINK+8/485 (2802) Port 8 */
+#define SEALEVEL_2803_1_PID    0X2813  /* SeaLINK+8 (2803) Port 1 */
+#define SEALEVEL_2803_2_PID    0X2823  /* SeaLINK+8 (2803) Port 2 */
+#define SEALEVEL_2803_3_PID    0X2833  /* SeaLINK+8 (2803) Port 3 */
+#define SEALEVEL_2803_4_PID    0X2843  /* SeaLINK+8 (2803) Port 4 */
+#define SEALEVEL_2803_5_PID    0X2853  /* SeaLINK+8 (2803) Port 5 */
+#define SEALEVEL_2803_6_PID    0X2863  /* SeaLINK+8 (2803) Port 6 */
+#define SEALEVEL_2803_7_PID    0X2873  /* SeaLINK+8 (2803) Port 7 */
+#define SEALEVEL_2803_8_PID    0X2883  /* SeaLINK+8 (2803) Port 8 */
+
+/*
+ * JETI SPECTROMETER SPECBOS 1201
+ * http://www.jeti.com/products/sys/scb/scb1201.php
+ */
+#define JETI_VID               0x0c6c
+#define JETI_SPC1201_PID       0x04b2
+
+/*
+ * FTDI USB UART chips used in construction projects from the
+ * Elektor Electronics magazine (http://elektor-electronics.co.uk)
+ */
+#define ELEKTOR_VID            0x0C7D
+#define ELEKTOR_FT323R_PID     0x0005  /* RFID-Reader, issue 09-2006 */
+
+/*
+ * Posiflex inc retail equipment (http://www.posiflex.com.tw)
+ */
+#define POSIFLEX_VID           0x0d3a  /* Vendor ID */
+#define POSIFLEX_PP7000_PID    0x0300  /* PP-7000II thermal printer */
+
+/*
+ * The following are the values for two KOBIL chipcard terminals.
+ */
+#define KOBIL_VID              0x0d46  /* KOBIL Vendor ID */
+#define KOBIL_CONV_B1_PID      0x2020  /* KOBIL Konverter for B1 */
+#define KOBIL_CONV_KAAN_PID    0x2021  /* KOBIL_Konverter for KAAN */
+
+#define FTDI_NF_RIC_VID        0x0DCD  /* Vendor Id */
+#define FTDI_NF_RIC_PID        0x0001  /* Product Id */
+
+/*
+ * Falcom Wireless Communications GmbH
+ */
+#define FALCOM_VID             0x0F94  /* Vendor Id */
+#define FALCOM_TWIST_PID       0x0001  /* Falcom Twist USB GPRS modem */
+#define FALCOM_SAMBA_PID       0x0005  /* Falcom Samba USB GPRS modem */
+
+/* Larsen and Brusgaard AltiTrack/USBtrack  */
+#define LARSENBRUSGAARD_VID            0x0FD8
+#define LB_ALTITRACK_PID               0x0001
+
+/*
+ * TTi (Thurlby Thandar Instruments)
+ */
+#define TTI_VID                        0x103E  /* Vendor Id */
+#define TTI_QL355P_PID         0x03E8  /* TTi QL355P power supply */
+
+/* Interbiometrics USB I/O Board */
+/* Developed for Interbiometrics by Rudolf Gugler */
+#define INTERBIOMETRICS_VID              0x1209
+#define INTERBIOMETRICS_IOBOARD_PID      0x1002
+#define INTERBIOMETRICS_MINI_IOBOARD_PID 0x1006
+
+/*
+ * Testo products (http://www.testo.com/)
+ * Submitted by Colin Leroy
+ */
+#define TESTO_VID                      0x128D
+#define TESTO_USB_INTERFACE_PID                0x0001
+
+/*
+ * Mobility Electronics products.
+ */
+#define MOBILITY_VID                   0x1342
+#define MOBILITY_USB_SERIAL_PID                0x0202  /* EasiDock USB 200 serial */
+
+/*
+ * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3
+ * Submitted by Harald Welte <laforge@openmoko.org>
+ */
+#define        FIC_VID                 0x1457
+#define        FIC_NEO1973_DEBUG_PID   0x5118
+
+/* Olimex */
+#define OLIMEX_VID                     0x15BA
+#define OLIMEX_ARM_USB_OCD_PID         0x0003
+
+/*
+ * Telldus Technologies
+ */
+#define TELLDUS_VID                    0x1781  /* Vendor ID */
+#define TELLDUS_TELLSTICK_PID          0x0C30  /* RF control dongle 433 MHz using FT232RL */
+
+/*
+ * Bayer Ascensia Contour blood glucose meter USB-converter cable.
+ * http://winglucofacts.com/cables/
+ */
+#define BAYER_VID                      0x1A79
+#define BAYER_CONTOUR_CABLE_PID        0x6001
+
+/*
+ * The following are the values for the Matrix Orbital FTDI Range
+ * Anything in this range will use an FT232RL.
+ */
+#define MTXORB_VID                     0x1B3D
+#define MTXORB_FTDI_RANGE_0100_PID     0x0100
+#define MTXORB_FTDI_RANGE_0101_PID     0x0101
+#define MTXORB_FTDI_RANGE_0102_PID     0x0102
+#define MTXORB_FTDI_RANGE_0103_PID     0x0103
+#define MTXORB_FTDI_RANGE_0104_PID     0x0104
+#define MTXORB_FTDI_RANGE_0105_PID     0x0105
+#define MTXORB_FTDI_RANGE_0106_PID     0x0106
+#define MTXORB_FTDI_RANGE_0107_PID     0x0107
+#define MTXORB_FTDI_RANGE_0108_PID     0x0108
+#define MTXORB_FTDI_RANGE_0109_PID     0x0109
+#define MTXORB_FTDI_RANGE_010A_PID     0x010A
+#define MTXORB_FTDI_RANGE_010B_PID     0x010B
+#define MTXORB_FTDI_RANGE_010C_PID     0x010C
+#define MTXORB_FTDI_RANGE_010D_PID     0x010D
+#define MTXORB_FTDI_RANGE_010E_PID     0x010E
+#define MTXORB_FTDI_RANGE_010F_PID     0x010F
+#define MTXORB_FTDI_RANGE_0110_PID     0x0110
+#define MTXORB_FTDI_RANGE_0111_PID     0x0111
+#define MTXORB_FTDI_RANGE_0112_PID     0x0112
+#define MTXORB_FTDI_RANGE_0113_PID     0x0113
+#define MTXORB_FTDI_RANGE_0114_PID     0x0114
+#define MTXORB_FTDI_RANGE_0115_PID     0x0115
+#define MTXORB_FTDI_RANGE_0116_PID     0x0116
+#define MTXORB_FTDI_RANGE_0117_PID     0x0117
+#define MTXORB_FTDI_RANGE_0118_PID     0x0118
+#define MTXORB_FTDI_RANGE_0119_PID     0x0119
+#define MTXORB_FTDI_RANGE_011A_PID     0x011A
+#define MTXORB_FTDI_RANGE_011B_PID     0x011B
+#define MTXORB_FTDI_RANGE_011C_PID     0x011C
+#define MTXORB_FTDI_RANGE_011D_PID     0x011D
+#define MTXORB_FTDI_RANGE_011E_PID     0x011E
+#define MTXORB_FTDI_RANGE_011F_PID     0x011F
+#define MTXORB_FTDI_RANGE_0120_PID     0x0120
+#define MTXORB_FTDI_RANGE_0121_PID     0x0121
+#define MTXORB_FTDI_RANGE_0122_PID     0x0122
+#define MTXORB_FTDI_RANGE_0123_PID     0x0123
+#define MTXORB_FTDI_RANGE_0124_PID     0x0124
+#define MTXORB_FTDI_RANGE_0125_PID     0x0125
+#define MTXORB_FTDI_RANGE_0126_PID     0x0126
+#define MTXORB_FTDI_RANGE_0127_PID     0x0127
+#define MTXORB_FTDI_RANGE_0128_PID     0x0128
+#define MTXORB_FTDI_RANGE_0129_PID     0x0129
+#define MTXORB_FTDI_RANGE_012A_PID     0x012A
+#define MTXORB_FTDI_RANGE_012B_PID     0x012B
+#define MTXORB_FTDI_RANGE_012C_PID     0x012C
+#define MTXORB_FTDI_RANGE_012D_PID     0x012D
+#define MTXORB_FTDI_RANGE_012E_PID     0x012E
+#define MTXORB_FTDI_RANGE_012F_PID     0x012F
+#define MTXORB_FTDI_RANGE_0130_PID     0x0130
+#define MTXORB_FTDI_RANGE_0131_PID     0x0131
+#define MTXORB_FTDI_RANGE_0132_PID     0x0132
+#define MTXORB_FTDI_RANGE_0133_PID     0x0133
+#define MTXORB_FTDI_RANGE_0134_PID     0x0134
+#define MTXORB_FTDI_RANGE_0135_PID     0x0135
+#define MTXORB_FTDI_RANGE_0136_PID     0x0136
+#define MTXORB_FTDI_RANGE_0137_PID     0x0137
+#define MTXORB_FTDI_RANGE_0138_PID     0x0138
+#define MTXORB_FTDI_RANGE_0139_PID     0x0139
+#define MTXORB_FTDI_RANGE_013A_PID     0x013A
+#define MTXORB_FTDI_RANGE_013B_PID     0x013B
+#define MTXORB_FTDI_RANGE_013C_PID     0x013C
+#define MTXORB_FTDI_RANGE_013D_PID     0x013D
+#define MTXORB_FTDI_RANGE_013E_PID     0x013E
+#define MTXORB_FTDI_RANGE_013F_PID     0x013F
+#define MTXORB_FTDI_RANGE_0140_PID     0x0140
+#define MTXORB_FTDI_RANGE_0141_PID     0x0141
+#define MTXORB_FTDI_RANGE_0142_PID     0x0142
+#define MTXORB_FTDI_RANGE_0143_PID     0x0143
+#define MTXORB_FTDI_RANGE_0144_PID     0x0144
+#define MTXORB_FTDI_RANGE_0145_PID     0x0145
+#define MTXORB_FTDI_RANGE_0146_PID     0x0146
+#define MTXORB_FTDI_RANGE_0147_PID     0x0147
+#define MTXORB_FTDI_RANGE_0148_PID     0x0148
+#define MTXORB_FTDI_RANGE_0149_PID     0x0149
+#define MTXORB_FTDI_RANGE_014A_PID     0x014A
+#define MTXORB_FTDI_RANGE_014B_PID     0x014B
+#define MTXORB_FTDI_RANGE_014C_PID     0x014C
+#define MTXORB_FTDI_RANGE_014D_PID     0x014D
+#define MTXORB_FTDI_RANGE_014E_PID     0x014E
+#define MTXORB_FTDI_RANGE_014F_PID     0x014F
+#define MTXORB_FTDI_RANGE_0150_PID     0x0150
+#define MTXORB_FTDI_RANGE_0151_PID     0x0151
+#define MTXORB_FTDI_RANGE_0152_PID     0x0152
+#define MTXORB_FTDI_RANGE_0153_PID     0x0153
+#define MTXORB_FTDI_RANGE_0154_PID     0x0154
+#define MTXORB_FTDI_RANGE_0155_PID     0x0155
+#define MTXORB_FTDI_RANGE_0156_PID     0x0156
+#define MTXORB_FTDI_RANGE_0157_PID     0x0157
+#define MTXORB_FTDI_RANGE_0158_PID     0x0158
+#define MTXORB_FTDI_RANGE_0159_PID     0x0159
+#define MTXORB_FTDI_RANGE_015A_PID     0x015A
+#define MTXORB_FTDI_RANGE_015B_PID     0x015B
+#define MTXORB_FTDI_RANGE_015C_PID     0x015C
+#define MTXORB_FTDI_RANGE_015D_PID     0x015D
+#define MTXORB_FTDI_RANGE_015E_PID     0x015E
+#define MTXORB_FTDI_RANGE_015F_PID     0x015F
+#define MTXORB_FTDI_RANGE_0160_PID     0x0160
+#define MTXORB_FTDI_RANGE_0161_PID     0x0161
+#define MTXORB_FTDI_RANGE_0162_PID     0x0162
+#define MTXORB_FTDI_RANGE_0163_PID     0x0163
+#define MTXORB_FTDI_RANGE_0164_PID     0x0164
+#define MTXORB_FTDI_RANGE_0165_PID     0x0165
+#define MTXORB_FTDI_RANGE_0166_PID     0x0166
+#define MTXORB_FTDI_RANGE_0167_PID     0x0167
+#define MTXORB_FTDI_RANGE_0168_PID     0x0168
+#define MTXORB_FTDI_RANGE_0169_PID     0x0169
+#define MTXORB_FTDI_RANGE_016A_PID     0x016A
+#define MTXORB_FTDI_RANGE_016B_PID     0x016B
+#define MTXORB_FTDI_RANGE_016C_PID     0x016C
+#define MTXORB_FTDI_RANGE_016D_PID     0x016D
+#define MTXORB_FTDI_RANGE_016E_PID     0x016E
+#define MTXORB_FTDI_RANGE_016F_PID     0x016F
+#define MTXORB_FTDI_RANGE_0170_PID     0x0170
+#define MTXORB_FTDI_RANGE_0171_PID     0x0171
+#define MTXORB_FTDI_RANGE_0172_PID     0x0172
+#define MTXORB_FTDI_RANGE_0173_PID     0x0173
+#define MTXORB_FTDI_RANGE_0174_PID     0x0174
+#define MTXORB_FTDI_RANGE_0175_PID     0x0175
+#define MTXORB_FTDI_RANGE_0176_PID     0x0176
+#define MTXORB_FTDI_RANGE_0177_PID     0x0177
+#define MTXORB_FTDI_RANGE_0178_PID     0x0178
+#define MTXORB_FTDI_RANGE_0179_PID     0x0179
+#define MTXORB_FTDI_RANGE_017A_PID     0x017A
+#define MTXORB_FTDI_RANGE_017B_PID     0x017B
+#define MTXORB_FTDI_RANGE_017C_PID     0x017C
+#define MTXORB_FTDI_RANGE_017D_PID     0x017D
+#define MTXORB_FTDI_RANGE_017E_PID     0x017E
+#define MTXORB_FTDI_RANGE_017F_PID     0x017F
+#define MTXORB_FTDI_RANGE_0180_PID     0x0180
+#define MTXORB_FTDI_RANGE_0181_PID     0x0181
+#define MTXORB_FTDI_RANGE_0182_PID     0x0182
+#define MTXORB_FTDI_RANGE_0183_PID     0x0183
+#define MTXORB_FTDI_RANGE_0184_PID     0x0184
+#define MTXORB_FTDI_RANGE_0185_PID     0x0185
+#define MTXORB_FTDI_RANGE_0186_PID     0x0186
+#define MTXORB_FTDI_RANGE_0187_PID     0x0187
+#define MTXORB_FTDI_RANGE_0188_PID     0x0188
+#define MTXORB_FTDI_RANGE_0189_PID     0x0189
+#define MTXORB_FTDI_RANGE_018A_PID     0x018A
+#define MTXORB_FTDI_RANGE_018B_PID     0x018B
+#define MTXORB_FTDI_RANGE_018C_PID     0x018C
+#define MTXORB_FTDI_RANGE_018D_PID     0x018D
+#define MTXORB_FTDI_RANGE_018E_PID     0x018E
+#define MTXORB_FTDI_RANGE_018F_PID     0x018F
+#define MTXORB_FTDI_RANGE_0190_PID     0x0190
+#define MTXORB_FTDI_RANGE_0191_PID     0x0191
+#define MTXORB_FTDI_RANGE_0192_PID     0x0192
+#define MTXORB_FTDI_RANGE_0193_PID     0x0193
+#define MTXORB_FTDI_RANGE_0194_PID     0x0194
+#define MTXORB_FTDI_RANGE_0195_PID     0x0195
+#define MTXORB_FTDI_RANGE_0196_PID     0x0196
+#define MTXORB_FTDI_RANGE_0197_PID     0x0197
+#define MTXORB_FTDI_RANGE_0198_PID     0x0198
+#define MTXORB_FTDI_RANGE_0199_PID     0x0199
+#define MTXORB_FTDI_RANGE_019A_PID     0x019A
+#define MTXORB_FTDI_RANGE_019B_PID     0x019B
+#define MTXORB_FTDI_RANGE_019C_PID     0x019C
+#define MTXORB_FTDI_RANGE_019D_PID     0x019D
+#define MTXORB_FTDI_RANGE_019E_PID     0x019E
+#define MTXORB_FTDI_RANGE_019F_PID     0x019F
+#define MTXORB_FTDI_RANGE_01A0_PID     0x01A0
+#define MTXORB_FTDI_RANGE_01A1_PID     0x01A1
+#define MTXORB_FTDI_RANGE_01A2_PID     0x01A2
+#define MTXORB_FTDI_RANGE_01A3_PID     0x01A3
+#define MTXORB_FTDI_RANGE_01A4_PID     0x01A4
+#define MTXORB_FTDI_RANGE_01A5_PID     0x01A5
+#define MTXORB_FTDI_RANGE_01A6_PID     0x01A6
+#define MTXORB_FTDI_RANGE_01A7_PID     0x01A7
+#define MTXORB_FTDI_RANGE_01A8_PID     0x01A8
+#define MTXORB_FTDI_RANGE_01A9_PID     0x01A9
+#define MTXORB_FTDI_RANGE_01AA_PID     0x01AA
+#define MTXORB_FTDI_RANGE_01AB_PID     0x01AB
+#define MTXORB_FTDI_RANGE_01AC_PID     0x01AC
+#define MTXORB_FTDI_RANGE_01AD_PID     0x01AD
+#define MTXORB_FTDI_RANGE_01AE_PID     0x01AE
+#define MTXORB_FTDI_RANGE_01AF_PID     0x01AF
+#define MTXORB_FTDI_RANGE_01B0_PID     0x01B0
+#define MTXORB_FTDI_RANGE_01B1_PID     0x01B1
+#define MTXORB_FTDI_RANGE_01B2_PID     0x01B2
+#define MTXORB_FTDI_RANGE_01B3_PID     0x01B3
+#define MTXORB_FTDI_RANGE_01B4_PID     0x01B4
+#define MTXORB_FTDI_RANGE_01B5_PID     0x01B5
+#define MTXORB_FTDI_RANGE_01B6_PID     0x01B6
+#define MTXORB_FTDI_RANGE_01B7_PID     0x01B7
+#define MTXORB_FTDI_RANGE_01B8_PID     0x01B8
+#define MTXORB_FTDI_RANGE_01B9_PID     0x01B9
+#define MTXORB_FTDI_RANGE_01BA_PID     0x01BA
+#define MTXORB_FTDI_RANGE_01BB_PID     0x01BB
+#define MTXORB_FTDI_RANGE_01BC_PID     0x01BC
+#define MTXORB_FTDI_RANGE_01BD_PID     0x01BD
+#define MTXORB_FTDI_RANGE_01BE_PID     0x01BE
+#define MTXORB_FTDI_RANGE_01BF_PID     0x01BF
+#define MTXORB_FTDI_RANGE_01C0_PID     0x01C0
+#define MTXORB_FTDI_RANGE_01C1_PID     0x01C1
+#define MTXORB_FTDI_RANGE_01C2_PID     0x01C2
+#define MTXORB_FTDI_RANGE_01C3_PID     0x01C3
+#define MTXORB_FTDI_RANGE_01C4_PID     0x01C4
+#define MTXORB_FTDI_RANGE_01C5_PID     0x01C5
+#define MTXORB_FTDI_RANGE_01C6_PID     0x01C6
+#define MTXORB_FTDI_RANGE_01C7_PID     0x01C7
+#define MTXORB_FTDI_RANGE_01C8_PID     0x01C8
+#define MTXORB_FTDI_RANGE_01C9_PID     0x01C9
+#define MTXORB_FTDI_RANGE_01CA_PID     0x01CA
+#define MTXORB_FTDI_RANGE_01CB_PID     0x01CB
+#define MTXORB_FTDI_RANGE_01CC_PID     0x01CC
+#define MTXORB_FTDI_RANGE_01CD_PID     0x01CD
+#define MTXORB_FTDI_RANGE_01CE_PID     0x01CE
+#define MTXORB_FTDI_RANGE_01CF_PID     0x01CF
+#define MTXORB_FTDI_RANGE_01D0_PID     0x01D0
+#define MTXORB_FTDI_RANGE_01D1_PID     0x01D1
+#define MTXORB_FTDI_RANGE_01D2_PID     0x01D2
+#define MTXORB_FTDI_RANGE_01D3_PID     0x01D3
+#define MTXORB_FTDI_RANGE_01D4_PID     0x01D4
+#define MTXORB_FTDI_RANGE_01D5_PID     0x01D5
+#define MTXORB_FTDI_RANGE_01D6_PID     0x01D6
+#define MTXORB_FTDI_RANGE_01D7_PID     0x01D7
+#define MTXORB_FTDI_RANGE_01D8_PID     0x01D8
+#define MTXORB_FTDI_RANGE_01D9_PID     0x01D9
+#define MTXORB_FTDI_RANGE_01DA_PID     0x01DA
+#define MTXORB_FTDI_RANGE_01DB_PID     0x01DB
+#define MTXORB_FTDI_RANGE_01DC_PID     0x01DC
+#define MTXORB_FTDI_RANGE_01DD_PID     0x01DD
+#define MTXORB_FTDI_RANGE_01DE_PID     0x01DE
+#define MTXORB_FTDI_RANGE_01DF_PID     0x01DF
+#define MTXORB_FTDI_RANGE_01E0_PID     0x01E0
+#define MTXORB_FTDI_RANGE_01E1_PID     0x01E1
+#define MTXORB_FTDI_RANGE_01E2_PID     0x01E2
+#define MTXORB_FTDI_RANGE_01E3_PID     0x01E3
+#define MTXORB_FTDI_RANGE_01E4_PID     0x01E4
+#define MTXORB_FTDI_RANGE_01E5_PID     0x01E5
+#define MTXORB_FTDI_RANGE_01E6_PID     0x01E6
+#define MTXORB_FTDI_RANGE_01E7_PID     0x01E7
+#define MTXORB_FTDI_RANGE_01E8_PID     0x01E8
+#define MTXORB_FTDI_RANGE_01E9_PID     0x01E9
+#define MTXORB_FTDI_RANGE_01EA_PID     0x01EA
+#define MTXORB_FTDI_RANGE_01EB_PID     0x01EB
+#define MTXORB_FTDI_RANGE_01EC_PID     0x01EC
+#define MTXORB_FTDI_RANGE_01ED_PID     0x01ED
+#define MTXORB_FTDI_RANGE_01EE_PID     0x01EE
+#define MTXORB_FTDI_RANGE_01EF_PID     0x01EF
+#define MTXORB_FTDI_RANGE_01F0_PID     0x01F0
+#define MTXORB_FTDI_RANGE_01F1_PID     0x01F1
+#define MTXORB_FTDI_RANGE_01F2_PID     0x01F2
+#define MTXORB_FTDI_RANGE_01F3_PID     0x01F3
+#define MTXORB_FTDI_RANGE_01F4_PID     0x01F4
+#define MTXORB_FTDI_RANGE_01F5_PID     0x01F5
+#define MTXORB_FTDI_RANGE_01F6_PID     0x01F6
+#define MTXORB_FTDI_RANGE_01F7_PID     0x01F7
+#define MTXORB_FTDI_RANGE_01F8_PID     0x01F8
+#define MTXORB_FTDI_RANGE_01F9_PID     0x01F9
+#define MTXORB_FTDI_RANGE_01FA_PID     0x01FA
+#define MTXORB_FTDI_RANGE_01FB_PID     0x01FB
+#define MTXORB_FTDI_RANGE_01FC_PID     0x01FC
+#define MTXORB_FTDI_RANGE_01FD_PID     0x01FD
+#define MTXORB_FTDI_RANGE_01FE_PID     0x01FE
+#define MTXORB_FTDI_RANGE_01FF_PID     0x01FF
+
+
+
+/*
+ * The Mobility Lab (TML)
+ * Submitted by Pierre Castella
+ */
+#define TML_VID                        0x1B91  /* Vendor ID */
+#define TML_USB_SERIAL_PID     0x0064  /* USB - Serial Converter */
+
+/* Alti-2 products  http://www.alti-2.com */
+#define ALTI2_VID      0x1BC9
+#define ALTI2_N3_PID   0x6001  /* Neptune 3 */
+
+/*
+ * Dresden Elektronic Sensor Terminal Board
+ */
+#define DE_VID                 0x1cf1 /* Vendor ID */
+#define STB_PID                        0x0001 /* Sensor Terminal Board */
+#define WHT_PID                        0x0004 /* Wireless Handheld Terminal */
+
+/*
+ * Papouch products (http://www.papouch.com/)
+ * Submitted by Folkert van Heusden
+ */
+
+#define PAPOUCH_VID                    0x5050  /* Vendor ID */
+#define PAPOUCH_TMU_PID                        0x0400  /* TMU USB Thermometer */
+#define PAPOUCH_QUIDO4x4_PID           0x0900  /* Quido 4/4 Module */
+
+/*
+ * Marvell SheevaPlug
+ */
+#define MARVELL_VID            0x9e88
+#define MARVELL_SHEEVAPLUG_PID 0x9e8f
+
+/*
+ * Evolution Robotics products (http://www.evolution.com/).
+ * Submitted by Shawn M. Lavelle.
+ */
+#define EVOLUTION_VID          0xDEEE  /* Vendor ID */
+#define EVOLUTION_ER1_PID      0x0300  /* ER1 Control Module */
+#define EVO_8U232AM_PID        0x02FF  /* Evolution robotics RCM2 (FT232AM)*/
+#define EVO_HYBRID_PID         0x0302  /* Evolution robotics RCM4 PID (FT232BM)*/
+#define EVO_RCM4_PID           0x0303  /* Evolution robotics RCM4 PID */
index bbe005c..f1ea3a3 100644 (file)
@@ -276,7 +276,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port)
        if (port->write_urb_busy)
                start_io = false;
        else {
-               start_io = (__kfifo_len(port->write_fifo) != 0);
+               start_io = (kfifo_len(&port->write_fifo) != 0);
                port->write_urb_busy = start_io;
        }
        spin_unlock_irqrestore(&port->lock, flags);
@@ -285,7 +285,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port)
                return 0;
 
        data = port->write_urb->transfer_buffer;
-       count = kfifo_get(port->write_fifo, data, port->bulk_out_size);
+       count = kfifo_out_locked(&port->write_fifo, data, port->bulk_out_size, &port->lock);
        usb_serial_debug_data(debug, &port->dev, __func__, count, data);
 
        /* set up our urb */
@@ -345,7 +345,7 @@ int usb_serial_generic_write(struct tty_struct *tty,
                return usb_serial_multi_urb_write(tty, port,
                                                  buf, count);
 
-       count = kfifo_put(port->write_fifo, buf, count);
+       count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
        result = usb_serial_generic_write_start(port);
 
        if (result >= 0)
@@ -370,7 +370,7 @@ int usb_serial_generic_write_room(struct tty_struct *tty)
                                (serial->type->max_in_flight_urbs -
                                 port->urbs_in_flight);
        } else if (serial->num_bulk_out)
-               room = port->write_fifo->size - __kfifo_len(port->write_fifo);
+               room = kfifo_avail(&port->write_fifo);
        spin_unlock_irqrestore(&port->lock, flags);
 
        dbg("%s - returns %d", __func__, room);
@@ -391,7 +391,7 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
                chars = port->tx_bytes_flight;
                spin_unlock_irqrestore(&port->lock, flags);
        } else if (serial->num_bulk_out)
-               chars = kfifo_len(port->write_fifo);
+               chars = kfifo_len(&port->write_fifo);
 
        dbg("%s - returns %d", __func__, chars);
        return chars;
@@ -507,7 +507,7 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
                if (status) {
                        dbg("%s - nonzero multi-urb write bulk status "
                                "received: %d", __func__, status);
-                       kfifo_reset(port->write_fifo);
+                       kfifo_reset_out(&port->write_fifo);
                } else
                        usb_serial_generic_write_start(port);
        }
index 485fa9c..2cfe245 100644 (file)
 #define BANDB_DEVICE_ID_US9ML2_4       0xAC30
 #define BANDB_DEVICE_ID_USPTL4_2       0xAC31
 #define BANDB_DEVICE_ID_USPTL4_4       0xAC32
-#define BANDB_DEVICE_ID_USOPTL4_2       0xAC42
-#define BANDB_DEVICE_ID_USOPTL4_4       0xAC44
+#define BANDB_DEVICE_ID_USOPTL4_2      0xAC42
+#define BANDB_DEVICE_ID_USOPTL4_4      0xAC44
+#define BANDB_DEVICE_ID_USOPTL2_4      0xAC24
 
 /* This driver also supports
  * ATEN UC2324 device using Moschip MCS7840
@@ -191,6 +192,7 @@ static struct usb_device_id moschip_port_id_table[] = {
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+       {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)},
        {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
        {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
        {}                      /* terminating entry */
@@ -207,6 +209,7 @@ static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+       {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)},
        {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
        {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
        {}                      /* terminating entry */
index 9a2b903..6e94a67 100644 (file)
@@ -340,6 +340,10 @@ static int  option_resume(struct usb_serial *serial);
 #define FOUR_G_SYSTEMS_VENDOR_ID               0x1c9e
 #define FOUR_G_SYSTEMS_PRODUCT_W14             0x9603
 
+/* Haier products */
+#define HAIER_VENDOR_ID                                0x201e
+#define HAIER_PRODUCT_CE100                    0x2009
+
 static struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -641,6 +645,7 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
        { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
        { USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14) },
+       { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 4543f35..33c85f7 100644 (file)
@@ -595,8 +595,7 @@ static void port_release(struct device *dev)
        usb_free_urb(port->write_urb);
        usb_free_urb(port->interrupt_in_urb);
        usb_free_urb(port->interrupt_out_urb);
-       if (!IS_ERR(port->write_fifo) && port->write_fifo)
-               kfifo_free(port->write_fifo);
+       kfifo_free(&port->write_fifo);
        kfree(port->bulk_in_buffer);
        kfree(port->bulk_out_buffer);
        kfree(port->interrupt_in_buffer);
@@ -939,9 +938,7 @@ int usb_serial_probe(struct usb_interface *interface,
                        dev_err(&interface->dev, "No free urbs available\n");
                        goto probe_error;
                }
-               port->write_fifo = kfifo_alloc(PAGE_SIZE, GFP_KERNEL,
-                       &port->lock);
-               if (IS_ERR(port->write_fifo))
+               if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
                        goto probe_error;
                buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
                port->bulk_out_size = buffer_size;
index da84fd0..088f32f 100644 (file)
@@ -368,7 +368,7 @@ config ALIM7101_WDT
 
 config GEODE_WDT
        tristate "AMD Geode CS5535/CS5536 Watchdog"
-       depends on MGEODE_LX
+       depends on CS5535_MFGPT
        help
          This driver enables a watchdog capability built into the
          CS5535/CS5536 companion chips for the AMD Geode GX and LX
index 9acf001..38252ff 100644 (file)
@@ -1,6 +1,7 @@
-/* Watchdog timer for the Geode GX/LX with the CS5535/CS5536 companion chip
+/* Watchdog timer for machines with the CS5535/CS5536 companion chip
  *
  * Copyright (C) 2006-2007, Advanced Micro Devices, Inc.
+ * Copyright (C) 2009  Andres Salomon <dilinger@collabora.co.uk>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -19,7 +20,7 @@
 #include <linux/reboot.h>
 #include <linux/uaccess.h>
 
-#include <asm/geode.h>
+#include <linux/cs5535.h>
 
 #define GEODEWDT_HZ 500
 #define GEODEWDT_SCALE 6
@@ -46,25 +47,25 @@ MODULE_PARM_DESC(nowayout,
 
 static struct platform_device *geodewdt_platform_device;
 static unsigned long wdt_flags;
-static int wdt_timer;
+static struct cs5535_mfgpt_timer *wdt_timer;
 static int safe_close;
 
 static void geodewdt_ping(void)
 {
        /* Stop the counter */
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
 
        /* Reset the counter */
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
 
        /* Enable the counter */
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
 }
 
 static void geodewdt_disable(void)
 {
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
 }
 
 static int geodewdt_set_heartbeat(int val)
@@ -72,10 +73,10 @@ static int geodewdt_set_heartbeat(int val)
        if (val < 1 || val > GEODEWDT_MAX_SECONDS)
                return -EINVAL;
 
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_CMP2, val * GEODEWDT_HZ);
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_CMP2, val * GEODEWDT_HZ);
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
 
        timeout = val;
        return 0;
@@ -215,28 +216,25 @@ static struct miscdevice geodewdt_miscdev = {
 
 static int __devinit geodewdt_probe(struct platform_device *dev)
 {
-       int ret, timer;
-
-       timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING);
+       int ret;
 
-       if (timer == -1) {
+       wdt_timer = cs5535_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING);
+       if (!wdt_timer) {
                printk(KERN_ERR "geodewdt:  No timers were available\n");
                return -ENODEV;
        }
 
-       wdt_timer = timer;
-
        /* Set up the timer */
 
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP,
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP,
                          GEODEWDT_SCALE | (3 << 8));
 
        /* Set up comparator 2 to reset when the event fires */
-       geode_mfgpt_toggle_event(wdt_timer, MFGPT_CMP2, MFGPT_EVENT_RESET, 1);
+       cs5535_mfgpt_toggle_event(wdt_timer, MFGPT_CMP2, MFGPT_EVENT_RESET, 1);
 
        /* Set up the initial timeout */
 
-       geode_mfgpt_write(wdt_timer, MFGPT_REG_CMP2,
+       cs5535_mfgpt_write(wdt_timer, MFGPT_REG_CMP2,
                timeout * GEODEWDT_HZ);
 
        ret = misc_register(&geodewdt_miscdev);
index 2c99459..9f0bf13 100644 (file)
@@ -121,13 +121,13 @@ struct file *anon_inode_getfile(const char *name,
        d_instantiate(path.dentry, anon_inode_inode);
 
        error = -ENFILE;
-       file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops);
+       file = alloc_file(&path, OPEN_FMODE(flags), fops);
        if (!file)
                goto err_dput;
        file->f_mapping = anon_inode_inode->i_mapping;
 
        file->f_pos = 0;
-       file->f_flags = O_RDWR | (flags & O_NONBLOCK);
+       file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
        file->f_version = 0;
        file->private_data = priv;
 
index 14cbc83..332dd00 100644 (file)
@@ -1600,8 +1600,6 @@ static long do_ioctl_trans(int fd, unsigned int cmd,
        case KDSKBMETA:
        case KDSKBLED:
        case KDSETLED:
-       /* SG stuff */
-       case SG_SET_TRANSFORM:
        /* AUTOFS */
        case AUTOFS_IOC_READY:
        case AUTOFS_IOC_FAIL:
index 8b47e42..d26402f 100644 (file)
@@ -339,7 +339,7 @@ struct file *eventfd_file_create(unsigned int count, int flags)
        ctx->flags = flags;
 
        file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx,
-                                 flags & EFD_SHARED_FCNTL_FLAGS);
+                                 O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS));
        if (IS_ERR(file))
                eventfd_free_ctx(ctx);
 
index 366c503..bd056a5 100644 (file)
@@ -1206,7 +1206,7 @@ SYSCALL_DEFINE1(epoll_create1, int, flags)
         * a file structure and a free file descriptor.
         */
        error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
-                                flags & O_CLOEXEC);
+                                O_RDWR | (flags & O_CLOEXEC));
        if (error < 0)
                ep_free(ep);
 
index ad14227..455e6e6 100644 (file)
@@ -970,7 +970,7 @@ static int ext3_get_block(struct inode *inode, sector_t iblock,
                if (max_blocks > DIO_MAX_BLOCKS)
                        max_blocks = DIO_MAX_BLOCKS;
                handle = ext3_journal_start(inode, DIO_CREDITS +
-                               2 * EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb));
+                               EXT3_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb));
                if (IS_ERR(handle)) {
                        ret = PTR_ERR(handle);
                        goto out;
@@ -3146,8 +3146,8 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
 
                /* (user+group)*(old+new) structure, inode write (sb,
                 * inode block, ? - but truncate inode update has it) */
-               handle = ext3_journal_start(inode, 2*(EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)+
-                                       EXT3_QUOTA_DEL_BLOCKS(inode->i_sb))+3);
+               handle = ext3_journal_start(inode, EXT3_MAXQUOTAS_INIT_BLOCKS(inode->i_sb)+
+                                       EXT3_MAXQUOTAS_DEL_BLOCKS(inode->i_sb)+3);
                if (IS_ERR(handle)) {
                        error = PTR_ERR(handle);
                        goto err_out;
@@ -3239,7 +3239,7 @@ static int ext3_writepage_trans_blocks(struct inode *inode)
 #ifdef CONFIG_QUOTA
        /* We know that structure was already allocated during vfs_dq_init so
         * we will be updating only the data blocks + inodes */
-       ret += 2*EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb);
+       ret += EXT3_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb);
 #endif
 
        return ret;
index aad6400..7b0e44f 100644 (file)
@@ -1699,7 +1699,7 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
+                                       EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -1733,7 +1733,7 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
+                                       EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -1769,7 +1769,7 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
+                                       EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -1920,7 +1920,7 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode)
        struct ext3_iloc iloc;
        int err = 0, rc;
 
-       lock_super(sb);
+       mutex_lock(&EXT3_SB(sb)->s_orphan_lock);
        if (!list_empty(&EXT3_I(inode)->i_orphan))
                goto out_unlock;
 
@@ -1929,9 +1929,13 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode)
 
        /* @@@ FIXME: Observation from aviro:
         * I think I can trigger J_ASSERT in ext3_orphan_add().  We block
-        * here (on lock_super()), so race with ext3_link() which might bump
+        * here (on s_orphan_lock), so race with ext3_link() which might bump
         * ->i_nlink. For, say it, character device. Not a regular file,
         * not a directory, not a symlink and ->i_nlink > 0.
+        *
+        * tytso, 4/25/2009: I'm not sure how that could happen;
+        * shouldn't the fs core protect us from these sort of
+        * unlink()/link() races?
         */
        J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
                S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
@@ -1968,7 +1972,7 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode)
        jbd_debug(4, "orphan inode %lu will point to %d\n",
                        inode->i_ino, NEXT_ORPHAN(inode));
 out_unlock:
-       unlock_super(sb);
+       mutex_unlock(&EXT3_SB(sb)->s_orphan_lock);
        ext3_std_error(inode->i_sb, err);
        return err;
 }
@@ -1986,11 +1990,9 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode)
        struct ext3_iloc iloc;
        int err = 0;
 
-       lock_super(inode->i_sb);
-       if (list_empty(&ei->i_orphan)) {
-               unlock_super(inode->i_sb);
-               return 0;
-       }
+       mutex_lock(&EXT3_SB(inode->i_sb)->s_orphan_lock);
+       if (list_empty(&ei->i_orphan))
+               goto out;
 
        ino_next = NEXT_ORPHAN(inode);
        prev = ei->i_orphan.prev;
@@ -2040,7 +2042,7 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode)
 out_err:
        ext3_std_error(inode->i_sb, err);
 out:
-       unlock_super(inode->i_sb);
+       mutex_unlock(&EXT3_SB(inode->i_sb)->s_orphan_lock);
        return err;
 
 out_brelse:
@@ -2175,7 +2177,7 @@ static int ext3_symlink (struct inode * dir,
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
+                                       EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
index 5f83b61..54351ac 100644 (file)
@@ -209,7 +209,7 @@ static int setup_new_group_blocks(struct super_block *sb,
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_resize_lock);
        if (input->group != sbi->s_groups_count) {
                err = -EBUSY;
                goto exit_journal;
@@ -324,7 +324,7 @@ exit_bh:
        brelse(bh);
 
 exit_journal:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_resize_lock);
        if ((err2 = ext3_journal_stop(handle)) && !err)
                err = err2;
 
@@ -662,11 +662,12 @@ exit_free:
  * important part is that the new block and inode counts are in the backup
  * superblocks, and the location of the new group metadata in the GDT backups.
  *
- * We do not need lock_super() for this, because these blocks are not
- * otherwise touched by the filesystem code when it is mounted.  We don't
- * need to worry about last changing from sbi->s_groups_count, because the
- * worst that can happen is that we do not copy the full number of backups
- * at this time.  The resize which changed s_groups_count will backup again.
+ * We do not need take the s_resize_lock for this, because these
+ * blocks are not otherwise touched by the filesystem code when it is
+ * mounted.  We don't need to worry about last changing from
+ * sbi->s_groups_count, because the worst that can happen is that we
+ * do not copy the full number of backups at this time.  The resize
+ * which changed s_groups_count will backup again.
  */
 static void update_backups(struct super_block *sb,
                           int blk_off, char *data, int size)
@@ -825,7 +826,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
                goto exit_put;
        }
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_resize_lock);
        if (input->group != sbi->s_groups_count) {
                ext3_warning(sb, __func__,
                             "multiple resizers run on filesystem!");
@@ -856,7 +857,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
        /*
         * OK, now we've set up the new group.  Time to make it active.
         *
-        * Current kernels don't lock all allocations via lock_super(),
+        * We do not lock all allocations via s_resize_lock
         * so we have to be safe wrt. concurrent accesses the group
         * data.  So we need to be careful to set all of the relevant
         * group descriptor data etc. *before* we enable the group.
@@ -900,12 +901,12 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
         *
         * The precise rules we use are:
         *
-        * * Writers of s_groups_count *must* hold lock_super
+        * * Writers of s_groups_count *must* hold s_resize_lock
         * AND
         * * Writers must perform a smp_wmb() after updating all dependent
         *   data and before modifying the groups count
         *
-        * * Readers must hold lock_super() over the access
+        * * Readers must hold s_resize_lock over the access
         * OR
         * * Readers must perform an smp_rmb() after reading the groups count
         *   and before reading any dependent data.
@@ -936,7 +937,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
        ext3_journal_dirty_metadata(handle, sbi->s_sbh);
 
 exit_journal:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_resize_lock);
        if ((err2 = ext3_journal_stop(handle)) && !err)
                err = err2;
        if (!err) {
@@ -973,7 +974,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
 
        /* We don't need to worry about locking wrt other resizers just
         * yet: we're going to revalidate es->s_blocks_count after
-        * taking lock_super() below. */
+        * taking the s_resize_lock below. */
        o_blocks_count = le32_to_cpu(es->s_blocks_count);
        o_groups_count = EXT3_SB(sb)->s_groups_count;
 
@@ -1045,11 +1046,11 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
                goto exit_put;
        }
 
-       lock_super(sb);
+       mutex_lock(&EXT3_SB(sb)->s_resize_lock);
        if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
                ext3_warning(sb, __func__,
                             "multiple resizers run on filesystem!");
-               unlock_super(sb);
+               mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
                ext3_journal_stop(handle);
                err = -EBUSY;
                goto exit_put;
@@ -1059,13 +1060,13 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
                                                 EXT3_SB(sb)->s_sbh))) {
                ext3_warning(sb, __func__,
                             "error %d on journal write access", err);
-               unlock_super(sb);
+               mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
                ext3_journal_stop(handle);
                goto exit_put;
        }
        es->s_blocks_count = cpu_to_le32(o_blocks_count + add);
        ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-       unlock_super(sb);
+       mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
        ext3_debug("freeing blocks %lu through "E3FSBLK"\n", o_blocks_count,
                   o_blocks_count + add);
        ext3_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks);
index 7ad1e8c..afa2b56 100644 (file)
@@ -1928,6 +1928,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        sb->dq_op = &ext3_quota_operations;
 #endif
        INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
+       mutex_init(&sbi->s_orphan_lock);
+       mutex_init(&sbi->s_resize_lock);
 
        sb->s_root = NULL;
 
@@ -2014,14 +2016,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        }
 
        ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-       /*
-        * akpm: core read_super() calls in here with the superblock locked.
-        * That deadlocks, because orphan cleanup needs to lock the superblock
-        * in numerous places.  Here we just pop the lock - it's relatively
-        * harmless, because we are now ready to accept write_super() requests,
-        * and aviro says that's the only reason for hanging onto the
-        * superblock lock.
-        */
+
        EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS;
        ext3_orphan_cleanup(sb, es);
        EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS;
@@ -2403,13 +2398,11 @@ static void ext3_mark_recovery_complete(struct super_block * sb,
        if (journal_flush(journal) < 0)
                goto out;
 
-       lock_super(sb);
        if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
            sb->s_flags & MS_RDONLY) {
                EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
                ext3_commit_super(sb, es, 1);
        }
-       unlock_super(sb);
 
 out:
        journal_unlock_updates(journal);
@@ -2601,13 +2594,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                            (sbi->s_mount_state & EXT3_VALID_FS))
                                es->s_state = cpu_to_le16(sbi->s_mount_state);
 
-                       /*
-                        * We have to unlock super so that we can wait for
-                        * transactions.
-                        */
-                       unlock_super(sb);
                        ext3_mark_recovery_complete(sb, es);
-                       lock_super(sb);
                } else {
                        __le32 ret;
                        if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb,
index ab31e65..56f9271 100644 (file)
@@ -704,6 +704,10 @@ struct ext4_inode_info {
        __u16 i_extra_isize;
 
        spinlock_t i_block_reservation_lock;
+#ifdef CONFIG_QUOTA
+       /* quota space reservation, managed internally by quota code */
+       qsize_t i_reserved_quota;
+#endif
 
        /* completed async DIOs that might need unwritten extents handling */
        struct list_head i_aio_dio_complete_list;
@@ -1435,7 +1439,7 @@ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks);
 extern int ext4_block_truncate_page(handle_t *handle,
                struct address_space *mapping, loff_t from);
 extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
-extern qsize_t ext4_get_reserved_space(struct inode *inode);
+extern qsize_t *ext4_get_reserved_space(struct inode *inode);
 extern int flush_aio_dio_completed_IO(struct inode *inode);
 /* ioctl.c */
 extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
index 5352db1..ab80796 100644 (file)
@@ -1003,17 +1003,12 @@ out:
        return err;
 }
 
-qsize_t ext4_get_reserved_space(struct inode *inode)
+#ifdef CONFIG_QUOTA
+qsize_t *ext4_get_reserved_space(struct inode *inode)
 {
-       unsigned long long total;
-
-       spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
-       total = EXT4_I(inode)->i_reserved_data_blocks +
-               EXT4_I(inode)->i_reserved_meta_blocks;
-       spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
-
-       return (total << inode->i_blkbits);
+       return &EXT4_I(inode)->i_reserved_quota;
 }
+#endif
 /*
  * Calculate the number of metadata blocks need to reserve
  * to allocate @blocks for non extent file based file
@@ -1051,7 +1046,7 @@ static int ext4_calc_metadata_amount(struct inode *inode, int blocks)
 static void ext4_da_update_reserve_space(struct inode *inode, int used)
 {
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-       int total, mdb, mdb_free;
+       int total, mdb, mdb_free, mdb_claim = 0;
 
        spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
        /* recalculate the number of metablocks still need to be reserved */
@@ -1064,7 +1059,9 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
 
        if (mdb_free) {
                /* Account for allocated meta_blocks */
-               mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks;
+               mdb_claim = EXT4_I(inode)->i_allocated_meta_blocks;
+               BUG_ON(mdb_free < mdb_claim);
+               mdb_free -= mdb_claim;
 
                /* update fs dirty blocks counter */
                percpu_counter_sub(&sbi->s_dirtyblocks_counter, mdb_free);
@@ -1075,8 +1072,11 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
        /* update per-inode reservations */
        BUG_ON(used  > EXT4_I(inode)->i_reserved_data_blocks);
        EXT4_I(inode)->i_reserved_data_blocks -= used;
+       percpu_counter_sub(&sbi->s_dirtyblocks_counter, used + mdb_claim);
        spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 
+       vfs_dq_claim_block(inode, used + mdb_claim);
+
        /*
         * free those over-booking quota for metadata blocks
         */
@@ -1816,19 +1816,17 @@ repeat:
 
        md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks;
        total = md_needed + nrblocks;
+       spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 
        /*
         * Make quota reservation here to prevent quota overflow
         * later. Real quota accounting is done at pages writeout
         * time.
         */
-       if (vfs_dq_reserve_block(inode, total)) {
-               spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+       if (vfs_dq_reserve_block(inode, total))
                return -EDQUOT;
-       }
 
        if (ext4_claim_free_blocks(sbi, total)) {
-               spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
                vfs_dq_release_reservation_block(inode, total);
                if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
                        yield();
@@ -1836,10 +1834,11 @@ repeat:
                }
                return -ENOSPC;
        }
+       spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
        EXT4_I(inode)->i_reserved_data_blocks += nrblocks;
-       EXT4_I(inode)->i_reserved_meta_blocks = mdblocks;
-
+       EXT4_I(inode)->i_reserved_meta_blocks += md_needed;
        spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+
        return 0;       /* success */
 }
 
@@ -4794,6 +4793,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
                        ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
        inode->i_size = ext4_isize(raw_inode);
        ei->i_disksize = inode->i_size;
+#ifdef CONFIG_QUOTA
+       ei->i_reserved_quota = 0;
+#endif
        inode->i_generation = le32_to_cpu(raw_inode->i_generation);
        ei->i_block_group = iloc.block_group;
        ei->i_last_alloc_group = ~0;
index b1fd3da..d34afad 100644 (file)
@@ -2755,12 +2755,6 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
                /* release all the reserved blocks if non delalloc */
                percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_blks);
-       else {
-               percpu_counter_sub(&sbi->s_dirtyblocks_counter,
-                                               ac->ac_b_ex.fe_len);
-               /* convert reserved quota blocks to real quota blocks */
-               vfs_dq_claim_block(ac->ac_inode, ac->ac_b_ex.fe_len);
-       }
 
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi,
index 827bde1..6ed9aa9 100644 (file)
@@ -704,6 +704,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        ei->i_allocated_meta_blocks = 0;
        ei->i_delalloc_reserved_flag = 0;
        spin_lock_init(&(ei->i_block_reservation_lock));
+#ifdef CONFIG_QUOTA
+       ei->i_reserved_quota = 0;
+#endif
        INIT_LIST_HEAD(&ei->i_aio_dio_complete_list);
        ei->cur_aio_dio = NULL;
        ei->i_sync_tid = 0;
@@ -1014,7 +1017,9 @@ static const struct dquot_operations ext4_quota_operations = {
        .reserve_space  = dquot_reserve_space,
        .claim_space    = dquot_claim_space,
        .release_rsv    = dquot_release_reserved_space,
+#ifdef CONFIG_QUOTA
        .get_reserved_space = ext4_get_reserved_space,
+#endif
        .alloc_inode    = dquot_alloc_inode,
        .free_space     = dquot_free_space,
        .free_inode     = dquot_free_inode,
index 0afacf6..69652c5 100644 (file)
@@ -186,10 +186,8 @@ struct file *alloc_file(struct path *path, fmode_t mode,
         * that we can do debugging checks at __fput()
         */
        if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) {
-               int error = 0;
                file_take_write(file);
-               error = mnt_clone_write(path->mnt);
-               WARN_ON(error);
+               WARN_ON(mnt_clone_write(path->mnt));
        }
        ima_counts_get(file);
        return file;
index f67cd14..e96a166 100644 (file)
@@ -85,3 +85,10 @@ extern struct file *get_empty_filp(void);
  * super.c
  */
 extern int do_remount_sb(struct super_block *, int, void *, int);
+
+/*
+ * open.c
+ */
+struct nameidata;
+extern struct file *nameidata_to_filp(struct nameidata *);
+extern void release_open_intent(struct nameidata *);
index 4160afa..bd224ee 100644 (file)
@@ -1913,7 +1913,7 @@ static void __init jbd_create_debugfs_entry(void)
 {
        jbd_debugfs_dir = debugfs_create_dir("jbd", NULL);
        if (jbd_debugfs_dir)
-               jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO,
+               jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO | S_IWUSR,
                                               jbd_debugfs_dir,
                                               &journal_enable_debug);
 }
index b7ca3a9..17af879 100644 (file)
@@ -2115,7 +2115,8 @@ static void __init jbd2_create_debugfs_entry(void)
 {
        jbd2_debugfs_dir = debugfs_create_dir("jbd2", NULL);
        if (jbd2_debugfs_dir)
-               jbd2_debug = debugfs_create_u8(JBD2_DEBUG_NAME, S_IRUGO,
+               jbd2_debug = debugfs_create_u8(JBD2_DEBUG_NAME,
+                                              S_IRUGO | S_IWUSR,
                                               jbd2_debugfs_dir,
                                               &jbd2_journal_enable_debug);
 }
index 2234c73..d929a82 100644 (file)
@@ -524,7 +524,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
         * Page cache is indexed by long.
         * I would use MAX_LFS_FILESIZE, but it's only half as big
         */
-       sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes);
+       sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, (u64)sb->s_maxbytes);
 #endif
        sb->s_time_gran = 1;
        return 0;
index dad4b80..68921d9 100644 (file)
@@ -37,8 +37,6 @@
 
 #include "internal.h"
 
-#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
-
 /* [Feb-1997 T. Schoebel-Theuer]
  * Fundamental changes in the pathname lookup mechanisms (namei)
  * were necessary because of omirr.  The reason is that omirr needs
@@ -1640,6 +1638,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
                if (filp == NULL)
                        return ERR_PTR(-ENFILE);
                nd.intent.open.file = filp;
+               filp->f_flags = open_flag;
                nd.intent.open.flags = flag;
                nd.intent.open.create_mode = 0;
                error = do_path_lookup(dfd, pathname,
@@ -1685,6 +1684,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
        if (filp == NULL)
                goto exit_parent;
        nd.intent.open.file = filp;
+       filp->f_flags = open_flag;
        nd.intent.open.flags = flag;
        nd.intent.open.create_mode = mode;
        dir = nd.path.dentry;
@@ -1725,7 +1725,7 @@ do_last:
                        mnt_drop_write(nd.path.mnt);
                        goto exit;
                }
-               filp = nameidata_to_filp(&nd, open_flag);
+               filp = nameidata_to_filp(&nd);
                mnt_drop_write(nd.path.mnt);
                if (nd.root.mnt)
                        path_put(&nd.root);
@@ -1789,7 +1789,7 @@ ok:
                        mnt_drop_write(nd.path.mnt);
                goto exit;
        }
-       filp = nameidata_to_filp(&nd, open_flag);
+       filp = nameidata_to_filp(&nd);
        if (!IS_ERR(filp)) {
                error = ima_path_check(&filp->f_path, filp->f_mode &
                               (MAY_READ | MAY_WRITE | MAY_EXEC));
index 1c12177..55c8e63 100644 (file)
@@ -89,7 +89,7 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
        int flags = nfsexp_flags(rqstp, exp);
 
        /* Check if the request originated from a secure port. */
-       if (!rqstp->rq_secure && (flags & NFSEXP_INSECURE_PORT)) {
+       if (!rqstp->rq_secure && !(flags & NFSEXP_INSECURE_PORT)) {
                RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
                dprintk(KERN_WARNING
                       "nfsd: request from insecure port %s!\n",
index fb4e672..d17bdc7 100644 (file)
@@ -1765,9 +1765,9 @@ set_and_inc:
  *
  * The array index of the subtree root is passed back.
  */
-static int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
-                                  struct ocfs2_path *left,
-                                  struct ocfs2_path *right)
+int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
+                           struct ocfs2_path *left,
+                           struct ocfs2_path *right)
 {
        int i = 0;
 
@@ -2872,8 +2872,8 @@ out:
  * This looks similar, but is subtly different to
  * ocfs2_find_cpos_for_left_leaf().
  */
-static int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
-                                         struct ocfs2_path *path, u32 *cpos)
+int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
+                                  struct ocfs2_path *path, u32 *cpos)
 {
        int i, j, ret = 0;
        u64 blkno;
index 9c122d5..1db4359 100644 (file)
@@ -317,4 +317,9 @@ int ocfs2_path_bh_journal_access(handle_t *handle,
 int ocfs2_journal_access_path(struct ocfs2_caching_info *ci,
                              handle_t *handle,
                              struct ocfs2_path *path);
+int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
+                                  struct ocfs2_path *path, u32 *cpos);
+int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
+                           struct ocfs2_path *left,
+                           struct ocfs2_path *right);
 #endif /* OCFS2_ALLOC_H */
index f010b22..3e9b460 100644 (file)
@@ -2108,6 +2108,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
        }
        did_quota_inode = 1;
 
+       inode->i_nlink = 0;
        /* do the real work now. */
        status = ocfs2_mknod_locked(osb, dir, inode,
                                    0, &new_di_bh, parent_di_bh, handle,
@@ -2136,6 +2137,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
        if (status < 0)
                mlog_errno(status);
 
+       insert_inode_hash(inode);
 leave:
        if (status < 0 && did_quota_inode)
                vfs_dq_free_inode(inode);
@@ -2267,6 +2269,8 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
        di = (struct ocfs2_dinode *)di_bh->b_data;
        le32_add_cpu(&di->i_flags, -OCFS2_ORPHANED_FL);
        di->i_orphaned_slot = 0;
+       inode->i_nlink = 1;
+       ocfs2_set_links_count(di, inode->i_nlink);
        ocfs2_journal_dirty(handle, di_bh);
 
        status = ocfs2_add_entry(handle, dentry, inode,
@@ -2284,7 +2288,6 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
                goto out_commit;
        }
 
-       insert_inode_hash(inode);
        dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
        status = 0;
index 30967e3..74db2be 100644 (file)
@@ -276,7 +276,7 @@ static void ocfs2_erase_refcount_tree_from_list(struct ocfs2_super *osb,
        spin_unlock(&osb->osb_lock);
 }
 
-void ocfs2_kref_remove_refcount_tree(struct kref *kref)
+static void ocfs2_kref_remove_refcount_tree(struct kref *kref)
 {
        struct ocfs2_refcount_tree *tree =
                container_of(kref, struct ocfs2_refcount_tree, rf_getcnt);
@@ -524,23 +524,6 @@ out:
        return ret;
 }
 
-int ocfs2_lock_refcount_tree_by_inode(struct inode *inode, int rw,
-                                     struct ocfs2_refcount_tree **ret_tree,
-                                     struct buffer_head **ref_bh)
-{
-       int ret;
-       u64 ref_blkno;
-
-       ret = ocfs2_get_refcount_block(inode, &ref_blkno);
-       if (ret) {
-               mlog_errno(ret);
-               return ret;
-       }
-
-       return ocfs2_lock_refcount_tree(OCFS2_SB(inode->i_sb), ref_blkno,
-                                       rw, ret_tree, ref_bh);
-}
-
 void ocfs2_unlock_refcount_tree(struct ocfs2_super *osb,
                                struct ocfs2_refcount_tree *tree, int rw)
 {
@@ -969,6 +952,103 @@ out:
 }
 
 /*
+ * Find the end range for a leaf refcount block indicated by
+ * el->l_recs[index].e_blkno.
+ */
+static int ocfs2_get_refcount_cpos_end(struct ocfs2_caching_info *ci,
+                                      struct buffer_head *ref_root_bh,
+                                      struct ocfs2_extent_block *eb,
+                                      struct ocfs2_extent_list *el,
+                                      int index,  u32 *cpos_end)
+{
+       int ret, i, subtree_root;
+       u32 cpos;
+       u64 blkno;
+       struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
+       struct ocfs2_path *left_path = NULL, *right_path = NULL;
+       struct ocfs2_extent_tree et;
+       struct ocfs2_extent_list *tmp_el;
+
+       if (index < le16_to_cpu(el->l_next_free_rec) - 1) {
+               /*
+                * We have a extent rec after index, so just use the e_cpos
+                * of the next extent rec.
+                */
+               *cpos_end = le32_to_cpu(el->l_recs[index+1].e_cpos);
+               return 0;
+       }
+
+       if (!eb || (eb && !eb->h_next_leaf_blk)) {
+               /*
+                * We are the last extent rec, so any high cpos should
+                * be stored in this leaf refcount block.
+                */
+               *cpos_end = UINT_MAX;
+               return 0;
+       }
+
+       /*
+        * If the extent block isn't the last one, we have to find
+        * the subtree root between this extent block and the next
+        * leaf extent block and get the corresponding e_cpos from
+        * the subroot. Otherwise we may corrupt the b-tree.
+        */
+       ocfs2_init_refcount_extent_tree(&et, ci, ref_root_bh);
+
+       left_path = ocfs2_new_path_from_et(&et);
+       if (!left_path) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       cpos = le32_to_cpu(eb->h_list.l_recs[index].e_cpos);
+       ret = ocfs2_find_path(ci, left_path, cpos);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       right_path = ocfs2_new_path_from_path(left_path);
+       if (!right_path) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_find_cpos_for_right_leaf(sb, left_path, &cpos);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_find_path(ci, right_path, cpos);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       subtree_root = ocfs2_find_subtree_root(&et, left_path,
+                                              right_path);
+
+       tmp_el = left_path->p_node[subtree_root].el;
+       blkno = left_path->p_node[subtree_root+1].bh->b_blocknr;
+       for (i = 0; i < le32_to_cpu(tmp_el->l_next_free_rec); i++) {
+               if (le64_to_cpu(tmp_el->l_recs[i].e_blkno) == blkno) {
+                       *cpos_end = le32_to_cpu(tmp_el->l_recs[i+1].e_cpos);
+                       break;
+               }
+       }
+
+       BUG_ON(i == le32_to_cpu(tmp_el->l_next_free_rec));
+
+out:
+       ocfs2_free_path(left_path);
+       ocfs2_free_path(right_path);
+       return ret;
+}
+
+/*
  * Given a cpos and len, try to find the refcount record which contains cpos.
  * 1. If cpos can be found in one refcount record, return the record.
  * 2. If cpos can't be found, return a fake record which start from cpos
@@ -983,10 +1063,10 @@ static int ocfs2_get_refcount_rec(struct ocfs2_caching_info *ci,
                                  struct buffer_head **ret_bh)
 {
        int ret = 0, i, found;
-       u32 low_cpos;
+       u32 low_cpos, uninitialized_var(cpos_end);
        struct ocfs2_extent_list *el;
-       struct ocfs2_extent_rec *tmp, *rec = NULL;
-       struct ocfs2_extent_block *eb;
+       struct ocfs2_extent_rec *rec = NULL;
+       struct ocfs2_extent_block *eb = NULL;
        struct buffer_head *eb_bh = NULL, *ref_leaf_bh = NULL;
        struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
        struct ocfs2_refcount_block *rb =
@@ -1034,12 +1114,16 @@ static int ocfs2_get_refcount_rec(struct ocfs2_caching_info *ci,
                }
        }
 
-       /* adjust len when we have ocfs2_extent_rec after it. */
-       if (found && i < le16_to_cpu(el->l_next_free_rec) - 1) {
-               tmp = &el->l_recs[i+1];
+       if (found) {
+               ret = ocfs2_get_refcount_cpos_end(ci, ref_root_bh,
+                                                 eb, el, i, &cpos_end);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
 
-               if (le32_to_cpu(tmp->e_cpos) < cpos + len)
-                       len = le32_to_cpu(tmp->e_cpos) - cpos;
+               if (cpos_end < low_cpos + len)
+                       len = cpos_end - low_cpos;
        }
 
        ret = ocfs2_read_refcount_block(ci, le64_to_cpu(rec->e_blkno),
@@ -1418,7 +1502,7 @@ static int ocfs2_divide_leaf_refcount_block(struct buffer_head *ref_leaf_bh,
 
        /* change old and new rl_used accordingly. */
        le16_add_cpu(&rl->rl_used, -num_moved);
-       new_rl->rl_used = cpu_to_le32(num_moved);
+       new_rl->rl_used = cpu_to_le16(num_moved);
 
        sort(&rl->rl_recs, le16_to_cpu(rl->rl_used),
             sizeof(struct ocfs2_refcount_rec),
@@ -1797,7 +1881,8 @@ static int ocfs2_split_refcount_rec(handle_t *handle,
                recs_need++;
 
        /* If the leaf block don't have enough record, expand it. */
-       if (le16_to_cpu(rf_list->rl_used) + recs_need > rf_list->rl_count) {
+       if (le16_to_cpu(rf_list->rl_used) + recs_need >
+                                        le16_to_cpu(rf_list->rl_count)) {
                struct ocfs2_refcount_rec tmp_rec;
                u64 cpos = le64_to_cpu(orig_rec->r_cpos);
                len = le32_to_cpu(orig_rec->r_clusters);
@@ -1859,7 +1944,7 @@ static int ocfs2_split_refcount_rec(handle_t *handle,
                memcpy(tail_rec, orig_rec, sizeof(struct ocfs2_refcount_rec));
                le64_add_cpu(&tail_rec->r_cpos,
                             le32_to_cpu(tail_rec->r_clusters) - len);
-               tail_rec->r_clusters = le32_to_cpu(len);
+               tail_rec->r_clusters = cpu_to_le32(len);
        }
 
        /*
@@ -3840,8 +3925,7 @@ static int ocfs2_add_refcounted_extent(struct inode *inode,
        }
 
        ret = ocfs2_insert_extent(handle, et, cpos,
-                       cpu_to_le64(ocfs2_clusters_to_blocks(inode->i_sb,
-                                                            p_cluster)),
+                       ocfs2_clusters_to_blocks(inode->i_sb, p_cluster),
                        num_clusters, ext_flags, meta_ac);
        if (ret) {
                mlog_errno(ret);
@@ -4253,8 +4337,8 @@ static int ocfs2_user_path_parent(const char __user *path,
  * @new_dentry:        target dentry
  * @preserve:  if true, preserve all file attributes
  */
-int ocfs2_vfs_reflink(struct dentry *old_dentry, struct inode *dir,
-                     struct dentry *new_dentry, bool preserve)
+static int ocfs2_vfs_reflink(struct dentry *old_dentry, struct inode *dir,
+                            struct dentry *new_dentry, bool preserve)
 {
        struct inode *inode = old_dentry->d_inode;
        int error;
index ca69241..040cef7 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -821,15 +821,14 @@ static inline int __get_file_write_access(struct inode *inode,
 }
 
 static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
-                                       int flags, struct file *f,
+                                       struct file *f,
                                        int (*open)(struct inode *, struct file *),
                                        const struct cred *cred)
 {
        struct inode *inode;
        int error;
 
-       f->f_flags = flags;
-       f->f_mode = (__force fmode_t)((flags+1) & O_ACCMODE) | FMODE_LSEEK |
+       f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
                                FMODE_PREAD | FMODE_PWRITE;
        inode = dentry->d_inode;
        if (f->f_mode & FMODE_WRITE) {
@@ -930,7 +929,6 @@ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry
        if (IS_ERR(dentry))
                goto out_err;
        nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
-                                            nd->intent.open.flags - 1,
                                             nd->intent.open.file,
                                             open, cred);
 out:
@@ -949,7 +947,7 @@ EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
  *
  * Note that this function destroys the original nameidata
  */
-struct file *nameidata_to_filp(struct nameidata *nd, int flags)
+struct file *nameidata_to_filp(struct nameidata *nd)
 {
        const struct cred *cred = current_cred();
        struct file *filp;
@@ -958,7 +956,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags)
        filp = nd->intent.open.file;
        /* Has the filesystem initialised the file for us? */
        if (filp->f_path.dentry == NULL)
-               filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp,
+               filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp,
                                     NULL, cred);
        else
                path_put(&nd->path);
@@ -997,7 +995,8 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
                return ERR_PTR(error);
        }
 
-       return __dentry_open(dentry, mnt, flags, f, NULL, cred);
+       f->f_flags = flags;
+       return __dentry_open(dentry, mnt, f, NULL, cred);
 }
 EXPORT_SYMBOL(dentry_open);
 
index 4badde1..f560325 100644 (file)
@@ -134,13 +134,16 @@ static inline void task_name(struct seq_file *m, struct task_struct *p)
  * simple bit tests.
  */
 static const char *task_state_array[] = {
-       "R (running)",          /*  0 */
-       "S (sleeping)",         /*  1 */
-       "D (disk sleep)",       /*  2 */
-       "T (stopped)",          /*  4 */
-       "T (tracing stop)",     /*  8 */
-       "Z (zombie)",           /* 16 */
-       "X (dead)"              /* 32 */
+       "R (running)",          /*   0 */
+       "S (sleeping)",         /*   1 */
+       "D (disk sleep)",       /*   2 */
+       "T (stopped)",          /*   4 */
+       "t (tracing stop)",     /*   8 */
+       "Z (zombie)",           /*  16 */
+       "X (dead)",             /*  32 */
+       "x (dead)",             /*  64 */
+       "K (wakekill)",         /* 128 */
+       "W (waking)",           /* 256 */
 };
 
 static inline const char *get_task_state(struct task_struct *tsk)
@@ -148,6 +151,8 @@ static inline const char *get_task_state(struct task_struct *tsk)
        unsigned int state = (tsk->state & TASK_REPORT) | tsk->exit_state;
        const char **p = &task_state_array[0];
 
+       BUILD_BUG_ON(1 + ilog2(TASK_STATE_MAX) != ARRAY_SIZE(task_state_array));
+
        while (state) {
                p++;
                state >>= 1;
index cd6bb9a..dea86ab 100644 (file)
@@ -323,6 +323,30 @@ int dquot_mark_dquot_dirty(struct dquot *dquot)
 }
 EXPORT_SYMBOL(dquot_mark_dquot_dirty);
 
+/* Dirtify all the dquots - this can block when journalling */
+static inline int mark_all_dquot_dirty(struct dquot * const *dquot)
+{
+       int ret, err, cnt;
+
+       ret = err = 0;
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+               if (dquot[cnt])
+                       /* Even in case of error we have to continue */
+                       ret = mark_dquot_dirty(dquot[cnt]);
+               if (!err)
+                       err = ret;
+       }
+       return err;
+}
+
+static inline void dqput_all(struct dquot **dquot)
+{
+       unsigned int cnt;
+
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+               dqput(dquot[cnt]);
+}
+
 /* This function needs dq_list_lock */
 static inline int clear_dquot_dirty(struct dquot *dquot)
 {
@@ -1268,8 +1292,7 @@ int dquot_initialize(struct inode *inode, int type)
 out_err:
        up_write(&sb_dqopt(sb)->dqptr_sem);
        /* Drop unused references */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               dqput(got[cnt]);
+       dqput_all(got);
        return ret;
 }
 EXPORT_SYMBOL(dquot_initialize);
@@ -1288,9 +1311,7 @@ int dquot_drop(struct inode *inode)
                inode->i_dquot[cnt] = NULL;
        }
        up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               dqput(put[cnt]);
+       dqput_all(put);
        return 0;
 }
 EXPORT_SYMBOL(dquot_drop);
@@ -1319,6 +1340,67 @@ void vfs_dq_drop(struct inode *inode)
 EXPORT_SYMBOL(vfs_dq_drop);
 
 /*
+ * inode_reserved_space is managed internally by quota, and protected by
+ * i_lock similar to i_blocks+i_bytes.
+ */
+static qsize_t *inode_reserved_space(struct inode * inode)
+{
+       /* Filesystem must explicitly define it's own method in order to use
+        * quota reservation interface */
+       BUG_ON(!inode->i_sb->dq_op->get_reserved_space);
+       return inode->i_sb->dq_op->get_reserved_space(inode);
+}
+
+static void inode_add_rsv_space(struct inode *inode, qsize_t number)
+{
+       spin_lock(&inode->i_lock);
+       *inode_reserved_space(inode) += number;
+       spin_unlock(&inode->i_lock);
+}
+
+
+static void inode_claim_rsv_space(struct inode *inode, qsize_t number)
+{
+       spin_lock(&inode->i_lock);
+       *inode_reserved_space(inode) -= number;
+       __inode_add_bytes(inode, number);
+       spin_unlock(&inode->i_lock);
+}
+
+static void inode_sub_rsv_space(struct inode *inode, qsize_t number)
+{
+       spin_lock(&inode->i_lock);
+       *inode_reserved_space(inode) -= number;
+       spin_unlock(&inode->i_lock);
+}
+
+static qsize_t inode_get_rsv_space(struct inode *inode)
+{
+       qsize_t ret;
+       spin_lock(&inode->i_lock);
+       ret = *inode_reserved_space(inode);
+       spin_unlock(&inode->i_lock);
+       return ret;
+}
+
+static void inode_incr_space(struct inode *inode, qsize_t number,
+                               int reserve)
+{
+       if (reserve)
+               inode_add_rsv_space(inode, number);
+       else
+               inode_add_bytes(inode, number);
+}
+
+static void inode_decr_space(struct inode *inode, qsize_t number, int reserve)
+{
+       if (reserve)
+               inode_sub_rsv_space(inode, number);
+       else
+               inode_sub_bytes(inode, number);
+}
+
+/*
  * Following four functions update i_blocks+i_bytes fields and
  * quota information (together with appropriate checks)
  * NOTE: We absolutely rely on the fact that caller dirties
@@ -1336,6 +1418,21 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number,
        int cnt, ret = QUOTA_OK;
        char warntype[MAXQUOTAS];
 
+       /*
+        * First test before acquiring mutex - solves deadlocks when we
+        * re-enter the quota code and are already holding the mutex
+        */
+       if (IS_NOQUOTA(inode)) {
+               inode_incr_space(inode, number, reserve);
+               goto out;
+       }
+
+       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+       if (IS_NOQUOTA(inode)) {
+               inode_incr_space(inode, number, reserve);
+               goto out_unlock;
+       }
+
        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
                warntype[cnt] = QUOTA_NL_NOWARN;
 
@@ -1346,7 +1443,8 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number,
                if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt)
                    == NO_QUOTA) {
                        ret = NO_QUOTA;
-                       goto out_unlock;
+                       spin_unlock(&dq_data_lock);
+                       goto out_flush_warn;
                }
        }
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1357,64 +1455,29 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number,
                else
                        dquot_incr_space(inode->i_dquot[cnt], number);
        }
-       if (!reserve)
-               inode_add_bytes(inode, number);
-out_unlock:
+       inode_incr_space(inode, number, reserve);
        spin_unlock(&dq_data_lock);
+
+       if (reserve)
+               goto out_flush_warn;
+       mark_all_dquot_dirty(inode->i_dquot);
+out_flush_warn:
        flush_warnings(inode->i_dquot, warntype);
+out_unlock:
+       up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
        return ret;
 }
 
 int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
 {
-       int cnt, ret = QUOTA_OK;
-
-       /*
-        * First test before acquiring mutex - solves deadlocks when we
-        * re-enter the quota code and are already holding the mutex
-        */
-       if (IS_NOQUOTA(inode)) {
-               inode_add_bytes(inode, number);
-               goto out;
-       }
-
-       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-       if (IS_NOQUOTA(inode)) {
-               inode_add_bytes(inode, number);
-               goto out_unlock;
-       }
-
-       ret = __dquot_alloc_space(inode, number, warn, 0);
-       if (ret == NO_QUOTA)
-               goto out_unlock;
-
-       /* Dirtify all the dquots - this can block when journalling */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               if (inode->i_dquot[cnt])
-                       mark_dquot_dirty(inode->i_dquot[cnt]);
-out_unlock:
-       up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-out:
-       return ret;
+       return __dquot_alloc_space(inode, number, warn, 0);
 }
 EXPORT_SYMBOL(dquot_alloc_space);
 
 int dquot_reserve_space(struct inode *inode, qsize_t number, int warn)
 {
-       int ret = QUOTA_OK;
-
-       if (IS_NOQUOTA(inode))
-               goto out;
-
-       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-       if (IS_NOQUOTA(inode))
-               goto out_unlock;
-
-       ret = __dquot_alloc_space(inode, number, warn, 1);
-out_unlock:
-       up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-out:
-       return ret;
+       return __dquot_alloc_space(inode, number, warn, 1);
 }
 EXPORT_SYMBOL(dquot_reserve_space);
 
@@ -1455,10 +1518,7 @@ int dquot_alloc_inode(const struct inode *inode, qsize_t number)
 warn_put_all:
        spin_unlock(&dq_data_lock);
        if (ret == QUOTA_OK)
-               /* Dirtify all the dquots - this can block when journalling */
-               for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-                       if (inode->i_dquot[cnt])
-                               mark_dquot_dirty(inode->i_dquot[cnt]);
+               mark_all_dquot_dirty(inode->i_dquot);
        flush_warnings(inode->i_dquot, warntype);
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        return ret;
@@ -1471,14 +1531,14 @@ int dquot_claim_space(struct inode *inode, qsize_t number)
        int ret = QUOTA_OK;
 
        if (IS_NOQUOTA(inode)) {
-               inode_add_bytes(inode, number);
+               inode_claim_rsv_space(inode, number);
                goto out;
        }
 
        down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        if (IS_NOQUOTA(inode))  {
                up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-               inode_add_bytes(inode, number);
+               inode_claim_rsv_space(inode, number);
                goto out;
        }
 
@@ -1490,12 +1550,9 @@ int dquot_claim_space(struct inode *inode, qsize_t number)
                                                        number);
        }
        /* Update inode bytes */
-       inode_add_bytes(inode, number);
+       inode_claim_rsv_space(inode, number);
        spin_unlock(&dq_data_lock);
-       /* Dirtify all the dquots - this can block when journalling */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               if (inode->i_dquot[cnt])
-                       mark_dquot_dirty(inode->i_dquot[cnt]);
+       mark_all_dquot_dirty(inode->i_dquot);
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 out:
        return ret;
@@ -1503,38 +1560,9 @@ out:
 EXPORT_SYMBOL(dquot_claim_space);
 
 /*
- * Release reserved quota space
- */
-void dquot_release_reserved_space(struct inode *inode, qsize_t number)
-{
-       int cnt;
-
-       if (IS_NOQUOTA(inode))
-               goto out;
-
-       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-       if (IS_NOQUOTA(inode))
-               goto out_unlock;
-
-       spin_lock(&dq_data_lock);
-       /* Release reserved dquots */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               if (inode->i_dquot[cnt])
-                       dquot_free_reserved_space(inode->i_dquot[cnt], number);
-       }
-       spin_unlock(&dq_data_lock);
-
-out_unlock:
-       up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-out:
-       return;
-}
-EXPORT_SYMBOL(dquot_release_reserved_space);
-
-/*
  * This operation can block, but only after everything is updated
  */
-int dquot_free_space(struct inode *inode, qsize_t number)
+int __dquot_free_space(struct inode *inode, qsize_t number, int reserve)
 {
        unsigned int cnt;
        char warntype[MAXQUOTAS];
@@ -1543,7 +1571,7 @@ int dquot_free_space(struct inode *inode, qsize_t number)
          * re-enter the quota code and are already holding the mutex */
        if (IS_NOQUOTA(inode)) {
 out_sub:
-               inode_sub_bytes(inode, number);
+               inode_decr_space(inode, number, reserve);
                return QUOTA_OK;
        }
 
@@ -1558,21 +1586,40 @@ out_sub:
                if (!inode->i_dquot[cnt])
                        continue;
                warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number);
-               dquot_decr_space(inode->i_dquot[cnt], number);
+               if (reserve)
+                       dquot_free_reserved_space(inode->i_dquot[cnt], number);
+               else
+                       dquot_decr_space(inode->i_dquot[cnt], number);
        }
-       inode_sub_bytes(inode, number);
+       inode_decr_space(inode, number, reserve);
        spin_unlock(&dq_data_lock);
-       /* Dirtify all the dquots - this can block when journalling */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               if (inode->i_dquot[cnt])
-                       mark_dquot_dirty(inode->i_dquot[cnt]);
+
+       if (reserve)
+               goto out_unlock;
+       mark_all_dquot_dirty(inode->i_dquot);
+out_unlock:
        flush_warnings(inode->i_dquot, warntype);
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        return QUOTA_OK;
 }
+
+int dquot_free_space(struct inode *inode, qsize_t number)
+{
+       return  __dquot_free_space(inode, number, 0);
+}
 EXPORT_SYMBOL(dquot_free_space);
 
 /*
+ * Release reserved quota space
+ */
+void dquot_release_reserved_space(struct inode *inode, qsize_t number)
+{
+       __dquot_free_space(inode, number, 1);
+
+}
+EXPORT_SYMBOL(dquot_release_reserved_space);
+
+/*
  * This operation can block, but only after everything is updated
  */
 int dquot_free_inode(const struct inode *inode, qsize_t number)
@@ -1599,10 +1646,7 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
                dquot_decr_inodes(inode->i_dquot[cnt], number);
        }
        spin_unlock(&dq_data_lock);
-       /* Dirtify all the dquots - this can block when journalling */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               if (inode->i_dquot[cnt])
-                       mark_dquot_dirty(inode->i_dquot[cnt]);
+       mark_all_dquot_dirty(inode->i_dquot);
        flush_warnings(inode->i_dquot, warntype);
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        return QUOTA_OK;
@@ -1610,19 +1654,6 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
 EXPORT_SYMBOL(dquot_free_inode);
 
 /*
- * call back function, get reserved quota space from underlying fs
- */
-qsize_t dquot_get_reserved_space(struct inode *inode)
-{
-       qsize_t reserved_space = 0;
-
-       if (sb_any_quota_active(inode->i_sb) &&
-           inode->i_sb->dq_op->get_reserved_space)
-               reserved_space = inode->i_sb->dq_op->get_reserved_space(inode);
-       return reserved_space;
-}
-
-/*
  * Transfer the number of inode and blocks from one diskquota to an other.
  *
  * This operation can block, but only after everything is updated
@@ -1665,7 +1696,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
        }
        spin_lock(&dq_data_lock);
        cur_space = inode_get_bytes(inode);
-       rsv_space = dquot_get_reserved_space(inode);
+       rsv_space = inode_get_rsv_space(inode);
        space = cur_space + rsv_space;
        /* Build the transfer_from list and check the limits */
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1709,25 +1740,18 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
        spin_unlock(&dq_data_lock);
        up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
 
-       /* Dirtify all the dquots - this can block when journalling */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               if (transfer_from[cnt])
-                       mark_dquot_dirty(transfer_from[cnt]);
-               if (transfer_to[cnt]) {
-                       mark_dquot_dirty(transfer_to[cnt]);
-                       /* The reference we got is transferred to the inode */
-                       transfer_to[cnt] = NULL;
-               }
-       }
+       mark_all_dquot_dirty(transfer_from);
+       mark_all_dquot_dirty(transfer_to);
+       /* The reference we got is transferred to the inode */
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+               transfer_to[cnt] = NULL;
 warn_put_all:
        flush_warnings(transfer_to, warntype_to);
        flush_warnings(transfer_from, warntype_from_inodes);
        flush_warnings(transfer_from, warntype_from_space);
 put_all:
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               dqput(transfer_from[cnt]);
-               dqput(transfer_to[cnt]);
-       }
+       dqput_all(transfer_from);
+       dqput_all(transfer_to);
        return ret;
 over_quota:
        spin_unlock(&dq_data_lock);
index 3dfc23e..e3da02f 100644 (file)
@@ -97,8 +97,11 @@ static int v2_read_file_info(struct super_block *sb, int type)
        unsigned int version;
 
        if (!v2_read_header(sb, type, &dqhead))
-               return 0;
+               return -1;
        version = le32_to_cpu(dqhead.dqh_version);
+       if ((info->dqi_fmt_id == QFMT_VFS_V0 && version != 0) ||
+           (info->dqi_fmt_id == QFMT_VFS_V1 && version != 1))
+               return -1;
 
        size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
               sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
@@ -120,8 +123,8 @@ static int v2_read_file_info(struct super_block *sb, int type)
                info->dqi_maxilimit = 0xffffffff;
        } else {
                /* used space is stored as unsigned 64-bit value */
-               info->dqi_maxblimit = 0xffffffffffffffff;       /* 2^64-1 */
-               info->dqi_maxilimit = 0xffffffffffffffff;
+               info->dqi_maxblimit = 0xffffffffffffffffULL;    /* 2^64-1 */
+               info->dqi_maxilimit = 0xffffffffffffffffULL;
        }
        info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
        info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
index b07565c..1dabe4e 100644 (file)
@@ -236,7 +236,7 @@ SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
                 * anon_inode_getfd() will install the fd.
                 */
                ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx,
-                                      flags & (O_CLOEXEC | O_NONBLOCK));
+                                      O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK)));
                if (ufd < 0)
                        kfree(ctx);
        } else {
index 075694e..c4ecd52 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -401,9 +401,9 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, char __user *, filename,
 }
 #endif /* __ARCH_WANT_STAT64 */
 
-void inode_add_bytes(struct inode *inode, loff_t bytes)
+/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
+void __inode_add_bytes(struct inode *inode, loff_t bytes)
 {
-       spin_lock(&inode->i_lock);
        inode->i_blocks += bytes >> 9;
        bytes &= 511;
        inode->i_bytes += bytes;
@@ -411,6 +411,12 @@ void inode_add_bytes(struct inode *inode, loff_t bytes)
                inode->i_blocks++;
                inode->i_bytes -= 512;
        }
+}
+
+void inode_add_bytes(struct inode *inode, loff_t bytes)
+{
+       spin_lock(&inode->i_lock);
+       __inode_add_bytes(inode, bytes);
        spin_unlock(&inode->i_lock);
 }
 
index 19eb70b..aff046b 100644 (file)
@@ -901,8 +901,9 @@ int get_sb_single(struct file_system_type *fs_type,
                        return error;
                }
                s->s_flags |= MS_ACTIVE;
+       } else {
+               do_remount_sb(s, flags, data, 0);
        }
-       do_remount_sb(s, flags, data, 0);
        simple_set_mnt(mnt, s);
        return 0;
 }
index 60c702b..a0a500a 100644 (file)
@@ -483,7 +483,8 @@ void unmap_bin_file(struct sysfs_dirent *attr_sd)
  *     @attr:  attribute descriptor.
  */
 
-int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+int sysfs_create_bin_file(struct kobject *kobj,
+                         const struct bin_attribute *attr)
 {
        BUG_ON(!kobj || !kobj->sd || !attr);
 
@@ -497,7 +498,8 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
  *     @attr:  attribute descriptor.
  */
 
-void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+void sysfs_remove_bin_file(struct kobject *kobj,
+                          const struct bin_attribute *attr)
 {
        sysfs_hash_and_remove(kobj->sd, attr->attr.name);
 }
index b042bd7..1bfc95a 100644 (file)
@@ -200,7 +200,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
        hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
 
        ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
-                              flags & TFD_SHARED_FCNTL_FLAGS);
+                              O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS));
        if (ufd < 0)
                kfree(ctx);
 
index 29245c6..0ea5ef4 100644 (file)
@@ -224,8 +224,6 @@ struct acpi_processor {
        struct acpi_processor_throttling throttling;
        struct acpi_processor_limit limit;
        struct thermal_cooling_device *cdev;
-       /* the _PDC objects for this processor, if any */
-       struct acpi_object_list *pdc;
 };
 
 struct acpi_processor_errata {
@@ -257,9 +255,6 @@ int acpi_processor_notify_smm(struct module *calling_module);
 DECLARE_PER_CPU(struct acpi_processor *, processors);
 extern struct acpi_processor_errata errata;
 
-void arch_acpi_processor_init_pdc(struct acpi_processor *pr);
-void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr);
-
 #ifdef ARCH_HAS_POWER_INIT
 void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
                                        unsigned int cpu);
@@ -325,6 +320,9 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
 
 #endif                         /* CONFIG_CPU_FREQ */
 
+/* in processor_pdc.c */
+void acpi_processor_set_pdc(acpi_handle handle);
+
 /* in processor_throttling.c */
 int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
 int acpi_processor_get_throttling_info(struct acpi_processor *pr);
index 19ef8eb..71dafb6 100644 (file)
@@ -296,6 +296,7 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
 #define        DRM_MASTER      0x2
 #define DRM_ROOT_ONLY  0x4
 #define DRM_CONTROL_ALLOW 0x8
+#define DRM_UNLOCKED   0x10
 
 struct drm_ioctl_desc {
        unsigned int cmd;
@@ -1128,8 +1129,8 @@ static inline int drm_mtrr_del(int handle, unsigned long offset,
                                /* Driver support (drm_drv.h) */
 extern int drm_init(struct drm_driver *driver);
 extern void drm_exit(struct drm_driver *driver);
-extern int drm_ioctl(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg);
+extern long drm_ioctl(struct file *filp,
+                     unsigned int cmd, unsigned long arg);
 extern long drm_compat_ioctl(struct file *filp,
                             unsigned int cmd, unsigned long arg);
 extern int drm_lastclose(struct drm_device *dev);
index 12ff8c3..5032b9a 100644 (file)
@@ -25,7 +25,7 @@ static void *malloc(int size)
        void *p;
 
        if (size < 0)
-               error("Malloc error");
+               return NULL;
        if (!malloc_ptr)
                malloc_ptr = free_mem_ptr;
 
@@ -35,7 +35,7 @@ static void *malloc(int size)
        malloc_ptr += size;
 
        if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr)
-               error("Out of memory");
+               return NULL;
 
        malloc_count++;
        return p;
index 2a73d9b..a62799f 100644 (file)
@@ -166,9 +166,9 @@ struct driver_attribute driver_attr_##_name =               \
        __ATTR(_name, _mode, _show, _store)
 
 extern int __must_check driver_create_file(struct device_driver *driver,
-                                          struct driver_attribute *attr);
+                                       const struct driver_attribute *attr);
 extern void driver_remove_file(struct device_driver *driver,
-                              struct driver_attribute *attr);
+                              const struct driver_attribute *attr);
 
 extern int __must_check driver_add_kobj(struct device_driver *drv,
                                        struct kobject *kobj,
@@ -319,13 +319,13 @@ struct device_attribute {
 struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
 
 extern int __must_check device_create_file(struct device *device,
-                                          struct device_attribute *entry);
+                                       const struct device_attribute *entry);
 extern void device_remove_file(struct device *dev,
-                              struct device_attribute *attr);
+                              const struct device_attribute *attr);
 extern int __must_check device_create_bin_file(struct device *dev,
-                                              struct bin_attribute *attr);
+                                       const struct bin_attribute *attr);
 extern void device_remove_bin_file(struct device *dev,
-                                  struct bin_attribute *attr);
+                                  const struct bin_attribute *attr);
 extern int device_schedule_callback_owner(struct device *dev,
                void (*func)(struct device *dev), struct module *owner);
 
diff --git a/include/linux/dst.h b/include/linux/dst.h
deleted file mode 100644 (file)
index e26fed8..0000000
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
-
-#ifndef __DST_H
-#define __DST_H
-
-#include <linux/types.h>
-#include <linux/connector.h>
-
-#define DST_NAMELEN            32
-#define DST_NAME               "dst"
-
-enum {
-       /* Remove node with given id from storage */
-       DST_DEL_NODE    = 0,
-       /* Add remote node with given id to the storage */
-       DST_ADD_REMOTE,
-       /* Add local node with given id to the storage to be exported and used by remote peers */
-       DST_ADD_EXPORT,
-       /* Crypto initialization command (hash/cipher used to protect the connection) */
-       DST_CRYPTO,
-       /* Security attributes for given connection (permissions for example) */
-       DST_SECURITY,
-       /* Register given node in the block layer subsystem */
-       DST_START,
-       DST_CMD_MAX
-};
-
-struct dst_ctl
-{
-       /* Storage name */
-       char                    name[DST_NAMELEN];
-       /* Command flags */
-       __u32                   flags;
-       /* Command itself (see above) */
-       __u32                   cmd;
-       /* Maximum number of pages per single request in this device */
-       __u32                   max_pages;
-       /* Stale/error transaction scanning timeout in milliseconds */
-       __u32                   trans_scan_timeout;
-       /* Maximum number of retry sends before completing transaction as broken */
-       __u32                   trans_max_retries;
-       /* Storage size */
-       __u64                   size;
-};
-
-/* Reply command carries completion status */
-struct dst_ctl_ack
-{
-       struct cn_msg           msg;
-       int                     error;
-       int                     unused[3];
-};
-
-/*
- * Unfortunaltely socket address structure is not exported to userspace
- * and is redefined there.
- */
-#define SADDR_MAX_DATA 128
-
-struct saddr {
-       /* address family, AF_xxx       */
-       unsigned short          sa_family;
-       /* 14 bytes of protocol address */
-       char                    sa_data[SADDR_MAX_DATA];
-       /* Number of bytes used in sa_data */
-       unsigned short          sa_data_len;
-};
-
-/* Address structure */
-struct dst_network_ctl
-{
-       /* Socket type: datagram, stream...*/
-       unsigned int            type;
-       /* Let me guess, is it a Jupiter diameter? */
-       unsigned int            proto;
-       /* Peer's address */
-       struct saddr            addr;
-};
-
-struct dst_crypto_ctl
-{
-       /* Cipher and hash names */
-       char                    cipher_algo[DST_NAMELEN];
-       char                    hash_algo[DST_NAMELEN];
-
-       /* Key sizes. Can be zero for digest for example */
-       unsigned int            cipher_keysize, hash_keysize;
-       /* Alignment. Calculated by the DST itself. */
-       unsigned int            crypto_attached_size;
-       /* Number of threads to perform crypto operations */
-       int                     thread_num;
-};
-
-/* Export security attributes have this bits checked in when client connects */
-#define DST_PERM_READ          (1<<0)
-#define DST_PERM_WRITE         (1<<1)
-
-/*
- * Right now it is simple model, where each remote address
- * is assigned to set of permissions it is allowed to perform.
- * In real world block device does not know anything but
- * reading and writing, so it should be more than enough.
- */
-struct dst_secure_user
-{
-       unsigned int            permissions;
-       struct saddr            addr;
-};
-
-/*
- * Export control command: device to export and network address to accept
- * clients to work with given device
- */
-struct dst_export_ctl
-{
-       char                    device[DST_NAMELEN];
-       struct dst_network_ctl  ctl;
-};
-
-enum {
-       DST_CFG = 1,            /* Request remote configuration */
-       DST_IO,                 /* IO command */
-       DST_IO_RESPONSE,        /* IO response */
-       DST_PING,               /* Keepalive message */
-       DST_NCMD_MAX,
-};
-
-struct dst_cmd
-{
-       /* Network command itself, see above */
-       __u32                   cmd;
-       /*
-        * Size of the attached data
-        * (in most cases, for READ command it means how many bytes were requested)
-        */
-       __u32                   size;
-       /* Crypto size: number of attached bytes with digest/hmac */
-       __u32                   csize;
-       /* Here we can carry secret data */
-       __u32                   reserved;
-       /* Read/write bits, see how they are encoded in bio structure */
-       __u64                   rw;
-       /* BIO flags */
-       __u64                   flags;
-       /* Unique command id (like transaction ID) */
-       __u64                   id;
-       /* Sector to start IO from */
-       __u64                   sector;
-       /* Hash data is placed after this header */
-       __u8                    hash[0];
-};
-
-/*
- * Convert command to/from network byte order.
- * We do not use hton*() functions, since there is
- * no 64-bit implementation.
- */
-static inline void dst_convert_cmd(struct dst_cmd *c)
-{
-       c->cmd = __cpu_to_be32(c->cmd);
-       c->csize = __cpu_to_be32(c->csize);
-       c->size = __cpu_to_be32(c->size);
-       c->sector = __cpu_to_be64(c->sector);
-       c->id = __cpu_to_be64(c->id);
-       c->flags = __cpu_to_be64(c->flags);
-       c->rw = __cpu_to_be64(c->rw);
-}
-
-/* Transaction id */
-typedef __u64 dst_gen_t;
-
-#ifdef __KERNEL__
-
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/device.h>
-#include <linux/mempool.h>
-#include <linux/net.h>
-#include <linux/poll.h>
-#include <linux/rbtree.h>
-
-#ifdef CONFIG_DST_DEBUG
-#define dprintk(f, a...) printk(KERN_NOTICE f, ##a)
-#else
-static inline void __attribute__ ((format (printf, 1, 2)))
-       dprintk(const char *fmt, ...) {}
-#endif
-
-struct dst_node;
-
-struct dst_trans
-{
-       /* DST node we are working with */
-       struct dst_node         *n;
-
-       /* Entry inside transaction tree */
-       struct rb_node          trans_entry;
-
-       /* Merlin kills this transaction when this memory cell equals zero */
-       atomic_t                refcnt;
-
-       /* How this transaction should be processed by crypto engine */
-       short                   enc;
-       /* How many times this transaction was resent */
-       short                   retries;
-       /* Completion status */
-       int                     error;
-
-       /* When did we send it to the remote peer */
-       long                    send_time;
-
-       /* My name is...
-        * Well, computers does not speak, they have unique id instead */
-       dst_gen_t               gen;
-
-       /* Block IO we are working with */
-       struct bio              *bio;
-
-       /* Network command for above block IO request */
-       struct dst_cmd          cmd;
-};
-
-struct dst_crypto_engine
-{
-       /* What should we do with all block requests */
-       struct crypto_hash      *hash;
-       struct crypto_ablkcipher        *cipher;
-
-       /* Pool of pages used to encrypt data into before sending */
-       int                     page_num;
-       struct page             **pages;
-
-       /* What to do with current request */
-       int                     enc;
-       /* Who we are and where do we go */
-       struct scatterlist      *src, *dst;
-
-       /* Maximum timeout waiting for encryption to be completed */
-       long                    timeout;
-       /* IV is a 64-bit sequential counter */
-       u64                     iv;
-
-       /* Secret data */
-       void                    *private;
-
-       /* Cached temporary data lives here */
-       int                     size;
-       void                    *data;
-};
-
-struct dst_state
-{
-       /* The main state protection */
-       struct mutex            state_lock;
-
-       /* Polling machinery for sockets */
-       wait_queue_t            wait;
-       wait_queue_head_t       *whead;
-       /* Most of events are being waited here */
-       wait_queue_head_t       thread_wait;
-
-       /* Who owns this? */
-       struct dst_node         *node;
-
-       /* Network address for this state */
-       struct dst_network_ctl  ctl;
-
-       /* Permissions to work with: read-only or rw connection */
-       u32                     permissions;
-
-       /* Called when we need to clean private data */
-       void                    (* cleanup)(struct dst_state *st);
-
-       /* Used by the server: BIO completion queues BIOs here */
-       struct list_head        request_list;
-       spinlock_t              request_lock;
-
-       /* Guess what? No, it is not number of planets */
-       atomic_t                refcnt;
-
-       /* This flags is set when connection should be dropped */
-       int                     need_exit;
-
-       /*
-        * Socket to work with. Second pointer is used for
-        * lockless check if socket was changed before performing
-        * next action (like working with cached polling result)
-        */
-       struct socket           *socket, *read_socket;
-
-       /* Cached preallocated data */
-       void                    *data;
-       unsigned int            size;
-
-       /* Currently processed command */
-       struct dst_cmd          cmd;
-};
-
-struct dst_info
-{
-       /* Device size */
-       u64                     size;
-
-       /* Local device name for export devices */
-       char                    local[DST_NAMELEN];
-
-       /* Network setup */
-       struct dst_network_ctl  net;
-
-       /* Sysfs bits use this */
-       struct device           device;
-};
-
-struct dst_node
-{
-       struct list_head        node_entry;
-
-       /* Hi, my name is stored here */
-       char                    name[DST_NAMELEN];
-       /* My cache name is stored here */
-       char                    cache_name[DST_NAMELEN];
-
-       /* Block device attached to given node.
-        * Only valid for exporting nodes */
-       struct block_device     *bdev;
-       /* Network state machine for given peer */
-       struct dst_state        *state;
-
-       /* Block IO machinery */
-       struct request_queue    *queue;
-       struct gendisk          *disk;
-
-       /* Number of threads in processing pool */
-       int                     thread_num;
-       /* Maximum number of pages in single IO */
-       int                     max_pages;
-
-       /* I'm that big in bytes */
-       loff_t                  size;
-
-       /* Exported to userspace node information */
-       struct dst_info         *info;
-
-       /*
-        * Security attribute list.
-        * Used only by exporting node currently.
-        */
-       struct list_head        security_list;
-       struct mutex            security_lock;
-
-       /*
-        * When this unerflows below zero, university collapses.
-        * But this will not happen, since node will be freed,
-        * when reference counter reaches zero.
-        */
-       atomic_t                refcnt;
-
-       /* How precisely should I be started? */
-       int                     (*start)(struct dst_node *);
-
-       /* Crypto capabilities */
-       struct dst_crypto_ctl   crypto;
-       u8                      *hash_key;
-       u8                      *cipher_key;
-
-       /* Pool of processing thread */
-       struct thread_pool      *pool;
-
-       /* Transaction IDs live here */
-       atomic_long_t           gen;
-
-       /*
-        * How frequently and how many times transaction
-        * tree should be scanned to drop stale objects.
-        */
-       long                    trans_scan_timeout;
-       int                     trans_max_retries;
-
-       /* Small gnomes live here */
-       struct rb_root          trans_root;
-       struct mutex            trans_lock;
-
-       /*
-        * Transaction cache/memory pool.
-        * It is big enough to contain not only transaction
-        * itself, but additional crypto data (digest/hmac).
-        */
-       struct kmem_cache       *trans_cache;
-       mempool_t               *trans_pool;
-
-       /* This entity scans transaction tree */
-       struct delayed_work     trans_work;
-
-       wait_queue_head_t       wait;
-};
-
-/* Kernel representation of the security attribute */
-struct dst_secure
-{
-       struct list_head        sec_entry;
-       struct dst_secure_user  sec;
-};
-
-int dst_process_bio(struct dst_node *n, struct bio *bio);
-
-int dst_node_init_connected(struct dst_node *n, struct dst_network_ctl *r);
-int dst_node_init_listened(struct dst_node *n, struct dst_export_ctl *le);
-
-static inline struct dst_state *dst_state_get(struct dst_state *st)
-{
-       BUG_ON(atomic_read(&st->refcnt) == 0);
-       atomic_inc(&st->refcnt);
-       return st;
-}
-
-void dst_state_put(struct dst_state *st);
-
-struct dst_state *dst_state_alloc(struct dst_node *n);
-int dst_state_socket_create(struct dst_state *st);
-void dst_state_socket_release(struct dst_state *st);
-
-void dst_state_exit_connected(struct dst_state *st);
-
-int dst_state_schedule_receiver(struct dst_state *st);
-
-void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str);
-
-static inline void dst_state_lock(struct dst_state *st)
-{
-       mutex_lock(&st->state_lock);
-}
-
-static inline void dst_state_unlock(struct dst_state *st)
-{
-       mutex_unlock(&st->state_lock);
-}
-
-void dst_poll_exit(struct dst_state *st);
-int dst_poll_init(struct dst_state *st);
-
-static inline unsigned int dst_state_poll(struct dst_state *st)
-{
-       unsigned int revents = POLLHUP | POLLERR;
-
-       dst_state_lock(st);
-       if (st->socket)
-               revents = st->socket->ops->poll(NULL, st->socket, NULL);
-       dst_state_unlock(st);
-
-       return revents;
-}
-
-static inline int dst_thread_setup(void *private, void *data)
-{
-       return 0;
-}
-
-void dst_node_put(struct dst_node *n);
-
-static inline struct dst_node *dst_node_get(struct dst_node *n)
-{
-       atomic_inc(&n->refcnt);
-       return n;
-}
-
-int dst_data_recv(struct dst_state *st, void *data, unsigned int size);
-int dst_recv_cdata(struct dst_state *st, void *cdata);
-int dst_data_send_header(struct socket *sock,
-               void *data, unsigned int size, int more);
-
-int dst_send_bio(struct dst_state *st, struct dst_cmd *cmd, struct bio *bio);
-
-int dst_process_io(struct dst_state *st);
-int dst_export_crypto(struct dst_node *n, struct bio *bio);
-int dst_export_send_bio(struct bio *bio);
-int dst_start_export(struct dst_node *n);
-
-int __init dst_export_init(void);
-void dst_export_exit(void);
-
-/* Private structure for export block IO requests */
-struct dst_export_priv
-{
-       struct list_head                request_entry;
-       struct dst_state                *state;
-       struct bio                      *bio;
-       struct dst_cmd                  cmd;
-};
-
-static inline void dst_trans_get(struct dst_trans *t)
-{
-       atomic_inc(&t->refcnt);
-}
-
-struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen);
-int dst_trans_remove(struct dst_trans *t);
-int dst_trans_remove_nolock(struct dst_trans *t);
-void dst_trans_put(struct dst_trans *t);
-
-/*
- * Convert bio into network command.
- */
-static inline void dst_bio_to_cmd(struct bio *bio, struct dst_cmd *cmd,
-               u32 command, u64 id)
-{
-       cmd->cmd = command;
-       cmd->flags = (bio->bi_flags << BIO_POOL_BITS) >> BIO_POOL_BITS;
-       cmd->rw = bio->bi_rw;
-       cmd->size = bio->bi_size;
-       cmd->csize = 0;
-       cmd->id = id;
-       cmd->sector = bio->bi_sector;
-};
-
-int dst_trans_send(struct dst_trans *t);
-int dst_trans_crypto(struct dst_trans *t);
-
-int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl);
-void dst_node_crypto_exit(struct dst_node *n);
-
-static inline int dst_need_crypto(struct dst_node *n)
-{
-       struct dst_crypto_ctl *c = &n->crypto;
-       /*
-        * Logical OR is appropriate here, but boolean one produces
-        * more optimal code, so it is used instead.
-        */
-       return (c->hash_algo[0] | c->cipher_algo[0]);
-}
-
-int dst_node_trans_init(struct dst_node *n, unsigned int size);
-void dst_node_trans_exit(struct dst_node *n);
-
-/*
- * Pool of threads.
- * Ready list contains threads currently free to be used,
- * active one contains threads with some work scheduled for them.
- * Caller can wait in given queue when thread is ready.
- */
-struct thread_pool
-{
-       int                     thread_num;
-       struct mutex            thread_lock;
-       struct list_head        ready_list, active_list;
-
-       wait_queue_head_t       wait;
-};
-
-void thread_pool_del_worker(struct thread_pool *p);
-void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id);
-int thread_pool_add_worker(struct thread_pool *p,
-               char *name,
-               unsigned int id,
-               void *(* init)(void *data),
-               void (* cleanup)(void *data),
-               void *data);
-
-void thread_pool_destroy(struct thread_pool *p);
-struct thread_pool *thread_pool_create(int num, char *name,
-               void *(* init)(void *data),
-               void (* cleanup)(void *data),
-               void *data);
-
-int thread_pool_schedule(struct thread_pool *p,
-               int (* setup)(void *stored_private, void *setup_data),
-               int (* action)(void *stored_private, void *setup_data),
-               void *setup_data, long timeout);
-int thread_pool_schedule_private(struct thread_pool *p,
-               int (* setup)(void *private, void *data),
-               int (* action)(void *private, void *data),
-               void *data, long timeout, void *id);
-
-#endif /* __KERNEL__ */
-#endif /* __DST_H */
index 90a4ed0..0cc4d55 100644 (file)
@@ -361,7 +361,7 @@ typedef struct elf64_shdr {
 #define NT_PPC_VSX     0x102           /* PowerPC VSX registers */
 #define NT_386_TLS     0x200           /* i386 TLS slots (struct user_desc) */
 #define NT_386_IOPERM  0x201           /* x86 io permission bitmap (1=deny) */
-#define NT_PRXSTATUS   0x300           /* s390 upper register halves */
+#define NT_S390_HIGH_GPRS      0x300   /* s390 upper register halves */
 
 
 /* Note header in a PT_NOTE section */
index f07f34d..258088a 100644 (file)
@@ -72,6 +72,8 @@ struct ext3_sb_info {
        struct inode * s_journal_inode;
        struct journal_s * s_journal;
        struct list_head s_orphan;
+       struct mutex s_orphan_lock;
+       struct mutex s_resize_lock;
        unsigned long s_commit_interval;
        struct block_device *journal_bdev;
 #ifdef CONFIG_JBD_DEBUG
index cf82d51..d7b5ddc 100644 (file)
 
 #define EXT3_DATA_TRANS_BLOCKS(sb)     (EXT3_SINGLEDATA_TRANS_BLOCKS + \
                                         EXT3_XATTR_TRANS_BLOCKS - 2 + \
-                                        2*EXT3_QUOTA_TRANS_BLOCKS(sb))
+                                        EXT3_MAXQUOTAS_TRANS_BLOCKS(sb))
 
 /* Delete operations potentially hit one directory's namespace plus an
  * entire inode, plus arbitrary amounts of bitmap/indirection data.  Be
  * generous.  We can grow the delete transaction later if necessary. */
 
-#define EXT3_DELETE_TRANS_BLOCKS(sb)   (2 * EXT3_DATA_TRANS_BLOCKS(sb) + 64)
+#define EXT3_DELETE_TRANS_BLOCKS(sb)   (EXT3_MAXQUOTAS_TRANS_BLOCKS(sb) + 64)
 
 /* Define an arbitrary limit for the amount of data we will anticipate
  * writing to any given transaction.  For unbounded transactions such as
@@ -86,6 +86,9 @@
 #define EXT3_QUOTA_INIT_BLOCKS(sb) 0
 #define EXT3_QUOTA_DEL_BLOCKS(sb) 0
 #endif
+#define EXT3_MAXQUOTAS_TRANS_BLOCKS(sb) (MAXQUOTAS*EXT3_QUOTA_TRANS_BLOCKS(sb))
+#define EXT3_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT3_QUOTA_INIT_BLOCKS(sb))
+#define EXT3_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT3_QUOTA_DEL_BLOCKS(sb))
 
 int
 ext3_mark_iloc_dirty(handle_t *handle,
index cca1919..9147ca8 100644 (file)
@@ -1624,8 +1624,6 @@ struct super_operations {
  *                     on the bit address once it is done.
  *
  * Q: What is the difference between I_WILL_FREE and I_FREEING?
- * Q: igrab() only checks on (I_FREEING|I_WILL_FREE).  Should it also check on
- *    I_CLEAR?  If not, why?
  */
 #define I_DIRTY_SYNC           1
 #define I_DIRTY_DATASYNC       2
@@ -2299,6 +2297,7 @@ extern const struct inode_operations page_symlink_inode_operations;
 extern int generic_readlink(struct dentry *, char __user *, int);
 extern void generic_fillattr(struct inode *, struct kstat *);
 extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+void __inode_add_bytes(struct inode *inode, loff_t bytes);
 void inode_add_bytes(struct inode *inode, loff_t bytes);
 void inode_sub_bytes(struct inode *inode, loff_t bytes);
 loff_t inode_get_bytes(struct inode *inode);
@@ -2464,5 +2463,8 @@ int proc_nr_files(struct ctl_table *table, int write,
 
 int __init get_filesystem_list(char *buf);
 
+#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
+#define OPEN_FMODE(flag) ((__force fmode_t)((flag + 1) & O_ACCMODE))
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_FS_H */
index ad6bdf5..3d44e9c 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * A simple kernel FIFO implementation.
+ * A generic kernel FIFO implementation.
  *
+ * Copyright (C) 2009 Stefani Seibold <stefani@seibold.net>
  * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+
+/*
+ * Howto porting drivers to the new generic fifo API:
+ *
+ * - Modify the declaration of the "struct kfifo *" object into a
+ *   in-place "struct kfifo" object
+ * - Init the in-place object with kfifo_alloc() or kfifo_init()
+ *   Note: The address of the in-place "struct kfifo" object must be
+ *   passed as the first argument to this functions
+ * - Replace the use of __kfifo_put into kfifo_in and __kfifo_get
+ *   into kfifo_out
+ * - Replace the use of kfifo_put into kfifo_in_locked and kfifo_get
+ *   into kfifo_out_locked
+ *   Note: the spinlock pointer formerly passed to kfifo_init/kfifo_alloc
+ *   must be passed now to the kfifo_in_locked and kfifo_out_locked
+ *   as the last parameter.
+ * - All formerly name __kfifo_* functions has been renamed into kfifo_*
+ */
+
 #ifndef _LINUX_KFIFO_H
 #define _LINUX_KFIFO_H
 
@@ -29,124 +49,562 @@ struct kfifo {
        unsigned int size;      /* the size of the allocated buffer */
        unsigned int in;        /* data is added at offset (in % size) */
        unsigned int out;       /* data is extracted from off. (out % size) */
-       spinlock_t *lock;       /* protects concurrent modifications */
 };
 
-extern struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
-                               gfp_t gfp_mask, spinlock_t *lock);
-extern struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask,
-                                spinlock_t *lock);
+/*
+ * Macros for declaration and initialization of the kfifo datatype
+ */
+
+/* helper macro */
+#define __kfifo_initializer(s, b) \
+       (struct kfifo) { \
+               .size   = s, \
+               .in     = 0, \
+               .out    = 0, \
+               .buffer = b \
+       }
+
+/**
+ * DECLARE_KFIFO - macro to declare a kfifo and the associated buffer
+ * @name: name of the declared kfifo datatype
+ * @size: size of the fifo buffer
+ *
+ * Note1: the macro can be used inside struct or union declaration
+ * Note2: the macro creates two objects:
+ *  A kfifo object with the given name and a buffer for the kfifo
+ *  object named name##kfifo_buffer
+ */
+#define DECLARE_KFIFO(name, size) \
+union { \
+       struct kfifo name; \
+       unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \
+}
+
+/**
+ * INIT_KFIFO - Initialize a kfifo declared by DECLARED_KFIFO
+ * @name: name of the declared kfifo datatype
+ */
+#define INIT_KFIFO(name) \
+       name = __kfifo_initializer(sizeof(name##kfifo_buffer) - \
+                               sizeof(struct kfifo), name##kfifo_buffer)
+
+/**
+ * DEFINE_KFIFO - macro to define and initialize a kfifo
+ * @name: name of the declared kfifo datatype
+ * @size: size of the fifo buffer
+ *
+ * Note1: the macro can be used for global and local kfifo data type variables
+ * Note2: the macro creates two objects:
+ *  A kfifo object with the given name and a buffer for the kfifo
+ *  object named name##kfifo_buffer
+ */
+#define DEFINE_KFIFO(name, size) \
+       unsigned char name##kfifo_buffer[size]; \
+       struct kfifo name = __kfifo_initializer(size, name##kfifo_buffer)
+
+#undef __kfifo_initializer
+
+extern void kfifo_init(struct kfifo *fifo, unsigned char *buffer,
+                       unsigned int size);
+extern __must_check int kfifo_alloc(struct kfifo *fifo, unsigned int size,
+                       gfp_t gfp_mask);
 extern void kfifo_free(struct kfifo *fifo);
-extern unsigned int __kfifo_put(struct kfifo *fifo,
-                               const unsigned char *buffer, unsigned int len);
-extern unsigned int __kfifo_get(struct kfifo *fifo,
-                               unsigned char *buffer, unsigned int len);
+extern unsigned int kfifo_in(struct kfifo *fifo,
+                               const unsigned char *from, unsigned int len);
+extern __must_check unsigned int kfifo_out(struct kfifo *fifo,
+                               unsigned char *to, unsigned int len);
 
 /**
- * __kfifo_reset - removes the entire FIFO contents, no locking version
+ * kfifo_reset - removes the entire FIFO contents
  * @fifo: the fifo to be emptied.
  */
-static inline void __kfifo_reset(struct kfifo *fifo)
+static inline void kfifo_reset(struct kfifo *fifo)
 {
        fifo->in = fifo->out = 0;
 }
 
 /**
- * kfifo_reset - removes the entire FIFO contents
+ * kfifo_reset_out - skip FIFO contents
  * @fifo: the fifo to be emptied.
  */
-static inline void kfifo_reset(struct kfifo *fifo)
+static inline void kfifo_reset_out(struct kfifo *fifo)
 {
-       unsigned long flags;
+       smp_mb();
+       fifo->out = fifo->in;
+}
 
-       spin_lock_irqsave(fifo->lock, flags);
+/**
+ * kfifo_size - returns the size of the fifo in bytes
+ * @fifo: the fifo to be used.
+ */
+static inline __must_check unsigned int kfifo_size(struct kfifo *fifo)
+{
+       return fifo->size;
+}
 
-       __kfifo_reset(fifo);
+/**
+ * kfifo_len - returns the number of used bytes in the FIFO
+ * @fifo: the fifo to be used.
+ */
+static inline unsigned int kfifo_len(struct kfifo *fifo)
+{
+       register unsigned int   out;
 
-       spin_unlock_irqrestore(fifo->lock, flags);
+       out = fifo->out;
+       smp_rmb();
+       return fifo->in - out;
 }
 
 /**
- * kfifo_put - puts some data into the FIFO
+ * kfifo_is_empty - returns true if the fifo is empty
  * @fifo: the fifo to be used.
- * @buffer: the data to be added.
- * @len: the length of the data to be added.
+ */
+static inline __must_check int kfifo_is_empty(struct kfifo *fifo)
+{
+       return fifo->in == fifo->out;
+}
+
+/**
+ * kfifo_is_full - returns true if the fifo is full
+ * @fifo: the fifo to be used.
+ */
+static inline __must_check int kfifo_is_full(struct kfifo *fifo)
+{
+       return kfifo_len(fifo) == kfifo_size(fifo);
+}
+
+/**
+ * kfifo_avail - returns the number of bytes available in the FIFO
+ * @fifo: the fifo to be used.
+ */
+static inline __must_check unsigned int kfifo_avail(struct kfifo *fifo)
+{
+       return kfifo_size(fifo) - kfifo_len(fifo);
+}
+
+/**
+ * kfifo_in_locked - puts some data into the FIFO using a spinlock for locking
+ * @fifo: the fifo to be used.
+ * @from: the data to be added.
+ * @n: the length of the data to be added.
+ * @lock: pointer to the spinlock to use for locking.
  *
- * This function copies at most @len bytes from the @buffer into
+ * This function copies at most @len bytes from the @from buffer into
  * the FIFO depending on the free space, and returns the number of
  * bytes copied.
  */
-static inline unsigned int kfifo_put(struct kfifo *fifo,
-                               const unsigned char *buffer, unsigned int len)
+static inline unsigned int kfifo_in_locked(struct kfifo *fifo,
+               const unsigned char *from, unsigned int n, spinlock_t *lock)
 {
        unsigned long flags;
        unsigned int ret;
 
-       spin_lock_irqsave(fifo->lock, flags);
+       spin_lock_irqsave(lock, flags);
 
-       ret = __kfifo_put(fifo, buffer, len);
+       ret = kfifo_in(fifo, from, n);
 
-       spin_unlock_irqrestore(fifo->lock, flags);
+       spin_unlock_irqrestore(lock, flags);
 
        return ret;
 }
 
 /**
- * kfifo_get - gets some data from the FIFO
+ * kfifo_out_locked - gets some data from the FIFO using a spinlock for locking
  * @fifo: the fifo to be used.
- * @buffer: where the data must be copied.
- * @len: the size of the destination buffer.
+ * @to: where the data must be copied.
+ * @n: the size of the destination buffer.
+ * @lock: pointer to the spinlock to use for locking.
  *
  * This function copies at most @len bytes from the FIFO into the
- * @buffer and returns the number of copied bytes.
+ * @to buffer and returns the number of copied bytes.
  */
-static inline unsigned int kfifo_get(struct kfifo *fifo,
-                                    unsigned char *buffer, unsigned int len)
+static inline __must_check unsigned int kfifo_out_locked(struct kfifo *fifo,
+       unsigned char *to, unsigned int n, spinlock_t *lock)
 {
        unsigned long flags;
        unsigned int ret;
 
-       spin_lock_irqsave(fifo->lock, flags);
+       spin_lock_irqsave(lock, flags);
 
-       ret = __kfifo_get(fifo, buffer, len);
+       ret = kfifo_out(fifo, to, n);
 
        /*
         * optimization: if the FIFO is empty, set the indices to 0
         * so we don't wrap the next time
         */
-       if (fifo->in == fifo->out)
-               fifo->in = fifo->out = 0;
+       if (kfifo_is_empty(fifo))
+               kfifo_reset(fifo);
+
+       spin_unlock_irqrestore(lock, flags);
+
+       return ret;
+}
+
+extern void kfifo_skip(struct kfifo *fifo, unsigned int len);
+
+extern __must_check unsigned int kfifo_from_user(struct kfifo *fifo,
+       const void __user *from, unsigned int n);
+
+extern __must_check unsigned int kfifo_to_user(struct kfifo *fifo,
+       void __user *to, unsigned int n);
+
+/*
+ * __kfifo_add_out internal helper function for updating the out offset
+ */
+static inline void __kfifo_add_out(struct kfifo *fifo,
+                               unsigned int off)
+{
+       smp_mb();
+       fifo->out += off;
+}
+
+/*
+ * __kfifo_add_in internal helper function for updating the in offset
+ */
+static inline void __kfifo_add_in(struct kfifo *fifo,
+                               unsigned int off)
+{
+       smp_wmb();
+       fifo->in += off;
+}
+
+/*
+ * __kfifo_off internal helper function for calculating the index of a
+ * given offeset
+ */
+static inline unsigned int __kfifo_off(struct kfifo *fifo, unsigned int off)
+{
+       return off & (fifo->size - 1);
+}
+
+/*
+ * __kfifo_peek_n internal helper function for determinate the length of
+ * the next record in the fifo
+ */
+static inline unsigned int __kfifo_peek_n(struct kfifo *fifo,
+                               unsigned int recsize)
+{
+#define __KFIFO_GET(fifo, off, shift) \
+       ((fifo)->buffer[__kfifo_off((fifo), (fifo)->out+(off))] << (shift))
+
+       unsigned int l;
+
+       l = __KFIFO_GET(fifo, 0, 0);
+
+       if (--recsize)
+               l |= __KFIFO_GET(fifo, 1, 8);
+
+       return l;
+#undef __KFIFO_GET
+}
+
+/*
+ * __kfifo_poke_n internal helper function for storing the length of
+ * the next record into the fifo
+ */
+static inline void __kfifo_poke_n(struct kfifo *fifo,
+                       unsigned int recsize, unsigned int n)
+{
+#define __KFIFO_PUT(fifo, off, val, shift) \
+               ( \
+               (fifo)->buffer[__kfifo_off((fifo), (fifo)->in+(off))] = \
+               (unsigned char)((val) >> (shift)) \
+               )
 
-       spin_unlock_irqrestore(fifo->lock, flags);
+       __KFIFO_PUT(fifo, 0, n, 0);
 
+       if (--recsize)
+               __KFIFO_PUT(fifo, 1, n, 8);
+#undef __KFIFO_PUT
+}
+
+/*
+ * __kfifo_in_... internal functions for put date into the fifo
+ * do not call it directly, use kfifo_in_rec() instead
+ */
+extern unsigned int __kfifo_in_n(struct kfifo *fifo,
+       const void *from, unsigned int n, unsigned int recsize);
+
+extern unsigned int __kfifo_in_generic(struct kfifo *fifo,
+       const void *from, unsigned int n, unsigned int recsize);
+
+static inline unsigned int __kfifo_in_rec(struct kfifo *fifo,
+       const void *from, unsigned int n, unsigned int recsize)
+{
+       unsigned int ret;
+
+       ret = __kfifo_in_n(fifo, from, n, recsize);
+
+       if (likely(ret == 0)) {
+               if (recsize)
+                       __kfifo_poke_n(fifo, recsize, n);
+               __kfifo_add_in(fifo, n + recsize);
+       }
        return ret;
 }
 
 /**
- * __kfifo_len - returns the number of bytes available in the FIFO, no locking version
+ * kfifo_in_rec - puts some record data into the FIFO
  * @fifo: the fifo to be used.
+ * @from: the data to be added.
+ * @n: the length of the data to be added.
+ * @recsize: size of record field
+ *
+ * This function copies @n bytes from the @from into the FIFO and returns
+ * the number of bytes which cannot be copied.
+ * A returned value greater than the @n value means that the record doesn't
+ * fit into the buffer.
+ *
+ * Note that with only one concurrent reader and one concurrent
+ * writer, you don't need extra locking to use these functions.
  */
-static inline unsigned int __kfifo_len(struct kfifo *fifo)
+static inline __must_check unsigned int kfifo_in_rec(struct kfifo *fifo,
+       void *from, unsigned int n, unsigned int recsize)
 {
-       return fifo->in - fifo->out;
+       if (!__builtin_constant_p(recsize))
+               return __kfifo_in_generic(fifo, from, n, recsize);
+       return __kfifo_in_rec(fifo, from, n, recsize);
+}
+
+/*
+ * __kfifo_out_... internal functions for get date from the fifo
+ * do not call it directly, use kfifo_out_rec() instead
+ */
+extern unsigned int __kfifo_out_n(struct kfifo *fifo,
+       void *to, unsigned int reclen, unsigned int recsize);
+
+extern unsigned int __kfifo_out_generic(struct kfifo *fifo,
+       void *to, unsigned int n,
+       unsigned int recsize, unsigned int *total);
+
+static inline unsigned int __kfifo_out_rec(struct kfifo *fifo,
+       void *to, unsigned int n, unsigned int recsize,
+       unsigned int *total)
+{
+       unsigned int l;
+
+       if (!recsize) {
+               l = n;
+               if (total)
+                       *total = l;
+       } else {
+               l = __kfifo_peek_n(fifo, recsize);
+               if (total)
+                       *total = l;
+               if (n < l)
+                       return l;
+       }
+
+       return __kfifo_out_n(fifo, to, l, recsize);
 }
 
 /**
- * kfifo_len - returns the number of bytes available in the FIFO
+ * kfifo_out_rec - gets some record data from the FIFO
  * @fifo: the fifo to be used.
+ * @to: where the data must be copied.
+ * @n: the size of the destination buffer.
+ * @recsize: size of record field
+ * @total: pointer where the total number of to copied bytes should stored
+ *
+ * This function copies at most @n bytes from the FIFO to @to and returns the
+ * number of bytes which cannot be copied.
+ * A returned value greater than the @n value means that the record doesn't
+ * fit into the @to buffer.
+ *
+ * Note that with only one concurrent reader and one concurrent
+ * writer, you don't need extra locking to use these functions.
  */
-static inline unsigned int kfifo_len(struct kfifo *fifo)
+static inline __must_check unsigned int kfifo_out_rec(struct kfifo *fifo,
+       void *to, unsigned int n, unsigned int recsize,
+       unsigned int *total)
+
 {
-       unsigned long flags;
-       unsigned int ret;
+       if (!__builtin_constant_p(recsize))
+               return __kfifo_out_generic(fifo, to, n, recsize, total);
+       return __kfifo_out_rec(fifo, to, n, recsize, total);
+}
+
+/*
+ * __kfifo_from_user_... internal functions for transfer from user space into
+ * the fifo. do not call it directly, use kfifo_from_user_rec() instead
+ */
+extern unsigned int __kfifo_from_user_n(struct kfifo *fifo,
+       const void __user *from, unsigned int n, unsigned int recsize);
 
-       spin_lock_irqsave(fifo->lock, flags);
+extern unsigned int __kfifo_from_user_generic(struct kfifo *fifo,
+       const void __user *from, unsigned int n, unsigned int recsize);
 
-       ret = __kfifo_len(fifo);
+static inline unsigned int __kfifo_from_user_rec(struct kfifo *fifo,
+       const void __user *from, unsigned int n, unsigned int recsize)
+{
+       unsigned int ret;
 
-       spin_unlock_irqrestore(fifo->lock, flags);
+       ret = __kfifo_from_user_n(fifo, from, n, recsize);
 
+       if (likely(ret == 0)) {
+               if (recsize)
+                       __kfifo_poke_n(fifo, recsize, n);
+               __kfifo_add_in(fifo, n + recsize);
+       }
        return ret;
 }
 
+/**
+ * kfifo_from_user_rec - puts some data from user space into the FIFO
+ * @fifo: the fifo to be used.
+ * @from: pointer to the data to be added.
+ * @n: the length of the data to be added.
+ * @recsize: size of record field
+ *
+ * This function copies @n bytes from the @from into the
+ * FIFO and returns the number of bytes which cannot be copied.
+ *
+ * If the returned value is equal or less the @n value, the copy_from_user()
+ * functions has failed. Otherwise the record doesn't fit into the buffer.
+ *
+ * Note that with only one concurrent reader and one concurrent
+ * writer, you don't need extra locking to use these functions.
+ */
+static inline __must_check unsigned int kfifo_from_user_rec(struct kfifo *fifo,
+       const void __user *from, unsigned int n, unsigned int recsize)
+{
+       if (!__builtin_constant_p(recsize))
+               return __kfifo_from_user_generic(fifo, from, n, recsize);
+       return __kfifo_from_user_rec(fifo, from, n, recsize);
+}
+
+/*
+ * __kfifo_to_user_... internal functions for transfer fifo data into user space
+ * do not call it directly, use kfifo_to_user_rec() instead
+ */
+extern unsigned int __kfifo_to_user_n(struct kfifo *fifo,
+       void __user *to, unsigned int n, unsigned int reclen,
+       unsigned int recsize);
+
+extern unsigned int __kfifo_to_user_generic(struct kfifo *fifo,
+       void __user *to, unsigned int n, unsigned int recsize,
+       unsigned int *total);
+
+static inline unsigned int __kfifo_to_user_rec(struct kfifo *fifo,
+       void __user *to, unsigned int n,
+       unsigned int recsize, unsigned int *total)
+{
+       unsigned int l;
+
+       if (!recsize) {
+               l = n;
+               if (total)
+                       *total = l;
+       } else {
+               l = __kfifo_peek_n(fifo, recsize);
+               if (total)
+                       *total = l;
+               if (n < l)
+                       return l;
+       }
+
+       return __kfifo_to_user_n(fifo, to, n, l, recsize);
+}
+
+/**
+ * kfifo_to_user_rec - gets data from the FIFO and write it to user space
+ * @fifo: the fifo to be used.
+ * @to: where the data must be copied.
+ * @n: the size of the destination buffer.
+ * @recsize: size of record field
+ * @total: pointer where the total number of to copied bytes should stored
+ *
+ * This function copies at most @n bytes from the FIFO to the @to.
+ * In case of an error, the function returns the number of bytes which cannot
+ * be copied.
+ * If the returned value is equal or less the @n value, the copy_to_user()
+ * functions has failed. Otherwise the record doesn't fit into the @to buffer.
+ *
+ * Note that with only one concurrent reader and one concurrent
+ * writer, you don't need extra locking to use these functions.
+ */
+static inline __must_check unsigned int kfifo_to_user_rec(struct kfifo *fifo,
+               void __user *to, unsigned int n, unsigned int recsize,
+               unsigned int *total)
+{
+       if (!__builtin_constant_p(recsize))
+               return __kfifo_to_user_generic(fifo, to, n, recsize, total);
+       return __kfifo_to_user_rec(fifo, to, n, recsize, total);
+}
+
+/*
+ * __kfifo_peek_... internal functions for peek into the next fifo record
+ * do not call it directly, use kfifo_peek_rec() instead
+ */
+extern unsigned int __kfifo_peek_generic(struct kfifo *fifo,
+                               unsigned int recsize);
+
+/**
+ * kfifo_peek_rec - gets the size of the next FIFO record data
+ * @fifo: the fifo to be used.
+ * @recsize: size of record field
+ *
+ * This function returns the size of the next FIFO record in number of bytes
+ */
+static inline __must_check unsigned int kfifo_peek_rec(struct kfifo *fifo,
+       unsigned int recsize)
+{
+       if (!__builtin_constant_p(recsize))
+               return __kfifo_peek_generic(fifo, recsize);
+       if (!recsize)
+               return kfifo_len(fifo);
+       return __kfifo_peek_n(fifo, recsize);
+}
+
+/*
+ * __kfifo_skip_... internal functions for skip the next fifo record
+ * do not call it directly, use kfifo_skip_rec() instead
+ */
+extern void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize);
+
+static inline void __kfifo_skip_rec(struct kfifo *fifo,
+       unsigned int recsize)
+{
+       unsigned int l;
+
+       if (recsize) {
+               l = __kfifo_peek_n(fifo, recsize);
+
+               if (l + recsize <= kfifo_len(fifo)) {
+                       __kfifo_add_out(fifo, l + recsize);
+                       return;
+               }
+       }
+       kfifo_reset_out(fifo);
+}
+
+/**
+ * kfifo_skip_rec - skip the next fifo out record
+ * @fifo: the fifo to be used.
+ * @recsize: size of record field
+ *
+ * This function skips the next FIFO record
+ */
+static inline void kfifo_skip_rec(struct kfifo *fifo,
+       unsigned int recsize)
+{
+       if (!__builtin_constant_p(recsize))
+               __kfifo_skip_generic(fifo, recsize);
+       else
+               __kfifo_skip_rec(fifo, recsize);
+}
+
+/**
+ * kfifo_avail_rec - returns the number of bytes available in a record FIFO
+ * @fifo: the fifo to be used.
+ * @recsize: size of record field
+ */
+static inline __must_check unsigned int kfifo_avail_rec(struct kfifo *fifo,
+       unsigned int recsize)
+{
+       unsigned int l = kfifo_size(fifo) - kfifo_len(fifo);
+
+       return (l > recsize) ? l - recsize : 0;
+}
+
 #endif
index 37fa19b..1adfe77 100644 (file)
@@ -50,6 +50,19 @@ struct memory_notify {
        int status_change_nid;
 };
 
+/*
+ * During pageblock isolation, count the number of pages within the
+ * range [start_pfn, start_pfn + nr_pages) which are owned by code
+ * in the notifier chain.
+ */
+#define MEM_ISOLATE_COUNT      (1<<0)
+
+struct memory_isolate_notify {
+       unsigned long start_pfn;        /* Start of range to check */
+       unsigned int nr_pages;          /* # pages in range to check */
+       unsigned int pages_found;       /* # pages owned found by callbacks */
+};
+
 struct notifier_block;
 struct mem_section;
 
@@ -76,14 +89,28 @@ static inline int memory_notify(unsigned long val, void *v)
 {
        return 0;
 }
+static inline int register_memory_isolate_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
+static inline void unregister_memory_isolate_notifier(struct notifier_block *nb)
+{
+}
+static inline int memory_isolate_notify(unsigned long val, void *v)
+{
+       return 0;
+}
 #else
 extern int register_memory_notifier(struct notifier_block *nb);
 extern void unregister_memory_notifier(struct notifier_block *nb);
+extern int register_memory_isolate_notifier(struct notifier_block *nb);
+extern void unregister_memory_isolate_notifier(struct notifier_block *nb);
 extern int register_new_memory(int, struct mem_section *);
 extern int unregister_memory_section(struct mem_section *);
 extern int memory_dev_init(void);
 extern int remove_memory_block(unsigned long, struct mem_section *, int);
 extern int memory_notify(unsigned long val, void *v);
+extern int memory_isolate_notify(unsigned long val, void *v);
 extern struct memory_block *find_memory_block(struct mem_section *);
 #define CONFIG_MEM_BLOCK_SIZE  (PAGES_PER_SECTION<<PAGE_SHIFT)
 enum mem_add_context { BOOT, HOTPLUG };
index 849b4a6..2265f28 100644 (file)
@@ -1037,6 +1037,9 @@ extern void add_active_range(unsigned int nid, unsigned long start_pfn,
 extern void remove_active_range(unsigned int nid, unsigned long start_pfn,
                                        unsigned long end_pfn);
 extern void remove_all_active_ranges(void);
+void sort_node_map(void);
+unsigned long __absent_pages_in_range(int nid, unsigned long start_pfn,
+                                               unsigned long end_pfn);
 extern unsigned long absent_pages_in_range(unsigned long start_pfn,
                                                unsigned long end_pfn);
 extern void get_pfn_range_for_nid(unsigned int nid,
index 0289467..05b441d 100644 (file)
@@ -72,8 +72,6 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
 
 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
                int (*open)(struct inode *, struct file *));
-extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
-extern void release_open_intent(struct nameidata *);
 
 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
 
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
deleted file mode 100644 (file)
index e3fb256..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- *  NOTE: this file will be removed in a future kernel release, it is
- *  provided as a courtesy copy of user-space code that relies on the
- *  old (pre-rename) symbols and constants.
- *
- *  Performance events:
- *
- *    Copyright (C) 2008-2009, Thomas Gleixner <tglx@linutronix.de>
- *    Copyright (C) 2008-2009, Red Hat, Inc., Ingo Molnar
- *    Copyright (C) 2008-2009, Red Hat, Inc., Peter Zijlstra
- *
- *  Data type definitions, declarations, prototypes.
- *
- *    Started by: Thomas Gleixner and Ingo Molnar
- *
- *  For licencing details see kernel-base/COPYING
- */
-#ifndef _LINUX_PERF_COUNTER_H
-#define _LINUX_PERF_COUNTER_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-#include <asm/byteorder.h>
-
-/*
- * User-space ABI bits:
- */
-
-/*
- * attr.type
- */
-enum perf_type_id {
-       PERF_TYPE_HARDWARE                      = 0,
-       PERF_TYPE_SOFTWARE                      = 1,
-       PERF_TYPE_TRACEPOINT                    = 2,
-       PERF_TYPE_HW_CACHE                      = 3,
-       PERF_TYPE_RAW                           = 4,
-
-       PERF_TYPE_MAX,                          /* non-ABI */
-};
-
-/*
- * Generalized performance counter event types, used by the
- * attr.event_id parameter of the sys_perf_counter_open()
- * syscall:
- */
-enum perf_hw_id {
-       /*
-        * Common hardware events, generalized by the kernel:
-        */
-       PERF_COUNT_HW_CPU_CYCLES                = 0,
-       PERF_COUNT_HW_INSTRUCTIONS              = 1,
-       PERF_COUNT_HW_CACHE_REFERENCES          = 2,
-       PERF_COUNT_HW_CACHE_MISSES              = 3,
-       PERF_COUNT_HW_BRANCH_INSTRUCTIONS       = 4,
-       PERF_COUNT_HW_BRANCH_MISSES             = 5,
-       PERF_COUNT_HW_BUS_CYCLES                = 6,
-
-       PERF_COUNT_HW_MAX,                      /* non-ABI */
-};
-
-/*
- * Generalized hardware cache counters:
- *
- *       { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x
- *       { read, write, prefetch } x
- *       { accesses, misses }
- */
-enum perf_hw_cache_id {
-       PERF_COUNT_HW_CACHE_L1D                 = 0,
-       PERF_COUNT_HW_CACHE_L1I                 = 1,
-       PERF_COUNT_HW_CACHE_LL                  = 2,
-       PERF_COUNT_HW_CACHE_DTLB                = 3,
-       PERF_COUNT_HW_CACHE_ITLB                = 4,
-       PERF_COUNT_HW_CACHE_BPU                 = 5,
-
-       PERF_COUNT_HW_CACHE_MAX,                /* non-ABI */
-};
-
-enum perf_hw_cache_op_id {
-       PERF_COUNT_HW_CACHE_OP_READ             = 0,
-       PERF_COUNT_HW_CACHE_OP_WRITE            = 1,
-       PERF_COUNT_HW_CACHE_OP_PREFETCH         = 2,
-
-       PERF_COUNT_HW_CACHE_OP_MAX,             /* non-ABI */
-};
-
-enum perf_hw_cache_op_result_id {
-       PERF_COUNT_HW_CACHE_RESULT_ACCESS       = 0,
-       PERF_COUNT_HW_CACHE_RESULT_MISS         = 1,
-
-       PERF_COUNT_HW_CACHE_RESULT_MAX,         /* non-ABI */
-};
-
-/*
- * Special "software" counters provided by the kernel, even if the hardware
- * does not support performance counters. These counters measure various
- * physical and sw events of the kernel (and allow the profiling of them as
- * well):
- */
-enum perf_sw_ids {
-       PERF_COUNT_SW_CPU_CLOCK                 = 0,
-       PERF_COUNT_SW_TASK_CLOCK                = 1,
-       PERF_COUNT_SW_PAGE_FAULTS               = 2,
-       PERF_COUNT_SW_CONTEXT_SWITCHES          = 3,
-       PERF_COUNT_SW_CPU_MIGRATIONS            = 4,
-       PERF_COUNT_SW_PAGE_FAULTS_MIN           = 5,
-       PERF_COUNT_SW_PAGE_FAULTS_MAJ           = 6,
-       PERF_COUNT_SW_ALIGNMENT_FAULTS          = 7,
-       PERF_COUNT_SW_EMULATION_FAULTS          = 8,
-
-       PERF_COUNT_SW_MAX,                      /* non-ABI */
-};
-
-/*
- * Bits that can be set in attr.sample_type to request information
- * in the overflow packets.
- */
-enum perf_counter_sample_format {
-       PERF_SAMPLE_IP                          = 1U << 0,
-       PERF_SAMPLE_TID                         = 1U << 1,
-       PERF_SAMPLE_TIME                        = 1U << 2,
-       PERF_SAMPLE_ADDR                        = 1U << 3,
-       PERF_SAMPLE_READ                        = 1U << 4,
-       PERF_SAMPLE_CALLCHAIN                   = 1U << 5,
-       PERF_SAMPLE_ID                          = 1U << 6,
-       PERF_SAMPLE_CPU                         = 1U << 7,
-       PERF_SAMPLE_PERIOD                      = 1U << 8,
-       PERF_SAMPLE_STREAM_ID                   = 1U << 9,
-       PERF_SAMPLE_RAW                         = 1U << 10,
-
-       PERF_SAMPLE_MAX = 1U << 11,             /* non-ABI */
-};
-
-/*
- * The format of the data returned by read() on a perf counter fd,
- * as specified by attr.read_format:
- *
- * struct read_format {
- *     { u64           value;
- *       { u64         time_enabled; } && PERF_FORMAT_ENABLED
- *       { u64         time_running; } && PERF_FORMAT_RUNNING
- *       { u64         id;           } && PERF_FORMAT_ID
- *     } && !PERF_FORMAT_GROUP
- *
- *     { u64           nr;
- *       { u64         time_enabled; } && PERF_FORMAT_ENABLED
- *       { u64         time_running; } && PERF_FORMAT_RUNNING
- *       { u64         value;
- *         { u64       id;           } && PERF_FORMAT_ID
- *       }             cntr[nr];
- *     } && PERF_FORMAT_GROUP
- * };
- */
-enum perf_counter_read_format {
-       PERF_FORMAT_TOTAL_TIME_ENABLED          = 1U << 0,
-       PERF_FORMAT_TOTAL_TIME_RUNNING          = 1U << 1,
-       PERF_FORMAT_ID                          = 1U << 2,
-       PERF_FORMAT_GROUP                       = 1U << 3,
-
-       PERF_FORMAT_MAX = 1U << 4,              /* non-ABI */
-};
-
-#define PERF_ATTR_SIZE_VER0    64      /* sizeof first published struct */
-
-/*
- * Hardware event to monitor via a performance monitoring counter:
- */
-struct perf_counter_attr {
-
-       /*
-        * Major type: hardware/software/tracepoint/etc.
-        */
-       __u32                   type;
-
-       /*
-        * Size of the attr structure, for fwd/bwd compat.
-        */
-       __u32                   size;
-
-       /*
-        * Type specific configuration information.
-        */
-       __u64                   config;
-
-       union {
-               __u64           sample_period;
-               __u64           sample_freq;
-       };
-
-       __u64                   sample_type;
-       __u64                   read_format;
-
-       __u64                   disabled       :  1, /* off by default        */
-                               inherit        :  1, /* children inherit it   */
-                               pinned         :  1, /* must always be on PMU */
-                               exclusive      :  1, /* only group on PMU     */
-                               exclude_user   :  1, /* don't count user      */
-                               exclude_kernel :  1, /* ditto kernel          */
-                               exclude_hv     :  1, /* ditto hypervisor      */
-                               exclude_idle   :  1, /* don't count when idle */
-                               mmap           :  1, /* include mmap data     */
-                               comm           :  1, /* include comm data     */
-                               freq           :  1, /* use freq, not period  */
-                               inherit_stat   :  1, /* per task counts       */
-                               enable_on_exec :  1, /* next exec enables     */
-                               task           :  1, /* trace fork/exit       */
-                               watermark      :  1, /* wakeup_watermark      */
-
-                               __reserved_1   : 49;
-
-       union {
-               __u32           wakeup_events;    /* wakeup every n events */
-               __u32           wakeup_watermark; /* bytes before wakeup   */
-       };
-       __u32                   __reserved_2;
-
-       __u64                   __reserved_3;
-};
-
-/*
- * Ioctls that can be done on a perf counter fd:
- */
-#define PERF_COUNTER_IOC_ENABLE                _IO ('$', 0)
-#define PERF_COUNTER_IOC_DISABLE       _IO ('$', 1)
-#define PERF_COUNTER_IOC_REFRESH       _IO ('$', 2)
-#define PERF_COUNTER_IOC_RESET         _IO ('$', 3)
-#define PERF_COUNTER_IOC_PERIOD                _IOW('$', 4, u64)
-#define PERF_COUNTER_IOC_SET_OUTPUT    _IO ('$', 5)
-#define PERF_COUNTER_IOC_SET_FILTER    _IOW('$', 6, char *)
-
-enum perf_counter_ioc_flags {
-       PERF_IOC_FLAG_GROUP             = 1U << 0,
-};
-
-/*
- * Structure of the page that can be mapped via mmap
- */
-struct perf_counter_mmap_page {
-       __u32   version;                /* version number of this structure */
-       __u32   compat_version;         /* lowest version this is compat with */
-
-       /*
-        * Bits needed to read the hw counters in user-space.
-        *
-        *   u32 seq;
-        *   s64 count;
-        *
-        *   do {
-        *     seq = pc->lock;
-        *
-        *     barrier()
-        *     if (pc->index) {
-        *       count = pmc_read(pc->index - 1);
-        *       count += pc->offset;
-        *     } else
-        *       goto regular_read;
-        *
-        *     barrier();
-        *   } while (pc->lock != seq);
-        *
-        * NOTE: for obvious reason this only works on self-monitoring
-        *       processes.
-        */
-       __u32   lock;                   /* seqlock for synchronization */
-       __u32   index;                  /* hardware counter identifier */
-       __s64   offset;                 /* add to hardware counter value */
-       __u64   time_enabled;           /* time counter active */
-       __u64   time_running;           /* time counter on cpu */
-
-               /*
-                * Hole for extension of the self monitor capabilities
-                */
-
-       __u64   __reserved[123];        /* align to 1k */
-
-       /*
-        * Control data for the mmap() data buffer.
-        *
-        * User-space reading the @data_head value should issue an rmb(), on
-        * SMP capable platforms, after reading this value -- see
-        * perf_counter_wakeup().
-        *
-        * When the mapping is PROT_WRITE the @data_tail value should be
-        * written by userspace to reflect the last read data. In this case
-        * the kernel will not over-write unread data.
-        */
-       __u64   data_head;              /* head in the data section */
-       __u64   data_tail;              /* user-space written tail */
-};
-
-#define PERF_EVENT_MISC_CPUMODE_MASK           (3 << 0)
-#define PERF_EVENT_MISC_CPUMODE_UNKNOWN                (0 << 0)
-#define PERF_EVENT_MISC_KERNEL                 (1 << 0)
-#define PERF_EVENT_MISC_USER                   (2 << 0)
-#define PERF_EVENT_MISC_HYPERVISOR             (3 << 0)
-
-struct perf_event_header {
-       __u32   type;
-       __u16   misc;
-       __u16   size;
-};
-
-enum perf_event_type {
-
-       /*
-        * The MMAP events record the PROT_EXEC mappings so that we can
-        * correlate userspace IPs to code. They have the following structure:
-        *
-        * struct {
-        *      struct perf_event_header        header;
-        *
-        *      u32                             pid, tid;
-        *      u64                             addr;
-        *      u64                             len;
-        *      u64                             pgoff;
-        *      char                            filename[];
-        * };
-        */
-       PERF_EVENT_MMAP                 = 1,
-
-       /*
-        * struct {
-        *      struct perf_event_header        header;
-        *      u64                             id;
-        *      u64                             lost;
-        * };
-        */
-       PERF_EVENT_LOST                 = 2,
-
-       /*
-        * struct {
-        *      struct perf_event_header        header;
-        *
-        *      u32                             pid, tid;
-        *      char                            comm[];
-        * };
-        */
-       PERF_EVENT_COMM                 = 3,
-
-       /*
-        * struct {
-        *      struct perf_event_header        header;
-        *      u32                             pid, ppid;
-        *      u32                             tid, ptid;
-        *      u64                             time;
-        * };
-        */
-       PERF_EVENT_EXIT                 = 4,
-
-       /*
-        * struct {
-        *      struct perf_event_header        header;
-        *      u64                             time;
-        *      u64                             id;
-        *      u64                             stream_id;
-        * };
-        */
-       PERF_EVENT_THROTTLE             = 5,
-       PERF_EVENT_UNTHROTTLE           = 6,
-
-       /*
-        * struct {
-        *      struct perf_event_header        header;
-        *      u32                             pid, ppid;
-        *      u32                             tid, ptid;
-        *      u64                             time;
-        * };
-        */
-       PERF_EVENT_FORK                 = 7,
-
-       /*
-        * struct {
-        *      struct perf_event_header        header;
-        *      u32                             pid, tid;
-        *
-        *      struct read_format              values;
-        * };
-        */
-       PERF_EVENT_READ                 = 8,
-
-       /*
-        * struct {
-        *      struct perf_event_header        header;
-        *
-        *      { u64                   ip;       } && PERF_SAMPLE_IP
-        *      { u32                   pid, tid; } && PERF_SAMPLE_TID
-        *      { u64                   time;     } && PERF_SAMPLE_TIME
-        *      { u64                   addr;     } && PERF_SAMPLE_ADDR
-        *      { u64                   id;       } && PERF_SAMPLE_ID
-        *      { u64                   stream_id;} && PERF_SAMPLE_STREAM_ID
-        *      { u32                   cpu, res; } && PERF_SAMPLE_CPU
-        *      { u64                   period;   } && PERF_SAMPLE_PERIOD
-        *
-        *      { struct read_format    values;   } && PERF_SAMPLE_READ
-        *
-        *      { u64                   nr,
-        *        u64                   ips[nr];  } && PERF_SAMPLE_CALLCHAIN
-        *
-        *      #
-        *      # The RAW record below is opaque data wrt the ABI
-        *      #
-        *      # That is, the ABI doesn't make any promises wrt to
-        *      # the stability of its content, it may vary depending
-        *      # on event, hardware, kernel version and phase of
-        *      # the moon.
-        *      #
-        *      # In other words, PERF_SAMPLE_RAW contents are not an ABI.
-        *      #
-        *
-        *      { u32                   size;
-        *        char                  data[size];}&& PERF_SAMPLE_RAW
-        * };
-        */
-       PERF_EVENT_SAMPLE               = 9,
-
-       PERF_EVENT_MAX,                 /* non-ABI */
-};
-
-enum perf_callchain_context {
-       PERF_CONTEXT_HV                 = (__u64)-32,
-       PERF_CONTEXT_KERNEL             = (__u64)-128,
-       PERF_CONTEXT_USER               = (__u64)-512,
-
-       PERF_CONTEXT_GUEST              = (__u64)-2048,
-       PERF_CONTEXT_GUEST_KERNEL       = (__u64)-2176,
-       PERF_CONTEXT_GUEST_USER         = (__u64)-2560,
-
-       PERF_CONTEXT_MAX                = (__u64)-4095,
-};
-
-#define PERF_FLAG_FD_NO_GROUP          (1U << 0)
-#define PERF_FLAG_FD_OUTPUT            (1U << 1)
-
-/*
- * In case some app still references the old symbols:
- */
-
-#define __NR_perf_counter_open         __NR_perf_event_open
-
-#define PR_TASK_PERF_COUNTERS_DISABLE  PR_TASK_PERF_EVENTS_DISABLE
-#define PR_TASK_PERF_COUNTERS_ENABLE   PR_TASK_PERF_EVENTS_ENABLE
-
-#endif /* _LINUX_PERF_COUNTER_H */
index e70e621..a6861f1 100644 (file)
@@ -315,8 +315,9 @@ struct dquot_operations {
        int (*claim_space) (struct inode *, qsize_t);
        /* release rsved quota for delayed alloc */
        void (*release_rsv) (struct inode *, qsize_t);
-       /* get reserved quota for delayed alloc */
-       qsize_t (*get_reserved_space) (struct inode *);
+       /* get reserved quota for delayed alloc, value returned is managed by
+        * quota code only */
+       qsize_t *(*get_reserved_space) (struct inode *);
 };
 
 /* Operations handling requests from userspace */
index c4ba9a7..96cc307 100644 (file)
@@ -101,4 +101,9 @@ static inline void exit_rcu(void)
 {
 }
 
+static inline int rcu_preempt_depth(void)
+{
+       return 0;
+}
+
 #endif /* __LINUX_RCUTINY_H */
index c93eee5..8044b1b 100644 (file)
@@ -45,6 +45,12 @@ extern void __rcu_read_unlock(void);
 extern void synchronize_rcu(void);
 extern void exit_rcu(void);
 
+/*
+ * Defined as macro as it is a very low level header
+ * included from areas that don't even know about current
+ */
+#define rcu_preempt_depth() (current->rcu_read_lock_nesting)
+
 #else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
 
 static inline void __rcu_read_lock(void)
@@ -63,6 +69,11 @@ static inline void exit_rcu(void)
 {
 }
 
+static inline int rcu_preempt_depth(void)
+{
+       return 0;
+}
+
 #endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
 
 static inline void __rcu_read_lock_bh(void)
index e898578..f2f842d 100644 (file)
@@ -192,6 +192,12 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
 #define TASK_DEAD              64
 #define TASK_WAKEKILL          128
 #define TASK_WAKING            256
+#define TASK_STATE_MAX         512
+
+#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW"
+
+extern char ___assert_task_state[1 - 2*!!(
+               sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)];
 
 /* Convenience macros for the sake of set_task_state */
 #define TASK_KILLABLE          (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
@@ -1091,7 +1097,8 @@ struct sched_class {
                              enum cpu_idle_type idle);
        void (*pre_schedule) (struct rq *this_rq, struct task_struct *task);
        void (*post_schedule) (struct rq *this_rq);
-       void (*task_wake_up) (struct rq *this_rq, struct task_struct *task);
+       void (*task_waking) (struct rq *this_rq, struct task_struct *task);
+       void (*task_woken) (struct rq *this_rq, struct task_struct *task);
 
        void (*set_cpus_allowed)(struct task_struct *p,
                                 const struct cpumask *newmask);
@@ -1115,7 +1122,7 @@ struct sched_class {
                                         struct task_struct *task);
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
-       void (*moved_group) (struct task_struct *p);
+       void (*moved_group) (struct task_struct *p, int on_rq);
 #endif
 };
 
@@ -2594,8 +2601,6 @@ static inline void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
 }
 #endif /* CONFIG_MM_OWNER */
 
-#define TASK_STATE_TO_CHAR_STR "RSDTtZX"
-
 #endif /* __KERNEL__ */
 
 #endif
index 9d68fed..cfa8308 100644 (file)
@@ -99,8 +99,9 @@ int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr,
 void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
 
 int __must_check sysfs_create_bin_file(struct kobject *kobj,
-                                      struct bin_attribute *attr);
-void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);
+                                      const struct bin_attribute *attr);
+void sysfs_remove_bin_file(struct kobject *kobj,
+                          const struct bin_attribute *attr);
 
 int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target,
                                   const char *name);
@@ -175,13 +176,13 @@ static inline void sysfs_remove_file(struct kobject *kobj,
 }
 
 static inline int sysfs_create_bin_file(struct kobject *kobj,
-                                       struct bin_attribute *attr)
+                                       const struct bin_attribute *attr)
 {
        return 0;
 }
 
 static inline void sysfs_remove_bin_file(struct kobject *kobj,
-                                        struct bin_attribute *attr)
+                                        const struct bin_attribute *attr)
 {
 }
 
index acf6e45..1819396 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kref.h>
 #include <linux/mutex.h>
 #include <linux/sysrq.h>
+#include <linux/kfifo.h>
 
 #define SERIAL_TTY_MAJOR       188     /* Nice legal number now */
 #define SERIAL_TTY_MINORS      254     /* loads of devices :) */
@@ -94,7 +95,7 @@ struct usb_serial_port {
        unsigned char           *bulk_out_buffer;
        int                     bulk_out_size;
        struct urb              *write_urb;
-       struct kfifo            *write_fifo;
+       struct kfifo            write_fifo;
        int                     write_urb_busy;
        __u8                    bulk_out_endpointAddress;
 
index 7394e3b..ff92b46 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mutex.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
+#include <linux/kfifo.h>
 #include <scsi/iscsi_proto.h>
 #include <scsi/iscsi_if.h>
 #include <scsi/scsi_transport_iscsi.h>
@@ -231,7 +232,7 @@ struct iscsi_conn {
 };
 
 struct iscsi_pool {
-       struct kfifo            *queue;         /* FIFO Queue */
+       struct kfifo            queue;          /* FIFO Queue */
        void                    **pool;         /* Pool of elements */
        int                     max;            /* Max number of elements */
 };
index 9e3182e..741ae7e 100644 (file)
@@ -80,7 +80,7 @@ struct iscsi_tcp_task {
        int                     data_offset;
        struct iscsi_r2t_info   *r2t;           /* in progress solict R2T */
        struct iscsi_pool       r2tpool;
-       struct kfifo            *r2tqueue;
+       struct kfifo            r2tqueue;
        void                    *dd_data;
 };
 
index ba615e4..07e3add 100644 (file)
@@ -21,7 +21,7 @@ struct srp_buf {
 struct srp_queue {
        void *pool;
        void *items;
-       struct kfifo *queue;
+       struct kfifo queue;
        spinlock_t lock;
 };
 
index 4c00edc..b37d34b 100644 (file)
@@ -413,7 +413,7 @@ static unsigned my_inptr;   /* index of next byte to be processed in inbuf */
 
 static char * __init unpack_to_rootfs(char *buf, unsigned len)
 {
-       int written;
+       int written, res;
        decompress_fn decompress;
        const char *compress_name;
        static __initdata char msg_buf[64];
@@ -445,10 +445,12 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len)
                }
                this_header = 0;
                decompress = decompress_method(buf, len, &compress_name);
-               if (decompress)
-                       decompress(buf, len, NULL, flush_buffer, NULL,
+               if (decompress) {
+                       res = decompress(buf, len, NULL, flush_buffer, NULL,
                                   &my_inptr, error);
-               else if (compress_name) {
+                       if (res)
+                               error("decompressor failed");
+               } else if (compress_name) {
                        if (!message) {
                                snprintf(msg_buf, sizeof msg_buf,
                                         "compression method %s not configured",
index c3db4a9..dac44a9 100644 (file)
@@ -369,12 +369,6 @@ static void __init smp_init(void)
 {
        unsigned int cpu;
 
-       /*
-        * Set up the current CPU as possible to migrate to.
-        * The other ones will be done by cpu_up/cpu_down()
-        */
-       set_cpu_active(smp_processor_id(), true);
-
        /* FIXME: This should be done in userspace --RR */
        for_each_present_cpu(cpu) {
                if (num_online_cpus() >= setup_max_cpus)
@@ -486,6 +480,7 @@ static void __init boot_cpu_init(void)
        int cpu = smp_processor_id();
        /* Mark the boot cpu "present", "online" etc for SMP and UP case */
        set_cpu_online(cpu, true);
+       set_cpu_active(cpu, true);
        set_cpu_present(cpu, true);
        set_cpu_possible(cpu, true);
 }
index 2451dc6..4b05bd9 100644 (file)
@@ -277,7 +277,7 @@ static void untag_chunk(struct node *p)
                owner->root = NULL;
        }
 
-       for (i = j = 0; i < size; i++, j++) {
+       for (i = j = 0; j <= size; i++, j++) {
                struct audit_tree *s;
                if (&chunk->owners[j] == p) {
                        list_del_init(&p->list);
@@ -290,7 +290,7 @@ static void untag_chunk(struct node *p)
                if (!s) /* result of earlier fallback */
                        continue;
                get_tree(s);
-               list_replace_init(&chunk->owners[i].list, &new->owners[j].list);
+               list_replace_init(&chunk->owners[j].list, &new->owners[i].list);
        }
 
        list_replace_rcu(&chunk->hash, &new->hash);
@@ -373,15 +373,17 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
        for (n = 0; n < old->count; n++) {
                if (old->owners[n].owner == tree) {
                        spin_unlock(&hash_lock);
-                       put_inotify_watch(watch);
+                       put_inotify_watch(&old->watch);
                        return 0;
                }
        }
        spin_unlock(&hash_lock);
 
        chunk = alloc_chunk(old->count + 1);
-       if (!chunk)
+       if (!chunk) {
+               put_inotify_watch(&old->watch);
                return -ENOMEM;
+       }
 
        mutex_lock(&inode->inotify_mutex);
        if (inotify_clone_watch(&old->watch, &chunk->watch) < 0) {
@@ -425,7 +427,8 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
        spin_unlock(&hash_lock);
        inotify_evict_watch(&old->watch);
        mutex_unlock(&inode->inotify_mutex);
-       put_inotify_watch(&old->watch);
+       put_inotify_watch(&old->watch); /* pair to inotify_find_watch */
+       put_inotify_watch(&old->watch); /* and kill it */
        return 0;
 }
 
index 267e484..fc0f928 100644 (file)
@@ -250,7 +250,6 @@ struct audit_context {
 #endif
 };
 
-#define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE])
 static inline int open_arg(int flags, int mask)
 {
        int n = ACC_MODE(flags);
index 291ac58..1c8ddd6 100644 (file)
@@ -209,6 +209,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
                return -ENOMEM;
 
        cpu_hotplug_begin();
+       set_cpu_active(cpu, false);
        err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod,
                                        hcpu, -1, &nr_calls);
        if (err == NOTIFY_BAD) {
@@ -280,18 +281,6 @@ int __ref cpu_down(unsigned int cpu)
                goto out;
        }
 
-       set_cpu_active(cpu, false);
-
-       /*
-        * Make sure the all cpus did the reschedule and are not
-        * using stale version of the cpu_active_mask.
-        * This is not strictly necessary becuase stop_machine()
-        * that we run down the line already provides the required
-        * synchronization. But it's really a side effect and we do not
-        * want to depend on the innards of the stop_machine here.
-        */
-       synchronize_sched();
-
        err = _cpu_down(cpu, 0);
 
 out:
@@ -382,19 +371,12 @@ int disable_nonboot_cpus(void)
                return error;
        cpu_maps_update_begin();
        first_cpu = cpumask_first(cpu_online_mask);
-       /* We take down all of the non-boot CPUs in one shot to avoid races
+       /*
+        * We take down all of the non-boot CPUs in one shot to avoid races
         * with the userspace trying to use the CPU hotplug at the same time
         */
        cpumask_clear(frozen_cpus);
 
-       for_each_online_cpu(cpu) {
-               if (cpu == first_cpu)
-                       continue;
-               set_cpu_active(cpu, false);
-       }
-
-       synchronize_sched();
-
        printk("Disabling non-boot CPUs ...\n");
        for_each_online_cpu(cpu) {
                if (cpu == first_cpu)
index 3765ff3..e92d519 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * A simple kernel FIFO implementation.
+ * A generic kernel FIFO implementation.
  *
+ * Copyright (C) 2009 Stefani Seibold <stefani@seibold.net>
  * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
  *
  * This program is free software; you can redistribute it and/or modify
 #include <linux/err.h>
 #include <linux/kfifo.h>
 #include <linux/log2.h>
+#include <linux/uaccess.h>
+
+static void _kfifo_init(struct kfifo *fifo, unsigned char *buffer,
+               unsigned int size)
+{
+       fifo->buffer = buffer;
+       fifo->size = size;
+
+       kfifo_reset(fifo);
+}
 
 /**
- * kfifo_init - allocates a new FIFO using a preallocated buffer
+ * kfifo_init - initialize a FIFO using a preallocated buffer
+ * @fifo: the fifo to assign the buffer
  * @buffer: the preallocated buffer to be used.
  * @size: the size of the internal buffer, this have to be a power of 2.
- * @gfp_mask: get_free_pages mask, passed to kmalloc()
- * @lock: the lock to be used to protect the fifo buffer
  *
- * Do NOT pass the kfifo to kfifo_free() after use! Simply free the
- * &struct kfifo with kfree().
  */
-struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
-                        gfp_t gfp_mask, spinlock_t *lock)
+void kfifo_init(struct kfifo *fifo, unsigned char *buffer, unsigned int size)
 {
-       struct kfifo *fifo;
-
        /* size must be a power of 2 */
        BUG_ON(!is_power_of_2(size));
 
-       fifo = kmalloc(sizeof(struct kfifo), gfp_mask);
-       if (!fifo)
-               return ERR_PTR(-ENOMEM);
-
-       fifo->buffer = buffer;
-       fifo->size = size;
-       fifo->in = fifo->out = 0;
-       fifo->lock = lock;
-
-       return fifo;
+       _kfifo_init(fifo, buffer, size);
 }
 EXPORT_SYMBOL(kfifo_init);
 
 /**
- * kfifo_alloc - allocates a new FIFO and its internal buffer
- * @size: the size of the internal buffer to be allocated.
+ * kfifo_alloc - allocates a new FIFO internal buffer
+ * @fifo: the fifo to assign then new buffer
+ * @size: the size of the buffer to be allocated, this have to be a power of 2.
  * @gfp_mask: get_free_pages mask, passed to kmalloc()
- * @lock: the lock to be used to protect the fifo buffer
+ *
+ * This function dynamically allocates a new fifo internal buffer
  *
  * The size will be rounded-up to a power of 2.
+ * The buffer will be release with kfifo_free().
+ * Return 0 if no error, otherwise the an error code
  */
-struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock)
+int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask)
 {
        unsigned char *buffer;
-       struct kfifo *ret;
 
        /*
         * round up to the next power of 2, since our 'let the indices
@@ -80,48 +79,91 @@ struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock)
        }
 
        buffer = kmalloc(size, gfp_mask);
-       if (!buffer)
-               return ERR_PTR(-ENOMEM);
-
-       ret = kfifo_init(buffer, size, gfp_mask, lock);
+       if (!buffer) {
+               _kfifo_init(fifo, 0, 0);
+               return -ENOMEM;
+       }
 
-       if (IS_ERR(ret))
-               kfree(buffer);
+       _kfifo_init(fifo, buffer, size);
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(kfifo_alloc);
 
 /**
- * kfifo_free - frees the FIFO
+ * kfifo_free - frees the FIFO internal buffer
  * @fifo: the fifo to be freed.
  */
 void kfifo_free(struct kfifo *fifo)
 {
        kfree(fifo->buffer);
-       kfree(fifo);
 }
 EXPORT_SYMBOL(kfifo_free);
 
 /**
- * __kfifo_put - puts some data into the FIFO, no locking version
+ * kfifo_skip - skip output data
  * @fifo: the fifo to be used.
- * @buffer: the data to be added.
- * @len: the length of the data to be added.
- *
- * This function copies at most @len bytes from the @buffer into
- * the FIFO depending on the free space, and returns the number of
- * bytes copied.
- *
- * Note that with only one concurrent reader and one concurrent
- * writer, you don't need extra locking to use these functions.
+ * @len: number of bytes to skip
  */
-unsigned int __kfifo_put(struct kfifo *fifo,
-                       const unsigned char *buffer, unsigned int len)
+void kfifo_skip(struct kfifo *fifo, unsigned int len)
+{
+       if (len < kfifo_len(fifo)) {
+               __kfifo_add_out(fifo, len);
+               return;
+       }
+       kfifo_reset_out(fifo);
+}
+EXPORT_SYMBOL(kfifo_skip);
+
+static inline void __kfifo_in_data(struct kfifo *fifo,
+               const void *from, unsigned int len, unsigned int off)
 {
        unsigned int l;
 
-       len = min(len, fifo->size - fifo->in + fifo->out);
+       /*
+        * Ensure that we sample the fifo->out index -before- we
+        * start putting bytes into the kfifo.
+        */
+
+       smp_mb();
+
+       off = __kfifo_off(fifo, fifo->in + off);
+
+       /* first put the data starting from fifo->in to buffer end */
+       l = min(len, fifo->size - off);
+       memcpy(fifo->buffer + off, from, l);
+
+       /* then put the rest (if any) at the beginning of the buffer */
+       memcpy(fifo->buffer, from + l, len - l);
+}
+
+static inline void __kfifo_out_data(struct kfifo *fifo,
+               void *to, unsigned int len, unsigned int off)
+{
+       unsigned int l;
+
+       /*
+        * Ensure that we sample the fifo->in index -before- we
+        * start removing bytes from the kfifo.
+        */
+
+       smp_rmb();
+
+       off = __kfifo_off(fifo, fifo->out + off);
+
+       /* first get the data from fifo->out until the end of the buffer */
+       l = min(len, fifo->size - off);
+       memcpy(to, fifo->buffer + off, l);
+
+       /* then get the rest (if any) from the beginning of the buffer */
+       memcpy(to + l, fifo->buffer, len - l);
+}
+
+static inline unsigned int __kfifo_from_user_data(struct kfifo *fifo,
+        const void __user *from, unsigned int len, unsigned int off)
+{
+       unsigned int l;
+       int ret;
 
        /*
         * Ensure that we sample the fifo->out index -before- we
@@ -130,68 +172,229 @@ unsigned int __kfifo_put(struct kfifo *fifo,
 
        smp_mb();
 
+       off = __kfifo_off(fifo, fifo->in + off);
+
        /* first put the data starting from fifo->in to buffer end */
-       l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
-       memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
+       l = min(len, fifo->size - off);
+       ret = copy_from_user(fifo->buffer + off, from, l);
+
+       if (unlikely(ret))
+               return ret + len - l;
 
        /* then put the rest (if any) at the beginning of the buffer */
-       memcpy(fifo->buffer, buffer + l, len - l);
+       return copy_from_user(fifo->buffer, from + l, len - l);
+}
+
+static inline unsigned int __kfifo_to_user_data(struct kfifo *fifo,
+               void __user *to, unsigned int len, unsigned int off)
+{
+       unsigned int l;
+       int ret;
 
        /*
-        * Ensure that we add the bytes to the kfifo -before-
-        * we update the fifo->in index.
+        * Ensure that we sample the fifo->in index -before- we
+        * start removing bytes from the kfifo.
         */
 
-       smp_wmb();
+       smp_rmb();
+
+       off = __kfifo_off(fifo, fifo->out + off);
+
+       /* first get the data from fifo->out until the end of the buffer */
+       l = min(len, fifo->size - off);
+       ret = copy_to_user(to, fifo->buffer + off, l);
+
+       if (unlikely(ret))
+               return ret + len - l;
+
+       /* then get the rest (if any) from the beginning of the buffer */
+       return copy_to_user(to + l, fifo->buffer, len - l);
+}
+
+unsigned int __kfifo_in_n(struct kfifo *fifo,
+       const void *from, unsigned int len, unsigned int recsize)
+{
+       if (kfifo_avail(fifo) < len + recsize)
+               return len + 1;
+
+       __kfifo_in_data(fifo, from, len, recsize);
+       return 0;
+}
+EXPORT_SYMBOL(__kfifo_in_n);
 
-       fifo->in += len;
+/**
+ * kfifo_in - puts some data into the FIFO
+ * @fifo: the fifo to be used.
+ * @from: the data to be added.
+ * @len: the length of the data to be added.
+ *
+ * This function copies at most @len bytes from the @from buffer into
+ * the FIFO depending on the free space, and returns the number of
+ * bytes copied.
+ *
+ * Note that with only one concurrent reader and one concurrent
+ * writer, you don't need extra locking to use these functions.
+ */
+unsigned int kfifo_in(struct kfifo *fifo, const unsigned char *from,
+                               unsigned int len)
+{
+       len = min(kfifo_avail(fifo), len);
 
+       __kfifo_in_data(fifo, from, len, 0);
+       __kfifo_add_in(fifo, len);
        return len;
 }
-EXPORT_SYMBOL(__kfifo_put);
+EXPORT_SYMBOL(kfifo_in);
+
+unsigned int __kfifo_in_generic(struct kfifo *fifo,
+       const void *from, unsigned int len, unsigned int recsize)
+{
+       return __kfifo_in_rec(fifo, from, len, recsize);
+}
+EXPORT_SYMBOL(__kfifo_in_generic);
+
+unsigned int __kfifo_out_n(struct kfifo *fifo,
+       void *to, unsigned int len, unsigned int recsize)
+{
+       if (kfifo_len(fifo) < len + recsize)
+               return len;
+
+       __kfifo_out_data(fifo, to, len, recsize);
+       __kfifo_add_out(fifo, len + recsize);
+       return 0;
+}
+EXPORT_SYMBOL(__kfifo_out_n);
 
 /**
- * __kfifo_get - gets some data from the FIFO, no locking version
+ * kfifo_out - gets some data from the FIFO
  * @fifo: the fifo to be used.
- * @buffer: where the data must be copied.
+ * @to: where the data must be copied.
  * @len: the size of the destination buffer.
  *
  * This function copies at most @len bytes from the FIFO into the
- * @buffer and returns the number of copied bytes.
+ * @to buffer and returns the number of copied bytes.
  *
  * Note that with only one concurrent reader and one concurrent
  * writer, you don't need extra locking to use these functions.
  */
-unsigned int __kfifo_get(struct kfifo *fifo,
-                        unsigned char *buffer, unsigned int len)
+unsigned int kfifo_out(struct kfifo *fifo, unsigned char *to, unsigned int len)
 {
-       unsigned int l;
+       len = min(kfifo_len(fifo), len);
 
-       len = min(len, fifo->in - fifo->out);
+       __kfifo_out_data(fifo, to, len, 0);
+       __kfifo_add_out(fifo, len);
 
-       /*
-        * Ensure that we sample the fifo->in index -before- we
-        * start removing bytes from the kfifo.
-        */
+       return len;
+}
+EXPORT_SYMBOL(kfifo_out);
 
-       smp_rmb();
+unsigned int __kfifo_out_generic(struct kfifo *fifo,
+       void *to, unsigned int len, unsigned int recsize,
+       unsigned int *total)
+{
+       return __kfifo_out_rec(fifo, to, len, recsize, total);
+}
+EXPORT_SYMBOL(__kfifo_out_generic);
 
-       /* first get the data from fifo->out until the end of the buffer */
-       l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
-       memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
+unsigned int __kfifo_from_user_n(struct kfifo *fifo,
+       const void __user *from, unsigned int len, unsigned int recsize)
+{
+       if (kfifo_avail(fifo) < len + recsize)
+               return len + 1;
 
-       /* then get the rest (if any) from the beginning of the buffer */
-       memcpy(buffer + l, fifo->buffer, len - l);
+       return __kfifo_from_user_data(fifo, from, len, recsize);
+}
+EXPORT_SYMBOL(__kfifo_from_user_n);
 
-       /*
-        * Ensure that we remove the bytes from the kfifo -before-
-        * we update the fifo->out index.
-        */
+/**
+ * kfifo_from_user - puts some data from user space into the FIFO
+ * @fifo: the fifo to be used.
+ * @from: pointer to the data to be added.
+ * @len: the length of the data to be added.
+ *
+ * This function copies at most @len bytes from the @from into the
+ * FIFO depending and returns the number of copied bytes.
+ *
+ * Note that with only one concurrent reader and one concurrent
+ * writer, you don't need extra locking to use these functions.
+ */
+unsigned int kfifo_from_user(struct kfifo *fifo,
+       const void __user *from, unsigned int len)
+{
+       len = min(kfifo_avail(fifo), len);
+       len -= __kfifo_from_user_data(fifo, from, len, 0);
+       __kfifo_add_in(fifo, len);
+       return len;
+}
+EXPORT_SYMBOL(kfifo_from_user);
 
-       smp_mb();
+unsigned int __kfifo_from_user_generic(struct kfifo *fifo,
+       const void __user *from, unsigned int len, unsigned int recsize)
+{
+       return __kfifo_from_user_rec(fifo, from, len, recsize);
+}
+EXPORT_SYMBOL(__kfifo_from_user_generic);
 
-       fifo->out += len;
+unsigned int __kfifo_to_user_n(struct kfifo *fifo,
+       void __user *to, unsigned int len, unsigned int reclen,
+       unsigned int recsize)
+{
+       unsigned int ret;
+
+       if (kfifo_len(fifo) < reclen + recsize)
+               return len;
+
+       ret = __kfifo_to_user_data(fifo, to, reclen, recsize);
 
+       if (likely(ret == 0))
+               __kfifo_add_out(fifo, reclen + recsize);
+
+       return ret;
+}
+EXPORT_SYMBOL(__kfifo_to_user_n);
+
+/**
+ * kfifo_to_user - gets data from the FIFO and write it to user space
+ * @fifo: the fifo to be used.
+ * @to: where the data must be copied.
+ * @len: the size of the destination buffer.
+ *
+ * This function copies at most @len bytes from the FIFO into the
+ * @to buffer and returns the number of copied bytes.
+ *
+ * Note that with only one concurrent reader and one concurrent
+ * writer, you don't need extra locking to use these functions.
+ */
+unsigned int kfifo_to_user(struct kfifo *fifo,
+       void __user *to, unsigned int len)
+{
+       len = min(kfifo_len(fifo), len);
+       len -= __kfifo_to_user_data(fifo, to, len, 0);
+       __kfifo_add_out(fifo, len);
        return len;
 }
-EXPORT_SYMBOL(__kfifo_get);
+EXPORT_SYMBOL(kfifo_to_user);
+
+unsigned int __kfifo_to_user_generic(struct kfifo *fifo,
+       void __user *to, unsigned int len, unsigned int recsize,
+       unsigned int *total)
+{
+       return __kfifo_to_user_rec(fifo, to, len, recsize, total);
+}
+EXPORT_SYMBOL(__kfifo_to_user_generic);
+
+unsigned int __kfifo_peek_generic(struct kfifo *fifo, unsigned int recsize)
+{
+       if (recsize == 0)
+               return kfifo_avail(fifo);
+
+       return __kfifo_peek_n(fifo, recsize);
+}
+EXPORT_SYMBOL(__kfifo_peek_generic);
+
+void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize)
+{
+       __kfifo_skip_rec(fifo, recsize);
+}
+EXPORT_SYMBOL(__kfifo_skip_generic);
+
index ab7ae57..fbb6222 100644 (file)
@@ -150,6 +150,29 @@ struct task_struct *kthread_create(int (*threadfn)(void *data),
 EXPORT_SYMBOL(kthread_create);
 
 /**
+ * kthread_bind - bind a just-created kthread to a cpu.
+ * @p: thread created by kthread_create().
+ * @cpu: cpu (might not be online, must be possible) for @k to run on.
+ *
+ * Description: This function is equivalent to set_cpus_allowed(),
+ * except that @cpu doesn't need to be online, and the thread must be
+ * stopped (i.e., just returned from kthread_create()).
+ */
+void kthread_bind(struct task_struct *p, unsigned int cpu)
+{
+       /* Must have done schedule() in kthread() before we set_task_cpu */
+       if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE)) {
+               WARN_ON(1);
+               return;
+       }
+
+       p->cpus_allowed = cpumask_of_cpu(cpu);
+       p->rt.nr_cpus_allowed = 1;
+       p->flags |= PF_THREAD_BOUND;
+}
+EXPORT_SYMBOL(kthread_bind);
+
+/**
  * kthread_stop - stop a thread created by kthread_create().
  * @k: thread created by kthread_create().
  *
index 97d1a3d..1f38270 100644 (file)
@@ -1381,6 +1381,9 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx)
                if (event->state != PERF_EVENT_STATE_ACTIVE)
                        continue;
 
+               if (event->cpu != -1 && event->cpu != smp_processor_id())
+                       continue;
+
                hwc = &event->hw;
 
                interrupts = hwc->interrupts;
@@ -3265,6 +3268,9 @@ static void perf_event_task_output(struct perf_event *event,
 
 static int perf_event_task_match(struct perf_event *event)
 {
+       if (event->cpu != -1 && event->cpu != smp_processor_id())
+               return 0;
+
        if (event->attr.comm || event->attr.mmap || event->attr.task)
                return 1;
 
@@ -3290,12 +3296,11 @@ static void perf_event_task_event(struct perf_task_event *task_event)
        rcu_read_lock();
        cpuctx = &get_cpu_var(perf_cpu_context);
        perf_event_task_ctx(&cpuctx->ctx, task_event);
-       put_cpu_var(perf_cpu_context);
-
        if (!ctx)
                ctx = rcu_dereference(task_event->task->perf_event_ctxp);
        if (ctx)
                perf_event_task_ctx(ctx, task_event);
+       put_cpu_var(perf_cpu_context);
        rcu_read_unlock();
 }
 
@@ -3372,6 +3377,9 @@ static void perf_event_comm_output(struct perf_event *event,
 
 static int perf_event_comm_match(struct perf_event *event)
 {
+       if (event->cpu != -1 && event->cpu != smp_processor_id())
+               return 0;
+
        if (event->attr.comm)
                return 1;
 
@@ -3408,15 +3416,10 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
        rcu_read_lock();
        cpuctx = &get_cpu_var(perf_cpu_context);
        perf_event_comm_ctx(&cpuctx->ctx, comm_event);
-       put_cpu_var(perf_cpu_context);
-
-       /*
-        * doesn't really matter which of the child contexts the
-        * events ends up in.
-        */
        ctx = rcu_dereference(current->perf_event_ctxp);
        if (ctx)
                perf_event_comm_ctx(ctx, comm_event);
+       put_cpu_var(perf_cpu_context);
        rcu_read_unlock();
 }
 
@@ -3491,6 +3494,9 @@ static void perf_event_mmap_output(struct perf_event *event,
 static int perf_event_mmap_match(struct perf_event *event,
                                   struct perf_mmap_event *mmap_event)
 {
+       if (event->cpu != -1 && event->cpu != smp_processor_id())
+               return 0;
+
        if (event->attr.mmap)
                return 1;
 
@@ -3564,15 +3570,10 @@ got_name:
        rcu_read_lock();
        cpuctx = &get_cpu_var(perf_cpu_context);
        perf_event_mmap_ctx(&cpuctx->ctx, mmap_event);
-       put_cpu_var(perf_cpu_context);
-
-       /*
-        * doesn't really matter which of the child contexts the
-        * events ends up in.
-        */
        ctx = rcu_dereference(current->perf_event_ctxp);
        if (ctx)
                perf_event_mmap_ctx(ctx, mmap_event);
+       put_cpu_var(perf_cpu_context);
        rcu_read_unlock();
 
        kfree(buf);
@@ -3863,6 +3864,9 @@ static int perf_swevent_match(struct perf_event *event,
                                struct perf_sample_data *data,
                                struct pt_regs *regs)
 {
+       if (event->cpu != -1 && event->cpu != smp_processor_id())
+               return 0;
+
        if (!perf_swevent_is_counting(event))
                return 0;
 
@@ -4720,7 +4724,7 @@ SYSCALL_DEFINE5(perf_event_open,
        if (IS_ERR(event))
                goto err_put_context;
 
-       err = anon_inode_getfd("[perf_event]", &perf_fops, event, 0);
+       err = anon_inode_getfd("[perf_event]", &perf_fops, event, O_RDWR);
        if (err < 0)
                goto err_free_put_context;
 
index dc15686..af96c1e 100644 (file)
@@ -308,37 +308,37 @@ static int find_resource(struct resource *root, struct resource *new,
                         void *alignf_data)
 {
        struct resource *this = root->child;
-       resource_size_t start, end;
+       struct resource tmp = *new;
 
-       start = root->start;
+       tmp.start = root->start;
        /*
         * Skip past an allocated resource that starts at 0, since the assignment
-        * of this->start - 1 to new->end below would cause an underflow.
+        * of this->start - 1 to tmp->end below would cause an underflow.
         */
        if (this && this->start == 0) {
-               start = this->end + 1;
+               tmp.start = this->end + 1;
                this = this->sibling;
        }
        for(;;) {
                if (this)
-                       end = this->start - 1;
+                       tmp.end = this->start - 1;
                else
-                       end = root->end;
-               if (start < min)
-                       start = min;
-               if (end > max)
-                       end = max;
-               start = ALIGN(start, align);
+                       tmp.end = root->end;
+               if (tmp.start < min)
+                       tmp.start = min;
+               if (tmp.end > max)
+                       tmp.end = max;
+               tmp.start = ALIGN(tmp.start, align);
                if (alignf)
-                       alignf(alignf_data, new, size, align);
-               if (start < end && end - start >= size - 1) {
-                       new->start = start;
-                       new->end = start + size - 1;
+                       alignf(alignf_data, &tmp, size, align);
+               if (tmp.start < tmp.end && tmp.end - tmp.start >= size - 1) {
+                       new->start = tmp.start;
+                       new->end = tmp.start + size - 1;
                        return 0;
                }
                if (!this)
                        break;
-               start = this->end + 1;
+               tmp.start = this->end + 1;
                this = this->sibling;
        }
        return -EBUSY;
index 18cceee..c535cc4 100644 (file)
@@ -2002,39 +2002,6 @@ static inline void check_class_changed(struct rq *rq, struct task_struct *p,
                p->sched_class->prio_changed(rq, p, oldprio, running);
 }
 
-/**
- * kthread_bind - bind a just-created kthread to a cpu.
- * @p: thread created by kthread_create().
- * @cpu: cpu (might not be online, must be possible) for @k to run on.
- *
- * Description: This function is equivalent to set_cpus_allowed(),
- * except that @cpu doesn't need to be online, and the thread must be
- * stopped (i.e., just returned from kthread_create()).
- *
- * Function lives here instead of kthread.c because it messes with
- * scheduler internals which require locking.
- */
-void kthread_bind(struct task_struct *p, unsigned int cpu)
-{
-       struct rq *rq = cpu_rq(cpu);
-       unsigned long flags;
-
-       /* Must have done schedule() in kthread() before we set_task_cpu */
-       if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE)) {
-               WARN_ON(1);
-               return;
-       }
-
-       raw_spin_lock_irqsave(&rq->lock, flags);
-       update_rq_clock(rq);
-       set_task_cpu(p, cpu);
-       p->cpus_allowed = cpumask_of_cpu(cpu);
-       p->rt.nr_cpus_allowed = 1;
-       p->flags |= PF_THREAD_BOUND;
-       raw_spin_unlock_irqrestore(&rq->lock, flags);
-}
-EXPORT_SYMBOL(kthread_bind);
-
 #ifdef CONFIG_SMP
 /*
  * Is this task likely cache-hot:
@@ -2044,6 +2011,9 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
 {
        s64 delta;
 
+       if (p->sched_class != &fair_sched_class)
+               return 0;
+
        /*
         * Buddy candidates are cache hot:
         */
@@ -2052,9 +2022,6 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
                         &p->se == cfs_rq_of(&p->se)->last))
                return 1;
 
-       if (p->sched_class != &fair_sched_class)
-               return 0;
-
        if (sysctl_sched_migration_cost == -1)
                return 1;
        if (sysctl_sched_migration_cost == 0)
@@ -2065,22 +2032,23 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
        return delta < (s64)sysctl_sched_migration_cost;
 }
 
-
 void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 {
-       int old_cpu = task_cpu(p);
-       struct cfs_rq *old_cfsrq = task_cfs_rq(p),
-                     *new_cfsrq = cpu_cfs_rq(old_cfsrq, new_cpu);
+#ifdef CONFIG_SCHED_DEBUG
+       /*
+        * We should never call set_task_cpu() on a blocked task,
+        * ttwu() will sort out the placement.
+        */
+       WARN_ON_ONCE(p->state != TASK_RUNNING && p->state != TASK_WAKING &&
+                       !(task_thread_info(p)->preempt_count & PREEMPT_ACTIVE));
+#endif
 
        trace_sched_migrate_task(p, new_cpu);
 
-       if (old_cpu != new_cpu) {
+       if (task_cpu(p) != new_cpu) {
                p->se.nr_migrations++;
-               perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS,
-                                    1, 1, NULL, 0);
+               perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, 1, NULL, 0);
        }
-       p->se.vruntime -= old_cfsrq->min_vruntime -
-                                        new_cfsrq->min_vruntime;
 
        __set_task_cpu(p, new_cpu);
 }
@@ -2105,13 +2073,10 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
 
        /*
         * If the task is not on a runqueue (and not running), then
-        * it is sufficient to simply update the task's cpu field.
+        * the next wake-up will properly place the task.
         */
-       if (!p->se.on_rq && !task_running(rq, p)) {
-               update_rq_clock(rq);
-               set_task_cpu(p, dest_cpu);
+       if (!p->se.on_rq && !task_running(rq, p))
                return 0;
-       }
 
        init_completion(&req->done);
        req->task = p;
@@ -2317,10 +2282,73 @@ void task_oncpu_function_call(struct task_struct *p,
 }
 
 #ifdef CONFIG_SMP
+static int select_fallback_rq(int cpu, struct task_struct *p)
+{
+       int dest_cpu;
+       const struct cpumask *nodemask = cpumask_of_node(cpu_to_node(cpu));
+
+       /* Look for allowed, online CPU in same node. */
+       for_each_cpu_and(dest_cpu, nodemask, cpu_active_mask)
+               if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed))
+                       return dest_cpu;
+
+       /* Any allowed, online CPU? */
+       dest_cpu = cpumask_any_and(&p->cpus_allowed, cpu_active_mask);
+       if (dest_cpu < nr_cpu_ids)
+               return dest_cpu;
+
+       /* No more Mr. Nice Guy. */
+       if (dest_cpu >= nr_cpu_ids) {
+               rcu_read_lock();
+               cpuset_cpus_allowed_locked(p, &p->cpus_allowed);
+               rcu_read_unlock();
+               dest_cpu = cpumask_any_and(cpu_active_mask, &p->cpus_allowed);
+
+               /*
+                * Don't tell them about moving exiting tasks or
+                * kernel threads (both mm NULL), since they never
+                * leave kernel.
+                */
+               if (p->mm && printk_ratelimit()) {
+                       printk(KERN_INFO "process %d (%s) no "
+                              "longer affine to cpu%d\n",
+                              task_pid_nr(p), p->comm, cpu);
+               }
+       }
+
+       return dest_cpu;
+}
+
+/*
+ * Called from:
+ *
+ *  - fork, @p is stable because it isn't on the tasklist yet
+ *
+ *  - exec, @p is unstable, retry loop
+ *
+ *  - wake-up, we serialize ->cpus_allowed against TASK_WAKING so
+ *             we should be good.
+ */
 static inline
 int select_task_rq(struct task_struct *p, int sd_flags, int wake_flags)
 {
-       return p->sched_class->select_task_rq(p, sd_flags, wake_flags);
+       int cpu = p->sched_class->select_task_rq(p, sd_flags, wake_flags);
+
+       /*
+        * In order not to call set_task_cpu() on a blocking task we need
+        * to rely on ttwu() to place the task on a valid ->cpus_allowed
+        * cpu.
+        *
+        * Since this is common to all placement strategies, this lives here.
+        *
+        * [ this allows ->select_task() to simply return task_cpu(p) and
+        *   not worry about this generic constraint ]
+        */
+       if (unlikely(!cpumask_test_cpu(cpu, &p->cpus_allowed) ||
+                    !cpu_online(cpu)))
+               cpu = select_fallback_rq(task_cpu(p), p);
+
+       return cpu;
 }
 #endif
 
@@ -2375,6 +2403,10 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state,
        if (task_contributes_to_load(p))
                rq->nr_uninterruptible--;
        p->state = TASK_WAKING;
+
+       if (p->sched_class->task_waking)
+               p->sched_class->task_waking(rq, p);
+
        __task_rq_unlock(rq);
 
        cpu = select_task_rq(p, SD_BALANCE_WAKE, wake_flags);
@@ -2438,8 +2470,8 @@ out_running:
 
        p->state = TASK_RUNNING;
 #ifdef CONFIG_SMP
-       if (p->sched_class->task_wake_up)
-               p->sched_class->task_wake_up(rq, p);
+       if (p->sched_class->task_woken)
+               p->sched_class->task_woken(rq, p);
 
        if (unlikely(rq->idle_stamp)) {
                u64 delta = rq->clock - rq->idle_stamp;
@@ -2538,14 +2570,6 @@ static void __sched_fork(struct task_struct *p)
 #ifdef CONFIG_PREEMPT_NOTIFIERS
        INIT_HLIST_HEAD(&p->preempt_notifiers);
 #endif
-
-       /*
-        * We mark the process as running here, but have not actually
-        * inserted it onto the runqueue yet. This guarantees that
-        * nobody will actually run it, and a signal or other external
-        * event cannot wake it up and insert it on the runqueue either.
-        */
-       p->state = TASK_RUNNING;
 }
 
 /*
@@ -2556,6 +2580,12 @@ void sched_fork(struct task_struct *p, int clone_flags)
        int cpu = get_cpu();
 
        __sched_fork(p);
+       /*
+        * We mark the process as waking here. This guarantees that
+        * nobody will actually run it, and a signal or other external
+        * event cannot wake it up and insert it on the runqueue either.
+        */
+       p->state = TASK_WAKING;
 
        /*
         * Revert to default priority/policy on fork if requested.
@@ -2624,14 +2654,15 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
        struct rq *rq;
 
        rq = task_rq_lock(p, &flags);
-       BUG_ON(p->state != TASK_RUNNING);
+       BUG_ON(p->state != TASK_WAKING);
+       p->state = TASK_RUNNING;
        update_rq_clock(rq);
        activate_task(rq, p, 0);
        trace_sched_wakeup_new(rq, p, 1);
        check_preempt_curr(rq, p, WF_FORK);
 #ifdef CONFIG_SMP
-       if (p->sched_class->task_wake_up)
-               p->sched_class->task_wake_up(rq, p);
+       if (p->sched_class->task_woken)
+               p->sched_class->task_woken(rq, p);
 #endif
        task_rq_unlock(rq, &flags);
 }
@@ -3101,21 +3132,36 @@ static void double_rq_unlock(struct rq *rq1, struct rq *rq2)
 }
 
 /*
- * If dest_cpu is allowed for this process, migrate the task to it.
- * This is accomplished by forcing the cpu_allowed mask to only
- * allow dest_cpu, which will force the cpu onto dest_cpu. Then
- * the cpu_allowed mask is restored.
+ * sched_exec - execve() is a valuable balancing opportunity, because at
+ * this point the task has the smallest effective memory and cache footprint.
  */
-static void sched_migrate_task(struct task_struct *p, int dest_cpu)
+void sched_exec(void)
 {
+       struct task_struct *p = current;
        struct migration_req req;
+       int dest_cpu, this_cpu;
        unsigned long flags;
        struct rq *rq;
 
+again:
+       this_cpu = get_cpu();
+       dest_cpu = select_task_rq(p, SD_BALANCE_EXEC, 0);
+       if (dest_cpu == this_cpu) {
+               put_cpu();
+               return;
+       }
+
        rq = task_rq_lock(p, &flags);
+       put_cpu();
+
+       /*
+        * select_task_rq() can race against ->cpus_allowed
+        */
        if (!cpumask_test_cpu(dest_cpu, &p->cpus_allowed)
-           || unlikely(!cpu_active(dest_cpu)))
-               goto out;
+           || unlikely(!cpu_active(dest_cpu))) {
+               task_rq_unlock(rq, &flags);
+               goto again;
+       }
 
        /* force the process onto the specified CPU */
        if (migrate_task(p, dest_cpu, &req)) {
@@ -3130,24 +3176,10 @@ static void sched_migrate_task(struct task_struct *p, int dest_cpu)
 
                return;
        }
-out:
        task_rq_unlock(rq, &flags);
 }
 
 /*
- * sched_exec - execve() is a valuable balancing opportunity, because at
- * this point the task has the smallest effective memory and cache footprint.
- */
-void sched_exec(void)
-{
-       int new_cpu, this_cpu = get_cpu();
-       new_cpu = select_task_rq(current, SD_BALANCE_EXEC, 0);
-       put_cpu();
-       if (new_cpu != this_cpu)
-               sched_migrate_task(current, new_cpu);
-}
-
-/*
  * pull_task - move a task from a remote runqueue to the local runqueue.
  * Both runqueues must be locked.
  */
@@ -5911,14 +5943,15 @@ EXPORT_SYMBOL(wait_for_completion_killable);
  */
 bool try_wait_for_completion(struct completion *x)
 {
+       unsigned long flags;
        int ret = 1;
 
-       spin_lock_irq(&x->wait.lock);
+       spin_lock_irqsave(&x->wait.lock, flags);
        if (!x->done)
                ret = 0;
        else
                x->done--;
-       spin_unlock_irq(&x->wait.lock);
+       spin_unlock_irqrestore(&x->wait.lock, flags);
        return ret;
 }
 EXPORT_SYMBOL(try_wait_for_completion);
@@ -5933,12 +5966,13 @@ EXPORT_SYMBOL(try_wait_for_completion);
  */
 bool completion_done(struct completion *x)
 {
+       unsigned long flags;
        int ret = 1;
 
-       spin_lock_irq(&x->wait.lock);
+       spin_lock_irqsave(&x->wait.lock, flags);
        if (!x->done)
                ret = 0;
-       spin_unlock_irq(&x->wait.lock);
+       spin_unlock_irqrestore(&x->wait.lock, flags);
        return ret;
 }
 EXPORT_SYMBOL(completion_done);
@@ -6457,7 +6491,7 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
                return -EINVAL;
 
        retval = -ESRCH;
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        p = find_process_by_pid(pid);
        if (p) {
                retval = security_task_getscheduler(p);
@@ -6465,7 +6499,7 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
                        retval = p->policy
                                | (p->sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0);
        }
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
        return retval;
 }
 
@@ -6483,7 +6517,7 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
        if (!param || pid < 0)
                return -EINVAL;
 
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        p = find_process_by_pid(pid);
        retval = -ESRCH;
        if (!p)
@@ -6494,7 +6528,7 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
                goto out_unlock;
 
        lp.sched_priority = p->rt_priority;
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 
        /*
         * This one might sleep, we cannot do it with a spinlock held ...
@@ -6504,7 +6538,7 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
        return retval;
 
 out_unlock:
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
        return retval;
 }
 
@@ -6515,22 +6549,18 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
        int retval;
 
        get_online_cpus();
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
 
        p = find_process_by_pid(pid);
        if (!p) {
-               read_unlock(&tasklist_lock);
+               rcu_read_unlock();
                put_online_cpus();
                return -ESRCH;
        }
 
-       /*
-        * It is not safe to call set_cpus_allowed with the
-        * tasklist_lock held. We will bump the task_struct's
-        * usage count and then drop tasklist_lock.
-        */
+       /* Prevent p going away */
        get_task_struct(p);
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 
        if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) {
                retval = -ENOMEM;
@@ -6616,7 +6646,7 @@ long sched_getaffinity(pid_t pid, struct cpumask *mask)
        int retval;
 
        get_online_cpus();
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
 
        retval = -ESRCH;
        p = find_process_by_pid(pid);
@@ -6632,7 +6662,7 @@ long sched_getaffinity(pid_t pid, struct cpumask *mask)
        task_rq_unlock(rq, &flags);
 
 out_unlock:
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
        put_online_cpus();
 
        return retval;
@@ -6876,7 +6906,7 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
                return -EINVAL;
 
        retval = -ESRCH;
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        p = find_process_by_pid(pid);
        if (!p)
                goto out_unlock;
@@ -6889,13 +6919,13 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
        time_slice = p->sched_class->get_rr_interval(rq, p);
        task_rq_unlock(rq, &flags);
 
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
        jiffies_to_timespec(time_slice, &t);
        retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
        return retval;
 
 out_unlock:
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
        return retval;
 }
 
@@ -6986,6 +7016,7 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
        raw_spin_lock_irqsave(&rq->lock, flags);
 
        __sched_fork(idle);
+       idle->state = TASK_RUNNING;
        idle->se.exec_start = sched_clock();
 
        cpumask_copy(&idle->cpus_allowed, cpumask_of(cpu));
@@ -7100,7 +7131,23 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
        struct rq *rq;
        int ret = 0;
 
+       /*
+        * Since we rely on wake-ups to migrate sleeping tasks, don't change
+        * the ->cpus_allowed mask from under waking tasks, which would be
+        * possible when we change rq->lock in ttwu(), so synchronize against
+        * TASK_WAKING to avoid that.
+        */
+again:
+       while (p->state == TASK_WAKING)
+               cpu_relax();
+
        rq = task_rq_lock(p, &flags);
+
+       if (p->state == TASK_WAKING) {
+               task_rq_unlock(rq, &flags);
+               goto again;
+       }
+
        if (!cpumask_intersects(new_mask, cpu_active_mask)) {
                ret = -EINVAL;
                goto out;
@@ -7156,7 +7203,7 @@ EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr);
 static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
        struct rq *rq_dest, *rq_src;
-       int ret = 0, on_rq;
+       int ret = 0;
 
        if (unlikely(!cpu_active(dest_cpu)))
                return ret;
@@ -7172,12 +7219,13 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
        if (!cpumask_test_cpu(dest_cpu, &p->cpus_allowed))
                goto fail;
 
-       on_rq = p->se.on_rq;
-       if (on_rq)
+       /*
+        * If we're not on a rq, the next wake-up will ensure we're
+        * placed properly.
+        */
+       if (p->se.on_rq) {
                deactivate_task(rq_src, p, 0);
-
-       set_task_cpu(p, dest_cpu);
-       if (on_rq) {
+               set_task_cpu(p, dest_cpu);
                activate_task(rq_dest, p, 0);
                check_preempt_curr(rq_dest, p, 0);
        }
@@ -7273,37 +7321,10 @@ static int __migrate_task_irq(struct task_struct *p, int src_cpu, int dest_cpu)
 static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
 {
        int dest_cpu;
-       const struct cpumask *nodemask = cpumask_of_node(cpu_to_node(dead_cpu));
 
 again:
-       /* Look for allowed, online CPU in same node. */
-       for_each_cpu_and(dest_cpu, nodemask, cpu_active_mask)
-               if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed))
-                       goto move;
-
-       /* Any allowed, online CPU? */
-       dest_cpu = cpumask_any_and(&p->cpus_allowed, cpu_active_mask);
-       if (dest_cpu < nr_cpu_ids)
-               goto move;
-
-       /* No more Mr. Nice Guy. */
-       if (dest_cpu >= nr_cpu_ids) {
-               cpuset_cpus_allowed_locked(p, &p->cpus_allowed);
-               dest_cpu = cpumask_any_and(cpu_active_mask, &p->cpus_allowed);
-
-               /*
-                * Don't tell them about moving exiting tasks or
-                * kernel threads (both mm NULL), since they never
-                * leave kernel.
-                */
-               if (p->mm && printk_ratelimit()) {
-                       printk(KERN_INFO "process %d (%s) no "
-                              "longer affine to cpu%d\n",
-                              task_pid_nr(p), p->comm, dead_cpu);
-               }
-       }
+       dest_cpu = select_fallback_rq(dead_cpu, p);
 
-move:
        /* It can have affinity changed while we were choosing. */
        if (unlikely(!__migrate_task_irq(p, dead_cpu, dest_cpu)))
                goto again;
@@ -9668,7 +9689,7 @@ void __init sched_init(void)
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
 static inline int preempt_count_equals(int preempt_offset)
 {
-       int nested = preempt_count() & ~PREEMPT_ACTIVE;
+       int nested = (preempt_count() & ~PREEMPT_ACTIVE) + rcu_preempt_depth();
 
        return (nested == PREEMPT_INATOMIC_BASE + preempt_offset);
 }
@@ -10083,7 +10104,7 @@ void sched_move_task(struct task_struct *tsk)
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
        if (tsk->sched_class->moved_group)
-               tsk->sched_class->moved_group(tsk);
+               tsk->sched_class->moved_group(tsk, on_rq);
 #endif
 
        if (unlikely(running))
index 479ce56..5b49613 100644 (file)
@@ -236,6 +236,18 @@ void sched_clock_idle_wakeup_event(u64 delta_ns)
 }
 EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event);
 
+unsigned long long cpu_clock(int cpu)
+{
+       unsigned long long clock;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       clock = sched_clock_cpu(cpu);
+       local_irq_restore(flags);
+
+       return clock;
+}
+
 #else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
 
 void sched_clock_init(void)
@@ -251,17 +263,12 @@ u64 sched_clock_cpu(int cpu)
        return sched_clock();
 }
 
-#endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
 
 unsigned long long cpu_clock(int cpu)
 {
-       unsigned long long clock;
-       unsigned long flags;
+       return sched_clock_cpu(cpu);
+}
 
-       local_irq_save(flags);
-       clock = sched_clock_cpu(cpu);
-       local_irq_restore(flags);
+#endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
 
-       return clock;
-}
 EXPORT_SYMBOL_GPL(cpu_clock);
index 5bedf6e..42ac3c9 100644 (file)
@@ -510,6 +510,7 @@ __update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr,
        curr->sum_exec_runtime += delta_exec;
        schedstat_add(cfs_rq, exec_clock, delta_exec);
        delta_exec_weighted = calc_delta_fair(delta_exec, curr);
+
        curr->vruntime += delta_exec_weighted;
        update_min_vruntime(cfs_rq);
 }
@@ -765,16 +766,26 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
        se->vruntime = vruntime;
 }
 
+#define ENQUEUE_WAKEUP 1
+#define ENQUEUE_MIGRATE 2
+
 static void
-enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup)
+enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 {
        /*
+        * Update the normalized vruntime before updating min_vruntime
+        * through callig update_curr().
+        */
+       if (!(flags & ENQUEUE_WAKEUP) || (flags & ENQUEUE_MIGRATE))
+               se->vruntime += cfs_rq->min_vruntime;
+
+       /*
         * Update run-time statistics of the 'current'.
         */
        update_curr(cfs_rq);
        account_entity_enqueue(cfs_rq, se);
 
-       if (wakeup) {
+       if (flags & ENQUEUE_WAKEUP) {
                place_entity(cfs_rq, se, 0);
                enqueue_sleeper(cfs_rq, se);
        }
@@ -828,6 +839,14 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)
                __dequeue_entity(cfs_rq, se);
        account_entity_dequeue(cfs_rq, se);
        update_min_vruntime(cfs_rq);
+
+       /*
+        * Normalize the entity after updating the min_vruntime because the
+        * update can refer to the ->curr item and we need to reflect this
+        * movement in our normalized position.
+        */
+       if (!sleep)
+               se->vruntime -= cfs_rq->min_vruntime;
 }
 
 /*
@@ -1038,13 +1057,19 @@ static void enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup)
 {
        struct cfs_rq *cfs_rq;
        struct sched_entity *se = &p->se;
+       int flags = 0;
+
+       if (wakeup)
+               flags |= ENQUEUE_WAKEUP;
+       if (p->state == TASK_WAKING)
+               flags |= ENQUEUE_MIGRATE;
 
        for_each_sched_entity(se) {
                if (se->on_rq)
                        break;
                cfs_rq = cfs_rq_of(se);
-               enqueue_entity(cfs_rq, se, wakeup);
-               wakeup = 1;
+               enqueue_entity(cfs_rq, se, flags);
+               flags = ENQUEUE_WAKEUP;
        }
 
        hrtick_update(rq);
@@ -1120,6 +1145,14 @@ static void yield_task_fair(struct rq *rq)
 
 #ifdef CONFIG_SMP
 
+static void task_waking_fair(struct rq *rq, struct task_struct *p)
+{
+       struct sched_entity *se = &p->se;
+       struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+       se->vruntime -= cfs_rq->min_vruntime;
+}
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
 /*
  * effective_load() calculates the load change as seen from the root_task_group
@@ -1429,6 +1462,9 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag
        }
 
        for_each_domain(cpu, tmp) {
+               if (!(tmp->flags & SD_LOAD_BALANCE))
+                       continue;
+
                /*
                 * If power savings logic is enabled for a domain, see if we
                 * are not overloaded, if so, don't balance wider.
@@ -1975,6 +2011,8 @@ static void task_fork_fair(struct task_struct *p)
                resched_task(rq->curr);
        }
 
+       se->vruntime -= cfs_rq->min_vruntime;
+
        raw_spin_unlock_irqrestore(&rq->lock, flags);
 }
 
@@ -2028,12 +2066,13 @@ static void set_curr_task_fair(struct rq *rq)
 }
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
-static void moved_group_fair(struct task_struct *p)
+static void moved_group_fair(struct task_struct *p, int on_rq)
 {
        struct cfs_rq *cfs_rq = task_cfs_rq(p);
 
        update_curr(cfs_rq);
-       place_entity(cfs_rq, &p->se, 1);
+       if (!on_rq)
+               place_entity(cfs_rq, &p->se, 1);
 }
 #endif
 
@@ -2073,6 +2112,8 @@ static const struct sched_class fair_sched_class = {
        .move_one_task          = move_one_task_fair,
        .rq_online              = rq_online_fair,
        .rq_offline             = rq_offline_fair,
+
+       .task_waking            = task_waking_fair,
 #endif
 
        .set_curr_task          = set_curr_task_fair,
index d2ea282..f48328a 100644 (file)
@@ -1472,7 +1472,7 @@ static void post_schedule_rt(struct rq *rq)
  * If we are not running and we are not going to reschedule soon, we should
  * try to push tasks away now
  */
-static void task_wake_up_rt(struct rq *rq, struct task_struct *p)
+static void task_woken_rt(struct rq *rq, struct task_struct *p)
 {
        if (!task_running(rq, p) &&
            !test_tsk_need_resched(rq->curr) &&
@@ -1753,7 +1753,7 @@ static const struct sched_class rt_sched_class = {
        .rq_offline             = rq_offline_rt,
        .pre_schedule           = pre_schedule_rt,
        .post_schedule          = post_schedule_rt,
-       .task_wake_up           = task_wake_up_rt,
+       .task_woken             = task_woken_rt,
        .switched_from          = switched_from_rt,
 #endif
 
index 1814e68..d09692b 100644 (file)
@@ -218,13 +218,13 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi
        struct user_struct *user;
 
        /*
-        * We won't get problems with the target's UID changing under us
-        * because changing it requires RCU be used, and if t != current, the
-        * caller must be holding the RCU readlock (by way of a spinlock) and
-        * we use RCU protection here
+        * Protect access to @t credentials. This can go away when all
+        * callers hold rcu read lock.
         */
+       rcu_read_lock();
        user = get_uid(__task_cred(t)->user);
        atomic_inc(&user->sigpending);
+       rcu_read_unlock();
 
        if (override_rlimit ||
            atomic_read(&user->sigpending) <=
@@ -1179,11 +1179,12 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
        int ret = -EINVAL;
        struct task_struct *p;
        const struct cred *pcred;
+       unsigned long flags;
 
        if (!valid_signal(sig))
                return ret;
 
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        p = pid_task(pid, PIDTYPE_PID);
        if (!p) {
                ret = -ESRCH;
@@ -1199,14 +1200,16 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
        ret = security_task_kill(p, info, sig, secid);
        if (ret)
                goto out_unlock;
-       if (sig && p->sighand) {
-               unsigned long flags;
-               spin_lock_irqsave(&p->sighand->siglock, flags);
-               ret = __send_signal(sig, info, p, 1, 0);
-               spin_unlock_irqrestore(&p->sighand->siglock, flags);
+
+       if (sig) {
+               if (lock_task_sighand(p, &flags)) {
+                       ret = __send_signal(sig, info, p, 1, 0);
+                       unlock_task_sighand(p, &flags);
+               } else
+                       ret = -ESRCH;
        }
 out_unlock:
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
        return ret;
 }
 EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);
index 20ccfb5..26a6b73 100644 (file)
@@ -162,6 +162,7 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
        if (niceval > 19)
                niceval = 19;
 
+       rcu_read_lock();
        read_lock(&tasklist_lock);
        switch (which) {
                case PRIO_PROCESS:
@@ -199,6 +200,7 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
        }
 out_unlock:
        read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 out:
        return error;
 }
index c6324d9..8047980 100644 (file)
@@ -136,6 +136,7 @@ static inline void warp_clock(void)
        write_seqlock_irq(&xtime_lock);
        wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60;
        xtime.tv_sec += sys_tz.tz_minuteswest * 60;
+       update_xtime_cache(0);
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
 }
index 3d5fc0f..6f740d9 100644 (file)
@@ -238,8 +238,9 @@ void clockevents_exchange_device(struct clock_event_device *old,
  */
 void clockevents_notify(unsigned long reason, void *arg)
 {
-       struct list_head *node, *tmp;
+       struct clock_event_device *dev, *tmp;
        unsigned long flags;
+       int cpu;
 
        raw_spin_lock_irqsave(&clockevents_lock, flags);
        clockevents_do_notify(reason, arg);
@@ -250,8 +251,19 @@ void clockevents_notify(unsigned long reason, void *arg)
                 * Unregister the clock event devices which were
                 * released from the users in the notify chain.
                 */
-               list_for_each_safe(node, tmp, &clockevents_released)
-                       list_del(node);
+               list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
+                       list_del(&dev->list);
+               /*
+                * Now check whether the CPU has left unused per cpu devices
+                */
+               cpu = *((int *)arg);
+               list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
+                       if (cpumask_test_cpu(cpu, dev->cpumask) &&
+                           cpumask_weight(dev->cpumask) == 1) {
+                               BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
+                               list_del(&dev->list);
+                       }
+               }
                break;
        default:
                break;
index af4135f..7faaa32 100644 (file)
@@ -165,6 +165,13 @@ struct timespec raw_time;
 /* flag for if timekeeping is suspended */
 int __read_mostly timekeeping_suspended;
 
+static struct timespec xtime_cache __attribute__ ((aligned (16)));
+void update_xtime_cache(u64 nsec)
+{
+       xtime_cache = xtime;
+       timespec_add_ns(&xtime_cache, nsec);
+}
+
 /* must hold xtime_lock */
 void timekeeping_leap_insert(int leapsecond)
 {
@@ -325,6 +332,8 @@ int do_settimeofday(struct timespec *tv)
 
        xtime = *tv;
 
+       update_xtime_cache(0);
+
        timekeeper.ntp_error = 0;
        ntp_clear();
 
@@ -550,6 +559,7 @@ void __init timekeeping_init(void)
        }
        set_normalized_timespec(&wall_to_monotonic,
                                -boot.tv_sec, -boot.tv_nsec);
+       update_xtime_cache(0);
        total_sleep_time.tv_sec = 0;
        total_sleep_time.tv_nsec = 0;
        write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -583,6 +593,7 @@ static int timekeeping_resume(struct sys_device *dev)
                wall_to_monotonic = timespec_sub(wall_to_monotonic, ts);
                total_sleep_time = timespec_add_safe(total_sleep_time, ts);
        }
+       update_xtime_cache(0);
        /* re-base the last cycle value */
        timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock);
        timekeeper.ntp_error = 0;
@@ -722,6 +733,7 @@ static void timekeeping_adjust(s64 offset)
                                timekeeper.ntp_error_shift;
 }
 
+
 /**
  * logarithmic_accumulation - shifted accumulation of cycles
  *
@@ -765,6 +777,7 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
        return offset;
 }
 
+
 /**
  * update_wall_time - Uses the current clocksource to increment the wall time
  *
@@ -774,6 +787,7 @@ void update_wall_time(void)
 {
        struct clocksource *clock;
        cycle_t offset;
+       u64 nsecs;
        int shift = 0, maxshift;
 
        /* Make sure we're fully resumed: */
@@ -839,6 +853,9 @@ void update_wall_time(void)
        timekeeper.ntp_error += timekeeper.xtime_nsec <<
                                timekeeper.ntp_error_shift;
 
+       nsecs = clocksource_cyc2ns(offset, timekeeper.mult, timekeeper.shift);
+       update_xtime_cache(nsecs);
+
        /* check to see if there is a new clocksource to use */
        update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult);
 }
@@ -875,13 +892,13 @@ void monotonic_to_bootbased(struct timespec *ts)
 
 unsigned long get_seconds(void)
 {
-       return xtime.tv_sec;
+       return xtime_cache.tv_sec;
 }
 EXPORT_SYMBOL(get_seconds);
 
 struct timespec __current_kernel_time(void)
 {
-       return xtime;
+       return xtime_cache;
 }
 
 struct timespec current_kernel_time(void)
@@ -891,7 +908,8 @@ struct timespec current_kernel_time(void)
 
        do {
                seq = read_seqbegin(&xtime_lock);
-               now = xtime;
+
+               now = xtime_cache;
        } while (read_seqretry(&xtime_lock, seq));
 
        return now;
@@ -905,7 +923,8 @@ struct timespec get_monotonic_coarse(void)
 
        do {
                seq = read_seqbegin(&xtime_lock);
-               now = xtime;
+
+               now = xtime_cache;
                mono = wall_to_monotonic;
        } while (read_seqretry(&xtime_lock, seq));
 
index 5db5a8d..15533b7 100644 (file)
@@ -656,8 +656,6 @@ __mod_timer(struct timer_list *timer, unsigned long expires,
 
        debug_activate(timer, expires);
 
-       new_base = __get_cpu_var(tvec_bases);
-
        cpu = smp_processor_id();
 
 #if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP)
index 7ecab06..375f81a 100644 (file)
@@ -282,6 +282,18 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
 static int kretprobe_dispatcher(struct kretprobe_instance *ri,
                                struct pt_regs *regs);
 
+/* Check the name is good for event/group */
+static int check_event_name(const char *name)
+{
+       if (!isalpha(*name) && *name != '_')
+               return 0;
+       while (*++name != '\0') {
+               if (!isalpha(*name) && !isdigit(*name) && *name != '_')
+                       return 0;
+       }
+       return 1;
+}
+
 /*
  * Allocate new trace_probe and initialize it (including kprobes).
  */
@@ -293,10 +305,11 @@ static struct trace_probe *alloc_trace_probe(const char *group,
                                             int nargs, int is_return)
 {
        struct trace_probe *tp;
+       int ret = -ENOMEM;
 
        tp = kzalloc(SIZEOF_TRACE_PROBE(nargs), GFP_KERNEL);
        if (!tp)
-               return ERR_PTR(-ENOMEM);
+               return ERR_PTR(ret);
 
        if (symbol) {
                tp->symbol = kstrdup(symbol, GFP_KERNEL);
@@ -312,14 +325,20 @@ static struct trace_probe *alloc_trace_probe(const char *group,
        else
                tp->rp.kp.pre_handler = kprobe_dispatcher;
 
-       if (!event)
+       if (!event || !check_event_name(event)) {
+               ret = -EINVAL;
                goto error;
+       }
+
        tp->call.name = kstrdup(event, GFP_KERNEL);
        if (!tp->call.name)
                goto error;
 
-       if (!group)
+       if (!group || !check_event_name(group)) {
+               ret = -EINVAL;
                goto error;
+       }
+
        tp->call.system = kstrdup(group, GFP_KERNEL);
        if (!tp->call.system)
                goto error;
@@ -330,7 +349,7 @@ error:
        kfree(tp->call.name);
        kfree(tp->symbol);
        kfree(tp);
-       return ERR_PTR(-ENOMEM);
+       return ERR_PTR(ret);
 }
 
 static void free_probe_arg(struct probe_arg *arg)
@@ -695,10 +714,10 @@ static int create_trace_probe(int argc, char **argv)
        if (!event) {
                /* Make a new event name */
                if (symbol)
-                       snprintf(buf, MAX_EVENT_NAME_LEN, "%c@%s%+ld",
+                       snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_%ld",
                                 is_return ? 'r' : 'p', symbol, offset);
                else
-                       snprintf(buf, MAX_EVENT_NAME_LEN, "%c@0x%p",
+                       snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p",
                                 is_return ? 'r' : 'p', addr);
                event = buf;
        }
index f669396..a7974a5 100644 (file)
@@ -93,6 +93,7 @@ static const struct stacktrace_ops backtrace_ops = {
        .warning_symbol         = backtrace_warning_symbol,
        .stack                  = backtrace_stack,
        .address                = backtrace_address,
+       .walk_stack             = print_context_stack,
 };
 
 static int
index 7607420..a4e971d 100644 (file)
@@ -637,6 +637,8 @@ static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, int len,
 
        /* Allocate bunzip_data.  Most fields initialize to zero. */
        bd = *bdp = malloc(i);
+       if (!bd)
+               return RETVAL_OUT_OF_MEMORY;
        memset(bd, 0, sizeof(struct bunzip_data));
        /* Setup input buffer */
        bd->inbuf = inbuf;
@@ -664,6 +666,8 @@ static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, int len,
        bd->dbufSize = 100000*(i-BZh0);
 
        bd->dbuf = large_malloc(bd->dbufSize * sizeof(int));
+       if (!bd->dbuf)
+               return RETVAL_OUT_OF_MEMORY;
        return RETVAL_OK;
 }
 
@@ -686,7 +690,7 @@ STATIC int INIT bunzip2(unsigned char *buf, int len,
 
        if (!outbuf) {
                error("Could not allocate output bufer");
-               return -1;
+               return RETVAL_OUT_OF_MEMORY;
        }
        if (buf)
                inbuf = buf;
@@ -694,6 +698,7 @@ STATIC int INIT bunzip2(unsigned char *buf, int len,
                inbuf = malloc(BZIP2_IOBUF_SIZE);
        if (!inbuf) {
                error("Could not allocate input bufer");
+               i = RETVAL_OUT_OF_MEMORY;
                goto exit_0;
        }
        i = start_bunzip(&bd, inbuf, len, fill);
@@ -720,11 +725,14 @@ STATIC int INIT bunzip2(unsigned char *buf, int len,
        } else if (i == RETVAL_UNEXPECTED_OUTPUT_EOF) {
                error("Compressed file ends unexpectedly");
        }
+       if (!bd)
+               goto exit_1;
        if (bd->dbuf)
                large_free(bd->dbuf);
        if (pos)
                *pos = bd->inbufPos;
        free(bd);
+exit_1:
        if (!buf)
                free(inbuf);
 exit_0:
index afce96a..9f75b4e 100644 (file)
@@ -338,10 +338,10 @@ EXPORT_SYMBOL(strnchr);
 #endif
 
 /**
- * skip_spaces - Removes leading whitespace from @s.
- * @s: The string to be stripped.
+ * skip_spaces - Removes leading whitespace from @str.
+ * @str: The string to be stripped.
  *
- * Returns a pointer to the first non-whitespace character in @s.
+ * Returns a pointer to the first non-whitespace character in @str.
  */
 char *skip_spaces(const char *str)
 {
index 74af449..d79b925 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/page_cgroup.h>
 #include <linux/debugobjects.h>
 #include <linux/kmemleak.h>
+#include <linux/memory.h>
 #include <trace/events/kmem.h>
 
 #include <asm/tlbflush.h>
@@ -3579,7 +3580,7 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid,
  * Return the number of holes in a range on a node. If nid is MAX_NUMNODES,
  * then all holes in the requested range will be accounted for.
  */
-static unsigned long __meminit __absent_pages_in_range(int nid,
+unsigned long __meminit __absent_pages_in_range(int nid,
                                unsigned long range_start_pfn,
                                unsigned long range_end_pfn)
 {
@@ -4108,7 +4109,7 @@ static int __init cmp_node_active_region(const void *a, const void *b)
 }
 
 /* sort the node_map by start_pfn */
-static void __init sort_node_map(void)
+void __init sort_node_map(void)
 {
        sort(early_node_map, (size_t)nr_nodemap_entries,
                        sizeof(struct node_active_region),
@@ -5008,23 +5009,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
 int set_migratetype_isolate(struct page *page)
 {
        struct zone *zone;
-       unsigned long flags;
+       struct page *curr_page;
+       unsigned long flags, pfn, iter;
+       unsigned long immobile = 0;
+       struct memory_isolate_notify arg;
+       int notifier_ret;
        int ret = -EBUSY;
        int zone_idx;
 
        zone = page_zone(page);
        zone_idx = zone_idx(zone);
+
        spin_lock_irqsave(&zone->lock, flags);
+       if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE ||
+           zone_idx == ZONE_MOVABLE) {
+               ret = 0;
+               goto out;
+       }
+
+       pfn = page_to_pfn(page);
+       arg.start_pfn = pfn;
+       arg.nr_pages = pageblock_nr_pages;
+       arg.pages_found = 0;
+
        /*
-        * In future, more migrate types will be able to be isolation target.
+        * It may be possible to isolate a pageblock even if the
+        * migratetype is not MIGRATE_MOVABLE. The memory isolation
+        * notifier chain is used by balloon drivers to return the
+        * number of pages in a range that are held by the balloon
+        * driver to shrink memory. If all the pages are accounted for
+        * by balloons, are free, or on the LRU, isolation can continue.
+        * Later, for example, when memory hotplug notifier runs, these
+        * pages reported as "can be isolated" should be isolated(freed)
+        * by the balloon driver through the memory notifier chain.
         */
-       if (get_pageblock_migratetype(page) != MIGRATE_MOVABLE &&
-           zone_idx != ZONE_MOVABLE)
+       notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg);
+       notifier_ret = notifier_to_errno(notifier_ret);
+       if (notifier_ret || !arg.pages_found)
                goto out;
-       set_pageblock_migratetype(page, MIGRATE_ISOLATE);
-       move_freepages_block(zone, page, MIGRATE_ISOLATE);
-       ret = 0;
+
+       for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) {
+               if (!pfn_valid_within(pfn))
+                       continue;
+
+               curr_page = pfn_to_page(iter);
+               if (!page_count(curr_page) || PageLRU(curr_page))
+                       continue;
+
+               immobile++;
+       }
+
+       if (arg.pages_found == immobile)
+               ret = 0;
+
 out:
+       if (!ret) {
+               set_pageblock_migratetype(page, MIGRATE_ISOLATE);
+               move_freepages_block(zone, page, MIGRATE_ISOLATE);
+       }
+
        spin_unlock_irqrestore(&zone->lock, flags);
        if (!ret)
                drain_all_pages();
index 5697500..18e7f5a 100644 (file)
@@ -770,7 +770,7 @@ static int hidp_setup_hid(struct hidp_session *session,
 
        hid = hid_allocate_device();
        if (IS_ERR(hid))
-               return PTR_ERR(session->hid);
+               return PTR_ERR(hid);
 
        session->hid = hid;
        session->req = req;
index 5129b88..1120cf1 100644 (file)
@@ -1212,6 +1212,7 @@ static void l2cap_monitor_timeout(unsigned long arg)
        bh_lock_sock(sk);
        if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
                l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk);
+               bh_unlock_sock(sk);
                return;
        }
 
@@ -3435,8 +3436,8 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
                            (pi->unacked_frames > 0))
                                __mod_retrans_timer();
 
-                       l2cap_ertm_send(sk);
                        pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+                       l2cap_ertm_send(sk);
                }
                break;
 
@@ -3471,9 +3472,9 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
                pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
 
                if (rx_control & L2CAP_CTRL_POLL) {
-                       l2cap_retransmit_frame(sk, tx_seq);
                        pi->expected_ack_seq = tx_seq;
                        l2cap_drop_acked_frames(sk);
+                       l2cap_retransmit_frame(sk, tx_seq);
                        l2cap_ertm_send(sk);
                        if (pi->conn_state & L2CAP_CONN_WAIT_F) {
                                pi->srej_save_reqseq = tx_seq;
index dc32842..a1362dc 100644 (file)
@@ -43,7 +43,7 @@ static int bufsize = 64 * 1024;
 static const char procname[] = "dccpprobe";
 
 static struct {
-       struct kfifo      *fifo;
+       struct kfifo      fifo;
        spinlock_t        lock;
        wait_queue_head_t wait;
        struct timespec   tstart;
@@ -67,7 +67,7 @@ static void printl(const char *fmt, ...)
        len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
        va_end(args);
 
-       kfifo_put(dccpw.fifo, tbuf, len);
+       kfifo_in_locked(&dccpw.fifo, tbuf, len, &dccpw.lock);
        wake_up(&dccpw.wait);
 }
 
@@ -109,7 +109,7 @@ static struct jprobe dccp_send_probe = {
 
 static int dccpprobe_open(struct inode *inode, struct file *file)
 {
-       kfifo_reset(dccpw.fifo);
+       kfifo_reset(&dccpw.fifo);
        getnstimeofday(&dccpw.tstart);
        return 0;
 }
@@ -131,11 +131,11 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf,
                return -ENOMEM;
 
        error = wait_event_interruptible(dccpw.wait,
-                                        __kfifo_len(dccpw.fifo) != 0);
+                                        kfifo_len(&dccpw.fifo) != 0);
        if (error)
                goto out_free;
 
-       cnt = kfifo_get(dccpw.fifo, tbuf, len);
+       cnt = kfifo_out_locked(&dccpw.fifo, tbuf, len, &dccpw.lock);
        error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0;
 
 out_free:
@@ -156,10 +156,8 @@ static __init int dccpprobe_init(void)
 
        init_waitqueue_head(&dccpw.wait);
        spin_lock_init(&dccpw.lock);
-       dccpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &dccpw.lock);
-       if (IS_ERR(dccpw.fifo))
-               return PTR_ERR(dccpw.fifo);
-
+       if (kfifo_alloc(&dccpw.fifo, bufsize, GFP_KERNEL))
+               return ret;
        if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &dccpprobe_fops))
                goto err0;
 
@@ -172,14 +170,14 @@ static __init int dccpprobe_init(void)
 err1:
        proc_net_remove(&init_net, procname);
 err0:
-       kfifo_free(dccpw.fifo);
+       kfifo_free(&dccpw.fifo);
        return ret;
 }
 module_init(dccpprobe_init);
 
 static __exit void dccpprobe_exit(void)
 {
-       kfifo_free(dccpw.fifo);
+       kfifo_free(&dccpw.fifo);
        proc_net_remove(&init_net, procname);
        unregister_jprobe(&dccp_send_probe);
 
index 3b3a956..2cddea3 100644 (file)
@@ -708,7 +708,8 @@ static void ip6_frags_ns_sysctl_unregister(struct net *net)
 
        table = net->ipv6.sysctl.frags_hdr->ctl_table_arg;
        unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr);
-       kfree(table);
+       if (!net_eq(net, &init_net))
+               kfree(table);
 }
 
 static struct ctl_table_header *ip6_ctl_header;
index db3b273..c2bd74c 100644 (file)
@@ -2630,6 +2630,7 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net)
                table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity;
                table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
                table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
+               table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
        }
 
        return table;
index 8346938..9a6c588 100644 (file)
@@ -12,7 +12,6 @@
 #include "common.h"
 #include "tomoyo.h"
 #include "realpath.h"
-#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 
 /*
  * tomoyo_globally_readable_file_entry is a structure which is used for holding
index 1497dce..c569986 100644 (file)
@@ -172,14 +172,15 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
        return v;
 }
 
-static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun)
+static inline void
+aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask)
 {
        u32 val;
        int timeout = 5000;
 
        do {
                val = readl(aacirun->base + AACI_SR);
-       } while (val & (SR_TXB|SR_RXB) && timeout--);
+       } while (val & mask && timeout--);
 }
 
 
@@ -208,8 +209,10 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
                        writel(0, aacirun->base + AACI_IE);
                        return;
                }
-               ptr = aacirun->ptr;
 
+               spin_lock(&aacirun->lock);
+
+               ptr = aacirun->ptr;
                do {
                        unsigned int len = aacirun->fifosz;
                        u32 val;
@@ -217,9 +220,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
                        if (aacirun->bytes <= 0) {
                                aacirun->bytes += aacirun->period;
                                aacirun->ptr = ptr;
-                               spin_unlock(&aaci->lock);
+                               spin_unlock(&aacirun->lock);
                                snd_pcm_period_elapsed(aacirun->substream);
-                               spin_lock(&aaci->lock);
+                               spin_lock(&aacirun->lock);
                        }
                        if (!(aacirun->cr & CR_EN))
                                break;
@@ -245,7 +248,10 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
                                        ptr = aacirun->start;
                        }
                } while(1);
+
                aacirun->ptr = ptr;
+
+               spin_unlock(&aacirun->lock);
        }
 
        if (mask & ISR_URINTR) {
@@ -263,6 +269,8 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
                        return;
                }
 
+               spin_lock(&aacirun->lock);
+
                ptr = aacirun->ptr;
                do {
                        unsigned int len = aacirun->fifosz;
@@ -271,9 +279,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
                        if (aacirun->bytes <= 0) {
                                aacirun->bytes += aacirun->period;
                                aacirun->ptr = ptr;
-                               spin_unlock(&aaci->lock);
+                               spin_unlock(&aacirun->lock);
                                snd_pcm_period_elapsed(aacirun->substream);
-                               spin_lock(&aaci->lock);
+                               spin_lock(&aacirun->lock);
                        }
                        if (!(aacirun->cr & CR_EN))
                                break;
@@ -301,6 +309,8 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
                } while (1);
 
                aacirun->ptr = ptr;
+
+               spin_unlock(&aacirun->lock);
        }
 }
 
@@ -310,7 +320,6 @@ static irqreturn_t aaci_irq(int irq, void *devid)
        u32 mask;
        int i;
 
-       spin_lock(&aaci->lock);
        mask = readl(aaci->base + AACI_ALLINTS);
        if (mask) {
                u32 m = mask;
@@ -320,7 +329,6 @@ static irqreturn_t aaci_irq(int irq, void *devid)
                        }
                }
        }
-       spin_unlock(&aaci->lock);
 
        return mask ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -330,63 +338,6 @@ static irqreturn_t aaci_irq(int irq, void *devid)
 /*
  * ALSA support.
  */
-
-struct aaci_stream {
-       unsigned char codec_idx;
-       unsigned char rate_idx;
-};
-
-static struct aaci_stream aaci_streams[] = {
-       [ACSTREAM_FRONT] = {
-               .codec_idx      = 0,
-               .rate_idx       = AC97_RATES_FRONT_DAC,
-       },
-       [ACSTREAM_SURROUND] = {
-               .codec_idx      = 0,
-               .rate_idx       = AC97_RATES_SURR_DAC,
-       },
-       [ACSTREAM_LFE] = {
-               .codec_idx      = 0,
-               .rate_idx       = AC97_RATES_LFE_DAC,
-       },
-};
-
-static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid)
-{
-       struct aaci_stream *s = aaci_streams + streamid;
-       return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx];
-}
-
-static unsigned int rate_list[] = {
-       5512, 8000, 11025, 16000, 22050, 32000, 44100,
-       48000, 64000, 88200, 96000, 176400, 192000
-};
-
-/*
- * Double-rate rule: we can support double rate iff channels == 2
- *  (unimplemented)
- */
-static int
-aaci_rule_rate_by_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule)
-{
-       struct aaci *aaci = rule->private;
-       unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512;
-       struct snd_interval *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS);
-
-       switch (c->max) {
-       case 6:
-               rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE);
-       case 4:
-               rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND);
-       case 2:
-               rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT);
-       }
-
-       return snd_interval_list(hw_param_interval(p, rule->var),
-                                ARRAY_SIZE(rate_list), rate_list,
-                                rate_mask);
-}
-
 static struct snd_pcm_hardware aaci_hw_info = {
        .info                   = SNDRV_PCM_INFO_MMAP |
                                  SNDRV_PCM_INFO_MMAP_VALID |
@@ -400,10 +351,7 @@ static struct snd_pcm_hardware aaci_hw_info = {
         */
        .formats                = SNDRV_PCM_FMTBIT_S16_LE,
 
-       /* should this be continuous or knot? */
-       .rates                  = SNDRV_PCM_RATE_CONTINUOUS,
-       .rate_max               = 48000,
-       .rate_min               = 4000,
+       /* rates are setup from the AC'97 codec */
        .channels_min           = 2,
        .channels_max           = 6,
        .buffer_bytes_max       = 64 * 1024,
@@ -423,6 +371,12 @@ static int __aaci_pcm_open(struct aaci *aaci,
        aacirun->substream = substream;
        runtime->private_data = aacirun;
        runtime->hw = aaci_hw_info;
+       runtime->hw.rates = aacirun->pcm->rates;
+       snd_pcm_limit_hw_rates(runtime);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+           aacirun->pcm->r[1].slots)
+               snd_ac97_pcm_double_rate_rules(runtime);
 
        /*
         * FIXME: ALSA specifies fifo_size in bytes.  If we're in normal
@@ -433,17 +387,6 @@ static int __aaci_pcm_open(struct aaci *aaci,
         */
        runtime->hw.fifo_size = aaci->fifosize * 2;
 
-       /*
-        * Add rule describing hardware rate dependency
-        * on the number of channels.
-        */
-       ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-                                 aaci_rule_rate_by_channels, aaci,
-                                 SNDRV_PCM_HW_PARAM_CHANNELS,
-                                 SNDRV_PCM_HW_PARAM_RATE, -1);
-       if (ret)
-               goto out;
-
        ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED|IRQF_DISABLED,
                          DRIVER_NAME, aaci);
        if (ret)
@@ -507,18 +450,22 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
 
        err = snd_pcm_lib_malloc_pages(substream,
                                       params_buffer_bytes(params));
-       if (err < 0)
-               goto out;
+       if (err >= 0) {
+               unsigned int rate = params_rate(params);
+               int dbl = rate > 48000;
 
-       err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
-                               params_channels(params),
-                               aacirun->pcm->r[0].slots);
-       if (err)
-               goto out;
+               err = snd_ac97_pcm_open(aacirun->pcm, rate,
+                                       params_channels(params),
+                                       aacirun->pcm->r[dbl].slots);
 
-       aacirun->pcm_open = 1;
+               aacirun->pcm_open = err == 0;
+               aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
+               aacirun->fifosz = aaci->fifosize * 4;
+
+               if (aacirun->cr & CR_COMPACT)
+                       aacirun->fifosz >>= 1;
+       }
 
- out:
        return err;
 }
 
@@ -527,7 +474,7 @@ static int aaci_pcm_prepare(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct aaci_runtime *aacirun = runtime->private_data;
 
-       aacirun->start  = (void *)runtime->dma_area;
+       aacirun->start  = runtime->dma_area;
        aacirun->end    = aacirun->start + snd_pcm_lib_buffer_bytes(substream);
        aacirun->ptr    = aacirun->start;
        aacirun->period =
@@ -627,14 +574,9 @@ static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
         * Enable FIFO, compact mode, 16 bits per sample.
         * FIXME: double rate slots?
         */
-       if (ret >= 0) {
-               aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
+       if (ret >= 0)
                aacirun->cr |= channels_to_txmask[channels];
 
-               aacirun->fifosz = aaci->fifosize * 4;
-               if (aacirun->cr & CR_COMPACT)
-                       aacirun->fifosz >>= 1;
-       }
        return ret;
 }
 
@@ -646,7 +588,7 @@ static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
        ie &= ~(IE_URIE|IE_TXIE);
        writel(ie, aacirun->base + AACI_IE);
        aacirun->cr &= ~CR_EN;
-       aaci_chan_wait_ready(aacirun);
+       aaci_chan_wait_ready(aacirun, SR_TXB);
        writel(aacirun->cr, aacirun->base + AACI_TXCR);
 }
 
@@ -654,7 +596,7 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
 {
        u32 ie;
 
-       aaci_chan_wait_ready(aacirun);
+       aaci_chan_wait_ready(aacirun, SR_TXB);
        aacirun->cr |= CR_EN;
 
        ie = readl(aacirun->base + AACI_IE);
@@ -665,12 +607,12 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
 
 static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-       struct aaci *aaci = substream->private_data;
        struct aaci_runtime *aacirun = substream->runtime->private_data;
        unsigned long flags;
        int ret = 0;
 
-       spin_lock_irqsave(&aaci->lock, flags);
+       spin_lock_irqsave(&aacirun->lock, flags);
+
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                aaci_pcm_playback_start(aacirun);
@@ -697,7 +639,8 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm
        default:
                ret = -EINVAL;
        }
-       spin_unlock_irqrestore(&aaci->lock, flags);
+
+       spin_unlock_irqrestore(&aacirun->lock, flags);
 
        return ret;
 }
@@ -721,18 +664,10 @@ static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream,
        int ret;
 
        ret = aaci_pcm_hw_params(substream, aacirun, params);
-
-       if (ret >= 0) {
-               aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
-
+       if (ret >= 0)
                /* Line in record: slot 3 and 4 */
                aacirun->cr |= CR_SL3 | CR_SL4;
 
-               aacirun->fifosz = aaci->fifosize * 4;
-
-               if (aacirun->cr & CR_COMPACT)
-                       aacirun->fifosz >>= 1;
-       }
        return ret;
 }
 
@@ -740,7 +675,7 @@ static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)
 {
        u32 ie;
 
-       aaci_chan_wait_ready(aacirun);
+       aaci_chan_wait_ready(aacirun, SR_RXB);
 
        ie = readl(aacirun->base + AACI_IE);
        ie &= ~(IE_ORIE | IE_RXIE);
@@ -755,7 +690,7 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
 {
        u32 ie;
 
-       aaci_chan_wait_ready(aacirun);
+       aaci_chan_wait_ready(aacirun, SR_RXB);
 
 #ifdef DEBUG
        /* RX Timeout value: bits 28:17 in RXCR */
@@ -772,12 +707,11 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
 
 static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-       struct aaci *aaci = substream->private_data;
        struct aaci_runtime *aacirun = substream->runtime->private_data;
        unsigned long flags;
        int ret = 0;
 
-       spin_lock_irqsave(&aaci->lock, flags);
+       spin_lock_irqsave(&aacirun->lock, flags);
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -806,7 +740,7 @@ static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd
                ret = -EINVAL;
        }
 
-       spin_unlock_irqrestore(&aaci->lock, flags);
+       spin_unlock_irqrestore(&aacirun->lock, flags);
 
        return ret;
 }
@@ -889,6 +823,12 @@ static struct ac97_pcm ac97_defs[] __devinitdata = {
                                          (1 << AC97_SLOT_PCM_SRIGHT) |
                                          (1 << AC97_SLOT_LFE),
                        },
+                       [1] = {
+                               .slots  = (1 << AC97_SLOT_PCM_LEFT) |
+                                         (1 << AC97_SLOT_PCM_RIGHT) |
+                                         (1 << AC97_SLOT_PCM_LEFT_0) |
+                                         (1 << AC97_SLOT_PCM_RIGHT_0),
+                       },
                },
        },
        [1] = { /* PCM in */
@@ -1001,7 +941,6 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
 
        aaci = card->private_data;
        mutex_init(&aaci->ac97_sem);
-       spin_lock_init(&aaci->lock);
        aaci->card = card;
        aaci->dev = dev;
 
@@ -1028,7 +967,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
                snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                                     NULL, 0, 64 * 104);
+                                                     NULL, 0, 64 * 1024);
        }
 
        return ret;
@@ -1088,12 +1027,14 @@ static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id)
        /*
         * Playback uses AACI channel 0
         */
+       spin_lock_init(&aaci->playback.lock);
        aaci->playback.base = aaci->base + AACI_CSCH1;
        aaci->playback.fifo = aaci->base + AACI_DR1;
 
        /*
         * Capture uses AACI channel 0
         */
+       spin_lock_init(&aaci->capture.lock);
        aaci->capture.base = aaci->base + AACI_CSCH1;
        aaci->capture.fifo = aaci->base + AACI_DR1;
 
index 924f69c..6a4a2ee 100644 (file)
 struct aaci_runtime {
        void                    __iomem *base;
        void                    __iomem *fifo;
+       spinlock_t              lock;
 
        struct ac97_pcm         *pcm;
        int                     pcm_open;
@@ -232,7 +233,6 @@ struct aaci {
        struct snd_ac97         *ac97;
 
        u32                     maincr;
-       spinlock_t              lock;
 
        struct aaci_runtime     playback;
        struct aaci_runtime     capture;
index c15682a..475455c 100644 (file)
@@ -5,6 +5,7 @@ config SND_TIMER
 config SND_PCM
        tristate
        select SND_TIMER
+       select GCD
 
 config SND_HWDEP
        tristate
index 30f4108..a27545b 100644 (file)
@@ -758,7 +758,7 @@ int snd_interval_ratnum(struct snd_interval *i,
                int diff;
                if (q == 0)
                        q = 1;
-               den = div_down(num, q);
+               den = div_up(num, q);
                if (den < rats[k].den_min)
                        continue;
                if (den > rats[k].den_max)
@@ -794,7 +794,7 @@ int snd_interval_ratnum(struct snd_interval *i,
                        i->empty = 1;
                        return -EINVAL;
                }
-               den = div_up(num, q);
+               den = div_down(num, q);
                if (den > rats[k].den_max)
                        continue;
                if (den < rats[k].den_min)
index ca8068b..b01d948 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <linux/time.h>
+#include <linux/gcd.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/timer.h>
  *  Timer functions
  */
 
-/* Greatest common divisor */
-static unsigned long gcd(unsigned long a, unsigned long b)
-{
-       unsigned long r;
-       if (a < b) {
-               r = a;
-               a = b;
-               b = r;
-       }
-       while ((r = a % b) != 0) {
-               a = b;
-               b = r;
-       }
-       return b;
-}
-
 void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
 {
        unsigned long rate, mult, fsize, l, post;
index cb9aa4c..4be562b 100644 (file)
@@ -162,7 +162,7 @@ int snd_msndmidi_new(struct snd_card *card, int device)
        err = snd_rawmidi_new(card, "MSND-MIDI", device, 1, 1, &rmidi);
        if (err < 0)
                return err;
-       mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL);
+       mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
        if (mpu == NULL) {
                snd_device_free(card, rmidi);
                return -ENOMEM;
index 96678d5..751762f 100644 (file)
@@ -393,8 +393,6 @@ size_dram(struct snd_emu8000 *emu)
 
        while (size < EMU8000_MAX_DRAM) {
 
-               size += 512 * 1024;  /* increment 512kbytes */
-
                /* Write a unique data on the test address.
                 * if the address is out of range, the data is written on
                 * 0x200000(=EMU8000_DRAM_OFFSET).  Then the id word is
@@ -414,7 +412,9 @@ size_dram(struct snd_emu8000 *emu)
                /*snd_emu8000_read_wait(emu);*/
                EMU8000_SMLD_READ(emu); /* discard stale data  */
                if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2)
-                       break; /* we must have wrapped around */
+                       break; /* no memory at this address */
+
+               size += 512 * 1024;  /* increment 512kbytes */
 
                snd_emu8000_read_wait(emu);
 
index 8691f4c..f1d9d16 100644 (file)
@@ -609,7 +609,7 @@ static int snd_sgio2audio_pcm_hw_params(struct snd_pcm_substream *substream,
        /* alloc virtual 'dma' area */
        if (runtime->dma_area)
                vfree(runtime->dma_area);
-       runtime->dma_area = vmalloc(size);
+       runtime->dma_area = vmalloc_user(size);
        if (runtime->dma_area == NULL)
                return -ENOMEM;
        runtime->dma_bytes = size;
index 83f5ee2..e19dd5d 100644 (file)
@@ -269,7 +269,7 @@ static int pss_reset_dsp(pss_confdata * devc)
        unsigned long   i, limit = jiffies + HZ/10;
 
        outw(0x2000, REG(PSS_CONTROL));
-       for (i = 0; i < 32768 && (limit-jiffies >= 0); i++)
+       for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
                inw(REG(PSS_CONTROL));
        outw(0x0000, REG(PSS_CONTROL));
        return 1;
@@ -369,11 +369,11 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size
                outw(0, REG(PSS_DATA));
 
                limit = jiffies + HZ/10;
-               for (i = 0; i < 32768 && (limit - jiffies >= 0); i++)
+               for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
                        val = inw(REG(PSS_STATUS));
 
                limit = jiffies + HZ/10;
-               for (i = 0; i < 32768 && (limit-jiffies >= 0); i++)
+               for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
                {
                        val = inw(REG(PSS_STATUS));
                        if (val & 0x4000)
index 9cfdb77..950ee5c 100644 (file)
@@ -1086,11 +1086,6 @@ int snd_hda_codec_configure(struct hda_codec *codec)
                if (err < 0)
                        return err;
        }
-       /* audio codec should override the mixer name */
-       if (codec->afg || !*codec->bus->card->mixername)
-               snprintf(codec->bus->card->mixername,
-                        sizeof(codec->bus->card->mixername),
-                        "%s %s", codec->vendor_name, codec->chip_name);
 
        if (is_generic_config(codec)) {
                err = snd_hda_parse_generic_codec(codec);
@@ -1109,6 +1104,11 @@ int snd_hda_codec_configure(struct hda_codec *codec)
  patched:
        if (!err && codec->patch_ops.unsol_event)
                err = init_unsol_queue(codec->bus);
+       /* audio codec should override the mixer name */
+       if (!err && (codec->afg || !*codec->bus->card->mixername))
+               snprintf(codec->bus->card->mixername,
+                        sizeof(codec->bus->card->mixername),
+                        "%s %s", codec->vendor_name, codec->chip_name);
        return err;
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
index 9b56f93..ff8ad46 100644 (file)
@@ -2322,6 +2322,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
  * white/black-list for enable_msi
  */
 static struct snd_pci_quirk msi_black_list[] __devinitdata = {
+       SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
        {}
 };
 
index 4b200da..fe0423c 100644 (file)
@@ -66,6 +66,7 @@ struct cs_spec {
 /* available models */
 enum {
        CS420X_MBP55,
+       CS420X_IMAC27,
        CS420X_AUTO,
        CS420X_MODELS
 };
@@ -827,7 +828,8 @@ static void cs_automute(struct hda_codec *codec)
                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
                                    hp_present ? 0 : PIN_OUT);
        }
-       if (spec->board_config == CS420X_MBP55) {
+       if (spec->board_config == CS420X_MBP55 ||
+           spec->board_config == CS420X_IMAC27) {
                unsigned int gpio = hp_present ? 0x02 : 0x08;
                snd_hda_codec_write(codec, 0x01, 0,
                                    AC_VERB_SET_GPIO_DATA, gpio);
@@ -1069,12 +1071,14 @@ static int cs_parse_auto_config(struct hda_codec *codec)
 
 static const char *cs420x_models[CS420X_MODELS] = {
        [CS420X_MBP55] = "mbp55",
+       [CS420X_IMAC27] = "imac27",
        [CS420X_AUTO] = "auto",
 };
 
 
 static struct snd_pci_quirk cs420x_cfg_tbl[] = {
        SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
+       SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),
        {} /* terminator */
 };
 
@@ -1097,8 +1101,23 @@ static struct cs_pincfg mbp55_pincfgs[] = {
        {} /* terminator */
 };
 
+static struct cs_pincfg imac27_pincfgs[] = {
+       { 0x09, 0x012b4050 },
+       { 0x0a, 0x90100140 },
+       { 0x0b, 0x90100142 },
+       { 0x0c, 0x018b3020 },
+       { 0x0d, 0x90a00110 },
+       { 0x0e, 0x400000f0 },
+       { 0x0f, 0x01cbe030 },
+       { 0x10, 0x014be060 },
+       { 0x12, 0x01ab9070 },
+       { 0x15, 0x400000f0 },
+       {} /* terminator */
+};
+
 static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
        [CS420X_MBP55] = mbp55_pincfgs,
+       [CS420X_IMAC27] = imac27_pincfgs,
 };
 
 static void fix_pincfg(struct hda_codec *codec, int model)
@@ -1128,6 +1147,7 @@ static int patch_cs420x(struct hda_codec *codec)
                fix_pincfg(codec, spec->board_config);
 
        switch (spec->board_config) {
+       case CS420X_IMAC27:
        case CS420X_MBP55:
                /* GPIO1 = headphones */
                /* GPIO3 = speakers */
index a09c03c..c578c28 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_beep.h"
 
 #define CXT_PIN_DIR_IN              0x00
 #define CXT_PIN_DIR_OUT             0x01
@@ -111,6 +112,7 @@ struct conexant_spec {
        unsigned int dell_automute;
        unsigned int port_d_mode;
        unsigned char ext_mic_bias;
+       unsigned int dell_vostro;
 };
 
 static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@@ -476,6 +478,7 @@ static void conexant_free(struct hda_codec *codec)
                snd_array_free(&spec->jacks);
        }
 #endif
+       snd_hda_detach_beep_device(codec);
        kfree(codec->spec);
 }
 
@@ -2109,9 +2112,12 @@ static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        int val;
+       hda_nid_t nid = kcontrol->private_value & 0xff;
+       int inout = (kcontrol->private_value & 0x100) ?
+               AC_AMP_GET_INPUT : AC_AMP_GET_OUTPUT;
 
-       val = snd_hda_codec_read(codec, 0x17, 0,
-               AC_VERB_GET_AMP_GAIN_MUTE, AC_AMP_GET_OUTPUT);
+       val = snd_hda_codec_read(codec, nid, 0,
+               AC_VERB_GET_AMP_GAIN_MUTE, inout);
 
        ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN;
        return 0;
@@ -2123,6 +2129,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
        unsigned int idx;
+       hda_nid_t nid = kcontrol->private_value & 0xff;
+       int inout = (kcontrol->private_value & 0x100) ?
+               AC_AMP_SET_INPUT : AC_AMP_SET_OUTPUT;
 
        if (!imux->num_items)
                return 0;
@@ -2130,9 +2139,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
        if (idx >= imux->num_items)
                idx = imux->num_items - 1;
 
-       snd_hda_codec_write_cache(codec, 0x17, 0,
+       snd_hda_codec_write_cache(codec, nid, 0,
                AC_VERB_SET_AMP_GAIN_MUTE,
-               AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT |
+               AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | inout |
                        imux->items[idx].index);
 
        return 1;
@@ -2201,10 +2210,11 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
 
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Analog Mic Boost Capture Enum",
+               .name = "Ext Mic Boost Capture Enum",
                .info = cxt5066_mic_boost_mux_enum_info,
                .get = cxt5066_mic_boost_mux_enum_get,
                .put = cxt5066_mic_boost_mux_enum_put,
+               .private_value = 0x17,
        },
 
        HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
@@ -2212,6 +2222,19 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
        {}
 };
 
+static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Int Mic Boost Capture Enum",
+               .info = cxt5066_mic_boost_mux_enum_info,
+               .get = cxt5066_mic_boost_mux_enum_get,
+               .put = cxt5066_mic_boost_mux_enum_put,
+               .private_value = 0x23 | 0x100,
+       },
+       HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
+       {}
+};
+
 static struct hda_verb cxt5066_init_verbs[] = {
        {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
        {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
@@ -2397,11 +2420,16 @@ static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
 /* initialize jack-sensing, too */
 static int cxt5066_init(struct hda_codec *codec)
 {
+       struct conexant_spec *spec = codec->spec;
+
        snd_printdd("CXT5066: init\n");
        conexant_init(codec);
        if (codec->patch_ops.unsol_event) {
                cxt5066_hp_automute(codec);
-               cxt5066_automic(codec);
+               if (spec->dell_vostro)
+                       cxt5066_vostro_automic(codec);
+               else
+                       cxt5066_automic(codec);
        }
        return 0;
 }
@@ -2500,7 +2528,10 @@ static int patch_cxt5066(struct hda_codec *codec)
                spec->init_verbs[0] = cxt5066_init_verbs_vostro;
                spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
                spec->mixers[spec->num_mixers++] = cxt5066_mixers;
+               spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers;
                spec->port_d_mode = 0;
+               spec->dell_vostro = 1;
+               snd_hda_attach_beep_device(codec, 0x13);
 
                /* no S/PDIF out */
                spec->multiout.dig_out_nid = 0;
index aeed4cc..c746505 100644 (file)
@@ -131,8 +131,8 @@ enum {
 enum {
        ALC269_BASIC,
        ALC269_QUANTA_FL1,
-       ALC269_ASUS_EEEPC_P703,
-       ALC269_ASUS_EEEPC_P901,
+       ALC269_ASUS_AMIC,
+       ALC269_ASUS_DMIC,
        ALC269_FUJITSU,
        ALC269_LIFEBOOK,
        ALC269_AUTO,
@@ -188,6 +188,8 @@ enum {
        ALC663_ASUS_MODE4,
        ALC663_ASUS_MODE5,
        ALC663_ASUS_MODE6,
+       ALC663_ASUS_MODE7,
+       ALC663_ASUS_MODE8,
        ALC272_DELL,
        ALC272_DELL_ZM1,
        ALC272_SAMSUNG_NC10,
@@ -335,6 +337,9 @@ struct alc_spec {
        /* hooks */
        void (*init_hook)(struct hda_codec *codec);
        void (*unsol_event)(struct hda_codec *codec, unsigned int res);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       void (*power_hook)(struct hda_codec *codec, int power);
+#endif
 
        /* for pin sensing */
        unsigned int sense_updated: 1;
@@ -386,6 +391,7 @@ struct alc_config_preset {
        void (*init_hook)(struct hda_codec *);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        struct hda_amp_list *loopbacks;
+       void (*power_hook)(struct hda_codec *codec, int power);
 #endif
 };
 
@@ -898,6 +904,7 @@ static void setup_preset(struct hda_codec *codec,
        spec->unsol_event = preset->unsol_event;
        spec->init_hook = preset->init_hook;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
+       spec->power_hook = preset->power_hook;
        spec->loopback.amplist = preset->loopbacks;
 #endif
 
@@ -1663,9 +1670,6 @@ static struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
 /*  some bit here disables the other DACs. Init=0x4900 */
        {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
        {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
-/* Enable amplifiers */
-       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
 /* DMIC fix
  * This laptop has a stereo digital microphone. The mics are only 1cm apart
  * which makes the stereo useless. However, either the mic or the ALC889
@@ -1778,6 +1782,25 @@ static struct snd_kcontrol_new alc888_base_mixer[] = {
        { } /* end */
 };
 
+static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+               HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       { } /* end */
+};
+
+
 static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -1808,6 +1831,16 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[2] = 0x1b;
 }
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static void alc889_power_eapd(struct hda_codec *codec, int power)
+{
+       snd_hda_codec_write(codec, 0x14, 0,
+                           AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0);
+       snd_hda_codec_write(codec, 0x15, 0,
+                           AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0);
+}
+#endif
+
 /*
  * ALC880 3-stack model
  *
@@ -3601,12 +3634,29 @@ static void alc_free(struct hda_codec *codec)
        snd_hda_detach_beep_device(codec);
 }
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int alc_suspend(struct hda_codec *codec, pm_message_t state)
+{
+       struct alc_spec *spec = codec->spec;
+       if (spec && spec->power_hook)
+               spec->power_hook(codec, 0);
+       return 0;
+}
+#endif
+
 #ifdef SND_HDA_NEEDS_RESUME
 static int alc_resume(struct hda_codec *codec)
 {
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       struct alc_spec *spec = codec->spec;
+#endif
        codec->patch_ops.init(codec);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       if (spec && spec->power_hook)
+               spec->power_hook(codec, 1);
+#endif
        return 0;
 }
 #endif
@@ -3623,6 +3673,7 @@ static struct hda_codec_ops alc_patch_ops = {
        .resume = alc_resume,
 #endif
 #ifdef CONFIG_SND_HDA_POWER_SAVE
+       .suspend = alc_suspend,
        .check_power_status = alc_check_power_status,
 #endif
 };
@@ -8919,7 +8970,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
-       SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG),
+       SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
        SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
@@ -9282,6 +9333,7 @@ static struct alc_config_preset alc882_presets[] = {
                .dac_nids = alc883_dac_nids,
                .adc_nids = alc883_adc_nids_alt,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+               .capsrc_nids = alc883_capsrc_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
@@ -9378,10 +9430,11 @@ static struct alc_config_preset alc882_presets[] = {
                .init_hook = alc_automute_amp,
        },
        [ALC888_ACER_ASPIRE_8930G] = {
-               .mixers = { alc888_base_mixer,
+               .mixers = { alc889_acer_aspire_8930g_mixer,
                                alc883_chmode_mixer },
                .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
-                               alc889_acer_aspire_8930g_verbs },
+                               alc889_acer_aspire_8930g_verbs,
+                               alc889_eapd_verbs},
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
@@ -9398,6 +9451,9 @@ static struct alc_config_preset alc882_presets[] = {
                .unsol_event = alc_automute_amp_unsol_event,
                .setup = alc889_acer_aspire_8930g_setup,
                .init_hook = alc_automute_amp,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+               .power_hook = alc889_power_eapd,
+#endif
        },
        [ALC888_ACER_ASPIRE_7730G] = {
                .mixers = { alc883_3ST_6ch_mixer,
@@ -9428,6 +9484,7 @@ static struct alc_config_preset alc882_presets[] = {
                .dac_nids = alc883_dac_nids,
                .adc_nids = alc883_adc_nids_alt,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+               .capsrc_nids = alc883_capsrc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
                .input_mux = &alc883_capture_source,
@@ -9489,6 +9546,7 @@ static struct alc_config_preset alc882_presets[] = {
                .dac_nids = alc883_dac_nids,
                .adc_nids = alc883_adc_nids_alt,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+               .capsrc_nids = alc883_capsrc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_lenovo_101e_capture_source,
@@ -9668,6 +9726,7 @@ static struct alc_config_preset alc882_presets[] = {
                        alc880_gpio1_init_verbs },
                .adc_nids = alc883_adc_nids,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+               .capsrc_nids = alc883_capsrc_nids,
                .dac_nids = alc883_dac_nids,
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .channel_mode = alc889A_mb31_6ch_modes,
@@ -10678,6 +10737,13 @@ static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
        {}
 };
 
+static struct hda_verb alc262_lenovo_3000_init_verbs[] = {
+       /* Front Mic pin: input vref at 50% */
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {}
+};
+
 static struct hda_input_mux alc262_fujitsu_capture_source = {
        .num_items = 3,
        .items = {
@@ -11720,7 +11786,8 @@ static struct alc_config_preset alc262_presets[] = {
        [ALC262_LENOVO_3000] = {
                .mixers = { alc262_lenovo_3000_mixer },
                .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
-                               alc262_lenovo_3000_unsol_verbs },
+                               alc262_lenovo_3000_unsol_verbs,
+                               alc262_lenovo_3000_init_verbs },
                .num_dacs = ARRAY_SIZE(alc262_dac_nids),
                .dac_nids = alc262_dac_nids,
                .hp_nid = 0x03,
@@ -12857,7 +12924,7 @@ static int patch_alc268(struct hda_codec *codec)
        int board_config;
        int i, has_beep, err;
 
-       spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
                return -ENOMEM;
 
@@ -13232,10 +13299,12 @@ static struct hda_verb alc269_eeepc_amic_init_verbs[] = {
 /* toggle speaker-output according to the hp-jack state */
 static void alc269_speaker_automute(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
+       unsigned int nid = spec->autocfg.hp_pins[0];
        unsigned int present;
        unsigned char bits;
 
-       present = snd_hda_jack_detect(codec, 0x15);
+       present = snd_hda_jack_detect(codec, nid);
        bits = present ? AMP_IN_MUTE(0) : 0;
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
                                AMP_IN_MUTE(0), bits);
@@ -13460,8 +13529,8 @@ static void alc269_auto_init(struct hda_codec *codec)
 static const char *alc269_models[ALC269_MODEL_LAST] = {
        [ALC269_BASIC]                  = "basic",
        [ALC269_QUANTA_FL1]             = "quanta",
-       [ALC269_ASUS_EEEPC_P703]        = "eeepc-p703",
-       [ALC269_ASUS_EEEPC_P901]        = "eeepc-p901",
+       [ALC269_ASUS_AMIC]              = "asus-amic",
+       [ALC269_ASUS_DMIC]              = "asus-dmic",
        [ALC269_FUJITSU]                = "fujitsu",
        [ALC269_LIFEBOOK]               = "lifebook",
        [ALC269_AUTO]                   = "auto",
@@ -13470,18 +13539,41 @@ static const char *alc269_models[ALC269_MODEL_LAST] = {
 static struct snd_pci_quirk alc269_cfg_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
        SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
-                     ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_EEEPC_P703),
+                     ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80JT", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_AMIC),
        SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
-                     ALC269_ASUS_EEEPC_P901),
+                     ALC269_ASUS_DMIC),
        SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
-                     ALC269_ASUS_EEEPC_P901),
-        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_EEEPC_P901),
+                     ALC269_ASUS_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_ASUS_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_ASUS_DMIC),
        SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
        {}
@@ -13511,7 +13603,7 @@ static struct alc_config_preset alc269_presets[] = {
                .setup = alc269_quanta_fl1_setup,
                .init_hook = alc269_quanta_fl1_init_hook,
        },
-       [ALC269_ASUS_EEEPC_P703] = {
+       [ALC269_ASUS_AMIC] = {
                .mixers = { alc269_eeepc_mixer },
                .cap_mixer = alc269_epc_capture_mixer,
                .init_verbs = { alc269_init_verbs,
@@ -13525,7 +13617,7 @@ static struct alc_config_preset alc269_presets[] = {
                .setup = alc269_eeepc_amic_setup,
                .init_hook = alc269_eeepc_inithook,
        },
-       [ALC269_ASUS_EEEPC_P901] = {
+       [ALC269_ASUS_DMIC] = {
                .mixers = { alc269_eeepc_mixer },
                .cap_mixer = alc269_epc_capture_mixer,
                .init_verbs = { alc269_init_verbs,
@@ -16160,6 +16252,52 @@ static struct snd_kcontrol_new alc663_g50v_mixer[] = {
        { } /* end */
 };
 
+static struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
+       .ops = &snd_hda_bind_sw,
+       .values = {
+               HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
+               0
+       },
+};
+
+static struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
+       .ops = &snd_hda_bind_sw,
+       .values = {
+               HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
+               0
+       },
+};
+
+static struct snd_kcontrol_new alc663_mode7_mixer[] = {
+       HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
+       HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
+       HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
+       HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+       { } /* end */
+};
+
+static struct snd_kcontrol_new alc663_mode8_mixer[] = {
+       HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
+       HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
+       HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
+       HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       { } /* end */
+};
+
+
 static struct snd_kcontrol_new alc662_chmode_mixer[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -16447,6 +16585,45 @@ static struct hda_verb alc272_dell_init_verbs[] = {
        {}
 };
 
+static struct hda_verb alc663_mode7_init_verbs[] = {
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},  /* Headphone */
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+       {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+       {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {}
+};
+
+static struct hda_verb alc663_mode8_init_verbs[] = {
+       {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},  /* Headphone */
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+       {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {}
+};
+
 static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
        HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
@@ -16626,6 +16803,54 @@ static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
        }
 }
 
+static void alc663_two_hp_m7_speaker_automute(struct hda_codec *codec)
+{
+       unsigned int present1, present2;
+
+       present1 = snd_hda_codec_read(codec, 0x1b, 0,
+                       AC_VERB_GET_PIN_SENSE, 0)
+                       & AC_PINSENSE_PRESENCE;
+       present2 = snd_hda_codec_read(codec, 0x21, 0,
+                       AC_VERB_GET_PIN_SENSE, 0)
+                       & AC_PINSENSE_PRESENCE;
+
+       if (present1 || present2) {
+               snd_hda_codec_write_cache(codec, 0x14, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+               snd_hda_codec_write_cache(codec, 0x17, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+       } else {
+               snd_hda_codec_write_cache(codec, 0x14, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+               snd_hda_codec_write_cache(codec, 0x17, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+       }
+}
+
+static void alc663_two_hp_m8_speaker_automute(struct hda_codec *codec)
+{
+       unsigned int present1, present2;
+
+       present1 = snd_hda_codec_read(codec, 0x21, 0,
+                       AC_VERB_GET_PIN_SENSE, 0)
+                       & AC_PINSENSE_PRESENCE;
+       present2 = snd_hda_codec_read(codec, 0x15, 0,
+                       AC_VERB_GET_PIN_SENSE, 0)
+                       & AC_PINSENSE_PRESENCE;
+
+       if (present1 || present2) {
+               snd_hda_codec_write_cache(codec, 0x14, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+               snd_hda_codec_write_cache(codec, 0x17, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+       } else {
+               snd_hda_codec_write_cache(codec, 0x14, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+               snd_hda_codec_write_cache(codec, 0x17, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+       }
+}
+
 static void alc663_m51va_unsol_event(struct hda_codec *codec,
                                           unsigned int res)
 {
@@ -16645,7 +16870,7 @@ static void alc663_m51va_setup(struct hda_codec *codec)
        spec->ext_mic.pin = 0x18;
        spec->ext_mic.mux_idx = 0;
        spec->int_mic.pin = 0x12;
-       spec->int_mic.mux_idx = 1;
+       spec->int_mic.mux_idx = 9;
        spec->auto_mic = 1;
 }
 
@@ -16657,7 +16882,17 @@ static void alc663_m51va_inithook(struct hda_codec *codec)
 
 /* ***************** Mode1 ******************************/
 #define alc663_mode1_unsol_event       alc663_m51va_unsol_event
-#define alc663_mode1_setup             alc663_m51va_setup
+
+static void alc663_mode1_setup(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x19;
+       spec->int_mic.mux_idx = 1;
+       spec->auto_mic = 1;
+}
+
 #define alc663_mode1_inithook          alc663_m51va_inithook
 
 /* ***************** Mode2 ******************************/
@@ -16674,7 +16909,7 @@ static void alc662_mode2_unsol_event(struct hda_codec *codec,
        }
 }
 
-#define alc662_mode2_setup     alc663_m51va_setup
+#define alc662_mode2_setup     alc663_mode1_setup
 
 static void alc662_mode2_inithook(struct hda_codec *codec)
 {
@@ -16695,7 +16930,7 @@ static void alc663_mode3_unsol_event(struct hda_codec *codec,
        }
 }
 
-#define alc663_mode3_setup     alc663_m51va_setup
+#define alc663_mode3_setup     alc663_mode1_setup
 
 static void alc663_mode3_inithook(struct hda_codec *codec)
 {
@@ -16716,7 +16951,7 @@ static void alc663_mode4_unsol_event(struct hda_codec *codec,
        }
 }
 
-#define alc663_mode4_setup     alc663_m51va_setup
+#define alc663_mode4_setup     alc663_mode1_setup
 
 static void alc663_mode4_inithook(struct hda_codec *codec)
 {
@@ -16737,7 +16972,7 @@ static void alc663_mode5_unsol_event(struct hda_codec *codec,
        }
 }
 
-#define alc663_mode5_setup     alc663_m51va_setup
+#define alc663_mode5_setup     alc663_mode1_setup
 
 static void alc663_mode5_inithook(struct hda_codec *codec)
 {
@@ -16758,7 +16993,7 @@ static void alc663_mode6_unsol_event(struct hda_codec *codec,
        }
 }
 
-#define alc663_mode6_setup     alc663_m51va_setup
+#define alc663_mode6_setup     alc663_mode1_setup
 
 static void alc663_mode6_inithook(struct hda_codec *codec)
 {
@@ -16766,6 +17001,50 @@ static void alc663_mode6_inithook(struct hda_codec *codec)
        alc_mic_automute(codec);
 }
 
+/* ***************** Mode7 ******************************/
+static void alc663_mode7_unsol_event(struct hda_codec *codec,
+                                          unsigned int res)
+{
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
+               alc663_two_hp_m7_speaker_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc_mic_automute(codec);
+               break;
+       }
+}
+
+#define alc663_mode7_setup     alc663_mode1_setup
+
+static void alc663_mode7_inithook(struct hda_codec *codec)
+{
+       alc663_two_hp_m7_speaker_automute(codec);
+       alc_mic_automute(codec);
+}
+
+/* ***************** Mode8 ******************************/
+static void alc663_mode8_unsol_event(struct hda_codec *codec,
+                                          unsigned int res)
+{
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
+               alc663_two_hp_m8_speaker_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc_mic_automute(codec);
+               break;
+       }
+}
+
+#define alc663_mode8_setup     alc663_m51va_setup
+
+static void alc663_mode8_inithook(struct hda_codec *codec)
+{
+       alc663_two_hp_m8_speaker_automute(codec);
+       alc_mic_automute(codec);
+}
+
 static void alc663_g71v_hp_automute(struct hda_codec *codec)
 {
        unsigned int present;
@@ -16900,6 +17179,8 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
        [ALC663_ASUS_MODE4] = "asus-mode4",
        [ALC663_ASUS_MODE5] = "asus-mode5",
        [ALC663_ASUS_MODE6] = "asus-mode6",
+       [ALC663_ASUS_MODE7] = "asus-mode7",
+       [ALC663_ASUS_MODE8] = "asus-mode8",
        [ALC272_DELL]           = "dell",
        [ALC272_DELL_ZM1]       = "dell-zm1",
        [ALC272_SAMSUNG_NC10]   = "samsung-nc10",
@@ -16916,12 +17197,22 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
        SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
+       SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1),
+       SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7),
+       SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7),
+       SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8),
+       SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3),
+       SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
        SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
        SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
        SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
        SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
        SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
@@ -17205,6 +17496,36 @@ static struct alc_config_preset alc662_presets[] = {
                .setup = alc663_mode6_setup,
                .init_hook = alc663_mode6_inithook,
        },
+       [ALC663_ASUS_MODE7] = {
+               .mixers = { alc663_mode7_mixer },
+               .cap_mixer = alc662_auto_capture_mixer,
+               .init_verbs = { alc662_init_verbs,
+                               alc663_mode7_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+               .hp_nid = 0x03,
+               .dac_nids = alc662_dac_nids,
+               .dig_out_nid = ALC662_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+               .channel_mode = alc662_3ST_2ch_modes,
+               .unsol_event = alc663_mode7_unsol_event,
+               .setup = alc663_mode7_setup,
+               .init_hook = alc663_mode7_inithook,
+       },
+       [ALC663_ASUS_MODE8] = {
+               .mixers = { alc663_mode8_mixer },
+               .cap_mixer = alc662_auto_capture_mixer,
+               .init_verbs = { alc662_init_verbs,
+                               alc663_mode8_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+               .hp_nid = 0x03,
+               .dac_nids = alc662_dac_nids,
+               .dig_out_nid = ALC662_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+               .channel_mode = alc662_3ST_2ch_modes,
+               .unsol_event = alc663_mode8_unsol_event,
+               .setup = alc663_mode8_setup,
+               .init_hook = alc663_mode8_inithook,
+       },
        [ALC272_DELL] = {
                .mixers = { alc663_m51va_mixer },
                .cap_mixer = alc272_auto_capture_mixer,
@@ -17688,7 +18009,9 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
        { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
        { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
+       { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
        { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
+       { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
        { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
          .patch = patch_alc861 },
        { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
index 3d59f83..eeda7be 100644 (file)
@@ -2104,6 +2104,7 @@ static unsigned int ref9205_pin_configs[12] = {
     10280204
     1028021F
     10280228 (Dell Vostro 1500)
+    10280229 (Dell Vostro 1700)
 */
 static unsigned int dell_9205_m42_pin_configs[12] = {
        0x0321101F, 0x03A11020, 0x400003FA, 0x90170310,
@@ -2189,6 +2190,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
                      "Dell Inspiron", STAC_9205_DELL_M44),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
                      "Dell Vostro 1500", STAC_9205_DELL_M42),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0229,
+                     "Dell Vostro 1700", STAC_9205_DELL_M42),
        /* Gateway */
        SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD),
        SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD),
@@ -3779,15 +3782,16 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
                err = snd_hda_attach_beep_device(codec, nid);
                if (err < 0)
                        return err;
-               /* IDT/STAC codecs have linear beep tone parameter */
-               codec->beep->linear_tone = 1;
-               /* if no beep switch is available, make its own one */
-               caps = query_amp_caps(codec, nid, HDA_OUTPUT);
-               if (codec->beep &&
-                   !((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT)) {
-                       err = stac92xx_beep_switch_ctl(codec);
-                       if (err < 0)
-                               return err;
+               if (codec->beep) {
+                       /* IDT/STAC codecs have linear beep tone parameter */
+                       codec->beep->linear_tone = 1;
+                       /* if no beep switch is available, make its own one */
+                       caps = query_amp_caps(codec, nid, HDA_OUTPUT);
+                       if (!(caps & AC_AMPCAP_MUTE)) {
+                               err = stac92xx_beep_switch_ctl(codec);
+                               if (err < 0)
+                                       return err;
+                       }
                }
        }
 #endif
index d057e64..5cfa608 100644 (file)
@@ -51,7 +51,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s
                        return 0; /* already enough large */
                vfree(runtime->dma_area);
        }
-       runtime->dma_area = vmalloc_32(size);
+       runtime->dma_area = vmalloc_32_user(size);
        if (! runtime->dma_area)
                return -ENOMEM;
        runtime->dma_bytes = size;
index b69861d..3ef16bb 100644 (file)
@@ -470,7 +470,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642);
 
 static int __init ak4642_modinit(void)
 {
-       int ret;
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&ak4642_i2c_driver);
 #endif
index bbc72c2..81b8c9d 100644 (file)
@@ -191,6 +191,7 @@ static int ac97_analog_prepare(struct snd_pcm_substream *substream,
        vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);
 
        vra |= 0x1; /* enable variable rate audio */
+       vra &= ~0x4; /* disable SPDIF output */
 
        stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);
 
@@ -221,22 +222,6 @@ static int ac97_digital_prepare(struct snd_pcm_substream *substream,
        return stac9766_ac97_write(codec, reg, runtime->rate);
 }
 
-static int ac97_digital_trigger(struct snd_pcm_substream *substream,
-                               int cmd, struct snd_soc_dai *dai)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       unsigned short vra;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_STOP:
-               vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);
-               vra &= !0x04;
-               stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);
-               break;
-       }
-       return 0;
-}
-
 static int stac9766_set_bias_level(struct snd_soc_codec *codec,
                                   enum snd_soc_bias_level level)
 {
@@ -315,7 +300,6 @@ static struct snd_soc_dai_ops stac9766_dai_ops_analog = {
 
 static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
        .prepare = ac97_digital_prepare,
-       .trigger = ac97_digital_trigger,
 };
 
 struct snd_soc_dai stac9766_dai[] = {
index 81c57b5..a808675 100644 (file)
@@ -47,7 +47,7 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
 };
 
 #define WM8974_POWER1_BIASEN  0x08
-#define WM8974_POWER1_BUFIOEN 0x10
+#define WM8974_POWER1_BUFIOEN 0x04
 
 struct wm8974_priv {
        struct snd_soc_codec codec;
index 0ac1215..e237bf6 100644 (file)
@@ -463,7 +463,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
 {
        u16 *cache = codec->reg_cache;
 
-       soc_ac97_ops.write(codec->ac97, reg, val);
+       if (reg < 0x7c)
+               soc_ac97_ops.write(codec->ac97, reg, val);
        reg = reg >> 1;
        if (reg < (ARRAY_SIZE(wm9712_reg)))
                cache[reg] = val;
index 0267d2d..07d2a24 100644 (file)
@@ -180,7 +180,8 @@ static int mx27vis_hifi_hw_free(struct snd_pcm_substream *substream)
        struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
 
        /* disable the PLL */
-       return codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, 0, 0);
+       return codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, IGNORED_ARG,
+                                      0, 0);
 }
 
 /*
index 9c49c11..42813b8 100644 (file)
@@ -876,7 +876,7 @@ static int fsi_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
-       if (!res || !irq) {
+       if (!res || (int)irq <= 0) {
                dev_err(&pdev->dev, "Not enough FSI platform resources.\n");
                ret = -ENODEV;
                goto exit;
index b074a59..4963def 100644 (file)
@@ -752,7 +752,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s
                        return 0; /* already large enough */
                vfree(runtime->dma_area);
        }
-       runtime->dma_area = vmalloc(size);
+       runtime->dma_area = vmalloc_user(size);
        if (!runtime->dma_area)
                return -ENOMEM;
        runtime->dma_bytes = size;
index 7814dbb..4390d22 100644 (file)
@@ -487,10 +487,11 @@ else
        msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
 endif
 
-ifneq ($(shell sh -c "(echo '\#include <libdwarf/dwarf.h>'; echo '\#include <libdwarf/libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
+ifneq ($(shell sh -c "(echo '\#ifndef _MIPS_SZLONG'; echo '\#define _MIPS_SZLONG 0'; echo '\#endif'; echo '\#include <dwarf.h>'; echo '\#include <libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/libdwarf -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
        msg := $(warning No libdwarf.h found or old libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel >= 20081231);
        BASIC_CFLAGS += -DNO_LIBDWARF
 else
+       BASIC_CFLAGS += -I/usr/include/libdwarf
        EXTLIBS += -lelf -ldwarf
        LIB_OBJS += util/probe-finder.o
 endif
index 7e741f5..c1e6774 100644 (file)
@@ -38,6 +38,7 @@
 #include "util/strlist.h"
 #include "util/event.h"
 #include "util/debug.h"
+#include "util/debugfs.h"
 #include "util/symbol.h"
 #include "util/thread.h"
 #include "util/session.h"
@@ -205,6 +206,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
        if ((!session.nr_probe && !session.dellist && !session.list_events))
                usage_with_options(probe_usage, options);
 
+       if (debugfs_valid_mountpoint(debugfs_path) < 0)
+               die("Failed to find debugfs path.");
+
        if (session.list_events) {
                if (session.nr_probe != 0 || session.dellist) {
                        pr_warning("  Error: Don't use --list with"
index e50a6b1..5c2ab53 100644 (file)
@@ -224,7 +224,7 @@ static int __cmd_report(void)
 
        perf_session__collapse_resort(session);
        perf_session__output_resort(session, session->events_stats.total);
-       fprintf(stdout, "# Samples: %ld\n#\n", session->events_stats.total);
+       fprintf(stdout, "# Samples: %Ld\n#\n", session->events_stats.total);
        perf_session__fprintf_hists(session, NULL, false, stdout);
        if (sort_order == default_sort_order &&
            parent_pattern == default_parent_pattern)
index 8027309..690a96d 100644 (file)
@@ -95,8 +95,8 @@ typedef union event_union {
 } event_t;
 
 struct events_stats {
-       unsigned long total;
-       unsigned long lost;
+       u64 total;
+       u64 lost;
 };
 
 void event__print_totals(void);
index 2ca6215..29465d4 100644 (file)
@@ -62,6 +62,18 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
        return ret;
 }
 
+/* Check the name is good for event/group */
+static bool check_event_name(const char *name)
+{
+       if (!isalpha(*name) && *name != '_')
+               return false;
+       while (*++name != '\0') {
+               if (!isalpha(*name) && !isdigit(*name) && *name != '_')
+                       return false;
+       }
+       return true;
+}
+
 /* Parse probepoint definition. */
 static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
 {
@@ -82,6 +94,9 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
                ptr = strchr(arg, ':');
                if (ptr)        /* Group name is not supported yet. */
                        semantic_error("Group name is not supported yet.");
+               if (!check_event_name(arg))
+                       semantic_error("%s is bad for event name -it must "
+                                      "follow C symbol-naming rule.", arg);
                pp->event = strdup(arg);
                arg = tmp;
        }
index 5e4050c..a4086aa 100644 (file)
@@ -1,9 +1,9 @@
 #ifndef _PROBE_FINDER_H
 #define _PROBE_FINDER_H
 
-#define MAX_PATH_LEN 256
-#define MAX_PROBE_BUFFER 1024
-#define MAX_PROBES 128
+#define MAX_PATH_LEN            256
+#define MAX_PROBE_BUFFER       1024
+#define MAX_PROBES              128
 
 static inline int is_c_varname(const char *name)
 {
@@ -12,48 +12,53 @@ static inline int is_c_varname(const char *name)
 }
 
 struct probe_point {
-       char    *event;         /* Event name */
-       char    *group;         /* Event group */
+       char                    *event;                 /* Event name */
+       char                    *group;                 /* Event group */
 
        /* Inputs */
-       char    *file;          /* File name */
-       int     line;           /* Line number */
+       char                    *file;                  /* File name */
+       int                     line;                   /* Line number */
 
-       char    *function;      /* Function name */
-       int     offset;         /* Offset bytes */
+       char                    *function;              /* Function name */
+       int                     offset;                 /* Offset bytes */
 
-       int     nr_args;        /* Number of arguments */
-       char    **args;         /* Arguments */
+       int                     nr_args;                /* Number of arguments */
+       char                    **args;                 /* Arguments */
 
-       int     retprobe;       /* Return probe */
+       int                     retprobe;               /* Return probe */
 
        /* Output */
-       int     found;          /* Number of found probe points */
-       char    *probes[MAX_PROBES];    /* Output buffers (will be allocated)*/
+       int                     found;                  /* Number of found probe points */
+       char                    *probes[MAX_PROBES];    /* Output buffers (will be allocated)*/
 };
 
 #ifndef NO_LIBDWARF
 extern int find_probepoint(int fd, struct probe_point *pp);
 
-#include <libdwarf/dwarf.h>
-#include <libdwarf/libdwarf.h>
+/* Workaround for undefined _MIPS_SZLONG bug in libdwarf.h: */
+#ifndef _MIPS_SZLONG
+# define _MIPS_SZLONG          0
+#endif
+
+#include <dwarf.h>
+#include <libdwarf.h>
 
 struct probe_finder {
-       struct probe_point      *pp;    /* Target probe point */
+       struct probe_point      *pp;                    /* Target probe point */
 
        /* For function searching */
-       Dwarf_Addr      addr;           /* Address */
-       Dwarf_Unsigned  fno;            /* File number */
-       Dwarf_Unsigned  lno;            /* Line number */
-       Dwarf_Off       inl_offs;       /* Inline offset */
-       Dwarf_Die       cu_die;         /* Current CU */
+       Dwarf_Addr              addr;                   /* Address */
+       Dwarf_Unsigned          fno;                    /* File number */
+       Dwarf_Unsigned          lno;                    /* Line number */
+       Dwarf_Off               inl_offs;               /* Inline offset */
+       Dwarf_Die               cu_die;                 /* Current CU */
 
        /* For variable searching */
-       Dwarf_Addr      cu_base;        /* Current CU base address */
-       Dwarf_Locdesc   fbloc;          /* Location of Current Frame Base */
-       const char      *var;           /* Current variable name */
-       char            *buf;           /* Current output buffer */
-       int             len;            /* Length of output buffer */
+       Dwarf_Addr              cu_base;                /* Current CU base address */
+       Dwarf_Locdesc           fbloc;                  /* Location of Current Frame Base */
+       const char              *var;                   /* Current variable name */
+       char                    *buf;                   /* Current output buffer */
+       int                     len;                    /* Length of output buffer */
 };
 #endif /* NO_LIBDWARF */
 
index e1f2bf8..b5af881 100644 (file)
@@ -1177,7 +1177,7 @@ static struct file_operations kvm_vcpu_fops = {
  */
 static int create_vcpu_fd(struct kvm_vcpu *vcpu)
 {
-       return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0);
+       return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, O_RDWR);
 }
 
 /*
@@ -1638,7 +1638,7 @@ static int kvm_dev_ioctl_create_vm(void)
        kvm = kvm_create_vm();
        if (IS_ERR(kvm))
                return PTR_ERR(kvm);
-       fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, 0);
+       fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, O_RDWR);
        if (fd < 0)
                kvm_put_kvm(kvm);