Merge branches 'acorn', 'ebsa110' and 'sa11x0' into platforms
authorRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 25 Mar 2012 22:57:55 +0000 (23:57 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 25 Mar 2012 22:57:55 +0000 (23:57 +0100)
325 files changed:
Documentation/DocBook/device-drivers.tmpl
Documentation/input/event-codes.txt
Documentation/sysctl/kernel.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/common/Kconfig
arch/arm/common/Makefile
arch/arm/common/sa1111.c
arch/arm/include/asm/hardware/sa1111.h
arch/arm/include/asm/tlb.h
arch/arm/kernel/Makefile
arch/arm/kernel/entry-armv.S
arch/arm/kernel/perf_event_v7.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/signal.c
arch/arm/mach-bcmring/arch.c
arch/arm/mach-bcmring/dma.c
arch/arm/mach-bcmring/include/mach/dma.h
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-davinci/board-omapl138-hawk.c
arch/arm/mach-davinci/board-sffsdr.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/prm2xxx_3xxx.c
arch/arm/mach-omap2/smartreflex.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-rpc/Makefile
arch/arm/mach-rpc/ecard.c [moved from arch/arm/kernel/ecard.c with 90% similarity]
arch/arm/mach-rpc/ecard.h [moved from arch/arm/kernel/ecard.h with 100% similarity]
arch/arm/mach-rpc/include/mach/irqs.h
arch/arm/mach-rpc/riscpc.c
arch/arm/mach-rpc/time.c [moved from arch/arm/common/time-acorn.c with 98% similarity]
arch/arm/mach-sa1100/Makefile
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/badge4.c
arch/arm/mach-sa1100/cerf.c
arch/arm/mach-sa1100/collie.c
arch/arm/mach-sa1100/dma.c [deleted file]
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/generic.h
arch/arm/mach-sa1100/h3100.c
arch/arm/mach-sa1100/h3600.c
arch/arm/mach-sa1100/h3xxx.c
arch/arm/mach-sa1100/hackkit.c
arch/arm/mach-sa1100/include/mach/SA-1100.h
arch/arm/mach-sa1100/include/mach/dma.h [deleted file]
arch/arm/mach-sa1100/include/mach/irqs.h
arch/arm/mach-sa1100/include/mach/mcp.h
arch/arm/mach-sa1100/include/mach/neponset.h
arch/arm/mach-sa1100/include/mach/shannon.h
arch/arm/mach-sa1100/irq.c
arch/arm/mach-sa1100/jornada720.c
arch/arm/mach-sa1100/lart.c
arch/arm/mach-sa1100/nanoengine.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-sa1100/pci-nanoengine.c
arch/arm/mach-sa1100/pleb.c
arch/arm/mach-sa1100/shannon.c
arch/arm/mach-sa1100/simpad.c
arch/arm/mach-sa1100/sleep.S
arch/arm/mach-sa1100/ssp.c
arch/arm/mach-sa1100/time.c
arch/arm/mach-shmobile/setup-sh7372.c
arch/arm/mm/ioremap.c
arch/avr32/Kconfig
arch/microblaze/kernel/setup.c
arch/mips/Kconfig
arch/mips/lib/iomap-pci.c
arch/sh/Kconfig
arch/sh/drivers/pci/pci.c
arch/sparc/Kconfig
arch/sparc/lib/divdi3.S
arch/x86/include/asm/cmpxchg.h
arch/x86/include/asm/kvm_emulate.h
arch/x86/kernel/dumpstack.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/reboot.c
arch/x86/kvm/emulate.c
arch/x86/kvm/x86.c
arch/x86/mm/fault.c
arch/xtensa/include/asm/string.h
drivers/acpi/processor_driver.c
drivers/block/rbd.c
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/at_hdmac.c
drivers/dma/at_hdmac_regs.h
drivers/dma/dmatest.c
drivers/dma/imx-sdma.c
drivers/dma/sa11x0-dma.c [new file with mode: 0644]
drivers/dma/shdma.c
drivers/firewire/ohci.c
drivers/gpio/gpio-lpc32xx.c
drivers/gpio/gpio-ml-ioh.c
drivers/gpio/gpio-pch.c
drivers/gpio/gpio-sa1100.c
drivers/gpio/gpio-samsung.c
drivers/gpu/drm/nouveau/nouveau_bios.h
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_mxm.c
drivers/gpu/drm/nouveau/nv50_pm.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/r600_blit_kms.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-wacom.c
drivers/hid/hid-wiimote-core.c
drivers/hid/usbhid/hiddev.c
drivers/hwmon/w83627ehf.c
drivers/i2c/busses/i2c-omap.c
drivers/infiniband/core/ucma.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/nes/nes.c
drivers/infiniband/hw/nes/nes.h
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_cm.h
drivers/infiniband/hw/nes/nes_context.h
drivers/infiniband/hw/nes/nes_hw.c
drivers/infiniband/hw/nes/nes_hw.h
drivers/infiniband/hw/nes/nes_mgt.c
drivers/infiniband/hw/nes/nes_mgt.h
drivers/infiniband/hw/nes/nes_nic.c
drivers/infiniband/hw/nes/nes_user.h
drivers/infiniband/hw/nes/nes_utils.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/hw/nes/nes_verbs.h
drivers/infiniband/hw/qib/qib_iba6120.c
drivers/infiniband/hw/qib/qib_pcie.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/infiniband/ulp/srpt/ib_srpt.h
drivers/input/evdev.c
drivers/input/keyboard/jornada720_kbd.c
drivers/input/keyboard/twl4030_keypad.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/rpckbd.c
drivers/input/serio/sa1111ps2.c
drivers/input/serio/serio_raw.c
drivers/input/touchscreen/jornada720_ts.c
drivers/iommu/amd_iommu.c
drivers/iommu/msm_iommu.c
drivers/leds/leds-lm3530.c
drivers/md/dm-raid.c
drivers/md/md.c
drivers/mfd/Kconfig
drivers/mfd/mcp-core.c
drivers/mfd/mcp-sa11x0.c
drivers/mfd/twl6040-core.c
drivers/mfd/ucb1x00-assabet.c
drivers/mfd/ucb1x00-core.c
drivers/mfd/ucb1x00-ts.c
drivers/misc/lkdtm.c
drivers/mtd/maps/sa1100-flash.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/nand_base.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/irda/Kconfig
drivers/net/irda/sa1100_ir.c
drivers/pcmcia/ds.c
drivers/pcmcia/sa1100_neponset.c
drivers/pcmcia/sa1111_generic.c
drivers/rtc/rtc-sa1100.c
drivers/scsi/arm/arxescsi.c
drivers/scsi/arm/fas216.c
drivers/scsi/arm/fas216.h
drivers/spi/Kconfig
drivers/spi/spi-topcliff-pch.c
drivers/staging/media/go7007/go7007-usb.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_erl1.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/target_core_alua.c
drivers/target/target_core_cdb.c
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_iblock.c
drivers/target/target_core_internal.h
drivers/target/target_core_pr.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_cmd.c
drivers/tty/serial/sa1100.c
drivers/tty/vt/vt_ioctl.c
drivers/usb/host/ohci-sa1111.c
drivers/video/atmel_lcdfb.c
drivers/video/fsl-diu-fb.c
drivers/video/intelfb/intelfbdrv.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/ti_hdmi.h
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
drivers/video/omap2/dss/venc.c
drivers/video/sa1100fb.c
drivers/video/sa1100fb.h
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/xattr.c
fs/cifs/Kconfig
fs/cifs/connect.c
fs/cifs/sess.c
fs/exec.c
fs/jffs2/erase.c
fs/logfs/dev_mtd.c
fs/nilfs2/ioctl.c
fs/proc/base.c
include/asm-generic/pci_iomap.h
include/linux/binfmts.h
include/linux/gpio_keys.h
include/linux/lp8727.h [changed mode: 0755->0644]
include/linux/mfd/mcp.h
include/linux/mfd/twl6040.h
include/linux/mfd/ucb1x00.h
include/linux/mpi.h
include/linux/mtd/mtd.h
include/linux/perf_event.h
include/linux/pm_qos.h
include/linux/sa11x0-dma.h [new file with mode: 0644]
include/linux/sched.h
include/linux/sh_dma.h
include/sound/core.h
include/target/target_core_backend.h
include/target/target_core_base.h
include/target/target_core_fabric.h
include/video/omapdss.h
include/video/sa1100fb.h [new file with mode: 0644]
kernel/events/core.c
kernel/exit.c
kernel/fork.c
kernel/kprobes.c
kernel/power/power.h
kernel/power/process.c
kernel/power/user.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/watchdog.c
lib/Kconfig
lib/Makefile
lib/bug.c
lib/clz_tab.c [new file with mode: 0644]
lib/digsig.c
lib/mpi/longlong.h
lib/mpi/mpi-bit.c
lib/mpi/mpi-div.c
lib/mpi/mpi-pow.c
lib/mpi/mpicoder.c
lib/mpi/mpih-div.c
lib/mpi/mpiutil.c
lib/pci_iomap.c
mm/compaction.c
mm/filemap.c
mm/filemap_xip.c
mm/huge_memory.c
mm/kmemleak.c
mm/memcontrol.c
mm/migrate.c
mm/process_vm_access.c
mm/swap.c
net/ceph/ceph_common.c
net/ceph/mon_client.c
scripts/checkpatch.pl
sound/isa/sb/emu8000_patch.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_jack.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/pci/oxygen/oxygen_mixer.c
sound/soc/codecs/cs42l73.c
sound/soc/codecs/wm5100.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8996.c
sound/soc/codecs/wm_hubs.c
sound/soc/samsung/neo1973_wm8753.c
sound/soc/soc-core.c
sound/usb/quirks-table.h
tools/perf/Makefile
tools/perf/builtin-probe.c
tools/perf/builtin-top.c
tools/perf/util/header.c
tools/perf/util/probe-event.c
tools/perf/util/symbol.c
tools/perf/util/trace-event-parse.c
tools/perf/util/ui/browsers/hists.c
tools/perf/util/ui/helpline.c
tools/perf/util/util.h
virt/kvm/kvm_main.c

index 2f7fd43..9c27e51 100644 (file)
@@ -102,9 +102,12 @@ X!Iinclude/linux/kobject.h
 !Iinclude/linux/device.h
      </sect1>
      <sect1><title>Device Drivers Base</title>
+!Idrivers/base/init.c
 !Edrivers/base/driver.c
 !Edrivers/base/core.c
+!Edrivers/base/syscore.c
 !Edrivers/base/class.c
+!Idrivers/base/node.c
 !Edrivers/base/firmware_class.c
 !Edrivers/base/transport_class.c
 <!-- Cannot be included, because
@@ -113,13 +116,18 @@ X!Iinclude/linux/kobject.h
      exceed allowed 44 characters maximum
 X!Edrivers/base/attribute_container.c
 -->
-!Edrivers/base/sys.c
+!Edrivers/base/dd.c
 <!--
 X!Edrivers/base/interface.c
 -->
 !Iinclude/linux/platform_device.h
 !Edrivers/base/platform.c
 !Edrivers/base/bus.c
+     </sect1>
+     <sect1><title>Device Drivers DMA Management</title>
+!Edrivers/base/dma-buf.c
+!Edrivers/base/dma-coherent.c
+!Edrivers/base/dma-mapping.c
      </sect1>
      <sect1><title>Device Drivers Power Management</title>
 !Edrivers/base/power/main.c
@@ -219,7 +227,7 @@ X!Isound/sound_firmware.c
   <chapter id="uart16x50">
      <title>16x50 UART Driver</title>
 !Edrivers/tty/serial/serial_core.c
-!Edrivers/tty/serial/8250.c
+!Edrivers/tty/serial/8250/8250.c
   </chapter>
 
   <chapter id="fbdev">
index 23fcb05..53305bd 100644 (file)
@@ -17,11 +17,11 @@ reports supported by a device are also provided by sysfs in
 class/input/event*/device/capabilities/, and the properties of a device are
 provided in class/input/event*/device/properties.
 
-Types:
-==========
-Types are groupings of codes under a logical input construct. Each type has a
-set of applicable codes to be used in generating events. See the Codes section
-for details on valid codes for each type.
+Event types:
+===========
+Event types are groupings of codes under a logical input construct. Each
+type has a set of applicable codes to be used in generating events. See the
+Codes section for details on valid codes for each type.
 
 * EV_SYN:
   - Used as markers to separate events. Events may be separated in time or in
@@ -63,9 +63,9 @@ for details on valid codes for each type.
 * EV_FF_STATUS:
   - Used to receive force feedback device status.
 
-Codes:
-==========
-Codes define the precise type of event.
+Event codes:
+===========
+Event codes define the precise type of event.
 
 EV_SYN:
 ----------
@@ -220,6 +220,56 @@ EV_PWR:
 EV_PWR events are a special type of event used specifically for power
 mangement. Its usage is not well defined. To be addressed later.
 
+Device properties:
+=================
+Normally, userspace sets up an input device based on the data it emits,
+i.e., the event types. In the case of two devices emitting the same event
+types, additional information can be provided in the form of device
+properties.
+
+INPUT_PROP_DIRECT + INPUT_PROP_POINTER:
+--------------------------------------
+The INPUT_PROP_DIRECT property indicates that device coordinates should be
+directly mapped to screen coordinates (not taking into account trivial
+transformations, such as scaling, flipping and rotating). Non-direct input
+devices require non-trivial transformation, such as absolute to relative
+transformation for touchpads. Typical direct input devices: touchscreens,
+drawing tablets; non-direct devices: touchpads, mice.
+
+The INPUT_PROP_POINTER property indicates that the device is not transposed
+on the screen and thus requires use of an on-screen pointer to trace user's
+movements.  Typical pointer devices: touchpads, tablets, mice; non-pointer
+device: touchscreen.
+
+If neither INPUT_PROP_DIRECT or INPUT_PROP_POINTER are set, the property is
+considered undefined and the device type should be deduced in the
+traditional way, using emitted event types.
+
+INPUT_PROP_BUTTONPAD:
+--------------------
+For touchpads where the button is placed beneath the surface, such that
+pressing down on the pad causes a button click, this property should be
+set. Common in clickpad notebooks and macbooks from 2009 and onwards.
+
+Originally, the buttonpad property was coded into the bcm5974 driver
+version field under the name integrated button. For backwards
+compatibility, both methods need to be checked in userspace.
+
+INPUT_PROP_SEMI_MT:
+------------------
+Some touchpads, most common between 2008 and 2011, can detect the presence
+of multiple contacts without resolving the individual positions; only the
+number of contacts and a rectangular shape is known. For such
+touchpads, the semi-mt property should be set.
+
+Depending on the device, the rectangle may enclose all touches, like a
+bounding box, or just some of them, for instance the two most recent
+touches. The diversity makes the rectangle of limited use, but some
+gestures can normally be extracted from it.
+
+If INPUT_PROP_SEMI_MT is not set, the device is assumed to be a true MT
+device.
+
 Guidelines:
 ==========
 The guidelines below ensure proper single-touch and multi-finger functionality.
@@ -240,6 +290,8 @@ used to report when a touch is active on the screen.
 BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch
 contact. BTN_TOOL_<name> events should be reported where possible.
 
+For new hardware, INPUT_PROP_DIRECT should be set.
+
 Trackpads:
 ----------
 Legacy trackpads that only provide relative position information must report
@@ -250,6 +302,8 @@ location of the touch. BTN_TOUCH should be used to report when a touch is active
 on the trackpad. Where multi-finger support is available, BTN_TOOL_<name> should
 be used to report the number of touches active on the trackpad.
 
+For new hardware, INPUT_PROP_POINTER should be set.
+
 Tablets:
 ----------
 BTN_TOOL_<name> events must be reported when a stylus or other tool is active on
@@ -260,3 +314,5 @@ button may be used for buttons on the tablet except BTN_{MOUSE,LEFT}.
 BTN_{0,1,2,etc} are good generic codes for unlabeled buttons. Do not use
 meaningful buttons, like BTN_FORWARD, unless the button is labeled for that
 purpose on the device.
+
+For new hardware, both INPUT_PROP_DIRECT and INPUT_PROP_POINTER should be set.
index 8c20fbd..6d78841 100644 (file)
@@ -601,6 +601,8 @@ can be ORed together:
         instead of using the one provided by the hardware.
  512 - A kernel warning has occurred.
 1024 - A module from drivers/staging was loaded.
+2048 - The system is working around a severe firmware bug.
+4096 - An out-of-tree module has been loaded.
 
 ==============================================================
 
index a1fce9a..55ca0be 100644 (file)
@@ -159,7 +159,7 @@ S:  Maintained
 F:     drivers/net/ethernet/realtek/r8169.c
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-serial@vger.kernel.org
 W:     http://serial.sourceforge.net
 S:     Maintained
@@ -789,12 +789,6 @@ F: arch/arm/mach-mx*/
 F:     arch/arm/mach-imx/
 F:     arch/arm/plat-mxc/
 
-ARM/FREESCALE IMX51
-M:     Amit Kucheria <amit.kucheria@canonical.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-F:     arch/arm/mach-mx5/
-
 ARM/FREESCALE IMX6
 M:     Shawn Guo <shawn.guo@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1783,9 +1777,9 @@ X:        net/wireless/wext*
 
 CHAR and MISC DRIVERS
 M:     Arnd Bergmann <arnd@arndb.de>
-M:     Greg Kroah-Hartman <greg@kroah.com>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
-S:     Maintained
+S:     Supported
 F:     drivers/char/*
 F:     drivers/misc/*
 
@@ -2287,7 +2281,7 @@ F:        drivers/acpi/dock.c
 DOCUMENTATION
 M:     Randy Dunlap <rdunlap@xenotime.net>
 L:     linux-doc@vger.kernel.org
-T:     quilt http://userweb.kernel.org/~rdunlap/kernel-doc-patches/current/
+T:     quilt http://xenotime.net/kernel-doc-patches/current/
 S:     Maintained
 F:     Documentation/
 
@@ -2320,7 +2314,7 @@ F:        lib/lru_cache.c
 F:     Documentation/blockdev/drbd/
 
 DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git
 S:     Supported
 F:     Documentation/kobject.txt
@@ -3992,11 +3986,11 @@ M:      Rusty Russell <rusty@rustcorp.com.au>
 L:     lguest@lists.ozlabs.org
 W:     http://lguest.ozlabs.org/
 S:     Odd Fixes
-F:     Documentation/virtual/lguest/
+F:     arch/x86/include/asm/lguest*.h
 F:     arch/x86/lguest/
 F:     drivers/lguest/
 F:     include/linux/lguest*.h
-F:     arch/x86/include/asm/lguest*.h
+F:     tools/lguest/
 
 LINUX FOR IBM pSERIES (RS/6000)
 M:     Paul Mackerras <paulus@au.ibm.com>
@@ -4136,7 +4130,7 @@ L:        linux-ntfs-dev@lists.sourceforge.net
 W:     http://www.linux-ntfs.org/content/view/19/37/
 S:     Maintained
 F:     Documentation/ldm.txt
-F:     fs/partitions/ldm.*
+F:     block/partitions/ldm.*
 
 LogFS
 M:     Joern Engel <joern@logfs.org>
@@ -5633,7 +5627,7 @@ W:        http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
 F:     arch/s390/
 F:     drivers/s390/
-F:     fs/partitions/ibm.c
+F:     block/partitions/ibm.c
 F:     Documentation/s390/
 F:     Documentation/DocBook/s390*
 
@@ -6276,15 +6270,15 @@ S:      Maintained
 F:     arch/alpha/kernel/srm_env.c
 
 STABLE BRANCH
-M:     Greg Kroah-Hartman <greg@kroah.com>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     stable@vger.kernel.org
-S:     Maintained
+S:     Supported
 
 STAGING SUBSYSTEM
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
 L:     devel@driverdev.osuosl.org
-S:     Maintained
+S:     Supported
 F:     drivers/staging/
 
 STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS
@@ -6396,11 +6390,6 @@ M:       Omar Ramirez Luna <omar.ramirez@ti.com>
 S:     Odd Fixes
 F:     drivers/staging/tidspbridge/
 
-STAGING - TRIDENT TVMASTER TMxxxx USB VIDEO CAPTURE DRIVERS
-L:     linux-media@vger.kernel.org
-S:     Odd Fixes
-F:     drivers/staging/tm6000/
-
 STAGING - USB ENE SM/MS CARD READER DRIVER
 M:     Al Cho <acho@novell.com>
 S:     Odd Fixes
@@ -6669,8 +6658,8 @@ S:        Maintained
 K:     ^Subject:.*(?i)trivial
 
 TTY LAYER
-M:     Greg Kroah-Hartman <gregkh@suse.de>
-S:     Maintained
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git
 F:     drivers/tty/
 F:     drivers/tty/serial/serial_core.c
@@ -6958,7 +6947,7 @@ S:        Maintained
 F:     drivers/usb/serial/digi_acceleport.c
 
 USB SERIAL DRIVER
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-usb@vger.kernel.org
 S:     Supported
 F:     Documentation/usb/usb-serial.txt
@@ -6973,9 +6962,8 @@ S:        Maintained
 F:     drivers/usb/serial/empeg.c
 
 USB SERIAL KEYSPAN DRIVER
-M:     Greg Kroah-Hartman <greg@kroah.com>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-usb@vger.kernel.org
-W:     http://www.kroah.com/linux/
 S:     Maintained
 F:     drivers/usb/serial/*keyspan*
 
@@ -7003,7 +6991,7 @@ F:        Documentation/video4linux/sn9c102.txt
 F:     drivers/media/video/sn9c102/
 
 USB SUBSYSTEM
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-usb@vger.kernel.org
 W:     http://www.linux-usb.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git
@@ -7090,7 +7078,7 @@ F:        fs/hppfs/
 
 USERSPACE I/O (UIO)
 M:     "Hans J. Koch" <hjk@hansjkoch.de>
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 S:     Maintained
 F:     Documentation/DocBook/uio-howto.tmpl
 F:     drivers/uio/
index e3b23e8..7c44b67 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Saber-toothed Squirrel
 
 # *DOCUMENTATION*
index a48aecc..4ade2d8 100644 (file)
@@ -731,7 +731,6 @@ config ARCH_RPC
        bool "RiscPC"
        select ARCH_ACORN
        select FIQ
-       select TIMER_ACORN
        select ARCH_MAY_HAVE_PC_FDC
        select HAVE_PATA_PLATFORM
        select ISA_DMA_API
@@ -760,6 +759,7 @@ config ARCH_SA1100
        select ARCH_REQUIRE_GPIOLIB
        select HAVE_IDE
        select NEED_MACH_MEMORY_H
+       select SPARSE_IRQ
        help
          Support for StrongARM 11x0 based boards.
 
index 81a933e..3bb1d75 100644 (file)
@@ -35,9 +35,6 @@ config DMABOUNCE
        bool
        select ZONE_DMA
 
-config TIMER_ACORN
-       bool
-
 config SHARP_LOCOMO
        bool
 
index 6ea9b6f..69feafe 100644 (file)
@@ -9,7 +9,6 @@ obj-$(CONFIG_PL330)             += pl330.o
 obj-$(CONFIG_SA1111)           += sa1111.o
 obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
 obj-$(CONFIG_DMABOUNCE)                += dmabounce.o
-obj-$(CONFIG_TIMER_ACORN)      += time-acorn.o
 obj-$(CONFIG_SHARP_LOCOMO)     += locomo.o
 obj-$(CONFIG_SHARP_PARAM)      += sharpsl_param.o
 obj-$(CONFIG_SHARP_SCOOP)      += scoop.o
index 61691cd..9173d11 100644 (file)
@@ -16,6 +16,7 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -28,9 +29,8 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
 #include <asm/mach/irq.h>
+#include <asm/mach-types.h>
 #include <asm/sizes.h>
 
 #include <asm/hardware/sa1111.h>
 #define IRQ_S1_CD_VALID                (52)
 #define IRQ_S0_BVD1_STSCHG     (53)
 #define IRQ_S1_BVD1_STSCHG     (54)
+#define SA1111_IRQ_NR          (55)
 
-extern void __init sa1110_mb_enable(void);
+extern void sa1110_mb_enable(void);
+extern void sa1110_mb_disable(void);
 
 /*
  * We keep the following data for the overall SA1111.  Note that the
@@ -104,6 +106,7 @@ struct sa1111 {
        int             irq_base;       /* base for cascaded on-chip IRQs */
        spinlock_t      lock;
        void __iomem    *base;
+       struct sa1111_platform_data *pdata;
 #ifdef CONFIG_PM
        void            *saved_state;
 #endif
@@ -118,6 +121,7 @@ static struct sa1111 *g_sa1111;
 struct sa1111_dev_info {
        unsigned long   offset;
        unsigned long   skpcr_mask;
+       bool            dma;
        unsigned int    devid;
        unsigned int    irq[6];
 };
@@ -126,6 +130,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
        {
                .offset         = SA1111_USB,
                .skpcr_mask     = SKPCR_UCLKEN,
+               .dma            = true,
                .devid          = SA1111_DEVID_USB,
                .irq = {
                        IRQ_USBPWR,
@@ -139,6 +144,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
        {
                .offset         = 0x0600,
                .skpcr_mask     = SKPCR_I2SCLKEN | SKPCR_L3CLKEN,
+               .dma            = true,
                .devid          = SA1111_DEVID_SAC,
                .irq = {
                        AUDXMTDMADONEA,
@@ -155,7 +161,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
        {
                .offset         = SA1111_KBD,
                .skpcr_mask     = SKPCR_PTCLKEN,
-               .devid          = SA1111_DEVID_PS2,
+               .devid          = SA1111_DEVID_PS2_KBD,
                .irq = {
                        IRQ_TPRXINT,
                        IRQ_TPTXINT
@@ -164,7 +170,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
        {
                .offset         = SA1111_MSE,
                .skpcr_mask     = SKPCR_PMCLKEN,
-               .devid          = SA1111_DEVID_PS2,
+               .devid          = SA1111_DEVID_PS2_MSE,
                .irq = {
                        IRQ_MSRXINT,
                        IRQ_MSTXINT
@@ -434,16 +440,28 @@ static struct irq_chip sa1111_high_chip = {
        .irq_set_wake   = sa1111_wake_highirq,
 };
 
-static void sa1111_setup_irq(struct sa1111 *sachip)
+static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
 {
        void __iomem *irqbase = sachip->base + SA1111_INTC;
-       unsigned int irq;
+       unsigned i, irq;
+       int ret;
 
        /*
         * We're guaranteed that this region hasn't been taken.
         */
        request_mem_region(sachip->phys + SA1111_INTC, 512, "irq");
 
+       ret = irq_alloc_descs(-1, irq_base, SA1111_IRQ_NR, -1);
+       if (ret <= 0) {
+               dev_err(sachip->dev, "unable to allocate %u irqs: %d\n",
+                       SA1111_IRQ_NR, ret);
+               if (ret == 0)
+                       ret = -EINVAL;
+               return ret;
+       }
+
+       sachip->irq_base = ret;
+
        /* disable all IRQs */
        sa1111_writel(0, irqbase + SA1111_INTEN0);
        sa1111_writel(0, irqbase + SA1111_INTEN1);
@@ -463,14 +481,16 @@ static void sa1111_setup_irq(struct sa1111 *sachip)
        sa1111_writel(~0, irqbase + SA1111_INTSTATCLR0);
        sa1111_writel(~0, irqbase + SA1111_INTSTATCLR1);
 
-       for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
+       for (i = IRQ_GPAIN0; i <= SSPROR; i++) {
+               irq = sachip->irq_base + i;
                irq_set_chip_and_handler(irq, &sa1111_low_chip,
                                         handle_edge_irq);
                irq_set_chip_data(irq, sachip);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) {
+       for (i = AUDXMTDMADONEA; i <= IRQ_S1_BVD1_STSCHG; i++) {
+               irq = sachip->irq_base + i;
                irq_set_chip_and_handler(irq, &sa1111_high_chip,
                                         handle_edge_irq);
                irq_set_chip_data(irq, sachip);
@@ -483,6 +503,11 @@ static void sa1111_setup_irq(struct sa1111 *sachip)
        irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
        irq_set_handler_data(sachip->irq, sachip);
        irq_set_chained_handler(sachip->irq, sa1111_irq_handler);
+
+       dev_info(sachip->dev, "Providing IRQ%u-%u\n",
+               sachip->irq_base, sachip->irq_base + SA1111_IRQ_NR - 1);
+
+       return 0;
 }
 
 /*
@@ -581,41 +606,10 @@ sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
 }
 #endif
 
-#ifdef CONFIG_DMABOUNCE
-/*
- * According to the "Intel StrongARM SA-1111 Microprocessor Companion
- * Chip Specification Update" (June 2000), erratum #7, there is a
- * significant bug in the SA1111 SDRAM shared memory controller.  If
- * an access to a region of memory above 1MB relative to the bank base,
- * it is important that address bit 10 _NOT_ be asserted. Depending
- * on the configuration of the RAM, bit 10 may correspond to one
- * of several different (processor-relative) address bits.
- *
- * This routine only identifies whether or not a given DMA address
- * is susceptible to the bug.
- *
- * This should only get called for sa1111_device types due to the
- * way we configure our device dma_masks.
- */
-static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
-{
-       /*
-        * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
-        * User's Guide" mentions that jumpers R51 and R52 control the
-        * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
-        * SDRAM bank 1 on Neponset). The default configuration selects
-        * Assabet, so any address in bank 1 is necessarily invalid.
-        */
-       return (machine_is_assabet() || machine_is_pfs168()) &&
-               (addr >= 0xc8000000 || (addr + size) >= 0xc8000000);
-}
-#endif
-
 static void sa1111_dev_release(struct device *_dev)
 {
        struct sa1111_dev *dev = SA1111_DEV(_dev);
 
-       release_resource(&dev->res);
        kfree(dev);
 }
 
@@ -624,67 +618,58 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
                      struct sa1111_dev_info *info)
 {
        struct sa1111_dev *dev;
+       unsigned i;
        int ret;
 
        dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL);
        if (!dev) {
                ret = -ENOMEM;
-               goto out;
+               goto err_alloc;
        }
 
+       device_initialize(&dev->dev);
        dev_set_name(&dev->dev, "%4.4lx", info->offset);
        dev->devid       = info->devid;
        dev->dev.parent  = sachip->dev;
        dev->dev.bus     = &sa1111_bus_type;
        dev->dev.release = sa1111_dev_release;
-       dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask;
        dev->res.start   = sachip->phys + info->offset;
        dev->res.end     = dev->res.start + 511;
        dev->res.name    = dev_name(&dev->dev);
        dev->res.flags   = IORESOURCE_MEM;
        dev->mapbase     = sachip->base + info->offset;
        dev->skpcr_mask  = info->skpcr_mask;
-       memmove(dev->irq, info->irq, sizeof(dev->irq));
-
-       ret = request_resource(parent, &dev->res);
-       if (ret) {
-               printk("SA1111: failed to allocate resource for %s\n",
-                       dev->res.name);
-               dev_set_name(&dev->dev, NULL);
-               kfree(dev);
-               goto out;
-       }
-
 
-       ret = device_register(&dev->dev);
-       if (ret) {
-               release_resource(&dev->res);
-               kfree(dev);
-               goto out;
-       }
+       for (i = 0; i < ARRAY_SIZE(info->irq); i++)
+               dev->irq[i] = sachip->irq_base + info->irq[i];
 
-#ifdef CONFIG_DMABOUNCE
        /*
-        * If the parent device has a DMA mask associated with it,
-        * propagate it down to the children.
+        * If the parent device has a DMA mask associated with it, and
+        * this child supports DMA, propagate it down to the children.
         */
-       if (sachip->dev->dma_mask) {
+       if (info->dma && sachip->dev->dma_mask) {
                dev->dma_mask = *sachip->dev->dma_mask;
                dev->dev.dma_mask = &dev->dma_mask;
+               dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask;
+       }
 
-               if (dev->dma_mask != 0xffffffffUL) {
-                       ret = dmabounce_register_dev(&dev->dev, 1024, 4096,
-                                       sa1111_needs_bounce);
-                       if (ret) {
-                               dev_err(&dev->dev, "SA1111: Failed to register"
-                                       " with dmabounce\n");
-                               device_unregister(&dev->dev);
-                       }
-               }
+       ret = request_resource(parent, &dev->res);
+       if (ret) {
+               dev_err(sachip->dev, "failed to allocate resource for %s\n",
+                       dev->res.name);
+               goto err_resource;
        }
-#endif
 
-out:
+       ret = device_add(&dev->dev);
+       if (ret)
+               goto err_add;
+       return 0;
+
+ err_add:
+       release_resource(&dev->res);
+ err_resource:
+       put_device(&dev->dev);
+ err_alloc:
        return ret;
 }
 
@@ -698,16 +683,21 @@ out:
  *     Returns:
  *     %-ENODEV        device not found.
  *     %-EBUSY         physical address already marked in-use.
+ *     %-EINVAL        no platform data passed
  *     %0              successful.
  */
 static int __devinit
 __sa1111_probe(struct device *me, struct resource *mem, int irq)
 {
+       struct sa1111_platform_data *pd = me->platform_data;
        struct sa1111 *sachip;
        unsigned long id;
        unsigned int has_devs;
        int i, ret = -ENODEV;
 
+       if (!pd)
+               return -EINVAL;
+
        sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL);
        if (!sachip)
                return -ENOMEM;
@@ -727,6 +717,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
        sachip->dev = me;
        dev_set_drvdata(sachip->dev, sachip);
 
+       sachip->pdata = pd;
        sachip->phys = mem->start;
        sachip->irq = irq;
 
@@ -759,6 +750,16 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
         */
        sa1111_wake(sachip);
 
+       /*
+        * The interrupt controller must be initialised before any
+        * other device to ensure that the interrupts are available.
+        */
+       if (sachip->irq != NO_IRQ) {
+               ret = sa1111_setup_irq(sachip, pd->irq_base);
+               if (ret)
+                       goto err_unmap;
+       }
+
 #ifdef CONFIG_ARCH_SA1100
        {
        unsigned int val;
@@ -789,24 +790,14 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
        }
 #endif
 
-       /*
-        * The interrupt controller must be initialised before any
-        * other device to ensure that the interrupts are available.
-        */
-       if (sachip->irq != NO_IRQ)
-               sa1111_setup_irq(sachip);
-
        g_sa1111 = sachip;
 
        has_devs = ~0;
-       if (machine_is_assabet() || machine_is_jornada720() ||
-           machine_is_badge4())
-               has_devs &= ~(1 << 4);
-       else
-               has_devs &= ~(1 << 1);
+       if (pd)
+               has_devs &= ~pd->disable_devs;
 
        for (i = 0; i < ARRAY_SIZE(sa1111_devices); i++)
-               if (has_devs & (1 << i))
+               if (sa1111_devices[i].devid & has_devs)
                        sa1111_init_one_child(sachip, mem, &sa1111_devices[i]);
 
        return 0;
@@ -824,7 +815,10 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
 
 static int sa1111_remove_one(struct device *dev, void *data)
 {
-       device_unregister(dev);
+       struct sa1111_dev *sadev = SA1111_DEV(dev);
+       device_del(&sadev->dev);
+       release_resource(&sadev->res);
+       put_device(&sadev->dev);
        return 0;
 }
 
@@ -846,6 +840,7 @@ static void __sa1111_remove(struct sa1111 *sachip)
        if (sachip->irq != NO_IRQ) {
                irq_set_chained_handler(sachip->irq, NULL);
                irq_set_handler_data(sachip->irq, NULL);
+               irq_free_descs(sachip->irq_base, SA1111_IRQ_NR);
 
                release_mem_region(sachip->phys + SA1111_INTC, 512);
        }
@@ -904,6 +899,9 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
        save->skpwm0   = sa1111_readl(base + SA1111_SKPWM0);
        save->skpwm1   = sa1111_readl(base + SA1111_SKPWM1);
 
+       sa1111_writel(0, sachip->base + SA1111_SKPWM0);
+       sa1111_writel(0, sachip->base + SA1111_SKPWM1);
+
        base = sachip->base + SA1111_INTC;
        save->intpol0  = sa1111_readl(base + SA1111_INTPOL0);
        save->intpol1  = sa1111_readl(base + SA1111_INTPOL1);
@@ -919,13 +917,15 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
         */
        val = sa1111_readl(sachip->base + SA1111_SKCR);
        sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
-       sa1111_writel(0, sachip->base + SA1111_SKPWM0);
-       sa1111_writel(0, sachip->base + SA1111_SKPWM1);
 
        clk_disable(sachip->clk);
 
        spin_unlock_irqrestore(&sachip->lock, flags);
 
+#ifdef CONFIG_ARCH_SA1100
+       sa1110_mb_disable();
+#endif
+
        return 0;
 }
 
@@ -966,6 +966,11 @@ static int sa1111_resume(struct platform_device *dev)
         */
        sa1111_wake(sachip);
 
+#ifdef CONFIG_ARCH_SA1100
+       /* Enable the memory bus request/grant signals */
+       sa1110_mb_enable();
+#endif
+
        /*
         * Only lock for write ops. Also, sa1111_wake must be called with
         * released spinlock!
@@ -1053,6 +1058,7 @@ static struct platform_driver sa1111_device_driver = {
        .resume         = sa1111_resume,
        .driver         = {
                .name   = "sa1111",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -1238,16 +1244,23 @@ EXPORT_SYMBOL(sa1111_set_sleep_io);
  *     sa1111_enable_device - enable an on-chip SA1111 function block
  *     @sadev: SA1111 function block device to enable
  */
-void sa1111_enable_device(struct sa1111_dev *sadev)
+int sa1111_enable_device(struct sa1111_dev *sadev)
 {
        struct sa1111 *sachip = sa1111_chip_driver(sadev);
        unsigned long flags;
        unsigned int val;
+       int ret = 0;
 
-       spin_lock_irqsave(&sachip->lock, flags);
-       val = sa1111_readl(sachip->base + SA1111_SKPCR);
-       sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
-       spin_unlock_irqrestore(&sachip->lock, flags);
+       if (sachip->pdata && sachip->pdata->enable)
+               ret = sachip->pdata->enable(sachip->pdata->data, sadev->devid);
+
+       if (ret == 0) {
+               spin_lock_irqsave(&sachip->lock, flags);
+               val = sa1111_readl(sachip->base + SA1111_SKPCR);
+               sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
+               spin_unlock_irqrestore(&sachip->lock, flags);
+       }
+       return ret;
 }
 EXPORT_SYMBOL(sa1111_enable_device);
 
@@ -1265,6 +1278,9 @@ void sa1111_disable_device(struct sa1111_dev *sadev)
        val = sa1111_readl(sachip->base + SA1111_SKPCR);
        sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
        spin_unlock_irqrestore(&sachip->lock, flags);
+
+       if (sachip->pdata && sachip->pdata->disable)
+               sachip->pdata->disable(sachip->pdata->data, sadev->devid);
 }
 EXPORT_SYMBOL(sa1111_disable_device);
 
@@ -1279,7 +1295,7 @@ static int sa1111_match(struct device *_dev, struct device_driver *_drv)
        struct sa1111_dev *dev = SA1111_DEV(_dev);
        struct sa1111_driver *drv = SA1111_DRV(_drv);
 
-       return dev->devid == drv->devid;
+       return dev->devid & drv->devid;
 }
 
 static int sa1111_bus_suspend(struct device *dev, pm_message_t state)
@@ -1304,6 +1320,14 @@ static int sa1111_bus_resume(struct device *dev)
        return ret;
 }
 
+static void sa1111_bus_shutdown(struct device *dev)
+{
+       struct sa1111_driver *drv = SA1111_DRV(dev->driver);
+
+       if (drv && drv->shutdown)
+               drv->shutdown(SA1111_DEV(dev));
+}
+
 static int sa1111_bus_probe(struct device *dev)
 {
        struct sa1111_dev *sadev = SA1111_DEV(dev);
@@ -1333,6 +1357,7 @@ struct bus_type sa1111_bus_type = {
        .remove         = sa1111_bus_remove,
        .suspend        = sa1111_bus_suspend,
        .resume         = sa1111_bus_resume,
+       .shutdown       = sa1111_bus_shutdown,
 };
 EXPORT_SYMBOL(sa1111_bus_type);
 
@@ -1349,9 +1374,70 @@ void sa1111_driver_unregister(struct sa1111_driver *driver)
 }
 EXPORT_SYMBOL(sa1111_driver_unregister);
 
+#ifdef CONFIG_DMABOUNCE
+/*
+ * According to the "Intel StrongARM SA-1111 Microprocessor Companion
+ * Chip Specification Update" (June 2000), erratum #7, there is a
+ * significant bug in the SA1111 SDRAM shared memory controller.  If
+ * an access to a region of memory above 1MB relative to the bank base,
+ * it is important that address bit 10 _NOT_ be asserted. Depending
+ * on the configuration of the RAM, bit 10 may correspond to one
+ * of several different (processor-relative) address bits.
+ *
+ * This routine only identifies whether or not a given DMA address
+ * is susceptible to the bug.
+ *
+ * This should only get called for sa1111_device types due to the
+ * way we configure our device dma_masks.
+ */
+static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
+{
+       /*
+        * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
+        * User's Guide" mentions that jumpers R51 and R52 control the
+        * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
+        * SDRAM bank 1 on Neponset). The default configuration selects
+        * Assabet, so any address in bank 1 is necessarily invalid.
+        */
+       return (machine_is_assabet() || machine_is_pfs168()) &&
+               (addr >= 0xc8000000 || (addr + size) >= 0xc8000000);
+}
+
+static int sa1111_notifier_call(struct notifier_block *n, unsigned long action,
+       void *data)
+{
+       struct sa1111_dev *dev = SA1111_DEV(data);
+
+       switch (action) {
+       case BUS_NOTIFY_ADD_DEVICE:
+               if (dev->dev.dma_mask && dev->dma_mask < 0xffffffffUL) {
+                       int ret = dmabounce_register_dev(&dev->dev, 1024, 4096,
+                                       sa1111_needs_bounce);
+                       if (ret)
+                               dev_err(&dev->dev, "failed to register with dmabounce: %d\n", ret);
+               }
+               break;
+
+       case BUS_NOTIFY_DEL_DEVICE:
+               if (dev->dev.dma_mask && dev->dma_mask < 0xffffffffUL)
+                       dmabounce_unregister_dev(&dev->dev);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block sa1111_bus_notifier = {
+       .notifier_call = sa1111_notifier_call,
+};
+#endif
+
 static int __init sa1111_init(void)
 {
        int ret = bus_register(&sa1111_bus_type);
+#ifdef CONFIG_DMABOUNCE
+       if (ret == 0)
+               bus_register_notifier(&sa1111_bus_type, &sa1111_bus_notifier);
+#endif
        if (ret == 0)
                platform_driver_register(&sa1111_device_driver);
        return ret;
@@ -1360,6 +1446,9 @@ static int __init sa1111_init(void)
 static void __exit sa1111_exit(void)
 {
        platform_driver_unregister(&sa1111_device_driver);
+#ifdef CONFIG_DMABOUNCE
+       bus_unregister_notifier(&sa1111_bus_type, &sa1111_bus_notifier);
+#endif
        bus_unregister(&sa1111_bus_type);
 }
 
index 92ed254..7c2bbc7 100644 (file)
 #define SKPCR_DCLKEN   (1<<7)
 #define SKPCR_PWMCLKEN (1<<8)
 
-/*
- * USB Host controller
- */
+/* USB Host controller */
 #define SA1111_USB             0x0400
 
-/*
- * Offsets from SA1111_USB_BASE
- */
-#define SA1111_USB_STATUS      0x0118
-#define SA1111_USB_RESET       0x011c
-#define SA1111_USB_IRQTEST     0x0120
-
-#define USB_RESET_FORCEIFRESET (1 << 0)
-#define USB_RESET_FORCEHCRESET (1 << 1)
-#define USB_RESET_CLKGENRESET  (1 << 2)
-#define USB_RESET_SIMSCALEDOWN (1 << 3)
-#define USB_RESET_USBINTTEST   (1 << 4)
-#define USB_RESET_SLEEPSTBYEN  (1 << 5)
-#define USB_RESET_PWRSENSELOW  (1 << 6)
-#define USB_RESET_PWRCTRLLOW   (1 << 7)
-
-#define USB_STATUS_IRQHCIRMTWKUP  (1 <<  7)
-#define USB_STATUS_IRQHCIBUFFACC  (1 <<  8)
-#define USB_STATUS_NIRQHCIM       (1 <<  9)
-#define USB_STATUS_NHCIMFCLR      (1 << 10)
-#define USB_STATUS_USBPWRSENSE    (1 << 11)
-
 /*
  * Serial Audio Controller
  *
  *    PC_SSR           GPIO Block C Sleep State
  */
 
-#define _PA_DDR                _SA1111( 0x1000 )
-#define _PA_DRR                _SA1111( 0x1004 )
-#define _PA_DWR                _SA1111( 0x1004 )
-#define _PA_SDR                _SA1111( 0x1008 )
-#define _PA_SSR                _SA1111( 0x100c )
-#define _PB_DDR                _SA1111( 0x1010 )
-#define _PB_DRR                _SA1111( 0x1014 )
-#define _PB_DWR                _SA1111( 0x1014 )
-#define _PB_SDR                _SA1111( 0x1018 )
-#define _PB_SSR                _SA1111( 0x101c )
-#define _PC_DDR                _SA1111( 0x1020 )
-#define _PC_DRR                _SA1111( 0x1024 )
-#define _PC_DWR                _SA1111( 0x1024 )
-#define _PC_SDR                _SA1111( 0x1028 )
-#define _PC_SSR                _SA1111( 0x102c )
-
 #define SA1111_GPIO    0x1000
 
 #define SA1111_GPIO_PADDR      (0x000)
 #define SA1111_WAKEPOL0                0x0034
 #define SA1111_WAKEPOL1                0x0038
 
-/*
- * PS/2 Trackpad and Mouse Interfaces
- *
- * Registers
- *    PS2CR            Control Register
- *    PS2STAT          Status Register
- *    PS2DATA          Transmit/Receive Data register
- *    PS2CLKDIV                Clock Division Register
- *    PS2PRECNT                Clock Precount Register
- *    PS2TEST1         Test register 1
- *    PS2TEST2         Test register 2
- *    PS2TEST3         Test register 3
- *    PS2TEST4         Test register 4
- */
-
+/* PS/2 Trackpad and Mouse Interfaces */
 #define SA1111_KBD             0x0a00
 #define SA1111_MSE             0x0c00
 
-/*
- * These are offsets from the above bases.
- */
-#define SA1111_PS2CR           0x0000
-#define SA1111_PS2STAT         0x0004
-#define SA1111_PS2DATA         0x0008
-#define SA1111_PS2CLKDIV       0x000c
-#define SA1111_PS2PRECNT       0x0010
-
-#define PS2CR_ENA              0x08
-#define PS2CR_FKD              0x02
-#define PS2CR_FKC              0x01
-
-#define PS2STAT_STP            0x0100
-#define PS2STAT_TXE            0x0080
-#define PS2STAT_TXB            0x0040
-#define PS2STAT_RXF            0x0020
-#define PS2STAT_RXB            0x0010
-#define PS2STAT_ENA            0x0008
-#define PS2STAT_RXP            0x0004
-#define PS2STAT_KBD            0x0002
-#define PS2STAT_KBC            0x0001
+/* PCMCIA Interface */
+#define SA1111_PCMCIA          0x1600
 
-/*
- * PCMCIA Interface
- *
- * Registers
- *    PCSR     Status Register
- *    PCCR     Control Register
- *    PCSSR    Sleep State Register
- */
-
-#define SA1111_PCMCIA  0x1600
-
-/*
- * These are offsets from the above base.
- */
-#define SA1111_PCCR    0x0000
-#define SA1111_PCSSR   0x0004
-#define SA1111_PCSR    0x0008
-
-#define PCSR_S0_READY  (1<<0)
-#define PCSR_S1_READY  (1<<1)
-#define PCSR_S0_DETECT (1<<2)
-#define PCSR_S1_DETECT (1<<3)
-#define PCSR_S0_VS1    (1<<4)
-#define PCSR_S0_VS2    (1<<5)
-#define PCSR_S1_VS1    (1<<6)
-#define PCSR_S1_VS2    (1<<7)
-#define PCSR_S0_WP     (1<<8)
-#define PCSR_S1_WP     (1<<9)
-#define PCSR_S0_BVD1   (1<<10)
-#define PCSR_S0_BVD2   (1<<11)
-#define PCSR_S1_BVD1   (1<<12)
-#define PCSR_S1_BVD2   (1<<13)
-
-#define PCCR_S0_RST    (1<<0)
-#define PCCR_S1_RST    (1<<1)
-#define PCCR_S0_FLT    (1<<2)
-#define PCCR_S1_FLT    (1<<3)
-#define PCCR_S0_PWAITEN        (1<<4)
-#define PCCR_S1_PWAITEN        (1<<5)
-#define PCCR_S0_PSE    (1<<6)
-#define PCCR_S1_PSE    (1<<7)
-
-#define PCSSR_S0_SLEEP (1<<0)
-#define PCSSR_S1_SLEEP (1<<1)
 
 
 
 
 extern struct bus_type sa1111_bus_type;
 
-#define SA1111_DEVID_SBI       0
-#define SA1111_DEVID_SK                1
-#define SA1111_DEVID_USB       2
-#define SA1111_DEVID_SAC       3
-#define SA1111_DEVID_SSP       4
-#define SA1111_DEVID_PS2       5
-#define SA1111_DEVID_GPIO      6
-#define SA1111_DEVID_INT       7
-#define SA1111_DEVID_PCMCIA    8
+#define SA1111_DEVID_SBI       (1 << 0)
+#define SA1111_DEVID_SK                (1 << 1)
+#define SA1111_DEVID_USB       (1 << 2)
+#define SA1111_DEVID_SAC       (1 << 3)
+#define SA1111_DEVID_SSP       (1 << 4)
+#define SA1111_DEVID_PS2       (3 << 5)
+#define SA1111_DEVID_PS2_KBD   (1 << 5)
+#define SA1111_DEVID_PS2_MSE   (1 << 6)
+#define SA1111_DEVID_GPIO      (1 << 7)
+#define SA1111_DEVID_INT       (1 << 8)
+#define SA1111_DEVID_PCMCIA    (1 << 9)
 
 struct sa1111_dev {
        struct device   dev;
@@ -548,6 +432,7 @@ struct sa1111_driver {
        int (*remove)(struct sa1111_dev *);
        int (*suspend)(struct sa1111_dev *, pm_message_t);
        int (*resume)(struct sa1111_dev *);
+       void (*shutdown)(struct sa1111_dev *);
 };
 
 #define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv)
@@ -555,9 +440,10 @@ struct sa1111_driver {
 #define SA1111_DRIVER_NAME(_sadev) ((_sadev)->dev.driver->name)
 
 /*
- * These frob the SKPCR register.
+ * These frob the SKPCR register, and call platform specific
+ * enable/disable functions.
  */
-void sa1111_enable_device(struct sa1111_dev *);
+int sa1111_enable_device(struct sa1111_dev *);
 void sa1111_disable_device(struct sa1111_dev *);
 
 unsigned int sa1111_pll_clock(struct sa1111_dev *);
@@ -580,6 +466,10 @@ void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned i
 
 struct sa1111_platform_data {
        int     irq_base;       /* base for cascaded on-chip IRQs */
+       unsigned disable_devs;
+       void    *data;
+       int     (*enable)(void *, unsigned);
+       void    (*disable)(void *, unsigned);
 };
 
 #endif  /* _ASM_ARCH_SA1111 */
index 5d3ed7e..314d466 100644 (file)
@@ -198,7 +198,15 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
        unsigned long addr)
 {
        pgtable_page_dtor(pte);
-       tlb_add_flush(tlb, addr);
+
+       /*
+        * With the classic ARM MMU, a pte page has two corresponding pmd
+        * entries, each covering 1MB.
+        */
+       addr &= PMD_MASK;
+       tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE);
+       tlb_add_flush(tlb, addr + SZ_1M);
+
        tlb_remove_page(tlb, pte);
 }
 
index 43b740d..17663c6 100644 (file)
@@ -23,7 +23,6 @@ obj-$(CONFIG_LEDS)            += leds.o
 obj-$(CONFIG_OC_ETM)           += etm.o
 
 obj-$(CONFIG_ISA_DMA_API)      += dma.o
-obj-$(CONFIG_ARCH_ACORN)       += ecard.o 
 obj-$(CONFIG_FIQ)              += fiq.o fiqasm.o
 obj-$(CONFIG_MODULES)          += armksyms.o module.o
 obj-$(CONFIG_ARTHUR)           += arthur.o
index 3a456c6..be16a48 100644 (file)
@@ -790,7 +790,7 @@ __kuser_cmpxchg64:                          @ 0xffff0f60
        smp_dmb arm
        rsbs    r0, r3, #0                      @ set returned val and C flag
        ldmfd   sp!, {r4, r5, r6, r7}
-       bx      lr
+       usr_ret lr
 
 #elif !defined(CONFIG_SMP)
 
index 460bbbb..6933244 100644 (file)
@@ -469,6 +469,20 @@ static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                        [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
        },
+       [C(NODE)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
 };
 
 /*
@@ -579,6 +593,20 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                        [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
        },
+       [C(NODE)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
 };
 
 /*
index e1d5e19..e33870f 100644 (file)
@@ -699,10 +699,13 @@ static int vfp_set(struct task_struct *target,
 {
        int ret;
        struct thread_info *thread = task_thread_info(target);
-       struct vfp_hard_struct new_vfp = thread->vfpstate.hard;
+       struct vfp_hard_struct new_vfp;
        const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
        const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
 
+       vfp_sync_hwstate(thread);
+       new_vfp = thread->vfpstate.hard;
+
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                  &new_vfp.fpregs,
                                  user_fpregs_offset,
@@ -723,9 +726,8 @@ static int vfp_set(struct task_struct *target,
        if (ret)
                return ret;
 
-       vfp_sync_hwstate(thread);
-       thread->vfpstate.hard = new_vfp;
        vfp_flush_hwstate(thread);
+       thread->vfpstate.hard = new_vfp;
 
        return 0;
 }
index 0340224..9e617bd 100644 (file)
@@ -227,6 +227,8 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
        if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
                return -EINVAL;
 
+       vfp_flush_hwstate(thread);
+
        /*
         * Copy the floating point registers. There can be unused
         * registers see asm/hwcap.h for details.
@@ -251,9 +253,6 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
        __get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
        __get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
 
-       if (!err)
-               vfp_flush_hwstate(thread);
-
        return err ? -EFAULT : 0;
 }
 
index 9e5e755..45c97b1 100644 (file)
@@ -194,6 +194,6 @@ MACHINE_START(BCMRING, "BCMRING")
        .init_early = bcmring_init_early,
        .init_irq = bcmring_init_irq,
        .timer = &bcmring_timer,
-       .init_machine = bcmring_init_machine
+       .init_machine = bcmring_init_machine,
        .restart = bcmring_restart,
 MACHINE_END
index 1a1a27d..1024396 100644 (file)
 
 #include <mach/timer.h>
 
-#include <linux/mm.h>
 #include <linux/pfn.h>
 #include <linux/atomic.h>
 #include <linux/sched.h>
 #include <mach/dma.h>
 
-/* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
-/* especially since dc4 doesn't use kmalloc'd memory. */
-
-#define ALLOW_MAP_OF_KMALLOC_MEMORY 0
-
 /* ---- Public Variables ------------------------------------------------- */
 
 /* ---- Private Constants and Types -------------------------------------- */
 #define CONTROLLER_FROM_HANDLE(handle)    (((handle) >> 4) & 0x0f)
 #define CHANNEL_FROM_HANDLE(handle)       ((handle) & 0x0f)
 
-#define DMA_MAP_DEBUG   0
-
-#if DMA_MAP_DEBUG
-#   define  DMA_MAP_PRINT(fmt, args...)   printk("%s: " fmt, __func__,  ## args)
-#else
-#   define  DMA_MAP_PRINT(fmt, args...)
-#endif
 
 /* ---- Private Variables ------------------------------------------------ */
 
 static DMA_Global_t gDMA;
 static struct proc_dir_entry *gDmaDir;
 
-static atomic_t gDmaStatMemTypeKmalloc = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeVmalloc = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeUser = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0);
-
 #include "dma_device.c"
 
 /* ---- Private Function Prototypes -------------------------------------- */
 
 /* ---- Functions  ------------------------------------------------------- */
 
-/****************************************************************************/
-/**
-*   Displays information for /proc/dma/mem-type
-*/
-/****************************************************************************/
-
-static int dma_proc_read_mem_type(char *buf, char **start, off_t offset,
-                                 int count, int *eof, void *data)
-{
-       int len = 0;
-
-       len += sprintf(buf + len, "dma_map_mem statistics\n");
-       len +=
-           sprintf(buf + len, "coherent: %d\n",
-                   atomic_read(&gDmaStatMemTypeCoherent));
-       len +=
-           sprintf(buf + len, "kmalloc:  %d\n",
-                   atomic_read(&gDmaStatMemTypeKmalloc));
-       len +=
-           sprintf(buf + len, "vmalloc:  %d\n",
-                   atomic_read(&gDmaStatMemTypeVmalloc));
-       len +=
-           sprintf(buf + len, "user:     %d\n",
-                   atomic_read(&gDmaStatMemTypeUser));
-
-       return len;
-}
-
 /****************************************************************************/
 /**
 *   Displays information for /proc/dma/channels
@@ -846,8 +800,6 @@ int dma_init(void)
                                       dma_proc_read_channels, NULL);
                create_proc_read_entry("devices", 0, gDmaDir,
                                       dma_proc_read_devices, NULL);
-               create_proc_read_entry("mem-type", 0, gDmaDir,
-                                      dma_proc_read_mem_type, NULL);
        }
 
 out:
@@ -1565,767 +1517,3 @@ int dma_set_device_handler(DMA_Device_t dev,    /* Device to set the callback for.
 }
 
 EXPORT_SYMBOL(dma_set_device_handler);
-
-/****************************************************************************/
-/**
-*   Initializes a memory mapping structure
-*/
-/****************************************************************************/
-
-int dma_init_mem_map(DMA_MemMap_t *memMap)
-{
-       memset(memMap, 0, sizeof(*memMap));
-
-       sema_init(&memMap->lock, 1);
-
-       return 0;
-}
-
-EXPORT_SYMBOL(dma_init_mem_map);
-
-/****************************************************************************/
-/**
-*   Releases any memory currently being held by a memory mapping structure.
-*/
-/****************************************************************************/
-
-int dma_term_mem_map(DMA_MemMap_t *memMap)
-{
-       down(&memMap->lock);    /* Just being paranoid */
-
-       /* Free up any allocated memory */
-
-       up(&memMap->lock);
-       memset(memMap, 0, sizeof(*memMap));
-
-       return 0;
-}
-
-EXPORT_SYMBOL(dma_term_mem_map);
-
-/****************************************************************************/
-/**
-*   Looks at a memory address and categorizes it.
-*
-*   @return One of the values from the DMA_MemType_t enumeration.
-*/
-/****************************************************************************/
-
-DMA_MemType_t dma_mem_type(void *addr)
-{
-       unsigned long addrVal = (unsigned long)addr;
-
-       if (addrVal >= CONSISTENT_BASE) {
-               /* NOTE: DMA virtual memory space starts at 0xFFxxxxxx */
-
-               /* dma_alloc_xxx pages are physically and virtually contiguous */
-
-               return DMA_MEM_TYPE_DMA;
-       }
-
-       /* Technically, we could add one more classification. Addresses between VMALLOC_END */
-       /* and the beginning of the DMA virtual address could be considered to be I/O space. */
-       /* Right now, nobody cares about this particular classification, so we ignore it. */
-
-       if (is_vmalloc_addr(addr)) {
-               /* Address comes from the vmalloc'd region. Pages are virtually */
-               /* contiguous but NOT physically contiguous */
-
-               return DMA_MEM_TYPE_VMALLOC;
-       }
-
-       if (addrVal >= PAGE_OFFSET) {
-               /* PAGE_OFFSET is typically 0xC0000000 */
-
-               /* kmalloc'd pages are physically contiguous */
-
-               return DMA_MEM_TYPE_KMALLOC;
-       }
-
-       return DMA_MEM_TYPE_USER;
-}
-
-EXPORT_SYMBOL(dma_mem_type);
-
-/****************************************************************************/
-/**
-*   Looks at a memory address and determines if we support DMA'ing to/from
-*   that type of memory.
-*
-*   @return boolean -
-*               return value != 0 means dma supported
-*               return value == 0 means dma not supported
-*/
-/****************************************************************************/
-
-int dma_mem_supports_dma(void *addr)
-{
-       DMA_MemType_t memType = dma_mem_type(addr);
-
-       return (memType == DMA_MEM_TYPE_DMA)
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
-           || (memType == DMA_MEM_TYPE_KMALLOC)
-#endif
-           || (memType == DMA_MEM_TYPE_USER);
-}
-
-EXPORT_SYMBOL(dma_mem_supports_dma);
-
-/****************************************************************************/
-/**
-*   Maps in a memory region such that it can be used for performing a DMA.
-*
-*   @return
-*/
-/****************************************************************************/
-
-int dma_map_start(DMA_MemMap_t *memMap,        /* Stores state information about the map */
-                 enum dma_data_direction dir   /* Direction that the mapping will be going */
-    ) {
-       int rc;
-
-       down(&memMap->lock);
-
-       DMA_MAP_PRINT("memMap: %p\n", memMap);
-
-       if (memMap->inUse) {
-               printk(KERN_ERR "%s: memory map %p is already being used\n",
-                      __func__, memMap);
-               rc = -EBUSY;
-               goto out;
-       }
-
-       memMap->inUse = 1;
-       memMap->dir = dir;
-       memMap->numRegionsUsed = 0;
-
-       rc = 0;
-
-out:
-
-       DMA_MAP_PRINT("returning %d", rc);
-
-       up(&memMap->lock);
-
-       return rc;
-}
-
-EXPORT_SYMBOL(dma_map_start);
-
-/****************************************************************************/
-/**
-*   Adds a segment of memory to a memory map. Each segment is both
-*   physically and virtually contiguous.
-*
-*   @return     0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-static int dma_map_add_segment(DMA_MemMap_t *memMap,   /* Stores state information about the map */
-                              DMA_Region_t *region,    /* Region that the segment belongs to */
-                              void *virtAddr,  /* Virtual address of the segment being added */
-                              dma_addr_t physAddr,     /* Physical address of the segment being added */
-                              size_t numBytes  /* Number of bytes of the segment being added */
-    ) {
-       DMA_Segment_t *segment;
-
-       DMA_MAP_PRINT("memMap:%p va:%p pa:0x%x #:%d\n", memMap, virtAddr,
-                     physAddr, numBytes);
-
-       /* Sanity check */
-
-       if (((unsigned long)virtAddr < (unsigned long)region->virtAddr)
-           || (((unsigned long)virtAddr + numBytes)) >
-           ((unsigned long)region->virtAddr + region->numBytes)) {
-               printk(KERN_ERR
-                      "%s: virtAddr %p is outside region @ %p len: %d\n",
-                      __func__, virtAddr, region->virtAddr, region->numBytes);
-               return -EINVAL;
-       }
-
-       if (region->numSegmentsUsed > 0) {
-               /* Check to see if this segment is physically contiguous with the previous one */
-
-               segment = &region->segment[region->numSegmentsUsed - 1];
-
-               if ((segment->physAddr + segment->numBytes) == physAddr) {
-                       /* It is - just add on to the end */
-
-                       DMA_MAP_PRINT("appending %d bytes to last segment\n",
-                                     numBytes);
-
-                       segment->numBytes += numBytes;
-
-                       return 0;
-               }
-       }
-
-       /* Reallocate to hold more segments, if required. */
-
-       if (region->numSegmentsUsed >= region->numSegmentsAllocated) {
-               DMA_Segment_t *newSegment;
-               size_t oldSize =
-                   region->numSegmentsAllocated * sizeof(*newSegment);
-               int newAlloc = region->numSegmentsAllocated + 4;
-               size_t newSize = newAlloc * sizeof(*newSegment);
-
-               newSegment = kmalloc(newSize, GFP_KERNEL);
-               if (newSegment == NULL) {
-                       return -ENOMEM;
-               }
-               memcpy(newSegment, region->segment, oldSize);
-               memset(&((uint8_t *) newSegment)[oldSize], 0,
-                      newSize - oldSize);
-               kfree(region->segment);
-
-               region->numSegmentsAllocated = newAlloc;
-               region->segment = newSegment;
-       }
-
-       segment = &region->segment[region->numSegmentsUsed];
-       region->numSegmentsUsed++;
-
-       segment->virtAddr = virtAddr;
-       segment->physAddr = physAddr;
-       segment->numBytes = numBytes;
-
-       DMA_MAP_PRINT("returning success\n");
-
-       return 0;
-}
-
-/****************************************************************************/
-/**
-*   Adds a region of memory to a memory map. Each region is virtually
-*   contiguous, but not necessarily physically contiguous.
-*
-*   @return     0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_add_region(DMA_MemMap_t *memMap,   /* Stores state information about the map */
-                      void *mem,       /* Virtual address that we want to get a map of */
-                      size_t numBytes  /* Number of bytes being mapped */
-    ) {
-       unsigned long addr = (unsigned long)mem;
-       unsigned int offset;
-       int rc = 0;
-       DMA_Region_t *region;
-       dma_addr_t physAddr;
-
-       down(&memMap->lock);
-
-       DMA_MAP_PRINT("memMap:%p va:%p #:%d\n", memMap, mem, numBytes);
-
-       if (!memMap->inUse) {
-               printk(KERN_ERR "%s: Make sure you call dma_map_start first\n",
-                      __func__);
-               rc = -EINVAL;
-               goto out;
-       }
-
-       /* Reallocate to hold more regions. */
-
-       if (memMap->numRegionsUsed >= memMap->numRegionsAllocated) {
-               DMA_Region_t *newRegion;
-               size_t oldSize =
-                   memMap->numRegionsAllocated * sizeof(*newRegion);
-               int newAlloc = memMap->numRegionsAllocated + 4;
-               size_t newSize = newAlloc * sizeof(*newRegion);
-
-               newRegion = kmalloc(newSize, GFP_KERNEL);
-               if (newRegion == NULL) {
-                       rc = -ENOMEM;
-                       goto out;
-               }
-               memcpy(newRegion, memMap->region, oldSize);
-               memset(&((uint8_t *) newRegion)[oldSize], 0, newSize - oldSize);
-
-               kfree(memMap->region);
-
-               memMap->numRegionsAllocated = newAlloc;
-               memMap->region = newRegion;
-       }
-
-       region = &memMap->region[memMap->numRegionsUsed];
-       memMap->numRegionsUsed++;
-
-       offset = addr & ~PAGE_MASK;
-
-       region->memType = dma_mem_type(mem);
-       region->virtAddr = mem;
-       region->numBytes = numBytes;
-       region->numSegmentsUsed = 0;
-       region->numLockedPages = 0;
-       region->lockedPages = NULL;
-
-       switch (region->memType) {
-       case DMA_MEM_TYPE_VMALLOC:
-               {
-                       atomic_inc(&gDmaStatMemTypeVmalloc);
-
-                       /* printk(KERN_ERR "%s: vmalloc'd pages are not supported\n", __func__); */
-
-                       /* vmalloc'd pages are not physically contiguous */
-
-                       rc = -EINVAL;
-                       break;
-               }
-
-       case DMA_MEM_TYPE_KMALLOC:
-               {
-                       atomic_inc(&gDmaStatMemTypeKmalloc);
-
-                       /* kmalloc'd pages are physically contiguous, so they'll have exactly */
-                       /* one segment */
-
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
-                       physAddr =
-                           dma_map_single(NULL, mem, numBytes, memMap->dir);
-                       rc = dma_map_add_segment(memMap, region, mem, physAddr,
-                                                numBytes);
-#else
-                       rc = -EINVAL;
-#endif
-                       break;
-               }
-
-       case DMA_MEM_TYPE_DMA:
-               {
-                       /* dma_alloc_xxx pages are physically contiguous */
-
-                       atomic_inc(&gDmaStatMemTypeCoherent);
-
-                       physAddr = (vmalloc_to_pfn(mem) << PAGE_SHIFT) + offset;
-
-                       dma_sync_single_for_cpu(NULL, physAddr, numBytes,
-                                               memMap->dir);
-                       rc = dma_map_add_segment(memMap, region, mem, physAddr,
-                                                numBytes);
-                       break;
-               }
-
-       case DMA_MEM_TYPE_USER:
-               {
-                       size_t firstPageOffset;
-                       size_t firstPageSize;
-                       struct page **pages;
-                       struct task_struct *userTask;
-
-                       atomic_inc(&gDmaStatMemTypeUser);
-
-#if 1
-                       /* If the pages are user pages, then the dma_mem_map_set_user_task function */
-                       /* must have been previously called. */
-
-                       if (memMap->userTask == NULL) {
-                               printk(KERN_ERR
-                                      "%s: must call dma_mem_map_set_user_task when using user-mode memory\n",
-                                      __func__);
-                               return -EINVAL;
-                       }
-
-                       /* User pages need to be locked. */
-
-                       firstPageOffset =
-                           (unsigned long)region->virtAddr & (PAGE_SIZE - 1);
-                       firstPageSize = PAGE_SIZE - firstPageOffset;
-
-                       region->numLockedPages = (firstPageOffset
-                                                 + region->numBytes +
-                                                 PAGE_SIZE - 1) / PAGE_SIZE;
-                       pages =
-                           kmalloc(region->numLockedPages *
-                                   sizeof(struct page *), GFP_KERNEL);
-
-                       if (pages == NULL) {
-                               region->numLockedPages = 0;
-                               return -ENOMEM;
-                       }
-
-                       userTask = memMap->userTask;
-
-                       down_read(&userTask->mm->mmap_sem);
-                       rc = get_user_pages(userTask,   /* task */
-                                           userTask->mm,       /* mm */
-                                           (unsigned long)region->virtAddr,    /* start */
-                                           region->numLockedPages,     /* len */
-                                           memMap->dir == DMA_FROM_DEVICE,     /* write */
-                                           0,  /* force */
-                                           pages,      /* pages (array of pointers to page) */
-                                           NULL);      /* vmas */
-                       up_read(&userTask->mm->mmap_sem);
-
-                       if (rc != region->numLockedPages) {
-                               kfree(pages);
-                               region->numLockedPages = 0;
-
-                               if (rc >= 0) {
-                                       rc = -EINVAL;
-                               }
-                       } else {
-                               uint8_t *virtAddr = region->virtAddr;
-                               size_t bytesRemaining;
-                               int pageIdx;
-
-                               rc = 0; /* Since get_user_pages returns +ve number */
-
-                               region->lockedPages = pages;
-
-                               /* We've locked the user pages. Now we need to walk them and figure */
-                               /* out the physical addresses. */
-
-                               /* The first page may be partial */
-
-                               dma_map_add_segment(memMap,
-                                                   region,
-                                                   virtAddr,
-                                                   PFN_PHYS(page_to_pfn
-                                                            (pages[0])) +
-                                                   firstPageOffset,
-                                                   firstPageSize);
-
-                               virtAddr += firstPageSize;
-                               bytesRemaining =
-                                   region->numBytes - firstPageSize;
-
-                               for (pageIdx = 1;
-                                    pageIdx < region->numLockedPages;
-                                    pageIdx++) {
-                                       size_t bytesThisPage =
-                                           (bytesRemaining >
-                                            PAGE_SIZE ? PAGE_SIZE :
-                                            bytesRemaining);
-
-                                       DMA_MAP_PRINT
-                                           ("pageIdx:%d pages[pageIdx]=%p pfn=%u phys=%u\n",
-                                            pageIdx, pages[pageIdx],
-                                            page_to_pfn(pages[pageIdx]),
-                                            PFN_PHYS(page_to_pfn
-                                                     (pages[pageIdx])));
-
-                                       dma_map_add_segment(memMap,
-                                                           region,
-                                                           virtAddr,
-                                                           PFN_PHYS(page_to_pfn
-                                                                    (pages
-                                                                     [pageIdx])),
-                                                           bytesThisPage);
-
-                                       virtAddr += bytesThisPage;
-                                       bytesRemaining -= bytesThisPage;
-                               }
-                       }
-#else
-                       printk(KERN_ERR
-                              "%s: User mode pages are not yet supported\n",
-                              __func__);
-
-                       /* user pages are not physically contiguous */
-
-                       rc = -EINVAL;
-#endif
-                       break;
-               }
-
-       default:
-               {
-                       printk(KERN_ERR "%s: Unsupported memory type: %d\n",
-                              __func__, region->memType);
-
-                       rc = -EINVAL;
-                       break;
-               }
-       }
-
-       if (rc != 0) {
-               memMap->numRegionsUsed--;
-       }
-
-out:
-
-       DMA_MAP_PRINT("returning %d\n", rc);
-
-       up(&memMap->lock);
-
-       return rc;
-}
-
-EXPORT_SYMBOL(dma_map_add_segment);
-
-/****************************************************************************/
-/**
-*   Maps in a memory region such that it can be used for performing a DMA.
-*
-*   @return     0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_mem(DMA_MemMap_t *memMap,  /* Stores state information about the map */
-               void *mem,      /* Virtual address that we want to get a map of */
-               size_t numBytes,        /* Number of bytes being mapped */
-               enum dma_data_direction dir     /* Direction that the mapping will be going */
-    ) {
-       int rc;
-
-       rc = dma_map_start(memMap, dir);
-       if (rc == 0) {
-               rc = dma_map_add_region(memMap, mem, numBytes);
-               if (rc < 0) {
-                       /* Since the add fails, this function will fail, and the caller won't */
-                       /* call unmap, so we need to do it here. */
-
-                       dma_unmap(memMap, 0);
-               }
-       }
-
-       return rc;
-}
-
-EXPORT_SYMBOL(dma_map_mem);
-
-/****************************************************************************/
-/**
-*   Setup a descriptor ring for a given memory map.
-*
-*   It is assumed that the descriptor ring has already been initialized, and
-*   this routine will only reallocate a new descriptor ring if the existing
-*   one is too small.
-*
-*   @return     0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_create_descriptor_ring(DMA_Device_t dev,   /* DMA device (where the ring is stored) */
-                                  DMA_MemMap_t *memMap,        /* Memory map that will be used */
-                                  dma_addr_t devPhysAddr       /* Physical address of device */
-    ) {
-       int rc;
-       int numDescriptors;
-       DMA_DeviceAttribute_t *devAttr;
-       DMA_Region_t *region;
-       DMA_Segment_t *segment;
-       dma_addr_t srcPhysAddr;
-       dma_addr_t dstPhysAddr;
-       int regionIdx;
-       int segmentIdx;
-
-       devAttr = &DMA_gDeviceAttribute[dev];
-
-       down(&memMap->lock);
-
-       /* Figure out how many descriptors we need */
-
-       numDescriptors = 0;
-       for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
-               region = &memMap->region[regionIdx];
-
-               for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
-                    segmentIdx++) {
-                       segment = &region->segment[segmentIdx];
-
-                       if (memMap->dir == DMA_TO_DEVICE) {
-                               srcPhysAddr = segment->physAddr;
-                               dstPhysAddr = devPhysAddr;
-                       } else {
-                               srcPhysAddr = devPhysAddr;
-                               dstPhysAddr = segment->physAddr;
-                       }
-
-                       rc =
-                            dma_calculate_descriptor_count(dev, srcPhysAddr,
-                                                           dstPhysAddr,
-                                                           segment->
-                                                           numBytes);
-                       if (rc < 0) {
-                               printk(KERN_ERR
-                                      "%s: dma_calculate_descriptor_count failed: %d\n",
-                                      __func__, rc);
-                               goto out;
-                       }
-                       numDescriptors += rc;
-               }
-       }
-
-       /* Adjust the size of the ring, if it isn't big enough */
-
-       if (numDescriptors > devAttr->ring.descriptorsAllocated) {
-               dma_free_descriptor_ring(&devAttr->ring);
-               rc =
-                    dma_alloc_descriptor_ring(&devAttr->ring,
-                                              numDescriptors);
-               if (rc < 0) {
-                       printk(KERN_ERR
-                              "%s: dma_alloc_descriptor_ring failed: %d\n",
-                              __func__, rc);
-                       goto out;
-               }
-       } else {
-               rc =
-                    dma_init_descriptor_ring(&devAttr->ring,
-                                             numDescriptors);
-               if (rc < 0) {
-                       printk(KERN_ERR
-                              "%s: dma_init_descriptor_ring failed: %d\n",
-                              __func__, rc);
-                       goto out;
-               }
-       }
-
-       /* Populate the descriptors */
-
-       for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
-               region = &memMap->region[regionIdx];
-
-               for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
-                    segmentIdx++) {
-                       segment = &region->segment[segmentIdx];
-
-                       if (memMap->dir == DMA_TO_DEVICE) {
-                               srcPhysAddr = segment->physAddr;
-                               dstPhysAddr = devPhysAddr;
-                       } else {
-                               srcPhysAddr = devPhysAddr;
-                               dstPhysAddr = segment->physAddr;
-                       }
-
-                       rc =
-                            dma_add_descriptors(&devAttr->ring, dev,
-                                                srcPhysAddr, dstPhysAddr,
-                                                segment->numBytes);
-                       if (rc < 0) {
-                               printk(KERN_ERR
-                                      "%s: dma_add_descriptors failed: %d\n",
-                                      __func__, rc);
-                               goto out;
-                       }
-               }
-       }
-
-       rc = 0;
-
-out:
-
-       up(&memMap->lock);
-       return rc;
-}
-
-EXPORT_SYMBOL(dma_map_create_descriptor_ring);
-
-/****************************************************************************/
-/**
-*   Maps in a memory region such that it can be used for performing a DMA.
-*
-*   @return
-*/
-/****************************************************************************/
-
-int dma_unmap(DMA_MemMap_t *memMap,    /* Stores state information about the map */
-             int dirtied       /* non-zero if any of the pages were modified */
-    ) {
-
-       int rc = 0;
-       int regionIdx;
-       int segmentIdx;
-       DMA_Region_t *region;
-       DMA_Segment_t *segment;
-
-       down(&memMap->lock);
-
-       for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
-               region = &memMap->region[regionIdx];
-
-               for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
-                    segmentIdx++) {
-                       segment = &region->segment[segmentIdx];
-
-                       switch (region->memType) {
-                       case DMA_MEM_TYPE_VMALLOC:
-                               {
-                                       printk(KERN_ERR
-                                              "%s: vmalloc'd pages are not yet supported\n",
-                                              __func__);
-                                       rc = -EINVAL;
-                                       goto out;
-                               }
-
-                       case DMA_MEM_TYPE_KMALLOC:
-                               {
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
-                                       dma_unmap_single(NULL,
-                                                        segment->physAddr,
-                                                        segment->numBytes,
-                                                        memMap->dir);
-#endif
-                                       break;
-                               }
-
-                       case DMA_MEM_TYPE_DMA:
-                               {
-                                       dma_sync_single_for_cpu(NULL,
-                                                               segment->
-                                                               physAddr,
-                                                               segment->
-                                                               numBytes,
-                                                               memMap->dir);
-                                       break;
-                               }
-
-                       case DMA_MEM_TYPE_USER:
-                               {
-                                       /* Nothing to do here. */
-
-                                       break;
-                               }
-
-                       default:
-                               {
-                                       printk(KERN_ERR
-                                              "%s: Unsupported memory type: %d\n",
-                                              __func__, region->memType);
-                                       rc = -EINVAL;
-                                       goto out;
-                               }
-                       }
-
-                       segment->virtAddr = NULL;
-                       segment->physAddr = 0;
-                       segment->numBytes = 0;
-               }
-
-               if (region->numLockedPages > 0) {
-                       int pageIdx;
-
-                       /* Some user pages were locked. We need to go and unlock them now. */
-
-                       for (pageIdx = 0; pageIdx < region->numLockedPages;
-                            pageIdx++) {
-                               struct page *page =
-                                   region->lockedPages[pageIdx];
-
-                               if (memMap->dir == DMA_FROM_DEVICE) {
-                                       SetPageDirty(page);
-                               }
-                               page_cache_release(page);
-                       }
-                       kfree(region->lockedPages);
-                       region->numLockedPages = 0;
-                       region->lockedPages = NULL;
-               }
-
-               region->memType = DMA_MEM_TYPE_NONE;
-               region->virtAddr = NULL;
-               region->numBytes = 0;
-               region->numSegmentsUsed = 0;
-       }
-       memMap->userTask = NULL;
-       memMap->numRegionsUsed = 0;
-       memMap->inUse = 0;
-
-out:
-       up(&memMap->lock);
-
-       return rc;
-}
-
-EXPORT_SYMBOL(dma_unmap);
index 1f2c531..7254378 100644 (file)
 /* ---- Include Files ---------------------------------------------------- */
 
 #include <linux/kernel.h>
-#include <linux/wait.h>
 #include <linux/semaphore.h>
 #include <csp/dmacHw.h>
 #include <mach/timer.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
 
 /* ---- Constants and Types ---------------------------------------------- */
 
@@ -111,78 +105,6 @@ typedef struct {
 
 } DMA_DescriptorRing_t;
 
-/****************************************************************************
-*
-*   The DMA_MemType_t and DMA_MemMap_t are helper structures used to setup
-*   DMA chains from a variety of memory sources.
-*
-*****************************************************************************/
-
-#define DMA_MEM_MAP_MIN_SIZE    4096   /* Pages less than this size are better */
-                                       /* off not being DMA'd. */
-
-typedef enum {
-       DMA_MEM_TYPE_NONE,      /* Not a valid setting */
-       DMA_MEM_TYPE_VMALLOC,   /* Memory came from vmalloc call */
-       DMA_MEM_TYPE_KMALLOC,   /* Memory came from kmalloc call */
-       DMA_MEM_TYPE_DMA,       /* Memory came from dma_alloc_xxx call */
-       DMA_MEM_TYPE_USER,      /* Memory came from user space. */
-
-} DMA_MemType_t;
-
-/* A segment represents a physically and virtually contiguous chunk of memory. */
-/* i.e. each segment can be DMA'd */
-/* A user of the DMA code will add memory regions. Each region may need to be */
-/* represented by one or more segments. */
-
-typedef struct {
-       void *virtAddr;         /* Virtual address used for this segment */
-       dma_addr_t physAddr;    /* Physical address this segment maps to */
-       size_t numBytes;        /* Size of the segment, in bytes */
-
-} DMA_Segment_t;
-
-/* A region represents a virtually contiguous chunk of memory, which may be */
-/* made up of multiple segments. */
-
-typedef struct {
-       DMA_MemType_t memType;
-       void *virtAddr;
-       size_t numBytes;
-
-       /* Each region (virtually contiguous) consists of one or more segments. Each */
-       /* segment is virtually and physically contiguous. */
-
-       int numSegmentsUsed;
-       int numSegmentsAllocated;
-       DMA_Segment_t *segment;
-
-       /* When a region corresponds to user memory, we need to lock all of the pages */
-       /* down before we can figure out the physical addresses. The lockedPage array contains */
-       /* the pages that were locked, and which subsequently need to be unlocked once the */
-       /* memory is unmapped. */
-
-       unsigned numLockedPages;
-       struct page **lockedPages;
-
-} DMA_Region_t;
-
-typedef struct {
-       int inUse;              /* Is this mapping currently being used? */
-       struct semaphore lock;  /* Acquired when using this structure */
-       enum dma_data_direction dir;    /* Direction this transfer is intended for */
-
-       /* In the event that we're mapping user memory, we need to know which task */
-       /* the memory is for, so that we can obtain the correct mm locks. */
-
-       struct task_struct *userTask;
-
-       int numRegionsUsed;
-       int numRegionsAllocated;
-       DMA_Region_t *region;
-
-} DMA_MemMap_t;
-
 /****************************************************************************
 *
 *   The DMA_DeviceAttribute_t contains information which describes a
@@ -568,124 +490,6 @@ int dma_alloc_double_dst_descriptors(DMA_Handle_t handle, /* DMA Handle */
                                     size_t numBytes    /* Number of bytes in each destination buffer */
     );
 
-/****************************************************************************/
-/**
-*   Initializes a DMA_MemMap_t data structure
-*/
-/****************************************************************************/
-
-int dma_init_mem_map(DMA_MemMap_t *memMap      /* Stores state information about the map */
-    );
-
-/****************************************************************************/
-/**
-*   Releases any memory currently being held by a memory mapping structure.
-*/
-/****************************************************************************/
-
-int dma_term_mem_map(DMA_MemMap_t *memMap      /* Stores state information about the map */
-    );
-
-/****************************************************************************/
-/**
-*   Looks at a memory address and categorizes it.
-*
-*   @return One of the values from the DMA_MemType_t enumeration.
-*/
-/****************************************************************************/
-
-DMA_MemType_t dma_mem_type(void *addr);
-
-/****************************************************************************/
-/**
-*   Sets the process (aka userTask) associated with a mem map. This is
-*   required if user-mode segments will be added to the mapping.
-*/
-/****************************************************************************/
-
-static inline void dma_mem_map_set_user_task(DMA_MemMap_t *memMap,
-                                            struct task_struct *task)
-{
-       memMap->userTask = task;
-}
-
-/****************************************************************************/
-/**
-*   Looks at a memory address and determines if we support DMA'ing to/from
-*   that type of memory.
-*
-*   @return boolean -
-*               return value != 0 means dma supported
-*               return value == 0 means dma not supported
-*/
-/****************************************************************************/
-
-int dma_mem_supports_dma(void *addr);
-
-/****************************************************************************/
-/**
-*   Initializes a memory map for use. Since this function acquires a
-*   sempaphore within the memory map, it is VERY important that dma_unmap
-*   be called when you're finished using the map.
-*/
-/****************************************************************************/
-
-int dma_map_start(DMA_MemMap_t *memMap,        /* Stores state information about the map */
-                 enum dma_data_direction dir   /* Direction that the mapping will be going */
-    );
-
-/****************************************************************************/
-/**
-*   Adds a segment of memory to a memory map.
-*
-*   @return     0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_add_region(DMA_MemMap_t *memMap,   /* Stores state information about the map */
-                      void *mem,       /* Virtual address that we want to get a map of */
-                      size_t numBytes  /* Number of bytes being mapped */
-    );
-
-/****************************************************************************/
-/**
-*   Creates a descriptor ring from a memory mapping.
-*
-*   @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_create_descriptor_ring(DMA_Device_t dev,   /* DMA device (where the ring is stored) */
-                                  DMA_MemMap_t *memMap,        /* Memory map that will be used */
-                                  dma_addr_t devPhysAddr       /* Physical address of device */
-    );
-
-/****************************************************************************/
-/**
-*   Maps in a memory region such that it can be used for performing a DMA.
-*
-*   @return
-*/
-/****************************************************************************/
-
-int dma_map_mem(DMA_MemMap_t *memMap,  /* Stores state information about the map */
-               void *addr,     /* Virtual address that we want to get a map of */
-               size_t count,   /* Number of bytes being mapped */
-               enum dma_data_direction dir     /* Direction that the mapping will be going */
-    );
-
-/****************************************************************************/
-/**
-*   Maps in a memory region such that it can be used for performing a DMA.
-*
-*   @return
-*/
-/****************************************************************************/
-
-int dma_unmap(DMA_MemMap_t *memMap,    /* Stores state information about the map */
-             int dirtied       /* non-zero if any of the pages were modified */
-    );
-
 /****************************************************************************/
 /**
 *   Initiates a transfer when the descriptors have already been setup.
index 6b22b54..d508890 100644 (file)
@@ -44,7 +44,7 @@
 #include <mach/aemif.h>
 #include <mach/spi.h>
 
-#define DA850_EVM_PHY_ID               "0:00"
+#define DA850_EVM_PHY_ID               "davinci_mdio-0:00"
 #define DA850_LCD_PWR_PIN              GPIO_TO_PIN(2, 8)
 #define DA850_LCD_BL_PIN               GPIO_TO_PIN(2, 15)
 
index 346e1de..849311d 100644 (file)
@@ -54,7 +54,7 @@ static inline int have_tvp7002(void)
        return 0;
 }
 
-#define DM365_EVM_PHY_ID               "0:01"
+#define DM365_EVM_PHY_ID               "davinci_mdio-0:01"
 /*
  * A MAX-II CPLD is used for various board control functions.
  */
index a64b49c..1247ecd 100644 (file)
@@ -40,7 +40,7 @@
 #include <mach/usb.h>
 #include <mach/aemif.h>
 
-#define DM644X_EVM_PHY_ID              "0:01"
+#define DM644X_EVM_PHY_ID              "davinci_mdio-0:01"
 #define LXT971_PHY_ID  (0x001378e2)
 #define LXT971_PHY_MASK        (0xfffffff0)
 
index 6401755..872ac69 100644 (file)
@@ -736,7 +736,7 @@ static struct davinci_uart_config uart_config __initdata = {
        .enabled_uarts = (1 << 0),
 };
 
-#define DM646X_EVM_PHY_ID              "0:01"
+#define DM646X_EVM_PHY_ID              "davinci_mdio-0:01"
 /*
  * The following EDMA channels/slots are not being used by drivers (for
  * example: Timer, GPIO, UART events etc) on dm646x, hence they are being
index 6c4a164..8d34f51 100644 (file)
@@ -39,7 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/usb.h>
 
-#define NEUROS_OSD2_PHY_ID             "0:01"
+#define NEUROS_OSD2_PHY_ID             "davinci_mdio-0:01"
 #define LXT971_PHY_ID                  0x001378e2
 #define LXT971_PHY_MASK                        0xfffffff0
 
index e7c0c7c..45e8157 100644 (file)
@@ -21,7 +21,7 @@
 #include <mach/da8xx.h>
 #include <mach/mux.h>
 
-#define HAWKBOARD_PHY_ID               "0:07"
+#define HAWKBOARD_PHY_ID               "davinci_mdio-0:07"
 #define DA850_HAWK_MMCSD_CD_PIN                GPIO_TO_PIN(3, 12)
 #define DA850_HAWK_MMCSD_WP_PIN                GPIO_TO_PIN(3, 13)
 
index 0b136a8..31da3c5 100644 (file)
@@ -42,7 +42,7 @@
 #include <mach/mux.h>
 #include <mach/usb.h>
 
-#define SFFSDR_PHY_ID          "0:01"
+#define SFFSDR_PHY_ID          "davinci_mdio-0:01"
 static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
        /* U-Boot Environment: Block 0
         * UBL:                Block 1
index 0ed7fdb..992c4c4 100644 (file)
@@ -153,34 +153,6 @@ static struct clk pll1_sysclk3 = {
        .div_reg        = PLLDIV3,
 };
 
-static struct clk pll1_sysclk4 = {
-       .name           = "pll1_sysclk4",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV4,
-};
-
-static struct clk pll1_sysclk5 = {
-       .name           = "pll1_sysclk5",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV5,
-};
-
-static struct clk pll1_sysclk6 = {
-       .name           = "pll0_sysclk6",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV6,
-};
-
-static struct clk pll1_sysclk7 = {
-       .name           = "pll1_sysclk7",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV7,
-};
-
 static struct clk i2c0_clk = {
        .name           = "i2c0",
        .parent         = &pll0_aux_clk,
@@ -397,10 +369,6 @@ static struct clk_lookup da850_clks[] = {
        CLK(NULL,               "pll1_aux",     &pll1_aux_clk),
        CLK(NULL,               "pll1_sysclk2", &pll1_sysclk2),
        CLK(NULL,               "pll1_sysclk3", &pll1_sysclk3),
-       CLK(NULL,               "pll1_sysclk4", &pll1_sysclk4),
-       CLK(NULL,               "pll1_sysclk5", &pll1_sysclk5),
-       CLK(NULL,               "pll1_sysclk6", &pll1_sysclk6),
-       CLK(NULL,               "pll1_sysclk7", &pll1_sysclk7),
        CLK("i2c_davinci.1",    NULL,           &i2c0_clk),
        CLK(NULL,               "timer0",       &timerp64_0_clk),
        CLK("watchdog",         NULL,           &timerp64_1_clk),
index 41e6612..d965da4 100644 (file)
@@ -213,13 +213,12 @@ config MACH_OMAP3_PANDORA
        depends on ARCH_OMAP3
        default y
        select OMAP_PACKAGE_CBB
-       select REGULATOR_FIXED_VOLTAGE
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config MACH_OMAP3_TOUCHBOOK
        bool "OMAP3 Touch Book"
        depends on ARCH_OMAP3
        default y
-       select BACKLIGHT_CLASS_DEVICE
 
 config MACH_OMAP_3430SDP
        bool "OMAP 3430 SDP board"
@@ -265,7 +264,7 @@ config MACH_OMAP_ZOOM2
        select SERIAL_8250
        select SERIAL_CORE_CONSOLE
        select SERIAL_8250_CONSOLE
-       select REGULATOR_FIXED_VOLTAGE
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config MACH_OMAP_ZOOM3
        bool "OMAP3630 Zoom3 board"
@@ -275,7 +274,7 @@ config MACH_OMAP_ZOOM3
        select SERIAL_8250
        select SERIAL_CORE_CONSOLE
        select SERIAL_8250_CONSOLE
-       select REGULATOR_FIXED_VOLTAGE
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config MACH_CM_T35
        bool "CompuLab CM-T35/CM-T3730 modules"
@@ -334,7 +333,7 @@ config MACH_OMAP_4430SDP
        depends on ARCH_OMAP4
        select OMAP_PACKAGE_CBL
        select OMAP_PACKAGE_CBS
-       select REGULATOR_FIXED_VOLTAGE
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config MACH_OMAP4_PANDA
        bool "OMAP4 Panda Board"
@@ -342,7 +341,7 @@ config MACH_OMAP4_PANDA
        depends on ARCH_OMAP4
        select OMAP_PACKAGE_CBL
        select OMAP_PACKAGE_CBS
-       select REGULATOR_FIXED_VOLTAGE
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config OMAP3_EMU
        bool "OMAP3 debugging peripherals"
index 39fba9d..21fc876 100644 (file)
@@ -52,8 +52,9 @@
 #define ETH_KS8851_QUART               138
 #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO       184
 #define OMAP4_SFH7741_ENABLE_GPIO              188
-#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
 #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define HDMI_GPIO_HPD  63 /* Hotplug detect */
 #define DISPLAY_SEL_GPIO       59      /* LCD2/PicoDLP switch */
 #define DLP_POWER_ON_GPIO      40
 
@@ -603,8 +604,9 @@ static void __init omap_sfh7741prox_init(void)
 }
 
 static struct gpio sdp4430_hdmi_gpios[] = {
-       { HDMI_GPIO_HPD,        GPIOF_OUT_INIT_HIGH,    "hdmi_gpio_hpd"   },
+       { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
        { HDMI_GPIO_LS_OE,      GPIOF_OUT_INIT_HIGH,    "hdmi_gpio_ls_oe" },
+       { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
 };
 
 static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
@@ -621,8 +623,7 @@ static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
 
 static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
 {
-       gpio_free(HDMI_GPIO_LS_OE);
-       gpio_free(HDMI_GPIO_HPD);
+       gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios));
 }
 
 static struct nokia_dsi_panel_data dsi1_panel = {
@@ -738,6 +739,10 @@ static void sdp4430_lcd_init(void)
                pr_err("%s: Could not get lcd2_reset_gpio\n", __func__);
 }
 
+static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
+       .hpd_gpio = HDMI_GPIO_HPD,
+};
+
 static struct omap_dss_device sdp4430_hdmi_device = {
        .name = "hdmi",
        .driver_name = "hdmi_panel",
@@ -745,6 +750,7 @@ static struct omap_dss_device sdp4430_hdmi_device = {
        .platform_enable = sdp4430_panel_enable_hdmi,
        .platform_disable = sdp4430_panel_disable_hdmi,
        .channel = OMAP_DSS_CHANNEL_DIGIT,
+       .data = &sdp4430_hdmi_data,
 };
 
 static struct picodlp_panel_data sdp4430_picodlp_pdata = {
@@ -829,6 +835,10 @@ static void omap_4430sdp_display_init(void)
                omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
        else
                omap_hdmi_init(0);
+
+       omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
 }
 
 #ifdef CONFIG_OMAP_MUX
index 30ad40d..b7779c2 100644 (file)
@@ -51,8 +51,9 @@
 #define GPIO_HUB_NRESET                62
 #define GPIO_WIFI_PMENA                43
 #define GPIO_WIFI_IRQ          53
-#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
 #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define HDMI_GPIO_HPD  63 /* Hotplug detect */
 
 /* wl127x BT, FM, GPS connectivity chip */
 static int wl1271_gpios[] = {46, -1, -1};
@@ -413,8 +414,9 @@ int __init omap4_panda_dvi_init(void)
 }
 
 static struct gpio panda_hdmi_gpios[] = {
-       { HDMI_GPIO_HPD,        GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd"   },
+       { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
        { HDMI_GPIO_LS_OE,      GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
+       { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
 };
 
 static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
@@ -431,10 +433,13 @@ static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
 
 static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev)
 {
-       gpio_free(HDMI_GPIO_LS_OE);
-       gpio_free(HDMI_GPIO_HPD);
+       gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios));
 }
 
+static struct omap_dss_hdmi_data omap4_panda_hdmi_data = {
+       .hpd_gpio = HDMI_GPIO_HPD,
+};
+
 static struct omap_dss_device  omap4_panda_hdmi_device = {
        .name = "hdmi",
        .driver_name = "hdmi_panel",
@@ -442,6 +447,7 @@ static struct omap_dss_device  omap4_panda_hdmi_device = {
        .platform_enable = omap4_panda_panel_enable_hdmi,
        .platform_disable = omap4_panda_panel_disable_hdmi,
        .channel = OMAP_DSS_CHANNEL_DIGIT,
+       .data = &omap4_panda_hdmi_data,
 };
 
 static struct omap_dss_device *omap4_panda_dss_devices[] = {
@@ -473,6 +479,10 @@ void omap4_panda_display_init(void)
                omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
        else
                omap_hdmi_init(0);
+
+       omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
 }
 
 static void __init omap4_panda_init(void)
index 0b510ad..283d11e 100644 (file)
@@ -405,6 +405,7 @@ static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
                        break;
        default:
                        pr_err("Invalid McSPI Revision value\n");
+                       kfree(pdata);
                        return -EINVAL;
        }
 
index 3c446d1..3677b1f 100644 (file)
@@ -103,12 +103,8 @@ static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
        u32 reg;
        u16 control_i2c_1;
 
-       /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
-       omap_mux_init_signal("hdmi_hpd",
-                       OMAP_PIN_INPUT_PULLUP);
        omap_mux_init_signal("hdmi_cec",
                        OMAP_PIN_INPUT_PULLUP);
-       /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
        omap_mux_init_signal("hdmi_ddc_scl",
                        OMAP_PIN_INPUT_PULLUP);
        omap_mux_init_signal("hdmi_ddc_sda",
index 130034b..dfffbbf 100644 (file)
@@ -528,7 +528,13 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
 
        case GPMC_CONFIG_DEV_SIZE:
                regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+               /* clear 2 target bits */
+               regval &= ~GPMC_CONFIG1_DEVICESIZE(3);
+
+               /* set the proper value */
                regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+
                gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
                break;
 
index bd844af..ad0adb5 100644 (file)
@@ -175,14 +175,15 @@ static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc)
 {
        u32 reg;
 
-       if (mmc->slots[0].internal_clock) {
-               reg = omap_ctrl_readl(control_devconf1_offset);
+       reg = omap_ctrl_readl(control_devconf1_offset);
+       if (mmc->slots[0].internal_clock)
                reg |= OMAP2_MMCSDIO2ADPCLKISEL;
-               omap_ctrl_writel(reg, control_devconf1_offset);
-       }
+       else
+               reg &= ~OMAP2_MMCSDIO2ADPCLKISEL;
+       omap_ctrl_writel(reg, control_devconf1_offset);
 }
 
-static void hsmmc23_before_set_reg(struct device *dev, int slot,
+static void hsmmc2_before_set_reg(struct device *dev, int slot,
                                   int power_on, int vdd)
 {
        struct omap_mmc_platform_data *mmc = dev->platform_data;
@@ -407,14 +408,13 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
                        c->caps &= ~MMC_CAP_8_BIT_DATA;
                        c->caps |= MMC_CAP_4_BIT_DATA;
                }
-               /* FALLTHROUGH */
-       case 3:
                if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
                        /* off-chip level shifting, or none */
-                       mmc->slots[0].before_set_reg = hsmmc23_before_set_reg;
+                       mmc->slots[0].before_set_reg = hsmmc2_before_set_reg;
                        mmc->slots[0].after_set_reg = NULL;
                }
                break;
+       case 3:
        case 4:
        case 5:
                mmc->slots[0].before_set_reg = NULL;
index 3f174d5..eb50c29 100644 (file)
@@ -388,7 +388,7 @@ static void __init omap_hwmod_init_postsetup(void)
        omap_pm_if_early_init();
 }
 
-#ifdef CONFIG_ARCH_OMAP2
+#ifdef CONFIG_SOC_OMAP2420
 void __init omap2420_init_early(void)
 {
        omap2_set_globals_242x();
@@ -400,7 +400,9 @@ void __init omap2420_init_early(void)
        omap_hwmod_init_postsetup();
        omap2420_clk_init();
 }
+#endif
 
+#ifdef CONFIG_SOC_OMAP2430
 void __init omap2430_init_early(void)
 {
        omap2_set_globals_243x();
index c11273d..f08e442 100644 (file)
@@ -55,27 +55,6 @@ struct omap_hwmod_class omap2_dss_hwmod_class = {
        .reset  = omap_dss_reset,
 };
 
-/*
- * 'dispc' class
- * display controller
- */
-
-static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
-       .rev_offs       = 0x0000,
-       .sysc_offs      = 0x0010,
-       .syss_offs      = 0x0014,
-       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
-                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-struct omap_hwmod_class omap2_dispc_hwmod_class = {
-       .name   = "dispc",
-       .sysc   = &omap2_dispc_sysc,
-};
-
 /*
  * 'rfbi' class
  * remote frame buffer interface
index 177dee2..2a67297 100644 (file)
@@ -28,6 +28,28 @@ struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = {
        { .name = "dispc", .dma_req = 5 },
        { .dma_req = -1 }
 };
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+                          MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dispc_hwmod_class = {
+       .name   = "dispc",
+       .sysc   = &omap2_dispc_sysc,
+};
+
 /* OMAP2xxx Timer Common */
 static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
        .rev_offs       = 0x0000,
index 5324e8d..3c8dd92 100644 (file)
@@ -1480,6 +1480,28 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {
        .masters_cnt    = ARRAY_SIZE(omap3xxx_dss_masters),
 };
 
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3_dispc_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+                          SYSC_HAS_ENAWAKEUP),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+                          MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3_dispc_hwmod_class = {
+       .name   = "dispc",
+       .sysc   = &omap3_dispc_sysc,
+};
+
 /* l4_core -> dss_dispc */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {
        .master         = &omap3xxx_l4_core_hwmod,
@@ -1503,7 +1525,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
 
 static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
        .name           = "dss_dispc",
-       .class          = &omap2_dispc_hwmod_class,
+       .class          = &omap3_dispc_hwmod_class,
        .mpu_irqs       = omap2_dispc_irqs,
        .main_clk       = "dss1_alwon_fck",
        .prcm           = {
@@ -3523,12 +3545,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_uart2_hwmod,
        &omap3xxx_uart3_hwmod,
 
-       /* dss class */
-       &omap3xxx_dss_dispc_hwmod,
-       &omap3xxx_dss_dsi1_hwmod,
-       &omap3xxx_dss_rfbi_hwmod,
-       &omap3xxx_dss_venc_hwmod,
-
        /* i2c class */
        &omap3xxx_i2c1_hwmod,
        &omap3xxx_i2c2_hwmod,
@@ -3635,6 +3651,15 @@ static __initdata struct omap_hwmod *am35xx_hwmods[] = {
        NULL
 };
 
+static __initdata struct omap_hwmod *omap3xxx_dss_hwmods[] = {
+       /* dss class */
+       &omap3xxx_dss_dispc_hwmod,
+       &omap3xxx_dss_dsi1_hwmod,
+       &omap3xxx_dss_rfbi_hwmod,
+       &omap3xxx_dss_venc_hwmod,
+       NULL
+};
+
 int __init omap3xxx_hwmod_init(void)
 {
        int r;
@@ -3708,6 +3733,21 @@ int __init omap3xxx_hwmod_init(void)
 
        if (h)
                r = omap_hwmod_register(h);
+       if (r < 0)
+               return r;
+
+       /*
+        * DSS code presumes that dss_core hwmod is handled first,
+        * _before_ any other DSS related hwmods so register common
+        * DSS hwmods last to ensure that dss_core is already registered.
+        * Otherwise some change things may happen, for ex. if dispc
+        * is handled before dss_core and DSS is enabled in bootloader
+        * DIPSC will be reset with outputs enabled which sometimes leads
+        * to unrecoverable L3 error.
+        * XXX The long-term fix to this is to ensure modules are set up
+        * in dependency order in the hwmod core code.
+        */
+       r = omap_hwmod_register(omap3xxx_dss_hwmods);
 
        return r;
 }
index f9f1510..ef0524c 100644 (file)
@@ -1031,6 +1031,7 @@ static struct omap_hwmod_dma_info omap44xx_dmic_sdma_reqs[] = {
 
 static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
        {
+               .name           = "mpu",
                .pa_start       = 0x4012e000,
                .pa_end         = 0x4012e07f,
                .flags          = ADDR_TYPE_RT
@@ -1049,6 +1050,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = {
 
 static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {
        {
+               .name           = "dma",
                .pa_start       = 0x4902e000,
                .pa_end         = 0x4902e07f,
                .flags          = ADDR_TYPE_RT
index c1c4d86..9ce7654 100644 (file)
@@ -19,6 +19,7 @@
 #include "common.h"
 #include <plat/cpu.h>
 #include <plat/prcm.h>
+#include <plat/irqs.h>
 
 #include "vp.h"
 
index 9dd9345..7e755bb 100644 (file)
@@ -897,7 +897,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
                ret = sr_late_init(sr_info);
                if (ret) {
                        pr_warning("%s: Error in SR late init\n", __func__);
-                       return ret;
+                       goto err_iounmap;
                }
        }
 
index 6eeff0e..5c9acea 100644 (file)
@@ -270,7 +270,7 @@ static struct clocksource clocksource_gpt = {
 static u32 notrace dmtimer_read_sched_clock(void)
 {
        if (clksrc.reserved)
-               return __omap_dm_timer_read_counter(clksrc.io_base, 1);
+               return __omap_dm_timer_read_counter(&clksrc, 1);
 
        return 0;
 }
index 6ebd276..6bb3f47 100644 (file)
@@ -223,6 +223,7 @@ static struct resource sa1111_resources[] = {
 
 static struct sa1111_platform_data sa1111_info = {
        .irq_base       = LUBBOCK_SA1111_IRQ_BASE,
+       .disable_devs   = SA1111_DEVID_SAC,
 };
 
 static struct platform_device sa1111_device = {
index aa77bc9..f893207 100644 (file)
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y                  := dma.o irq.o riscpc.o
+obj-y                  := dma.o ecard.o irq.o riscpc.o time.o
 obj-m                  :=
 obj-n                  :=
 obj-                   :=
similarity index 90%
rename from arch/arm/kernel/ecard.c
rename to arch/arm/mach-rpc/ecard.c
index 4dd0eda..0c01567 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/kthread.h>
+#include <linux/irq.h>
 #include <linux/io.h>
 
 #include <asm/dma.h>
 
 #include "ecard.h"
 
-#ifndef CONFIG_ARCH_RPC
-#define HAVE_EXPMASK
-#endif
-
 struct ecard_request {
        void            (*fn)(struct ecard_request *);
        ecard_t         *ec;
@@ -77,9 +74,6 @@ struct expcard_blacklist {
 static ecard_t *cards;
 static ecard_t *slot_to_expcard[MAX_ECARDS];
 static unsigned int ectcr;
-#ifdef HAS_EXPMASK
-static unsigned int have_expmask;
-#endif
 
 /* List of descriptions of cards which don't have an extended
  * identification, or chunk directories containing a description.
@@ -390,22 +384,10 @@ int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
 
 static void ecard_def_irq_enable(ecard_t *ec, int irqnr)
 {
-#ifdef HAS_EXPMASK
-       if (irqnr < 4 && have_expmask) {
-               have_expmask |= 1 << irqnr;
-               __raw_writeb(have_expmask, EXPMASK_ENABLE);
-       }
-#endif
 }
 
 static void ecard_def_irq_disable(ecard_t *ec, int irqnr)
 {
-#ifdef HAS_EXPMASK
-       if (irqnr < 4 && have_expmask) {
-               have_expmask &= ~(1 << irqnr);
-               __raw_writeb(have_expmask, EXPMASK_ENABLE);
-       }
-#endif
 }
 
 static int ecard_def_irq_pending(ecard_t *ec)
@@ -445,7 +427,7 @@ static expansioncard_ops_t ecard_default_ops = {
  */
 static void ecard_irq_unmask(struct irq_data *d)
 {
-       ecard_t *ec = slot_to_ecard(d->irq - 32);
+       ecard_t *ec = irq_data_get_irq_chip_data(d);
 
        if (ec) {
                if (!ec->ops)
@@ -461,7 +443,7 @@ static void ecard_irq_unmask(struct irq_data *d)
 
 static void ecard_irq_mask(struct irq_data *d)
 {
-       ecard_t *ec = slot_to_ecard(d->irq - 32);
+       ecard_t *ec = irq_data_get_irq_chip_data(d);
 
        if (ec) {
                if (!ec->ops)
@@ -578,7 +560,7 @@ ecard_irq_handler(unsigned int irq, struct irq_desc *desc)
        for (ec = cards; ec; ec = ec->next) {
                int pending;
 
-               if (!ec->claimed || ec->irq == NO_IRQ || ec->slot_no == 8)
+               if (!ec->claimed || !ec->irq || ec->slot_no == 8)
                        continue;
 
                if (ec->ops && ec->ops->irqpending)
@@ -597,83 +579,6 @@ ecard_irq_handler(unsigned int irq, struct irq_desc *desc)
                ecard_check_lockup(desc);
 }
 
-#ifdef HAS_EXPMASK
-static unsigned char priority_masks[] =
-{
-       0xf0, 0xf1, 0xf3, 0xf7, 0xff, 0xff, 0xff, 0xff
-};
-
-static unsigned char first_set[] =
-{
-       0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00
-};
-
-static void
-ecard_irqexp_handler(unsigned int irq, struct irq_desc *desc)
-{
-       const unsigned int statusmask = 15;
-       unsigned int status;
-
-       status = __raw_readb(EXPMASK_STATUS) & statusmask;
-       if (status) {
-               unsigned int slot = first_set[status];
-               ecard_t *ec = slot_to_ecard(slot);
-
-               if (ec->claimed) {
-                       /*
-                        * this ugly code is so that we can operate a
-                        * prioritorising system:
-                        *
-                        * Card 0       highest priority
-                        * Card 1
-                        * Card 2
-                        * Card 3       lowest priority
-                        *
-                        * Serial cards should go in 0/1, ethernet/scsi in 2/3
-                        * otherwise you will lose serial data at high speeds!
-                        */
-                       generic_handle_irq(ec->irq);
-               } else {
-                       printk(KERN_WARNING "card%d: interrupt from unclaimed "
-                              "card???\n", slot);
-                       have_expmask &= ~(1 << slot);
-                       __raw_writeb(have_expmask, EXPMASK_ENABLE);
-               }
-       } else
-               printk(KERN_WARNING "Wild interrupt from backplane (masks)\n");
-}
-
-static int __init ecard_probeirqhw(void)
-{
-       ecard_t *ec;
-       int found;
-
-       __raw_writeb(0x00, EXPMASK_ENABLE);
-       __raw_writeb(0xff, EXPMASK_STATUS);
-       found = (__raw_readb(EXPMASK_STATUS) & 15) == 0;
-       __raw_writeb(0xff, EXPMASK_ENABLE);
-
-       if (found) {
-               printk(KERN_DEBUG "Expansion card interrupt "
-                      "management hardware found\n");
-
-               /* for each card present, set a bit to '1' */
-               have_expmask = 0x80000000;
-
-               for (ec = cards; ec; ec = ec->next)
-                       have_expmask |= 1 << ec->slot_no;
-
-               __raw_writeb(have_expmask, EXPMASK_ENABLE);
-       }
-
-       return found;
-}
-#else
-#define ecard_irqexp_handler NULL
-#define ecard_probeirqhw() (0)
-#endif
-
 static void __iomem *__ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
 {
        void __iomem *address = NULL;
@@ -805,8 +710,8 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
 
        ec->slot_no = slot;
        ec->easi = type == ECARD_EASI;
-       ec->irq = NO_IRQ;
-       ec->fiq = NO_IRQ;
+       ec->irq = 0;
+       ec->fiq = 0;
        ec->dma = NO_DMA;
        ec->ops = &ecard_default_ops;
 
@@ -977,8 +882,7 @@ EXPORT_SYMBOL(ecardm_iomap);
  * If bit 1 of the first byte of the card is set, then the
  * card does not exist.
  */
-static int __init
-ecard_probe(int slot, card_type_t type)
+static int __init ecard_probe(int slot, unsigned irq, card_type_t type)
 {
        ecard_t **ecp;
        ecard_t *ec;
@@ -1032,18 +936,18 @@ ecard_probe(int slot, card_type_t type)
                        break;
                }
 
+       ec->irq = irq;
+
        /*
         * hook the interrupt handlers
         */
        if (slot < 8) {
-               ec->irq = 32 + slot;
                irq_set_chip_and_handler(ec->irq, &ecard_chip,
                                         handle_level_irq);
+               irq_set_chip_data(ec->irq, ec);
                set_irq_flags(ec->irq, IRQF_VALID);
        }
 
-       if (slot == 8)
-               ec->irq = 11;
 #ifdef CONFIG_ARCH_RPC
        /* On RiscPC, only first two slots have DMA capability */
        if (slot < 2)
@@ -1073,28 +977,30 @@ ecard_probe(int slot, card_type_t type)
 static int __init ecard_init(void)
 {
        struct task_struct *task;
-       int slot, irqhw;
+       int slot, irqbase;
+
+       irqbase = irq_alloc_descs(-1, 0, 8, -1);
+       if (irqbase < 0)
+               return irqbase;
 
        task = kthread_run(ecard_task, NULL, "kecardd");
        if (IS_ERR(task)) {
                printk(KERN_ERR "Ecard: unable to create kernel thread: %ld\n",
                       PTR_ERR(task));
+               irq_free_descs(irqbase, 8);
                return PTR_ERR(task);
        }
 
        printk("Probing expansion cards\n");
 
        for (slot = 0; slot < 8; slot ++) {
-               if (ecard_probe(slot, ECARD_EASI) == -ENODEV)
-                       ecard_probe(slot, ECARD_IOC);
+               if (ecard_probe(slot, irqbase + slot, ECARD_EASI) == -ENODEV)
+                       ecard_probe(slot, irqbase + slot, ECARD_IOC);
        }
 
-       ecard_probe(8, ECARD_IOC);
-
-       irqhw = ecard_probeirqhw();
+       ecard_probe(8, 11, ECARD_IOC);
 
-       irq_set_chained_handler(IRQ_EXPANSIONCARD,
-                               irqhw ? ecard_irqexp_handler : ecard_irq_handler);
+       irq_set_chained_handler(IRQ_EXPANSIONCARD, ecard_irq_handler);
 
        ecard_proc_init();
 
index 3d20374..6868e17 100644 (file)
@@ -42,6 +42,4 @@
  */
 #define FIQ_START              64
 
-#define IRQ_TIMER              IRQ_TIMER0
-
 #define NR_IRQS                        128
index 3d44a59..731552d 100644 (file)
@@ -98,15 +98,9 @@ static void __init rpc_map_io(void)
 }
 
 static struct resource acornfb_resources[] = {
-       {       /* VIDC */
-               .start          = 0x03400000,
-               .end            = 0x035fffff,
-               .flags          = IORESOURCE_MEM,
-       }, {
-               .start          = IRQ_VSYNCPULSE,
-               .end            = IRQ_VSYNCPULSE,
-               .flags          = IORESOURCE_IRQ,
-       },
+       /* VIDC */
+       DEFINE_RES_MEM(0x03400000, 0x00200000),
+       DEFINE_RES_IRQ(IRQ_VSYNCPULSE),
 };
 
 static struct platform_device acornfb_device = {
@@ -120,11 +114,7 @@ static struct platform_device acornfb_device = {
 };
 
 static struct resource iomd_resources[] = {
-       {
-               .start          = 0x03200000,
-               .end            = 0x0320ffff,
-               .flags          = IORESOURCE_MEM,
-       },
+       DEFINE_RES_MEM(0x03200000, 0x10000),
 };
 
 static struct platform_device iomd_device = {
@@ -134,18 +124,25 @@ static struct platform_device iomd_device = {
        .resource               = iomd_resources,
 };
 
+static struct resource iomd_kart_resources[] = {
+       DEFINE_RES_IRQ(IRQ_KEYBOARDRX),
+       DEFINE_RES_IRQ(IRQ_KEYBOARDTX),
+};
+
 static struct platform_device kbd_device = {
        .name                   = "kart",
        .id                     = -1,
        .dev                    = {
                .parent         = &iomd_device.dev,
        },
+       .num_resources          = ARRAY_SIZE(iomd_kart_resources),
+       .resource               = iomd_kart_resources,
 };
 
 static struct plat_serial8250_port serial_platform_data[] = {
        {
                .mapbase        = 0x03010fe0,
-               .irq            = 10,
+               .irq            = IRQ_SERIALPORT,
                .uartclk        = 1843200,
                .regshift       = 2,
                .iotype         = UPIO_MEM,
@@ -167,21 +164,9 @@ static struct pata_platform_info pata_platform_data = {
 };
 
 static struct resource pata_resources[] = {
-       [0] = {
-               .start          = 0x030107c0,
-               .end            = 0x030107df,
-               .flags          = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start          = 0x03010fd8,
-               .end            = 0x03010fdb,
-               .flags          = IORESOURCE_MEM,
-       },
-       [2] = {
-               .start          = IRQ_HARDDISK,
-               .end            = IRQ_HARDDISK,
-               .flags          = IORESOURCE_IRQ,
-       },
+       DEFINE_RES_MEM(0x030107c0, 0x20),
+       DEFINE_RES_MEM(0x03010fd8, 0x04),
+       DEFINE_RES_IRQ(IRQ_HARDDISK),
 };
 
 static struct platform_device pata_device = {
similarity index 98%
rename from arch/arm/common/time-acorn.c
rename to arch/arm/mach-rpc/time.c
index deeed56..581fca9 100644 (file)
@@ -85,7 +85,7 @@ static struct irqaction ioc_timer_irq = {
 static void __init ioc_timer_init(void)
 {
        ioctime_init();
-       setup_irq(IRQ_TIMER, &ioc_timer_irq);
+       setup_irq(IRQ_TIMER0, &ioc_timer_irq);
 }
 
 struct sys_timer ioc_timer = {
index ed7408d..60b97ec 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := clock.o generic.o irq.o dma.o time.o #nmi-oopser.o
+obj-y := clock.o generic.o irq.o time.o #nmi-oopser.o
 obj-m :=
 obj-n :=
 obj-  :=
index 0c4b76a..375d3f7 100644 (file)
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
+#include <linux/mfd/ucb1x00.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
 
+#include <video/sa1100fb.h>
+
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/mach/serial_sa1100.h>
 #include <mach/assabet.h>
 #include <mach/mcp.h>
+#include <mach/irqs.h>
 
 #include "generic.h"
 
 #define ASSABET_BCR_DB1110 \
-       (ASSABET_BCR_SPK_OFF    | ASSABET_BCR_QMUTE     | \
+       (ASSABET_BCR_SPK_OFF    | \
         ASSABET_BCR_LED_GREEN  | ASSABET_BCR_LED_RED   | \
         ASSABET_BCR_RS232EN    | ASSABET_BCR_LCD_12RGB | \
         ASSABET_BCR_IRDA_MD0)
 
 #define ASSABET_BCR_DB1111 \
-       (ASSABET_BCR_SPK_OFF    | ASSABET_BCR_QMUTE     | \
+       (ASSABET_BCR_SPK_OFF    | \
         ASSABET_BCR_LED_GREEN  | ASSABET_BCR_LED_RED   | \
         ASSABET_BCR_RS232EN    | ASSABET_BCR_LCD_12RGB | \
         ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_STEREO_LB | \
@@ -69,31 +72,10 @@ void ASSABET_BCR_frob(unsigned int mask, unsigned int val)
 
 EXPORT_SYMBOL(ASSABET_BCR_frob);
 
-static void assabet_backlight_power(int on)
-{
-#ifndef ASSABET_PAL_VIDEO
-       if (on)
-               ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON);
-       else
-#endif
-               ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
-}
-
-/*
- * Turn on/off the backlight.  When turning the backlight on,
- * we wait 500us after turning it on so we don't cause the
- * supplies to droop when we enable the LCD controller (and
- * cause a hard reset.)
- */
-static void assabet_lcd_power(int on)
+static void assabet_ucb1x00_reset(enum ucb1x00_reset state)
 {
-#ifndef ASSABET_PAL_VIDEO
-       if (on) {
-               ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
-               udelay(500);
-       } else
-#endif
-               ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
+       if (state == UCB_RST_PROBE)
+               ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
 }
 
 
@@ -152,15 +134,8 @@ static struct flash_platform_data assabet_flash_data = {
 };
 
 static struct resource assabet_flash_resources[] = {
-       {
-               .start  = SA1100_CS0_PHYS,
-               .end    = SA1100_CS0_PHYS + SZ_32M - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = SA1100_CS1_PHYS,
-               .end    = SA1100_CS1_PHYS + SZ_32M - 1,
-               .flags  = IORESOURCE_MEM,
-       }
+       DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M),
+       DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_32M),
 };
 
 
@@ -199,18 +174,126 @@ static struct irda_platform_data assabet_irda_data = {
        .set_speed      = assabet_irda_set_speed,
 };
 
+static struct ucb1x00_plat_data assabet_ucb1x00_data = {
+       .reset          = assabet_ucb1x00_reset,
+       .gpio_base      = -1,
+};
+
 static struct mcp_plat_data assabet_mcp_data = {
        .mccr0          = MCCR0_ADM,
        .sclk_rate      = 11981000,
+       .codec_pdata    = &assabet_ucb1x00_data,
+};
+
+static void assabet_lcd_set_visual(u32 visual)
+{
+       u_int is_true_color = visual == FB_VISUAL_TRUECOLOR;
+
+       if (machine_is_assabet()) {
+#if 1          // phase 4 or newer Assabet's
+               if (is_true_color)
+                       ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
+               else
+                       ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
+#else
+               // older Assabet's
+               if (is_true_color)
+                       ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
+               else
+                       ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
+#endif
+       }
+}
+
+#ifndef ASSABET_PAL_VIDEO
+static void assabet_lcd_backlight_power(int on)
+{
+       if (on)
+               ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON);
+       else
+               ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
+}
+
+/*
+ * Turn on/off the backlight.  When turning the backlight on, we wait
+ * 500us after turning it on so we don't cause the supplies to droop
+ * when we enable the LCD controller (and cause a hard reset.)
+ */
+static void assabet_lcd_power(int on)
+{
+       if (on) {
+               ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
+               udelay(500);
+       } else
+               ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
+}
+
+/*
+ * The assabet uses a sharp LQ039Q2DS54 LCD module.  It is actually
+ * takes an RGB666 signal, but we provide it with an RGB565 signal
+ * instead (def_rgb_16).
+ */
+static struct sa1100fb_mach_info lq039q2ds54_info = {
+       .pixclock       = 171521,       .bpp            = 16,
+       .xres           = 320,          .yres           = 240,
+
+       .hsync_len      = 5,            .vsync_len      = 1,
+       .left_margin    = 61,           .upper_margin   = 3,
+       .right_margin   = 9,            .lower_margin   = 0,
+
+       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+
+       .backlight_power = assabet_lcd_backlight_power,
+       .lcd_power = assabet_lcd_power,
+       .set_visual = assabet_lcd_set_visual,
+};
+#else
+static void assabet_pal_backlight_power(int on)
+{
+       ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
+}
+
+static void assabet_pal_power(int on)
+{
+       ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
+}
+
+static struct sa1100fb_mach_info pal_info = {
+       .pixclock       = 67797,        .bpp            = 16,
+       .xres           = 640,          .yres           = 512,
+
+       .hsync_len      = 64,           .vsync_len      = 6,
+       .left_margin    = 125,          .upper_margin   = 70,
+       .right_margin   = 115,          .lower_margin   = 36,
+
+       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
+
+       .backlight_power = assabet_pal_backlight_power,
+       .lcd_power = assabet_pal_power,
+       .set_visual = assabet_lcd_set_visual,
 };
+#endif
+
+#ifdef CONFIG_ASSABET_NEPONSET
+static struct resource neponset_resources[] = {
+       DEFINE_RES_MEM(0x10000000, 0x08000000),
+       DEFINE_RES_MEM(0x18000000, 0x04000000),
+       DEFINE_RES_MEM(0x40000000, SZ_8K),
+       DEFINE_RES_IRQ(IRQ_GPIO25),
+};
+#endif
 
 static void __init assabet_init(void)
 {
        /*
         * Ensure that the power supply is in "high power" mode.
         */
-       GPDR |= GPIO_GPIO16;
        GPSR = GPIO_GPIO16;
+       GPDR |= GPIO_GPIO16;
 
        /*
         * Ensure that these pins are set as outputs and are driving
@@ -218,8 +301,16 @@ static void __init assabet_init(void)
         * the WS latch in the CPLD, and we don't float causing
         * excessive power drain.  --rmk
         */
-       GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
        GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
+       GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
+
+       /*
+        * Also set GPIO27 as an output; this is used to clock UART3
+        * via the FPGA and as otherwise has no pullups or pulldowns,
+        * so stop it floating.
+        */
+       GPCR = GPIO_GPIO27;
+       GPDR |= GPIO_GPIO27;
 
        /*
         * Set up registers for sleep mode.
@@ -231,8 +322,7 @@ static void __init assabet_init(void)
        PPDR |= PPC_TXD3 | PPC_TXD1;
        PPSR |= PPC_TXD3 | PPC_TXD1;
 
-       sa1100fb_lcd_power = assabet_lcd_power;
-       sa1100fb_backlight_power = assabet_backlight_power;
+       sa11x0_ppc_configure_mcp();
 
        if (machine_has_neponset()) {
                /*
@@ -246,9 +336,17 @@ static void __init assabet_init(void)
 #ifndef CONFIG_ASSABET_NEPONSET
                printk( "Warning: Neponset detected but full support "
                        "hasn't been configured in the kernel\n" );
+#else
+               platform_device_register_simple("neponset", 0,
+                       neponset_resources, ARRAY_SIZE(neponset_resources));
 #endif
        }
 
+#ifndef ASSABET_PAL_VIDEO
+       sa11x0_register_lcd(&lq039q2ds54_info);
+#else
+       sa11x0_register_lcd(&pal_video);
+#endif
        sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources,
                            ARRAY_SIZE(assabet_flash_resources));
        sa11x0_register_irda(&assabet_irda_data);
@@ -412,21 +510,8 @@ static void __init assabet_map_io(void)
         */
        Ser1SDCR0 |= SDCR0_SUS;
 
-       if (machine_has_neponset()) {
-#ifdef CONFIG_ASSABET_NEPONSET
-               extern void neponset_map_io(void);
-
-               /*
-                * We map Neponset registers even if it isn't present since
-                * many drivers will try to probe their stuff (and fail).
-                * This is still more friendly than a kernel paging request
-                * crash.
-                */
-               neponset_map_io();
-#endif
-       } else {
+       if (!machine_has_neponset())
                sa1100_register_uart_fns(&assabet_port_fns);
-       }
 
        /*
         * When Neponset is attached, the first UART should be
@@ -449,6 +534,7 @@ MACHINE_START(ASSABET, "Intel-Assabet")
        .atag_offset    = 0x100,
        .fixup          = fixup_assabet,
        .map_io         = assabet_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
        .init_machine   = assabet_init,
index b07a2c0..e0f0c03 100644 (file)
 #include "generic.h"
 
 static struct resource sa1111_resources[] = {
-       [0] = {
-               .start          = BADGE4_SA1111_BASE,
-               .end            = BADGE4_SA1111_BASE + 0x00001fff,
-               .flags          = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start          = BADGE4_IRQ_GPIO_SA1111,
-               .end            = BADGE4_IRQ_GPIO_SA1111,
-               .flags          = IORESOURCE_IRQ,
-       },
+       [0] = DEFINE_RES_MEM(BADGE4_SA1111_BASE, 0x2000),
+       [1] = DEFINE_RES_IRQ(BADGE4_IRQ_GPIO_SA1111),
 };
 
+static int badge4_sa1111_enable(void *data, unsigned devid)
+{
+       if (devid == SA1111_DEVID_USB)
+               badge4_set_5V(BADGE4_5V_USB, 1);
+       return 0;
+}
+
+static void badge4_sa1111_disable(void *data, unsigned devid)
+{
+       if (devid == SA1111_DEVID_USB)
+               badge4_set_5V(BADGE4_5V_USB, 0);
+}
+
 static struct sa1111_platform_data sa1111_info = {
-       .irq_base       = IRQ_BOARD_END,
+       .disable_devs   = SA1111_DEVID_PS2_MSE,
+       .enable         = badge4_sa1111_enable,
+       .disable        = badge4_sa1111_disable,
 };
 
 static u64 sa1111_dmamask = 0xffffffffUL;
@@ -121,11 +128,8 @@ static struct flash_platform_data badge4_flash_data = {
        .nr_parts       = ARRAY_SIZE(badge4_partitions),
 };
 
-static struct resource badge4_flash_resource = {
-       .start          = SA1100_CS0_PHYS,
-       .end            = SA1100_CS0_PHYS + SZ_64M - 1,
-       .flags          = IORESOURCE_MEM,
-};
+static struct resource badge4_flash_resource =
+       DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_64M);
 
 static int five_v_on __initdata = 0;
 
@@ -269,11 +273,6 @@ static struct map_desc badge4_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(0x10000000),
                .length         = 0x00100000,
                .type           = MT_DEVICE
-       }, {    /* SA-1111      */
-               .virtual        = 0xf4000000,
-               .pfn            = __phys_to_pfn(0x48000000),
-               .length         = 0x00100000,
-               .type           = MT_DEVICE
        }
 };
 
@@ -304,6 +303,7 @@ static void __init badge4_map_io(void)
 MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
        .atag_offset    = 0x100,
        .map_io         = badge4_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
 #ifdef CONFIG_SA1111
index 11bb6d0..4a61f60 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
-#include <asm/irq.h>
 #include <mach/hardware.h>
 #include <asm/setup.h>
 
 
 #include <mach/cerf.h>
 #include <mach/mcp.h>
+#include <mach/irqs.h>
 #include "generic.h"
 
 static struct resource cerfuart2_resources[] = {
-       [0] = {
-               .start  = 0x80030000,
-               .end    = 0x8003ffff,
-               .flags  = IORESOURCE_MEM,
-       },
+       [0] = DEFINE_RES_MEM(0x80030000, SZ_64K),
 };
 
 static struct platform_device cerfuart2_device = {
@@ -87,11 +83,8 @@ static struct flash_platform_data cerf_flash_data = {
        .nr_parts       = ARRAY_SIZE(cerf_partitions),
 };
 
-static struct resource cerf_flash_resource = {
-       .start          = SA1100_CS0_PHYS,
-       .end            = SA1100_CS0_PHYS + SZ_32M - 1,
-       .flags          = IORESOURCE_MEM,
-};
+static struct resource cerf_flash_resource =
+       DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M);
 
 static void __init cerf_init_irq(void)
 {
@@ -128,6 +121,7 @@ static struct mcp_plat_data cerf_mcp_data = {
 
 static void __init cerf_init(void)
 {
+       sa11x0_ppc_configure_mcp();
        platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices));
        sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1);
        sa11x0_register_mcp(&cerf_mcp_data);
@@ -136,6 +130,7 @@ static void __init cerf_init(void)
 MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
        /* Maintainer: support@intrinsyc.com */
        .map_io         = cerf_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = cerf_init_irq,
        .timer          = &sa1100_timer,
        .init_machine   = cerf_init,
index fd56521..48885b7 100644 (file)
 #include <linux/tty.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/ucb1x00.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/timer.h>
 #include <linux/gpio.h>
 #include <linux/pda_power.h>
 
+#include <video/sa1100fb.h>
+
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/setup.h>
 #include <mach/collie.h>
 #include <asm/mach/sharpsl_param.h>
 #include <asm/hardware/locomo.h>
 #include <mach/mcp.h>
+#include <mach/irqs.h>
 
 #include "generic.h"
 
 static struct resource collie_scoop_resources[] = {
-       [0] = {
-               .start          = 0x40800000,
-               .end            = 0x40800fff,
-               .flags          = IORESOURCE_MEM,
-       },
+       [0] = DEFINE_RES_MEM(0x40800000, SZ_4K),
 };
 
 static struct scoop_config collie_scoop_setup = {
@@ -85,10 +84,14 @@ static struct scoop_pcmcia_config collie_pcmcia_config = {
        .num_devs       = 1,
 };
 
+static struct ucb1x00_plat_data collie_ucb1x00_data = {
+       .gpio_base      = COLLIE_TC35143_GPIO_BASE,
+};
+
 static struct mcp_plat_data collie_mcp_data = {
        .mccr0          = MCCR0_ADM | MCCR0_ExtClk,
        .sclk_rate      = 9216000,
-       .gpio_base      = COLLIE_TC35143_GPIO_BASE,
+       .codec_pdata    = &collie_ucb1x00_data,
 };
 
 /*
@@ -221,16 +224,8 @@ device_initcall(collie_uart_init);
 
 
 static struct resource locomo_resources[] = {
-       [0] = {
-               .start          = 0x40000000,
-               .end            = 0x40001fff,
-               .flags          = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start          = IRQ_GPIO25,
-               .end            = IRQ_GPIO25,
-               .flags          = IORESOURCE_IRQ,
-       },
+       [0] = DEFINE_RES_MEM(0x40000000, SZ_8K),
+       [1] = DEFINE_RES_IRQ(IRQ_GPIO25),
 };
 
 static struct locomo_platform_data locomo_info = {
@@ -303,11 +298,21 @@ static struct flash_platform_data collie_flash_data = {
 };
 
 static struct resource collie_flash_resources[] = {
-       {
-               .start  = SA1100_CS0_PHYS,
-               .end    = SA1100_CS0_PHYS + SZ_32M - 1,
-               .flags  = IORESOURCE_MEM,
-       }
+       DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M),
+};
+
+static struct sa1100fb_mach_info collie_lcd_info = {
+       .pixclock       = 171521,       .bpp            = 16,
+       .xres           = 320,          .yres           = 240,
+
+       .hsync_len      = 5,            .vsync_len      = 1,
+       .left_margin    = 11,           .upper_margin   = 2,
+       .right_margin   = 30,           .lower_margin   = 0,
+
+       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
 };
 
 static void __init collie_init(void)
@@ -341,6 +346,10 @@ static void __init collie_init(void)
 
        collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN);
        collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN);
+
+       sa11x0_ppc_configure_mcp();
+
+
        platform_scoop_config = &collie_pcmcia_config;
 
        ret = platform_add_devices(devices, ARRAY_SIZE(devices));
@@ -348,6 +357,7 @@ static void __init collie_init(void)
                printk(KERN_WARNING "collie: Unable to register LoCoMo device\n");
        }
 
+       sa11x0_register_lcd(&collie_lcd_info);
        sa11x0_register_mtd(&collie_flash_data, collie_flash_resources,
                            ARRAY_SIZE(collie_flash_resources));
        sa11x0_register_mcp(&collie_mcp_data);
@@ -383,6 +393,7 @@ static void __init collie_map_io(void)
 
 MACHINE_START(COLLIE, "Sharp-Collie")
        .map_io         = collie_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
        .init_machine   = collie_init,
diff --git a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c
deleted file mode 100644 (file)
index ad66035..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * arch/arm/mach-sa1100/dma.c
- *
- * Support functions for the SA11x0 internal DMA channels.
- *
- * Copyright (C) 2000, 2001 by Nicolas Pitre
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <mach/dma.h>
-
-
-#undef DEBUG
-#ifdef DEBUG
-#define DPRINTK( s, arg... )  printk( "dma<%p>: " s, regs , ##arg )
-#else
-#define DPRINTK( x... )
-#endif
-
-
-typedef struct {
-       const char *device_id;          /* device name */
-       u_long device;                  /* this channel device, 0  if unused*/
-       dma_callback_t callback;        /* to call when DMA completes */
-       void *data;                     /* ... with private data ptr */
-} sa1100_dma_t;
-
-static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS];
-
-static DEFINE_SPINLOCK(dma_list_lock);
-
-
-static irqreturn_t dma_irq_handler(int irq, void *dev_id)
-{
-       dma_regs_t *dma_regs = dev_id;
-       sa1100_dma_t *dma = dma_chan + (((u_int)dma_regs >> 5) & 7);
-       int status = dma_regs->RdDCSR;
-
-       if (status & (DCSR_ERROR)) {
-               printk(KERN_CRIT "DMA on \"%s\" caused an error\n", dma->device_id);
-               dma_regs->ClrDCSR = DCSR_ERROR;
-       }
-
-       dma_regs->ClrDCSR = status & (DCSR_DONEA | DCSR_DONEB);
-       if (dma->callback) {
-               if (status & DCSR_DONEA)
-                       dma->callback(dma->data);
-               if (status & DCSR_DONEB)
-                       dma->callback(dma->data);
-       }
-       return IRQ_HANDLED;
-}
-
-
-/**
- *     sa1100_request_dma - allocate one of the SA11x0's DMA channels
- *     @device: The SA11x0 peripheral targeted by this request
- *     @device_id: An ascii name for the claiming device
- *     @callback: Function to be called when the DMA completes
- *     @data: A cookie passed back to the callback function
- *     @dma_regs: Pointer to the location of the allocated channel's identifier
- *
- *     This function will search for a free DMA channel and returns the
- *     address of the hardware registers for that channel as the channel
- *     identifier. This identifier is written to the location pointed by
- *     @dma_regs. The list of possible values for @device are listed into
- *     arch/arm/mach-sa1100/include/mach/dma.h as a dma_device_t enum.
- *
- *     Note that reading from a port and writing to the same port are
- *     actually considered as two different streams requiring separate
- *     DMA registrations.
- *
- *     The @callback function is called from interrupt context when one
- *     of the two possible DMA buffers in flight has terminated. That
- *     function has to be small and efficient while posponing more complex
- *     processing to a lower priority execution context.
- *
- *     If no channels are available, or if the desired @device is already in
- *     use by another DMA channel, then an error code is returned.  This
- *     function must be called before any other DMA calls.
- **/
-
-int sa1100_request_dma (dma_device_t device, const char *device_id,
-                       dma_callback_t callback, void *data,
-                       dma_regs_t **dma_regs)
-{
-       sa1100_dma_t *dma = NULL;
-       dma_regs_t *regs;
-       int i, err;
-
-       *dma_regs = NULL;
-
-       err = 0;
-       spin_lock(&dma_list_lock);
-       for (i = 0; i < SA1100_DMA_CHANNELS; i++) {
-               if (dma_chan[i].device == device) {
-                       err = -EBUSY;
-                       break;
-               } else if (!dma_chan[i].device && !dma) {
-                       dma = &dma_chan[i];
-               }
-       }
-       if (!err) {
-               if (dma)
-                       dma->device = device;
-               else
-                       err = -ENOSR;
-       }
-       spin_unlock(&dma_list_lock);
-       if (err)
-               return err;
-
-       i = dma - dma_chan;
-       regs = (dma_regs_t *)&DDAR(i);
-       err = request_irq(IRQ_DMA0 + i, dma_irq_handler, IRQF_DISABLED,
-                         device_id, regs);
-       if (err) {
-               printk(KERN_ERR
-                      "%s: unable to request IRQ %d for %s\n",
-                      __func__, IRQ_DMA0 + i, device_id);
-               dma->device = 0;
-               return err;
-       }
-
-       *dma_regs = regs;
-       dma->device_id = device_id;
-       dma->callback = callback;
-       dma->data = data;
-
-       regs->ClrDCSR =
-               (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
-                DCSR_IE | DCSR_ERROR | DCSR_RUN);
-       regs->DDAR = device;
-
-       return 0;
-}
-
-
-/**
- *     sa1100_free_dma - free a SA11x0 DMA channel
- *     @regs: identifier for the channel to free
- *
- *     This clears all activities on a given DMA channel and releases it
- *     for future requests.  The @regs identifier is provided by a
- *     successful call to sa1100_request_dma().
- **/
-
-void sa1100_free_dma(dma_regs_t *regs)
-{
-       int i;
-
-       for (i = 0; i < SA1100_DMA_CHANNELS; i++)
-               if (regs == (dma_regs_t *)&DDAR(i))
-                       break;
-       if (i >= SA1100_DMA_CHANNELS) {
-               printk(KERN_ERR "%s: bad DMA identifier\n", __func__);
-               return;
-       }
-
-       if (!dma_chan[i].device) {
-               printk(KERN_ERR "%s: Trying to free free DMA\n", __func__);
-               return;
-       }
-
-       regs->ClrDCSR =
-               (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
-                DCSR_IE | DCSR_ERROR | DCSR_RUN);
-       free_irq(IRQ_DMA0 + i, regs);
-       dma_chan[i].device = 0;
-}
-
-
-/**
- *     sa1100_start_dma - submit a data buffer for DMA
- *     @regs: identifier for the channel to use
- *     @dma_ptr: buffer physical (or bus) start address
- *     @size: buffer size
- *
- *     This function hands the given data buffer to the hardware for DMA
- *     access. If another buffer is already in flight then this buffer
- *     will be queued so the DMA engine will switch to it automatically
- *     when the previous one is done.  The DMA engine is actually toggling
- *     between two buffers so at most 2 successful calls can be made before
- *     one of them terminates and the callback function is called.
- *
- *     The @regs identifier is provided by a successful call to
- *     sa1100_request_dma().
- *
- *     The @size must not be larger than %MAX_DMA_SIZE.  If a given buffer
- *     is larger than that then it's the caller's responsibility to split
- *     it into smaller chunks and submit them separately. If this is the
- *     case then a @size of %CUT_DMA_SIZE is recommended to avoid ending
- *     up with too small chunks. The callback function can be used to chain
- *     submissions of buffer chunks.
- *
- *     Error return values:
- *     %-EOVERFLOW:    Given buffer size is too big.
- *     %-EBUSY:        Both DMA buffers are already in use.
- *     %-EAGAIN:       Both buffers were busy but one of them just completed
- *                     but the interrupt handler has to execute first.
- *
- *     This function returs 0 on success.
- **/
-
-int sa1100_start_dma(dma_regs_t *regs, dma_addr_t dma_ptr, u_int size)
-{
-       unsigned long flags;
-       u_long status;
-       int ret;
-
-       if (dma_ptr & 3)
-               printk(KERN_WARNING "DMA: unaligned start address (0x%08lx)\n",
-                      (unsigned long)dma_ptr);
-
-       if (size > MAX_DMA_SIZE)
-               return -EOVERFLOW;
-
-       local_irq_save(flags);
-       status = regs->RdDCSR;
-
-       /* If both DMA buffers are started, there's nothing else we can do. */
-       if ((status & (DCSR_STRTA | DCSR_STRTB)) == (DCSR_STRTA | DCSR_STRTB)) {
-               DPRINTK("start: st %#x busy\n", status);
-               ret = -EBUSY;
-               goto out;
-       }
-
-       if (((status & DCSR_BIU) && (status & DCSR_STRTB)) ||
-           (!(status & DCSR_BIU) && !(status & DCSR_STRTA))) {
-               if (status & DCSR_DONEA) {
-                       /* give a chance for the interrupt to be processed */
-                       ret = -EAGAIN;
-                       goto out;
-               }
-               regs->DBSA = dma_ptr;
-               regs->DBTA = size;
-               regs->SetDCSR = DCSR_STRTA | DCSR_IE | DCSR_RUN;
-               DPRINTK("start a=%#x s=%d on A\n", dma_ptr, size);
-       } else {
-               if (status & DCSR_DONEB) {
-                       /* give a chance for the interrupt to be processed */
-                       ret = -EAGAIN;
-                       goto out;
-               }
-               regs->DBSB = dma_ptr;
-               regs->DBTB = size;
-               regs->SetDCSR = DCSR_STRTB | DCSR_IE | DCSR_RUN;
-               DPRINTK("start a=%#x s=%d on B\n", dma_ptr, size);
-       }
-       ret = 0;
-
-out:
-       local_irq_restore(flags);
-       return ret;
-}
-
-
-/**
- *     sa1100_get_dma_pos - return current DMA position
- *     @regs: identifier for the channel to use
- *
- *     This function returns the current physical (or bus) address for the
- *     given DMA channel.  If the channel is running i.e. not in a stopped
- *     state then the caller must disable interrupts prior calling this
- *     function and process the returned value before re-enabling them to
- *     prevent races with the completion interrupt handler and the callback
- *     function. The validation of the returned value is the caller's
- *     responsibility as well -- the hardware seems to return out of range
- *     values when the DMA engine completes a buffer.
- *
- *     The @regs identifier is provided by a successful call to
- *     sa1100_request_dma().
- **/
-
-dma_addr_t sa1100_get_dma_pos(dma_regs_t *regs)
-{
-       int status;
-
-       /*
-        * We must determine whether buffer A or B is active.
-        * Two possibilities: either we are in the middle of
-        * a buffer, or the DMA controller just switched to the
-        * next toggle but the interrupt hasn't been serviced yet.
-        * The former case is straight forward.  In the later case,
-        * we'll do like if DMA is just at the end of the previous
-        * toggle since all registers haven't been reset yet.
-        * This goes around the edge case and since we're always
-        * a little behind anyways it shouldn't make a big difference.
-        * If DMA has been stopped prior calling this then the
-        * position is exact.
-        */
-       status = regs->RdDCSR;
-       if ((!(status & DCSR_BIU) &&  (status & DCSR_STRTA)) ||
-           ( (status & DCSR_BIU) && !(status & DCSR_STRTB)))
-               return regs->DBSA;
-       else
-               return regs->DBSB;
-}
-
-
-/**
- *     sa1100_reset_dma - reset a DMA channel
- *     @regs: identifier for the channel to use
- *
- *     This function resets and reconfigure the given DMA channel. This is
- *     particularly useful after a sleep/wakeup event.
- *
- *     The @regs identifier is provided by a successful call to
- *     sa1100_request_dma().
- **/
-
-void sa1100_reset_dma(dma_regs_t *regs)
-{
-       int i;
-
-       for (i = 0; i < SA1100_DMA_CHANNELS; i++)
-               if (regs == (dma_regs_t *)&DDAR(i))
-                       break;
-       if (i >= SA1100_DMA_CHANNELS) {
-               printk(KERN_ERR "%s: bad DMA identifier\n", __func__);
-               return;
-       }
-
-       regs->ClrDCSR =
-               (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
-                DCSR_IE | DCSR_ERROR | DCSR_RUN);
-       regs->DDAR = dma_chan[i].device;
-}
-
-
-EXPORT_SYMBOL(sa1100_request_dma);
-EXPORT_SYMBOL(sa1100_free_dma);
-EXPORT_SYMBOL(sa1100_start_dma);
-EXPORT_SYMBOL(sa1100_get_dma_pos);
-EXPORT_SYMBOL(sa1100_reset_dma);
-
index bb10ee2..b184704 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/pm.h>
 #include <linux/cpufreq.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 
+#include <video/sa1100fb.h>
+
 #include <asm/div64.h>
-#include <mach/hardware.h>
 #include <asm/system.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 #include <asm/irq.h>
 
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
 #include "generic.h"
 
 unsigned int reset_status;
@@ -149,16 +154,8 @@ static void sa11x0_register_device(struct platform_device *dev, void *data)
 
 
 static struct resource sa11x0udc_resources[] = {
-       [0] = {
-               .start  = __PREG(Ser0UDCCR),
-               .end    = __PREG(Ser0UDCCR) + 0xffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_Ser0UDC,
-               .end    = IRQ_Ser0UDC,
-               .flags  = IORESOURCE_IRQ,
-       },
+       [0] = DEFINE_RES_MEM(__PREG(Ser0UDCCR), SZ_64K),
+       [1] = DEFINE_RES_IRQ(IRQ_Ser0UDC),
 };
 
 static u64 sa11x0udc_dma_mask = 0xffffffffUL;
@@ -175,16 +172,8 @@ static struct platform_device sa11x0udc_device = {
 };
 
 static struct resource sa11x0uart1_resources[] = {
-       [0] = {
-               .start  = __PREG(Ser1UTCR0),
-               .end    = __PREG(Ser1UTCR0) + 0xffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_Ser1UART,
-               .end    = IRQ_Ser1UART,
-               .flags  = IORESOURCE_IRQ,
-       },
+       [0] = DEFINE_RES_MEM(__PREG(Ser1UTCR0), SZ_64K),
+       [1] = DEFINE_RES_IRQ(IRQ_Ser1UART),
 };
 
 static struct platform_device sa11x0uart1_device = {
@@ -195,16 +184,8 @@ static struct platform_device sa11x0uart1_device = {
 };
 
 static struct resource sa11x0uart3_resources[] = {
-       [0] = {
-               .start  = __PREG(Ser3UTCR0),
-               .end    = __PREG(Ser3UTCR0) + 0xffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_Ser3UART,
-               .end    = IRQ_Ser3UART,
-               .flags  = IORESOURCE_IRQ,
-       },
+       [0] = DEFINE_RES_MEM(__PREG(Ser3UTCR0), SZ_64K),
+       [1] = DEFINE_RES_IRQ(IRQ_Ser3UART),
 };
 
 static struct platform_device sa11x0uart3_device = {
@@ -215,16 +196,9 @@ static struct platform_device sa11x0uart3_device = {
 };
 
 static struct resource sa11x0mcp_resources[] = {
-       [0] = {
-               .start  = __PREG(Ser4MCCR0),
-               .end    = __PREG(Ser4MCCR0) + 0xffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_Ser4MCP,
-               .end    = IRQ_Ser4MCP,
-               .flags  = IORESOURCE_IRQ,
-       },
+       [0] = DEFINE_RES_MEM(__PREG(Ser4MCCR0), SZ_64K),
+       [1] = DEFINE_RES_MEM(__PREG(Ser4MCCR1), 4),
+       [2] = DEFINE_RES_IRQ(IRQ_Ser4MCP),
 };
 
 static u64 sa11x0mcp_dma_mask = 0xffffffffUL;
@@ -240,22 +214,24 @@ static struct platform_device sa11x0mcp_device = {
        .resource       = sa11x0mcp_resources,
 };
 
+void __init sa11x0_ppc_configure_mcp(void)
+{
+       /* Setup the PPC unit for the MCP */
+       PPDR &= ~PPC_RXD4;
+       PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
+       PSDR |= PPC_RXD4;
+       PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+       PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+}
+
 void sa11x0_register_mcp(struct mcp_plat_data *data)
 {
        sa11x0_register_device(&sa11x0mcp_device, data);
 }
 
 static struct resource sa11x0ssp_resources[] = {
-       [0] = {
-               .start  = 0x80070000,
-               .end    = 0x8007ffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_Ser4SSP,
-               .end    = IRQ_Ser4SSP,
-               .flags  = IORESOURCE_IRQ,
-       },
+       [0] = DEFINE_RES_MEM(0x80070000, SZ_64K),
+       [1] = DEFINE_RES_IRQ(IRQ_Ser4SSP),
 };
 
 static u64 sa11x0ssp_dma_mask = 0xffffffffUL;
@@ -272,16 +248,8 @@ static struct platform_device sa11x0ssp_device = {
 };
 
 static struct resource sa11x0fb_resources[] = {
-       [0] = {
-               .start  = 0xb0100000,
-               .end    = 0xb010ffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_LCD,
-               .end    = IRQ_LCD,
-               .flags  = IORESOURCE_IRQ,
-       },
+       [0] = DEFINE_RES_MEM(0xb0100000, SZ_64K),
+       [1] = DEFINE_RES_IRQ(IRQ_LCD),
 };
 
 static struct platform_device sa11x0fb_device = {
@@ -294,6 +262,11 @@ static struct platform_device sa11x0fb_device = {
        .resource       = sa11x0fb_resources,
 };
 
+void sa11x0_register_lcd(struct sa1100fb_mach_info *inf)
+{
+       sa11x0_register_device(&sa11x0fb_device, inf);
+}
+
 static struct platform_device sa11x0pcmcia_device = {
        .name           = "sa11x0-pcmcia",
        .id             = -1,
@@ -314,23 +287,10 @@ void sa11x0_register_mtd(struct flash_platform_data *flash,
 }
 
 static struct resource sa11x0ir_resources[] = {
-       {
-               .start  = __PREG(Ser2UTCR0),
-               .end    = __PREG(Ser2UTCR0) + 0x24 - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = __PREG(Ser2HSCR0),
-               .end    = __PREG(Ser2HSCR0) + 0x1c - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = __PREG(Ser2HSCR2),
-               .end    = __PREG(Ser2HSCR2) + 0x04 - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = IRQ_Ser2ICP,
-               .end    = IRQ_Ser2ICP,
-               .flags  = IORESOURCE_IRQ,
-       }
+       DEFINE_RES_MEM(__PREG(Ser2UTCR0), 0x24),
+       DEFINE_RES_MEM(__PREG(Ser2HSCR0), 0x1c),
+       DEFINE_RES_MEM(__PREG(Ser2HSCR2), 0x04),
+       DEFINE_RES_IRQ(IRQ_Ser2ICP),
 };
 
 static struct platform_device sa11x0ir_device = {
@@ -350,14 +310,37 @@ static struct platform_device sa11x0rtc_device = {
        .id             = -1,
 };
 
+static struct resource sa11x0dma_resources[] = {
+       DEFINE_RES_MEM(DMA_PHYS, DMA_SIZE),
+       DEFINE_RES_IRQ(IRQ_DMA0),
+       DEFINE_RES_IRQ(IRQ_DMA1),
+       DEFINE_RES_IRQ(IRQ_DMA2),
+       DEFINE_RES_IRQ(IRQ_DMA3),
+       DEFINE_RES_IRQ(IRQ_DMA4),
+       DEFINE_RES_IRQ(IRQ_DMA5),
+};
+
+static u64 sa11x0dma_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device sa11x0dma_device = {
+       .name           = "sa11x0-dma",
+       .id             = -1,
+       .dev = {
+               .dma_mask = &sa11x0dma_dma_mask,
+               .coherent_dma_mask = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(sa11x0dma_resources),
+       .resource       = sa11x0dma_resources,
+};
+
 static struct platform_device *sa11x0_devices[] __initdata = {
        &sa11x0udc_device,
        &sa11x0uart1_device,
        &sa11x0uart3_device,
        &sa11x0ssp_device,
        &sa11x0pcmcia_device,
-       &sa11x0fb_device,
        &sa11x0rtc_device,
+       &sa11x0dma_device,
 };
 
 static int __init sa1100_init(void)
@@ -368,12 +351,6 @@ static int __init sa1100_init(void)
 
 arch_initcall(sa1100_init);
 
-void (*sa1100fb_backlight_power)(int on);
-void (*sa1100fb_lcd_power)(int on);
-
-EXPORT_SYMBOL(sa1100fb_backlight_power);
-EXPORT_SYMBOL(sa1100fb_lcd_power);
-
 
 /*
  * Common I/O mapping:
@@ -428,7 +405,7 @@ void __init sa1100_map_io(void)
  * the MBGNT signal false to ensure the SA1111 doesn't own the
  * SDRAM bus.
  */
-void __init sa1110_mb_disable(void)
+void sa1110_mb_disable(void)
 {
        unsigned long flags;
 
@@ -447,7 +424,7 @@ void __init sa1110_mb_disable(void)
  * If the system is going to use the SA-1111 DMA engines, set up
  * the memory bus request/grant pins.
  */
-void __devinit sa1110_mb_enable(void)
+void sa1110_mb_enable(void)
 {
        unsigned long flags;
 
index 33268cf..9eb3b3c 100644 (file)
@@ -16,9 +16,6 @@ extern void sa11x0_restart(char, const char *);
        mi->bank[__nr].start = (__start), \
        mi->bank[__nr].size = (__size)
 
-extern void (*sa1100fb_backlight_power)(int on);
-extern void (*sa1100fb_lcd_power)(int on);
-
 extern void sa1110_mb_enable(void);
 extern void sa1110_mb_disable(void);
 
@@ -39,4 +36,8 @@ struct irda_platform_data;
 void sa11x0_register_irda(struct irda_platform_data *irda);
 
 struct mcp_plat_data;
+void sa11x0_ppc_configure_mcp(void);
 void sa11x0_register_mcp(struct mcp_plat_data *data);
+
+struct sa1100fb_mach_info;
+void sa11x0_register_lcd(struct sa1100fb_mach_info *inf);
index 1e6b3c1..b2e8d0f 100644 (file)
 #include <linux/kernel.h>
 #include <linux/gpio.h>
 
+#include <video/sa1100fb.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irda.h>
 
 #include <mach/h3xxx.h>
+#include <mach/irqs.h>
 
 #include "generic.h"
 
@@ -36,13 +39,28 @@ static void h3100_lcd_power(int enable)
        }
 }
 
+static struct sa1100fb_mach_info h3100_lcd_info = {
+       .pixclock       = 406977,       .bpp            = 4,
+       .xres           = 320,          .yres           = 240,
+
+       .hsync_len      = 26,           .vsync_len      = 41,
+       .left_margin    = 4,            .upper_margin   = 0,
+       .right_margin   = 4,            .lower_margin   = 0,
+
+       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+       .cmap_greyscale = 1,
+       .cmap_inverse   = 1,
+
+       .lccr0          = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
+       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+
+       .lcd_power = h3100_lcd_power,
+};
 
 static void __init h3100_map_io(void)
 {
        h3xxx_map_io();
 
-       sa1100fb_lcd_power = h3100_lcd_power;
-
        /* Older bootldrs put GPIO2-9 in alternate mode on the
           assumption that they are used for video */
        GAFR &= ~0x000001fb;
@@ -80,12 +98,15 @@ static void __init h3100_mach_init(void)
 {
        h3xxx_init_gpio(h3100_default_gpio, ARRAY_SIZE(h3100_default_gpio));
        h3xxx_mach_init();
+
+       sa11x0_register_lcd(&h3100_lcd_info);
        sa11x0_register_irda(&h3100_irda_data);
 }
 
 MACHINE_START(H3100, "Compaq iPAQ H3100")
        .atag_offset    = 0x100,
        .map_io         = h3100_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
        .init_machine   = h3100_mach_init,
index 6b58e74..cb6659f 100644 (file)
 #include <linux/kernel.h>
 #include <linux/gpio.h>
 
+#include <video/sa1100fb.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irda.h>
 
 #include <mach/h3xxx.h>
+#include <mach/irqs.h>
 
 #include "generic.h"
 
@@ -56,11 +59,35 @@ err2:       gpio_free(H3XXX_EGPIO_LCD_ON);
 err1:  return;
 }
 
+static const struct sa1100fb_rgb h3600_rgb_16 = {
+       .red    = { .offset = 12, .length = 4, },
+       .green  = { .offset = 7,  .length = 4, },
+       .blue   = { .offset = 1,  .length = 4, },
+       .transp = { .offset = 0,  .length = 0, },
+};
+
+static struct sa1100fb_mach_info h3600_lcd_info = {
+       .pixclock       = 174757,       .bpp            = 16,
+       .xres           = 320,          .yres           = 240,
+
+       .hsync_len      = 3,            .vsync_len      = 3,
+       .left_margin    = 12,           .upper_margin   = 10,
+       .right_margin   = 17,           .lower_margin   = 1,
+
+       .cmap_static    = 1,
+
+       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+
+       .rgb[RGB_16] = &h3600_rgb_16,
+
+       .lcd_power = h3600_lcd_power,
+};
+
+
 static void __init h3600_map_io(void)
 {
        h3xxx_map_io();
-
-       sa1100fb_lcd_power = h3600_lcd_power;
 }
 
 /*
@@ -121,12 +148,15 @@ static void __init h3600_mach_init(void)
 {
        h3xxx_init_gpio(h3600_default_gpio, ARRAY_SIZE(h3600_default_gpio));
        h3xxx_mach_init();
+
+       sa11x0_register_lcd(&h3600_lcd_info);
        sa11x0_register_irda(&h3600_irda_data);
 }
 
 MACHINE_START(H3600, "Compaq iPAQ H3600")
        .atag_offset    = 0x100,
        .map_io         = h3600_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
        .init_machine   = h3600_mach_init,
index b0784c9..63150e1 100644 (file)
@@ -109,11 +109,8 @@ static struct flash_platform_data h3xxx_flash_data = {
        .nr_parts       = ARRAY_SIZE(h3xxx_partitions),
 };
 
-static struct resource h3xxx_flash_resource = {
-       .start          = SA1100_CS0_PHYS,
-       .end            = SA1100_CS0_PHYS + SZ_32M - 1,
-       .flags          = IORESOURCE_MEM,
-};
+static struct resource h3xxx_flash_resource =
+       DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M);
 
 
 /*
@@ -186,11 +183,7 @@ static struct sa1100_port_fns h3xxx_port_fns __initdata = {
  */
 
 static struct resource egpio_resources[] = {
-       [0] = {
-               .start  = H3600_EGPIO_PHYS,
-               .end    = H3600_EGPIO_PHYS + 0x4 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
+       [0] = DEFINE_RES_MEM(H3600_EGPIO_PHYS, 0x4),
 };
 
 static struct htc_egpio_chip egpio_chips[] = {
index c01bb36..5535475 100644 (file)
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/irq.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
@@ -35,6 +33,9 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/serial_sa1100.h>
 
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
 #include "generic.h"
 
 /**********************************************************************
@@ -179,11 +180,8 @@ static struct flash_platform_data hackkit_flash_data = {
        .nr_parts       = ARRAY_SIZE(hackkit_partitions),
 };
 
-static struct resource hackkit_flash_resource = {
-       .start          = SA1100_CS0_PHYS,
-       .end            = SA1100_CS0_PHYS + SZ_32M,
-       .flags          = IORESOURCE_MEM,
-};
+static struct resource hackkit_flash_resource =
+       DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M);
 
 static void __init hackkit_init(void)
 {
@@ -197,6 +195,7 @@ static void __init hackkit_init(void)
 MACHINE_START(HACKKIT, "HackKit Cpu Board")
        .atag_offset    = 0x100,
        .map_io         = hackkit_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
        .init_machine   = hackkit_init,
index bae8296..3f2d1b6 100644 (file)
 
 /*
  * Direct Memory Access (DMA) control registers
- *
- * Registers
- *    DDAR0            Direct Memory Access (DMA) Device Address Register
- *                     channel 0 (read/write).
- *    DCSR0            Direct Memory Access (DMA) Control and Status
- *                     Register channel 0 (read/write).
- *    DBSA0            Direct Memory Access (DMA) Buffer Start address
- *                     register A channel 0 (read/write).
- *    DBTA0            Direct Memory Access (DMA) Buffer Transfer count
- *                     register A channel 0 (read/write).
- *    DBSB0            Direct Memory Access (DMA) Buffer Start address
- *                     register B channel 0 (read/write).
- *    DBTB0            Direct Memory Access (DMA) Buffer Transfer count
- *                     register B channel 0 (read/write).
- *
- *    DDAR1            Direct Memory Access (DMA) Device Address Register
- *                     channel 1 (read/write).
- *    DCSR1            Direct Memory Access (DMA) Control and Status
- *                     Register channel 1 (read/write).
- *    DBSA1            Direct Memory Access (DMA) Buffer Start address
- *                     register A channel 1 (read/write).
- *    DBTA1            Direct Memory Access (DMA) Buffer Transfer count
- *                     register A channel 1 (read/write).
- *    DBSB1            Direct Memory Access (DMA) Buffer Start address
- *                     register B channel 1 (read/write).
- *    DBTB1            Direct Memory Access (DMA) Buffer Transfer count
- *                     register B channel 1 (read/write).
- *
- *    DDAR2            Direct Memory Access (DMA) Device Address Register
- *                     channel 2 (read/write).
- *    DCSR2            Direct Memory Access (DMA) Control and Status
- *                     Register channel 2 (read/write).
- *    DBSA2            Direct Memory Access (DMA) Buffer Start address
- *                     register A channel 2 (read/write).
- *    DBTA2            Direct Memory Access (DMA) Buffer Transfer count
- *                     register A channel 2 (read/write).
- *    DBSB2            Direct Memory Access (DMA) Buffer Start address
- *                     register B channel 2 (read/write).
- *    DBTB2            Direct Memory Access (DMA) Buffer Transfer count
- *                     register B channel 2 (read/write).
- *
- *    DDAR3            Direct Memory Access (DMA) Device Address Register
- *                     channel 3 (read/write).
- *    DCSR3            Direct Memory Access (DMA) Control and Status
- *                     Register channel 3 (read/write).
- *    DBSA3            Direct Memory Access (DMA) Buffer Start address
- *                     register A channel 3 (read/write).
- *    DBTA3            Direct Memory Access (DMA) Buffer Transfer count
- *                     register A channel 3 (read/write).
- *    DBSB3            Direct Memory Access (DMA) Buffer Start address
- *                     register B channel 3 (read/write).
- *    DBTB3            Direct Memory Access (DMA) Buffer Transfer count
- *                     register B channel 3 (read/write).
- *
- *    DDAR4            Direct Memory Access (DMA) Device Address Register
- *                     channel 4 (read/write).
- *    DCSR4            Direct Memory Access (DMA) Control and Status
- *                     Register channel 4 (read/write).
- *    DBSA4            Direct Memory Access (DMA) Buffer Start address
- *                     register A channel 4 (read/write).
- *    DBTA4            Direct Memory Access (DMA) Buffer Transfer count
- *                     register A channel 4 (read/write).
- *    DBSB4            Direct Memory Access (DMA) Buffer Start address
- *                     register B channel 4 (read/write).
- *    DBTB4            Direct Memory Access (DMA) Buffer Transfer count
- *                     register B channel 4 (read/write).
- *
- *    DDAR5            Direct Memory Access (DMA) Device Address Register
- *                     channel 5 (read/write).
- *    DCSR5            Direct Memory Access (DMA) Control and Status
- *                     Register channel 5 (read/write).
- *    DBSA5            Direct Memory Access (DMA) Buffer Start address
- *                     register A channel 5 (read/write).
- *    DBTA5            Direct Memory Access (DMA) Buffer Transfer count
- *                     register A channel 5 (read/write).
- *    DBSB5            Direct Memory Access (DMA) Buffer Start address
- *                     register B channel 5 (read/write).
- *    DBTB5            Direct Memory Access (DMA) Buffer Transfer count
- *                     register B channel 5 (read/write).
  */
-
-#define DMASp          0x00000020      /* DMA control reg. Space [byte]   */
-
-#define DDAR(Nb)       __REG(0xB0000000 + (Nb)*DMASp)  /* DMA Device Address Reg. channel [0..5] */
-#define SetDCSR(Nb)    __REG(0xB0000004 + (Nb)*DMASp)  /* Set DMA Control & Status Reg. channel [0..5] (write) */
-#define ClrDCSR(Nb)    __REG(0xB0000008 + (Nb)*DMASp)  /* Clear DMA Control & Status Reg. channel [0..5] (write) */
-#define RdDCSR(Nb)     __REG(0xB000000C + (Nb)*DMASp)  /* Read DMA Control & Status Reg. channel [0..5] (read) */
-#define DBSA(Nb)       __REG(0xB0000010 + (Nb)*DMASp)  /* DMA Buffer Start address reg. A channel [0..5] */
-#define DBTA(Nb)       __REG(0xB0000014 + (Nb)*DMASp)  /* DMA Buffer Transfer count reg. A channel [0..5] */
-#define DBSB(Nb)       __REG(0xB0000018 + (Nb)*DMASp)  /* DMA Buffer Start address reg. B channel [0..5] */
-#define DBTB(Nb)       __REG(0xB000001C + (Nb)*DMASp)  /* DMA Buffer Transfer count reg. B channel [0..5] */
-
-#define DDAR_RW        0x00000001      /* device data Read/Write          */
-#define DDAR_DevWr     (DDAR_RW*0)     /*  Device data Write              */
-                                       /*  (memory -> device)             */
-#define DDAR_DevRd     (DDAR_RW*1)     /*  Device data Read               */
-                                       /*  (device -> memory)             */
-#define DDAR_E         0x00000002      /* big/little Endian device        */
-#define DDAR_LtlEnd    (DDAR_E*0)      /*  Little Endian device           */
-#define DDAR_BigEnd    (DDAR_E*1)      /*  Big Endian device              */
-#define DDAR_BS        0x00000004      /* device Burst Size               */
-#define DDAR_Brst4     (DDAR_BS*0)     /*  Burst-of-4 device              */
-#define DDAR_Brst8     (DDAR_BS*1)     /*  Burst-of-8 device              */
-#define DDAR_DW        0x00000008      /* device Data Width               */
-#define DDAR_8BitDev   (DDAR_DW*0)     /*  8-Bit Device                   */
-#define DDAR_16BitDev  (DDAR_DW*1)     /*  16-Bit Device                  */
-#define DDAR_DS        Fld (4, 4)      /* Device Select                   */
-#define DDAR_Ser0UDCTr                 /*  Ser. port 0 UDC Transmit       */ \
-                       (0x0 << FShft (DDAR_DS))
-#define DDAR_Ser0UDCRc                 /*  Ser. port 0 UDC Receive        */ \
-                       (0x1 << FShft (DDAR_DS))
-#define DDAR_Ser1SDLCTr                        /*  Ser. port 1 SDLC Transmit      */ \
-                       (0x2 << FShft (DDAR_DS))
-#define DDAR_Ser1SDLCRc                        /*  Ser. port 1 SDLC Receive       */ \
-                       (0x3 << FShft (DDAR_DS))
-#define DDAR_Ser1UARTTr                        /*  Ser. port 1 UART Transmit      */ \
-                       (0x4 << FShft (DDAR_DS))
-#define DDAR_Ser1UARTRc                        /*  Ser. port 1 UART Receive       */ \
-                       (0x5 << FShft (DDAR_DS))
-#define DDAR_Ser2ICPTr                 /*  Ser. port 2 ICP Transmit       */ \
-                       (0x6 << FShft (DDAR_DS))
-#define DDAR_Ser2ICPRc                 /*  Ser. port 2 ICP Receive        */ \
-                       (0x7 << FShft (DDAR_DS))
-#define DDAR_Ser3UARTTr                        /*  Ser. port 3 UART Transmit      */ \
-                       (0x8 << FShft (DDAR_DS))
-#define DDAR_Ser3UARTRc                        /*  Ser. port 3 UART Receive       */ \
-                       (0x9 << FShft (DDAR_DS))
-#define DDAR_Ser4MCP0Tr                        /*  Ser. port 4 MCP 0 Transmit     */ \
-                                       /*  (audio)                        */ \
-                       (0xA << FShft (DDAR_DS))
-#define DDAR_Ser4MCP0Rc                        /*  Ser. port 4 MCP 0 Receive      */ \
-                                       /*  (audio)                        */ \
-                       (0xB << FShft (DDAR_DS))
-#define DDAR_Ser4MCP1Tr                        /*  Ser. port 4 MCP 1 Transmit     */ \
-                                       /*  (telecom)                      */ \
-                       (0xC << FShft (DDAR_DS))
-#define DDAR_Ser4MCP1Rc                        /*  Ser. port 4 MCP 1 Receive      */ \
-                                       /*  (telecom)                      */ \
-                       (0xD << FShft (DDAR_DS))
-#define DDAR_Ser4SSPTr                 /*  Ser. port 4 SSP Transmit       */ \
-                       (0xE << FShft (DDAR_DS))
-#define DDAR_Ser4SSPRc                 /*  Ser. port 4 SSP Receive        */ \
-                       (0xF << FShft (DDAR_DS))
-#define DDAR_DA        Fld (24, 8)     /* Device Address                  */
-#define DDAR_DevAdd(Add)               /*  Device Address                 */ \
-                       (((Add) & 0xF0000000) | \
-                        (((Add) & 0X003FFFFC) << (FShft (DDAR_DA) - 2)))
-#define DDAR_Ser0UDCWr                 /* Ser. port 0 UDC Write           */ \
-                       (DDAR_DevWr + DDAR_Brst8 + DDAR_8BitDev + \
-                        DDAR_Ser0UDCTr + DDAR_DevAdd (__PREG(Ser0UDCDR)))
-#define DDAR_Ser0UDCRd                 /* Ser. port 0 UDC Read            */ \
-                       (DDAR_DevRd + DDAR_Brst8 + DDAR_8BitDev + \
-                        DDAR_Ser0UDCRc + DDAR_DevAdd (__PREG(Ser0UDCDR)))
-#define DDAR_Ser1UARTWr                        /* Ser. port 1 UART Write          */ \
-                       (DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \
-                        DDAR_Ser1UARTTr + DDAR_DevAdd (__PREG(Ser1UTDR)))
-#define DDAR_Ser1UARTRd                        /* Ser. port 1 UART Read           */ \
-                       (DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \
-                        DDAR_Ser1UARTRc + DDAR_DevAdd (__PREG(Ser1UTDR)))
-#define DDAR_Ser1SDLCWr                        /* Ser. port 1 SDLC Write          */ \
-                       (DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \
-                        DDAR_Ser1SDLCTr + DDAR_DevAdd (__PREG(Ser1SDDR)))
-#define DDAR_Ser1SDLCRd                        /* Ser. port 1 SDLC Read           */ \
-                       (DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \
-                        DDAR_Ser1SDLCRc + DDAR_DevAdd (__PREG(Ser1SDDR)))
-#define DDAR_Ser2UARTWr                        /* Ser. port 2 UART Write          */ \
-                       (DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \
-                        DDAR_Ser2ICPTr + DDAR_DevAdd (__PREG(Ser2UTDR)))
-#define DDAR_Ser2UARTRd                        /* Ser. port 2 UART Read           */ \
-                       (DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \
-                        DDAR_Ser2ICPRc + DDAR_DevAdd (__PREG(Ser2UTDR)))
-#define DDAR_Ser2HSSPWr                        /* Ser. port 2 HSSP Write          */ \
-                       (DDAR_DevWr + DDAR_Brst8 + DDAR_8BitDev + \
-                        DDAR_Ser2ICPTr + DDAR_DevAdd (__PREG(Ser2HSDR)))
-#define DDAR_Ser2HSSPRd                        /* Ser. port 2 HSSP Read           */ \
-                       (DDAR_DevRd + DDAR_Brst8 + DDAR_8BitDev + \
-                        DDAR_Ser2ICPRc + DDAR_DevAdd (__PREG(Ser2HSDR)))
-#define DDAR_Ser3UARTWr                        /* Ser. port 3 UART Write          */ \
-                       (DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \
-                        DDAR_Ser3UARTTr + DDAR_DevAdd (__PREG(Ser3UTDR)))
-#define DDAR_Ser3UARTRd                        /* Ser. port 3 UART Read           */ \
-                       (DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \
-                        DDAR_Ser3UARTRc + DDAR_DevAdd (__PREG(Ser3UTDR)))
-#define DDAR_Ser4MCP0Wr                        /* Ser. port 4 MCP 0 Write (audio) */ \
-                       (DDAR_DevWr + DDAR_Brst4 + DDAR_16BitDev + \
-                        DDAR_Ser4MCP0Tr + DDAR_DevAdd (__PREG(Ser4MCDR0)))
-#define DDAR_Ser4MCP0Rd                        /* Ser. port 4 MCP 0 Read (audio)  */ \
-                       (DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \
-                        DDAR_Ser4MCP0Rc + DDAR_DevAdd (__PREG(Ser4MCDR0)))
-#define DDAR_Ser4MCP1Wr                        /* Ser. port 4 MCP 1 Write         */ \
-                                       /* (telecom)                       */ \
-                       (DDAR_DevWr + DDAR_Brst4 + DDAR_16BitDev + \
-                        DDAR_Ser4MCP1Tr + DDAR_DevAdd (__PREG(Ser4MCDR1)))
-#define DDAR_Ser4MCP1Rd                        /* Ser. port 4 MCP 1 Read          */ \
-                                       /* (telecom)                       */ \
-                       (DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \
-                        DDAR_Ser4MCP1Rc + DDAR_DevAdd (__PREG(Ser4MCDR1)))
-#define DDAR_Ser4SSPWr                 /* Ser. port 4 SSP Write (16 bits) */ \
-                       (DDAR_DevWr + DDAR_Brst4 + DDAR_16BitDev + \
-                        DDAR_Ser4SSPTr + DDAR_DevAdd (__PREG(Ser4SSDR)))
-#define DDAR_Ser4SSPRd                 /* Ser. port 4 SSP Read (16 bits)  */ \
-                       (DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \
-                        DDAR_Ser4SSPRc + DDAR_DevAdd (__PREG(Ser4SSDR)))
-
-#define DCSR_RUN       0x00000001      /* DMA running                     */
-#define DCSR_IE        0x00000002      /* DMA Interrupt Enable            */
-#define DCSR_ERROR     0x00000004      /* DMA ERROR                       */
-#define DCSR_DONEA     0x00000008      /* DONE DMA transfer buffer A      */
-#define DCSR_STRTA     0x00000010      /* STaRTed DMA transfer buffer A   */
-#define DCSR_DONEB     0x00000020      /* DONE DMA transfer buffer B      */
-#define DCSR_STRTB     0x00000040      /* STaRTed DMA transfer buffer B   */
-#define DCSR_BIU       0x00000080      /* DMA Buffer In Use               */
-#define DCSR_BufA      (DCSR_BIU*0)    /*  DMA Buffer A in use            */
-#define DCSR_BufB      (DCSR_BIU*1)    /*  DMA Buffer B in use            */
-
-#define DBT_TC         Fld (13, 0)     /* Transfer Count                  */
-#define DBTA_TCA       DBT_TC          /* Transfer Count buffer A         */
-#define DBTB_TCB       DBT_TC          /* Transfer Count buffer B         */
+#define DMA_SIZE       (6 * 0x20)
+#define DMA_PHYS       0xb0000000
 
 
 /*
 #define LCD_Int100_0A  0xF             /* LCD Intensity = 100.0% =  1     */
                                        /* (Alternative)                   */
 
-#define LCCR0          __REG(0xB0100000)  /* LCD Control Reg. 0 */
-#define LCSR           __REG(0xB0100004)  /* LCD Status Reg. */
-#define DBAR1          __REG(0xB0100010)  /* LCD DMA Base Address Reg. channel 1 */
-#define DCAR1          __REG(0xB0100014)  /* LCD DMA Current Address Reg. channel 1 */
-#define DBAR2          __REG(0xB0100018)  /* LCD DMA Base Address Reg.  channel 2 */
-#define DCAR2          __REG(0xB010001C)  /* LCD DMA Current Address Reg. channel 2 */
-#define LCCR1          __REG(0xB0100020)  /* LCD Control Reg. 1 */
-#define LCCR2          __REG(0xB0100024)  /* LCD Control Reg. 2 */
-#define LCCR3          __REG(0xB0100028)  /* LCD Control Reg. 3 */
-
 #define LCCR0_LEN      0x00000001      /* LCD ENable                      */
 #define LCCR0_CMS      0x00000002      /* Color/Monochrome display Select */
 #define LCCR0_Color    (LCCR0_CMS*0)   /*  Color display                  */
diff --git a/arch/arm/mach-sa1100/include/mach/dma.h b/arch/arm/mach-sa1100/include/mach/dma.h
deleted file mode 100644 (file)
index dda1b35..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * arch/arm/mach-sa1100/include/mach/dma.h
- *
- * Generic SA1100 DMA support
- *
- * Copyright (C) 2000 Nicolas Pitre
- *
- */
-
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#include "hardware.h"
-
-
-/*
- * The SA1100 has six internal DMA channels.
- */
-#define SA1100_DMA_CHANNELS    6
-
-/*
- * Maximum physical DMA buffer size
- */
-#define MAX_DMA_SIZE           0x1fff
-#define CUT_DMA_SIZE           0x1000
-
-/*
- * All possible SA1100 devices a DMA channel can be attached to.
- */
-typedef enum {
-       DMA_Ser0UDCWr  = DDAR_Ser0UDCWr,   /* Ser. port 0 UDC Write */
-       DMA_Ser0UDCRd  = DDAR_Ser0UDCRd,   /* Ser. port 0 UDC Read */
-       DMA_Ser1UARTWr = DDAR_Ser1UARTWr,  /* Ser. port 1 UART Write */
-       DMA_Ser1UARTRd = DDAR_Ser1UARTRd,  /* Ser. port 1 UART Read */
-       DMA_Ser1SDLCWr = DDAR_Ser1SDLCWr,  /* Ser. port 1 SDLC Write */
-       DMA_Ser1SDLCRd = DDAR_Ser1SDLCRd,  /* Ser. port 1 SDLC Read */
-       DMA_Ser2UARTWr = DDAR_Ser2UARTWr,  /* Ser. port 2 UART Write */
-       DMA_Ser2UARTRd = DDAR_Ser2UARTRd,  /* Ser. port 2 UART Read */
-       DMA_Ser2HSSPWr = DDAR_Ser2HSSPWr,  /* Ser. port 2 HSSP Write */
-       DMA_Ser2HSSPRd = DDAR_Ser2HSSPRd,  /* Ser. port 2 HSSP Read */
-       DMA_Ser3UARTWr = DDAR_Ser3UARTWr,  /* Ser. port 3 UART Write */
-       DMA_Ser3UARTRd = DDAR_Ser3UARTRd,  /* Ser. port 3 UART Read */
-       DMA_Ser4MCP0Wr = DDAR_Ser4MCP0Wr,  /* Ser. port 4 MCP 0 Write (audio) */
-       DMA_Ser4MCP0Rd = DDAR_Ser4MCP0Rd,  /* Ser. port 4 MCP 0 Read (audio) */
-       DMA_Ser4MCP1Wr = DDAR_Ser4MCP1Wr,  /* Ser. port 4 MCP 1 Write */
-       DMA_Ser4MCP1Rd = DDAR_Ser4MCP1Rd,  /* Ser. port 4 MCP 1 Read */
-       DMA_Ser4SSPWr  = DDAR_Ser4SSPWr,   /* Ser. port 4 SSP Write (16 bits) */
-       DMA_Ser4SSPRd  = DDAR_Ser4SSPRd    /* Ser. port 4 SSP Read (16 bits) */
-} dma_device_t;
-
-typedef struct {
-       volatile u_long DDAR;
-       volatile u_long SetDCSR;
-       volatile u_long ClrDCSR;
-       volatile u_long RdDCSR;
-       volatile dma_addr_t DBSA;
-       volatile u_long DBTA;
-       volatile dma_addr_t DBSB;
-       volatile u_long DBTB;
-} dma_regs_t;
-
-typedef void (*dma_callback_t)(void *data);
-
-/*
- * DMA function prototypes
- */
-
-extern int sa1100_request_dma( dma_device_t device, const char *device_id,
-                              dma_callback_t callback, void *data,
-                              dma_regs_t **regs );
-extern void sa1100_free_dma( dma_regs_t *regs );
-extern int sa1100_start_dma( dma_regs_t *regs, dma_addr_t dma_ptr, u_int size );
-extern dma_addr_t sa1100_get_dma_pos(dma_regs_t *regs);
-extern void sa1100_reset_dma(dma_regs_t *regs);
-
-/**
- *     sa1100_stop_dma - stop DMA in progress
- *     @regs: identifier for the channel to use
- *
- *     This stops DMA without clearing buffer pointers. Unlike
- *     sa1100_clear_dma() this allows subsequent use of sa1100_resume_dma()
- *     or sa1100_get_dma_pos().
- *
- *     The @regs identifier is provided by a successful call to
- *     sa1100_request_dma().
- **/
-
-#define sa1100_stop_dma(regs)  ((regs)->ClrDCSR = DCSR_IE|DCSR_RUN)
-
-/**
- *     sa1100_resume_dma - resume DMA on a stopped channel
- *     @regs: identifier for the channel to use
- *
- *     This resumes DMA on a channel previously stopped with
- *     sa1100_stop_dma().
- *
- *     The @regs identifier is provided by a successful call to
- *     sa1100_request_dma().
- **/
-
-#define sa1100_resume_dma(regs)        ((regs)->SetDCSR = DCSR_IE|DCSR_RUN)
-
-/**
- *     sa1100_clear_dma - clear DMA pointers
- *     @regs: identifier for the channel to use
- *
- *     This clear any DMA state so the DMA engine is ready to restart
- *     with new buffers through sa1100_start_dma(). Any buffers in flight
- *     are discarded.
- *
- *     The @regs identifier is provided by a successful call to
- *     sa1100_request_dma().
- **/
-
-#define sa1100_clear_dma(regs) ((regs)->ClrDCSR = DCSR_IE|DCSR_RUN|DCSR_STRTA|DCSR_STRTB)
-
-#endif /* _ASM_ARCH_DMA_H */
index d18f21a..3790298 100644 (file)
 /*
  * Figure out the MAX IRQ number.
  *
- * If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1.
- * If we have an LoCoMo, the max IRQ is IRQ_BOARD_START + 4
- * Otherwise, we have the standard IRQs only.
+ * Neponset, SA1111 and UCB1x00 are sparse IRQ aware, so can dynamically
+ * allocate their IRQs above NR_IRQS.
+ *
+ * LoCoMo has 4 additional IRQs, but is not sparse IRQ aware, and so has
+ * to be included in the NR_IRQS calculation.
  */
-#ifdef CONFIG_SA1111
-#define NR_IRQS                        (IRQ_BOARD_END + 55)
-#elif defined(CONFIG_SHARP_LOCOMO)
-#define NR_IRQS                        (IRQ_BOARD_START + 4)
+#ifdef CONFIG_SHARP_LOCOMO
+#define NR_IRQS_LOCOMO         4
 #else
-#define NR_IRQS                        (IRQ_BOARD_START)
+#define NR_IRQS_LOCOMO         0
 #endif
 
-/*
- * Board specific IRQs.  Define them here.
- * Do not surround them with ifdefs.
- */
-#define IRQ_NEPONSET_SMC9196   (IRQ_BOARD_START + 0)
-#define IRQ_NEPONSET_USAR      (IRQ_BOARD_START + 1)
-#define IRQ_NEPONSET_SA1111    (IRQ_BOARD_START + 2)
+#ifndef NR_IRQS
+#define NR_IRQS (IRQ_BOARD_START + NR_IRQS_LOCOMO)
+#endif
+#define SA1100_NR_IRQS (IRQ_BOARD_START + NR_IRQS_LOCOMO)
index ed1a331..4b2860a 100644 (file)
@@ -16,7 +16,7 @@ struct mcp_plat_data {
        u32 mccr0;
        u32 mccr1;
        unsigned int sclk_rate;
-       int gpio_base;
+       void *codec_pdata;
 };
 
 #endif
index ffe2bc4..5516a52 100644 (file)
 /*
  * Neponset definitions: 
  */
-
-#define NEPONSET_CPLD_BASE      (0x10000000)
-#define Nep_p2v( x )            ((x) - NEPONSET_CPLD_BASE + 0xf3000000)
-#define Nep_v2p( x )            ((x) - 0xf3000000 + NEPONSET_CPLD_BASE)
-
-#define _IRR                    0x10000024      /* Interrupt Reason Register */
-#define _AUD_CTL                0x100000c0      /* Audio controls (RW)       */
-#define _MDM_CTL_0              0x100000b0      /* Modem control 0 (RW)      */
-#define _MDM_CTL_1              0x100000b4      /* Modem control 1 (RW)      */
-#define _NCR_0                 0x100000a0      /* Control Register (RW)     */
-#define _KP_X_OUT               0x10000090      /* Keypad row write (RW)     */
-#define _KP_Y_IN                0x10000080      /* Keypad column read (RO)   */
-#define _SWPK                   0x10000020      /* Switch pack (RO)          */
-#define _WHOAMI                 0x10000000      /* System ID Register (RO)   */
-
-#define _LEDS                   0x10000010      /* LEDs [31:0] (WO)          */
-
-#define IRR                     (*((volatile u_char *) Nep_p2v(_IRR)))
-#define AUD_CTL                 (*((volatile u_char *) Nep_p2v(_AUD_CTL)))
-#define MDM_CTL_0               (*((volatile u_char *) Nep_p2v(_MDM_CTL_0)))
-#define MDM_CTL_1               (*((volatile u_char *) Nep_p2v(_MDM_CTL_1)))
-#define NCR_0                  (*((volatile u_char *) Nep_p2v(_NCR_0)))
-#define KP_X_OUT                (*((volatile u_char *) Nep_p2v(_KP_X_OUT)))
-#define KP_Y_IN                 (*((volatile u_char *) Nep_p2v(_KP_Y_IN)))
-#define SWPK                    (*((volatile u_char *) Nep_p2v(_SWPK)))
-#define WHOAMI                  (*((volatile u_char *) Nep_p2v(_WHOAMI)))
-
-#define LEDS                    (*((volatile Word   *) Nep_p2v(_LEDS)))
-
-#define IRR_ETHERNET           (1<<0)
-#define IRR_USAR               (1<<1)
-#define IRR_SA1111             (1<<2)
-
-#define AUD_SEL_1341            (1<<0)
-#define AUD_MUTE_1341           (1<<1)
-
-#define MDM_CTL0_RTS1          (1 << 0)
-#define MDM_CTL0_DTR1          (1 << 1)
-#define MDM_CTL0_RTS2          (1 << 2)
-#define MDM_CTL0_DTR2          (1 << 3)
-
-#define MDM_CTL1_CTS1          (1 << 0)
-#define MDM_CTL1_DSR1          (1 << 1)
-#define MDM_CTL1_DCD1          (1 << 2)
-#define MDM_CTL1_CTS2          (1 << 3)
-#define MDM_CTL1_DSR2          (1 << 4)
-#define MDM_CTL1_DCD2          (1 << 5)
-
 #define NCR_GP01_OFF           (1<<0)
 #define NCR_TP_PWR_EN          (1<<1)
 #define NCR_MS_PWR_EN          (1<<2)
@@ -71,4 +23,8 @@
 #define NCR_A0VPP              (1<<5)
 #define NCR_A1VPP              (1<<6)
 
+void neponset_ncr_frob(unsigned int, unsigned int);
+#define neponset_ncr_set(v)    neponset_ncr_frob(0, v)
+#define neponset_ncr_clear(v)  neponset_ncr_frob(v, 0)
+
 #endif
index ec27d6e..a0d1114 100644 (file)
@@ -21,7 +21,7 @@
 #define SHANNON_GPIO_U3_RTS            GPIO_GPIO (19)  /* ?? */
 #define SHANNON_GPIO_U3_CTS            GPIO_GPIO (20)  /* ?? */
 #define SHANNON_GPIO_SENSE_12V         GPIO_GPIO (21)  /* Input, 12v flash unprotect detected */
-#define SHANNON_GPIO_DISP_EN           GPIO_GPIO (22)  /* out */
+#define SHANNON_GPIO_DISP_EN           22              /* out */
 /* XXX GPIO 23 unaccounted for */
 #define SHANNON_GPIO_EJECT_0           GPIO_GPIO (24)  /* in */
 #define SHANNON_IRQ_GPIO_EJECT_0       IRQ_GPIO24
index dfbf824..516ccc2 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/syscore_ops.h>
 
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <asm/mach/irq.h>
 
 #include "generic.h"
@@ -221,11 +222,8 @@ static struct irq_chip sa1100_normal_chip = {
        .irq_set_wake   = sa1100_set_wake,
 };
 
-static struct resource irq_resource = {
-       .name   = "irqs",
-       .start  = 0x90050000,
-       .end    = 0x9005ffff,
-};
+static struct resource irq_resource =
+       DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs");
 
 static struct sa1100irq_state {
        unsigned int    saved;
index ee121d6..ca7a7e8 100644 (file)
@@ -23,9 +23,7 @@
 #include <linux/mtd/partitions.h>
 #include <video/s1d13xxxfb.h>
 
-#include <mach/hardware.h>
 #include <asm/hardware/sa1111.h>
-#include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
@@ -34,6 +32,9 @@
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
 
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
 #include "generic.h"
 
 /*
@@ -46,7 +47,7 @@
 
 /* memory space (line 52 of HP's doc) */
 #define SA1111REGSTART 0x40000000
-#define SA1111REGLEN   0x00001fff
+#define SA1111REGLEN   0x00002000
 #define EPSONREGSTART  0x48000000
 #define EPSONREGLEN    0x00100000
 #define EPSONFBSTART   0x48200000
@@ -174,16 +175,8 @@ static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
 };
 
 static struct resource s1d13xxxfb_resources[] = {
-       [0] = {
-               .start  = EPSONFBSTART,
-               .end    = EPSONFBSTART + EPSONFBLEN,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = EPSONREGSTART,
-               .end    = EPSONREGSTART + EPSONREGLEN,
-               .flags  = IORESOURCE_MEM,
-       }
+       [0] = DEFINE_RES_MEM(EPSONFBSTART, EPSONFBLEN),
+       [1] = DEFINE_RES_MEM(EPSONREGSTART, EPSONREGLEN),
 };
 
 static struct platform_device s1d13xxxfb_device = {
@@ -197,20 +190,12 @@ static struct platform_device s1d13xxxfb_device = {
 };
 
 static struct resource sa1111_resources[] = {
-       [0] = {
-               .start          = SA1111REGSTART,
-               .end            = SA1111REGSTART + SA1111REGLEN,
-               .flags          = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start          = IRQ_GPIO1,
-               .end            = IRQ_GPIO1,
-               .flags          = IORESOURCE_IRQ,
-       },
+       [0] = DEFINE_RES_MEM(SA1111REGSTART, SA1111REGLEN),
+       [1] = DEFINE_RES_IRQ(IRQ_GPIO1),
 };
 
 static struct sa1111_platform_data sa1111_info = {
-       .irq_base       = IRQ_BOARD_END,
+       .disable_devs   = SA1111_DEVID_PS2_MSE,
 };
 
 static u64 sa1111_dmamask = 0xffffffffUL;
@@ -284,11 +269,6 @@ static struct map_desc jornada720_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(EPSONFBSTART),
                .length         = EPSONFBLEN,
                .type           = MT_DEVICE
-       }, {    /* SA-1111 */
-               .virtual        = 0xf4000000,
-               .pfn            = __phys_to_pfn(SA1111REGSTART),
-               .length         = SA1111REGLEN,
-               .type           = MT_DEVICE
        }
 };
 
@@ -352,11 +332,8 @@ static struct flash_platform_data jornada720_flash_data = {
        .nr_parts       = ARRAY_SIZE(jornada720_partitions),
 };
 
-static struct resource jornada720_flash_resource = {
-       .start          = SA1100_CS0_PHYS,
-       .end            = SA1100_CS0_PHYS + SZ_32M - 1,
-       .flags          = IORESOURCE_MEM,
-};
+static struct resource jornada720_flash_resource =
+       DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M);
 
 static void __init jornada720_mach_init(void)
 {
@@ -367,6 +344,7 @@ MACHINE_START(JORNADA720, "HP Jornada 720")
        /* Maintainer: Kristoffer Ericson <Kristoffer.Ericson@gmail.com> */
        .atag_offset    = 0x100,
        .map_io         = jornada720_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
        .init_machine   = jornada720_mach_init,
index af4e276..eb6534e 100644 (file)
@@ -6,6 +6,8 @@
 #include <linux/kernel.h>
 #include <linux/tty.h>
 
+#include <video/sa1100fb.h>
+
 #include <mach/hardware.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -15,6 +17,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
 #include <mach/mcp.h>
+#include <mach/irqs.h>
 
 #include "generic.h"
 
@@ -26,8 +29,86 @@ static struct mcp_plat_data lart_mcp_data = {
        .sclk_rate      = 11981000,
 };
 
+#ifdef LART_GREY_LCD
+static struct sa1100fb_mach_info lart_grey_info = {
+       .pixclock       = 150000,       .bpp            = 4,
+       .xres           = 320,          .yres           = 240,
+
+       .hsync_len      = 1,            .vsync_len      = 1,
+       .left_margin    = 4,            .upper_margin   = 0,
+       .right_margin   = 2,            .lower_margin   = 0,
+
+       .cmap_greyscale = 1,
+       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       .lccr0          = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
+       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
+};
+#endif
+#ifdef LART_COLOR_LCD
+static struct sa1100fb_mach_info lart_color_info = {
+       .pixclock       = 150000,       .bpp            = 16,
+       .xres           = 320,          .yres           = 240,
+
+       .hsync_len      = 2,            .vsync_len      = 3,
+       .left_margin    = 69,           .upper_margin   = 14,
+       .right_margin   = 8,            .lower_margin   = 4,
+
+       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       .lccr3          = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
+};
+#endif
+#ifdef LART_VIDEO_OUT
+static struct sa1100fb_mach_info lart_video_info = {
+       .pixclock       = 39721,        .bpp            = 16,
+       .xres           = 640,          .yres           = 480,
+
+       .hsync_len      = 95,           .vsync_len      = 2,
+       .left_margin    = 40,           .upper_margin   = 32,
+       .right_margin   = 24,           .lower_margin   = 11,
+
+       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       .lccr3          = LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
+};
+#endif
+
+#ifdef LART_KIT01_LCD
+static struct sa1100fb_mach_info lart_kit01_info = {
+       .pixclock       = 63291,        .bpp            = 16,
+       .xres           = 640,          .yres           = 480,
+
+       .hsync_len      = 64,           .vsync_len      = 3,
+       .left_margin    = 122,          .upper_margin   = 45,
+       .right_margin   = 10,           .lower_margin   = 10,
+
+       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       .lccr3          = LCCR3_OutEnH | LCCR3_PixFlEdg
+};
+#endif
+
 static void __init lart_init(void)
 {
+       struct sa1100fb_mach_info *inf = NULL;
+
+#ifdef LART_GREY_LCD
+       inf = &lart_grey_info;
+#endif
+#ifdef LART_COLOR_LCD
+       inf = &lart_color_info;
+#endif
+#ifdef LART_VIDEO_OUT
+       inf = &lart_video_info;
+#endif
+#ifdef LART_KIT01_LCD
+       inf = &lart_kit01_info;
+#endif
+
+       if (inf)
+               sa11x0_register_lcd(inf);
+
+       sa11x0_ppc_configure_mcp();
        sa11x0_register_mcp(&lart_mcp_data);
 }
 
@@ -63,6 +144,7 @@ static void __init lart_map_io(void)
 MACHINE_START(LART, "LART")
        .atag_offset    = 0x100,
        .map_io         = lart_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .init_machine   = lart_init,
        .timer          = &sa1100_timer,
index 85f6ee6..8f6446b 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <mach/hardware.h>
 #include <mach/nanoengine.h>
+#include <mach/irqs.h>
 
 #include "generic.h"
 
@@ -58,15 +59,8 @@ static struct flash_platform_data nanoengine_flash_data = {
 };
 
 static struct resource nanoengine_flash_resources[] = {
-       {
-               .start  = SA1100_CS0_PHYS,
-               .end    = SA1100_CS0_PHYS + SZ_32M - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = SA1100_CS1_PHYS,
-               .end    = SA1100_CS1_PHYS + SZ_32M - 1,
-               .flags  = IORESOURCE_MEM,
-       }
+       DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M),
+       DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_32M),
 };
 
 static struct map_desc nanoengine_io_desc[] __initdata = {
@@ -114,6 +108,7 @@ static void __init nanoengine_init(void)
 MACHINE_START(NANOENGINE, "BSE nanoEngine")
        .atag_offset    = 0x100,
        .map_io         = nanoengine_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
        .init_machine   = nanoengine_init,
index b4fa53a..6c58f01 100644 (file)
 /*
  * linux/arch/arm/mach-sa1100/neponset.c
- *
  */
-#include <linux/kernel.h>
+#include <linux/err.h>
 #include <linux/init.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
-#include <linux/serial_core.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/serial_core.h>
+#include <linux/slab.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/irq.h>
 #include <asm/mach/map.h>
-#include <asm/mach/irq.h>
 #include <asm/mach/serial_sa1100.h>
-#include <mach/assabet.h>
-#include <mach/neponset.h>
 #include <asm/hardware/sa1111.h>
 #include <asm/sizes.h>
 
-/*
- * Install handler for Neponset IRQ.  Note that we have to loop here
- * since the ETHERNET and USAR IRQs are level based, and we need to
- * ensure that the IRQ signal is deasserted before returning.  This
- * is rather unfortunate.
- */
-static void
-neponset_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-       unsigned int irr;
-
-       while (1) {
-               /*
-                * Acknowledge the parent IRQ.
-                */
-               desc->irq_data.chip->irq_ack(&desc->irq_data);
-
-               /*
-                * Read the interrupt reason register.  Let's have all
-                * active IRQ bits high.  Note: there is a typo in the
-                * Neponset user's guide for the SA1111 IRR level.
-                */
-               irr = IRR ^ (IRR_ETHERNET | IRR_USAR);
-
-               if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0)
-                       break;
-
-               /*
-                * Since there is no individual mask, we have to
-                * mask the parent IRQ.  This is safe, since we'll
-                * recheck the register for any pending IRQs.
-                */
-               if (irr & (IRR_ETHERNET | IRR_USAR)) {
-                       desc->irq_data.chip->irq_mask(&desc->irq_data);
-
-                       /*
-                        * Ack the interrupt now to prevent re-entering
-                        * this neponset handler.  Again, this is safe
-                        * since we'll check the IRR register prior to
-                        * leaving.
-                        */
-                       desc->irq_data.chip->irq_ack(&desc->irq_data);
+#include <mach/hardware.h>
+#include <mach/assabet.h>
+#include <mach/neponset.h>
+#include <mach/irqs.h>
+
+#define NEP_IRQ_SMC91X 0
+#define NEP_IRQ_USAR   1
+#define NEP_IRQ_SA1111 2
+#define NEP_IRQ_NR     3
+
+#define WHOAMI         0x00
+#define LEDS           0x10
+#define SWPK           0x20
+#define IRR            0x24
+#define KP_Y_IN                0x80
+#define KP_X_OUT       0x90
+#define NCR_0          0xa0
+#define MDM_CTL_0      0xb0
+#define MDM_CTL_1      0xb4
+#define AUD_CTL                0xc0
+
+#define IRR_ETHERNET   (1 << 0)
+#define IRR_USAR       (1 << 1)
+#define IRR_SA1111     (1 << 2)
+
+#define MDM_CTL0_RTS1  (1 << 0)
+#define MDM_CTL0_DTR1  (1 << 1)
+#define MDM_CTL0_RTS2  (1 << 2)
+#define MDM_CTL0_DTR2  (1 << 3)
+
+#define MDM_CTL1_CTS1  (1 << 0)
+#define MDM_CTL1_DSR1  (1 << 1)
+#define MDM_CTL1_DCD1  (1 << 2)
+#define MDM_CTL1_CTS2  (1 << 3)
+#define MDM_CTL1_DSR2  (1 << 4)
+#define MDM_CTL1_DCD2  (1 << 5)
+
+#define AUD_SEL_1341   (1 << 0)
+#define AUD_MUTE_1341  (1 << 1)
 
-                       if (irr & IRR_ETHERNET) {
-                               generic_handle_irq(IRQ_NEPONSET_SMC9196);
-                       }
+extern void sa1110_mb_disable(void);
 
-                       if (irr & IRR_USAR) {
-                               generic_handle_irq(IRQ_NEPONSET_USAR);
-                       }
+struct neponset_drvdata {
+       void __iomem *base;
+       struct platform_device *sa1111;
+       struct platform_device *smc91x;
+       unsigned irq_base;
+#ifdef CONFIG_PM_SLEEP
+       u32 ncr0;
+       u32 mdm_ctl_0;
+#endif
+};
 
-                       desc->irq_data.chip->irq_unmask(&desc->irq_data);
-               }
+static void __iomem *nep_base;
 
-               if (irr & IRR_SA1111) {
-                       generic_handle_irq(IRQ_NEPONSET_SA1111);
-               }
+void neponset_ncr_frob(unsigned int mask, unsigned int val)
+{
+       void __iomem *base = nep_base;
+
+       if (base) {
+               unsigned long flags;
+               unsigned v;
+
+               local_irq_save(flags);
+               v = readb_relaxed(base + NCR_0);
+               writeb_relaxed((v & ~mask) | val, base + NCR_0);
+               local_irq_restore(flags);
+       } else {
+               WARN(1, "nep_base unset\n");
        }
 }
 
 static void neponset_set_mctrl(struct uart_port *port, u_int mctrl)
 {
-       u_int mdm_ctl0 = MDM_CTL_0;
+       void __iomem *base = nep_base;
+       u_int mdm_ctl0;
 
+       if (!base)
+               return;
+
+       mdm_ctl0 = readb_relaxed(base + MDM_CTL_0);
        if (port->mapbase == _Ser1UTCR0) {
                if (mctrl & TIOCM_RTS)
                        mdm_ctl0 &= ~MDM_CTL0_RTS2;
@@ -106,14 +121,19 @@ static void neponset_set_mctrl(struct uart_port *port, u_int mctrl)
                        mdm_ctl0 |= MDM_CTL0_DTR1;
        }
 
-       MDM_CTL_0 = mdm_ctl0;
+       writeb_relaxed(mdm_ctl0, base + MDM_CTL_0);
 }
 
 static u_int neponset_get_mctrl(struct uart_port *port)
 {
+       void __iomem *base = nep_base;
        u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
-       u_int mdm_ctl1 = MDM_CTL_1;
+       u_int mdm_ctl1;
+
+       if (!base)
+               return ret;
 
+       mdm_ctl1 = readb_relaxed(base + MDM_CTL_1);
        if (port->mapbase == _Ser1UTCR0) {
                if (mdm_ctl1 & MDM_CTL1_DCD2)
                        ret &= ~TIOCM_CD;
@@ -138,209 +158,278 @@ static struct sa1100_port_fns neponset_port_fns __devinitdata = {
        .get_mctrl      = neponset_get_mctrl,
 };
 
-static int __devinit neponset_probe(struct platform_device *dev)
+/*
+ * Install handler for Neponset IRQ.  Note that we have to loop here
+ * since the ETHERNET and USAR IRQs are level based, and we need to
+ * ensure that the IRQ signal is deasserted before returning.  This
+ * is rather unfortunate.
+ */
+static void neponset_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
-       sa1100_register_uart_fns(&neponset_port_fns);
+       struct neponset_drvdata *d = irq_desc_get_handler_data(desc);
+       unsigned int irr;
 
-       /*
-        * Install handler for GPIO25.
-        */
-       irq_set_irq_type(IRQ_GPIO25, IRQ_TYPE_EDGE_RISING);
-       irq_set_chained_handler(IRQ_GPIO25, neponset_irq_handler);
+       while (1) {
+               /*
+                * Acknowledge the parent IRQ.
+                */
+               desc->irq_data.chip->irq_ack(&desc->irq_data);
 
-       /*
-        * We would set IRQ_GPIO25 to be a wake-up IRQ, but
-        * unfortunately something on the Neponset activates
-        * this IRQ on sleep (ethernet?)
-        */
-#if 0
-       enable_irq_wake(IRQ_GPIO25);
-#endif
+               /*
+                * Read the interrupt reason register.  Let's have all
+                * active IRQ bits high.  Note: there is a typo in the
+                * Neponset user's guide for the SA1111 IRR level.
+                */
+               irr = readb_relaxed(d->base + IRR);
+               irr ^= IRR_ETHERNET | IRR_USAR;
 
-       /*
-        * Setup other Neponset IRQs.  SA1111 will be done by the
-        * generic SA1111 code.
-        */
-       irq_set_handler(IRQ_NEPONSET_SMC9196, handle_simple_irq);
-       set_irq_flags(IRQ_NEPONSET_SMC9196, IRQF_VALID | IRQF_PROBE);
-       irq_set_handler(IRQ_NEPONSET_USAR, handle_simple_irq);
-       set_irq_flags(IRQ_NEPONSET_USAR, IRQF_VALID | IRQF_PROBE);
+               if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0)
+                       break;
 
-       /*
-        * Disable GPIO 0/1 drivers so the buttons work on the module.
-        */
-       NCR_0 = NCR_GP01_OFF;
+               /*
+                * Since there is no individual mask, we have to
+                * mask the parent IRQ.  This is safe, since we'll
+                * recheck the register for any pending IRQs.
+                */
+               if (irr & (IRR_ETHERNET | IRR_USAR)) {
+                       desc->irq_data.chip->irq_mask(&desc->irq_data);
 
-       return 0;
-}
+                       /*
+                        * Ack the interrupt now to prevent re-entering
+                        * this neponset handler.  Again, this is safe
+                        * since we'll check the IRR register prior to
+                        * leaving.
+                        */
+                       desc->irq_data.chip->irq_ack(&desc->irq_data);
 
-#ifdef CONFIG_PM
+                       if (irr & IRR_ETHERNET)
+                               generic_handle_irq(d->irq_base + NEP_IRQ_SMC91X);
 
-/*
- * LDM power management.
- */
-static unsigned int neponset_saved_state;
+                       if (irr & IRR_USAR)
+                               generic_handle_irq(d->irq_base + NEP_IRQ_USAR);
 
-static int neponset_suspend(struct platform_device *dev, pm_message_t state)
-{
-       /*
-        * Save state.
-        */
-       neponset_saved_state = NCR_0;
+                       desc->irq_data.chip->irq_unmask(&desc->irq_data);
+               }
 
-       return 0;
+               if (irr & IRR_SA1111)
+                       generic_handle_irq(d->irq_base + NEP_IRQ_SA1111);
+       }
 }
 
-static int neponset_resume(struct platform_device *dev)
+/* Yes, we really do not have any kind of masking or unmasking */
+static void nochip_noop(struct irq_data *irq)
 {
-       NCR_0 = neponset_saved_state;
-
-       return 0;
 }
 
-#else
-#define neponset_suspend NULL
-#define neponset_resume  NULL
-#endif
-
-static struct platform_driver neponset_device_driver = {
-       .probe          = neponset_probe,
-       .suspend        = neponset_suspend,
-       .resume         = neponset_resume,
-       .driver         = {
-               .name   = "neponset",
-       },
-};
-
-static struct resource neponset_resources[] = {
-       [0] = {
-               .start  = 0x10000000,
-               .end    = 0x17ffffff,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device neponset_device = {
-       .name           = "neponset",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(neponset_resources),
-       .resource       = neponset_resources,
-};
-
-static struct resource sa1111_resources[] = {
-       [0] = {
-               .start  = 0x40000000,
-               .end    = 0x40001fff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_NEPONSET_SA1111,
-               .end    = IRQ_NEPONSET_SA1111,
-               .flags  = IORESOURCE_IRQ,
-       },
+static struct irq_chip nochip = {
+       .name = "neponset",
+       .irq_ack = nochip_noop,
+       .irq_mask = nochip_noop,
+       .irq_unmask = nochip_noop,
 };
 
 static struct sa1111_platform_data sa1111_info = {
-       .irq_base       = IRQ_BOARD_END,
+       .disable_devs   = SA1111_DEVID_PS2_MSE,
 };
 
-static u64 sa1111_dmamask = 0xffffffffUL;
+static int __devinit neponset_probe(struct platform_device *dev)
+{
+       struct neponset_drvdata *d;
+       struct resource *nep_res, *sa1111_res, *smc91x_res;
+       struct resource sa1111_resources[] = {
+               DEFINE_RES_MEM(0x40000000, SZ_8K),
+               { .flags = IORESOURCE_IRQ },
+       };
+       struct platform_device_info sa1111_devinfo = {
+               .parent = &dev->dev,
+               .name = "sa1111",
+               .id = 0,
+               .res = sa1111_resources,
+               .num_res = ARRAY_SIZE(sa1111_resources),
+               .data = &sa1111_info,
+               .size_data = sizeof(sa1111_info),
+               .dma_mask = 0xffffffffUL,
+       };
+       struct resource smc91x_resources[] = {
+               DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS,
+                       0x02000000, "smc91x-regs"),
+               DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS + 0x02000000,
+                       0x02000000, "smc91x-attrib"),
+               { .flags = IORESOURCE_IRQ },
+       };
+       struct platform_device_info smc91x_devinfo = {
+               .parent = &dev->dev,
+               .name = "smc91x",
+               .id = 0,
+               .res = smc91x_resources,
+               .num_res = ARRAY_SIZE(smc91x_resources),
+       };
+       int ret, irq;
+
+       if (nep_base)
+               return -EBUSY;
+
+       irq = ret = platform_get_irq(dev, 0);
+       if (ret < 0)
+               goto err_alloc;
+
+       nep_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       smc91x_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+       sa1111_res = platform_get_resource(dev, IORESOURCE_MEM, 2);
+       if (!nep_res || !smc91x_res || !sa1111_res) {
+               ret = -ENXIO;
+               goto err_alloc;
+       }
 
-static struct platform_device sa1111_device = {
-       .name           = "sa1111",
-       .id             = 0,
-       .dev            = {
-               .dma_mask = &sa1111_dmamask,
-               .coherent_dma_mask = 0xffffffff,
-               .platform_data = &sa1111_info,
-       },
-       .num_resources  = ARRAY_SIZE(sa1111_resources),
-       .resource       = sa1111_resources,
-};
+       d = kzalloc(sizeof(*d), GFP_KERNEL);
+       if (!d) {
+               ret = -ENOMEM;
+               goto err_alloc;
+       }
 
-static struct resource smc91x_resources[] = {
-       [0] = {
-               .name   = "smc91x-regs",
-               .start  = SA1100_CS3_PHYS,
-               .end    = SA1100_CS3_PHYS + 0x01ffffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_NEPONSET_SMC9196,
-               .end    = IRQ_NEPONSET_SMC9196,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .name   = "smc91x-attrib",
-               .start  = SA1100_CS3_PHYS + 0x02000000,
-               .end    = SA1100_CS3_PHYS + 0x03ffffff,
-               .flags  = IORESOURCE_MEM,
-       },
-};
+       d->base = ioremap(nep_res->start, SZ_4K);
+       if (!d->base) {
+               ret = -ENOMEM;
+               goto err_ioremap;
+       }
 
-static struct platform_device smc91x_device = {
-       .name           = "smc91x",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(smc91x_resources),
-       .resource       = smc91x_resources,
-};
+       if (readb_relaxed(d->base + WHOAMI) != 0x11) {
+               dev_warn(&dev->dev, "Neponset board detected, but wrong ID: %02x\n",
+                        readb_relaxed(d->base + WHOAMI));
+               ret = -ENODEV;
+               goto err_id;
+       }
 
-static struct platform_device *devices[] __initdata = {
-       &neponset_device,
-       &sa1111_device,
-       &smc91x_device,
-};
+       ret = irq_alloc_descs(-1, IRQ_BOARD_START, NEP_IRQ_NR, -1);
+       if (ret <= 0) {
+               dev_err(&dev->dev, "unable to allocate %u irqs: %d\n",
+                       NEP_IRQ_NR, ret);
+               if (ret == 0)
+                       ret = -ENOMEM;
+               goto err_irq_alloc;
+       }
 
-extern void sa1110_mb_disable(void);
+       d->irq_base = ret;
 
-static int __init neponset_init(void)
-{
-       platform_driver_register(&neponset_device_driver);
+       irq_set_chip_and_handler(d->irq_base + NEP_IRQ_SMC91X, &nochip,
+               handle_simple_irq);
+       set_irq_flags(d->irq_base + NEP_IRQ_SMC91X, IRQF_VALID | IRQF_PROBE);
+       irq_set_chip_and_handler(d->irq_base + NEP_IRQ_USAR, &nochip,
+               handle_simple_irq);
+       set_irq_flags(d->irq_base + NEP_IRQ_USAR, IRQF_VALID | IRQF_PROBE);
+       irq_set_chip(d->irq_base + NEP_IRQ_SA1111, &nochip);
 
-       /*
-        * The Neponset is only present on the Assabet machine type.
-        */
-       if (!machine_is_assabet())
-               return -ENODEV;
+       irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+       irq_set_handler_data(irq, d);
+       irq_set_chained_handler(irq, neponset_irq_handler);
 
        /*
-        * Ensure that the memory bus request/grant signals are setup,
-        * and the grant is held in its inactive state, whether or not
-        * we actually have a Neponset attached.
+        * We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately
+        * something on the Neponset activates this IRQ on sleep (eth?)
         */
+#if 0
+       enable_irq_wake(irq);
+#endif
+
+       dev_info(&dev->dev, "Neponset daughter board, providing IRQ%u-%u\n",
+                d->irq_base, d->irq_base + NEP_IRQ_NR - 1);
+       nep_base = d->base;
+
+       sa1100_register_uart_fns(&neponset_port_fns);
+
+       /* Ensure that the memory bus request/grant signals are setup */
        sa1110_mb_disable();
 
-       if (!machine_has_neponset()) {
-               printk(KERN_DEBUG "Neponset expansion board not present\n");
-               return -ENODEV;
-       }
+       /* Disable GPIO 0/1 drivers so the buttons work on the Assabet */
+       writeb_relaxed(NCR_GP01_OFF, d->base + NCR_0);
 
-       if (WHOAMI != 0x11) {
-               printk(KERN_WARNING "Neponset board detected, but "
-                       "wrong ID: %02x\n", WHOAMI);
-               return -ENODEV;
-       }
+       sa1111_resources[0].parent = sa1111_res;
+       sa1111_resources[1].start = d->irq_base + NEP_IRQ_SA1111;
+       sa1111_resources[1].end = d->irq_base + NEP_IRQ_SA1111;
+       d->sa1111 = platform_device_register_full(&sa1111_devinfo);
+
+       smc91x_resources[0].parent = smc91x_res;
+       smc91x_resources[1].parent = smc91x_res;
+       smc91x_resources[2].start = d->irq_base + NEP_IRQ_SMC91X;
+       smc91x_resources[2].end = d->irq_base + NEP_IRQ_SMC91X;
+       d->smc91x = platform_device_register_full(&smc91x_devinfo);
+
+       platform_set_drvdata(dev, d);
 
-       return platform_add_devices(devices, ARRAY_SIZE(devices));
+       return 0;
+
+ err_irq_alloc:
+ err_id:
+       iounmap(d->base);
+ err_ioremap:
+       kfree(d);
+ err_alloc:
+       return ret;
 }
 
-subsys_initcall(neponset_init);
+static int __devexit neponset_remove(struct platform_device *dev)
+{
+       struct neponset_drvdata *d = platform_get_drvdata(dev);
+       int irq = platform_get_irq(dev, 0);
+
+       if (!IS_ERR(d->sa1111))
+               platform_device_unregister(d->sa1111);
+       if (!IS_ERR(d->smc91x))
+               platform_device_unregister(d->smc91x);
+       irq_set_chained_handler(irq, NULL);
+       irq_free_descs(d->irq_base, NEP_IRQ_NR);
+       nep_base = NULL;
+       iounmap(d->base);
+       kfree(d);
 
-static struct map_desc neponset_io_desc[] __initdata = {
-       {       /* System Registers */
-               .virtual        =  0xf3000000,
-               .pfn            = __phys_to_pfn(0x10000000),
-               .length         = SZ_1M,
-               .type           = MT_DEVICE
-       }, {    /* SA-1111 */
-               .virtual        =  0xf4000000,
-               .pfn            = __phys_to_pfn(0x40000000),
-               .length         = SZ_1M,
-               .type           = MT_DEVICE
-       }
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int neponset_suspend(struct device *dev)
+{
+       struct neponset_drvdata *d = dev_get_drvdata(dev);
+
+       d->ncr0 = readb_relaxed(d->base + NCR_0);
+       d->mdm_ctl_0 = readb_relaxed(d->base + MDM_CTL_0);
+
+       return 0;
+}
+
+static int neponset_resume(struct device *dev)
+{
+       struct neponset_drvdata *d = dev_get_drvdata(dev);
+
+       writeb_relaxed(d->ncr0, d->base + NCR_0);
+       writeb_relaxed(d->mdm_ctl_0, d->base + MDM_CTL_0);
+
+       return 0;
+}
+
+static const struct dev_pm_ops neponset_pm_ops = {
+       .suspend_noirq = neponset_suspend,
+       .resume_noirq = neponset_resume,
+       .freeze_noirq = neponset_suspend,
+       .restore_noirq = neponset_resume,
+};
+#define PM_OPS &neponset_pm_ops
+#else
+#define PM_OPS NULL
+#endif
+
+static struct platform_driver neponset_device_driver = {
+       .probe          = neponset_probe,
+       .remove         = __devexit_p(neponset_remove),
+       .driver         = {
+               .name   = "neponset",
+               .owner  = THIS_MODULE,
+               .pm     = PM_OPS,
+       },
 };
 
-void __init neponset_map_io(void)
+static int __init neponset_init(void)
 {
-       iotable_init(neponset_io_desc, ARRAY_SIZE(neponset_io_desc));
+       return platform_driver_register(&neponset_device_driver);
 }
+
+subsys_initcall(neponset_init);
index 0d01ca7..41bb018 100644 (file)
@@ -135,12 +135,8 @@ struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys
                                 &sys->resources);
 }
 
-static struct resource pci_io_ports = {
-       .name   = "PCI IO",
-       .start  = 0x400,
-       .end    = 0x7FF,
-       .flags  = IORESOURCE_IO,
-};
+static struct resource pci_io_ports =
+       DEFINE_RES_IO_NAMED(0x400, 0x400, "PCI IO");
 
 static struct resource pci_non_prefetchable_memory = {
        .name   = "PCI non-prefetchable",
index 9307df0..1602575 100644 (file)
 #define IRQ_GPIO_ETH0_IRQ      IRQ_GPIO21
 
 static struct resource smc91x_resources[] = {
-       [0] = {
-               .start  = PLEB_ETH0_P,
-               .end    = PLEB_ETH0_P | 0x03ffffff,
-               .flags  = IORESOURCE_MEM,
-       },
+       [0] = DEFINE_RES_MEM(PLEB_ETH0_P, 0x04000000),
 #if 0 /* Autoprobe instead, to get rising/falling edge characteristic right */
-       [1] = {
-               .start  = IRQ_GPIO_ETH0_IRQ,
-               .end    = IRQ_GPIO_ETH0_IRQ,
-               .flags  = IORESOURCE_IRQ,
-       },
+       [1] = DEFINE_RES_IRQ(IRQ_GPIO_ETH0_IRQ),
 #endif
 };
 
@@ -70,16 +62,8 @@ static struct platform_device *devices[] __initdata = {
  * the two SA1100 lowest chip select outputs.
  */
 static struct resource pleb_flash_resources[] = {
-       [0] = {
-               .start = SA1100_CS0_PHYS,
-               .end   = SA1100_CS0_PHYS + SZ_8M - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = SA1100_CS1_PHYS,
-               .end   = SA1100_CS1_PHYS + SZ_8M - 1,
-               .flags = IORESOURCE_MEM,
-       }
+       [0] = DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_8M),
+       [1] = DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_8M),
 };
 
 
@@ -147,6 +131,7 @@ static void __init pleb_map_io(void)
 
 MACHINE_START(PLEB, "PLEB")
        .map_io         = pleb_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
        .init_machine   = pleb_init,
index 318b2b7..ca8bf59 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
+#include <video/sa1100fb.h>
+
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
@@ -19,6 +21,7 @@
 #include <asm/mach/serial_sa1100.h>
 #include <mach/mcp.h>
 #include <mach/shannon.h>
+#include <mach/irqs.h>
 
 #include "generic.h"
 
@@ -46,19 +49,32 @@ static struct flash_platform_data shannon_flash_data = {
        .nr_parts       = ARRAY_SIZE(shannon_partitions),
 };
 
-static struct resource shannon_flash_resource = {
-       .start          = SA1100_CS0_PHYS,
-       .end            = SA1100_CS0_PHYS + SZ_4M - 1,
-       .flags          = IORESOURCE_MEM,
-};
+static struct resource shannon_flash_resource =
+       DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_4M);
 
 static struct mcp_plat_data shannon_mcp_data = {
        .mccr0          = MCCR0_ADM,
        .sclk_rate      = 11981000,
 };
 
+static struct sa1100fb_mach_info shannon_lcd_info = {
+       .pixclock       = 152500,       .bpp            = 8,
+       .xres           = 640,          .yres           = 480,
+
+       .hsync_len      = 4,            .vsync_len      = 3,
+       .left_margin    = 2,            .upper_margin   = 0,
+       .right_margin   = 1,            .lower_margin   = 0,
+
+       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       .lccr0          = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
+       .lccr3          = LCCR3_ACBsDiv(512),
+};
+
 static void __init shannon_init(void)
 {
+       sa11x0_ppc_configure_mcp();
+       sa11x0_register_lcd(&shannon_lcd_info);
        sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1);
        sa11x0_register_mcp(&shannon_mcp_data);
 }
@@ -84,6 +100,7 @@ static void __init shannon_map_io(void)
 MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
        .atag_offset    = 0x100,
        .map_io         = shannon_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
        .init_machine   = shannon_init,
index e17c04d..3efae03 100644 (file)
@@ -7,15 +7,15 @@
 #include <linux/kernel.h>
 #include <linux/tty.h>
 #include <linux/proc_fs.h>
-#include <linux/string.h> 
+#include <linux/string.h>
 #include <linux/pm.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/ucb1x00.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-#include <asm/irq.h>
 #include <mach/hardware.h>
 #include <asm/setup.h>
 
@@ -26,6 +26,7 @@
 #include <asm/mach/serial_sa1100.h>
 #include <mach/mcp.h>
 #include <mach/simpad.h>
+#include <mach/irqs.h>
 
 #include <linux/serial_core.h>
 #include <linux/ioport.h>
@@ -176,21 +177,18 @@ static struct flash_platform_data simpad_flash_data = {
 
 
 static struct resource simpad_flash_resources [] = {
-       {
-               .start     = SA1100_CS0_PHYS,
-               .end       = SA1100_CS0_PHYS + SZ_16M -1,
-               .flags     = IORESOURCE_MEM,
-       }, {
-               .start     = SA1100_CS1_PHYS,
-               .end       = SA1100_CS1_PHYS + SZ_16M -1,
-               .flags     = IORESOURCE_MEM,
-       }
+       DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_16M),
+       DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_16M),
+};
+
+static struct ucb1x00_plat_data simpad_ucb1x00_data = {
+       .gpio_base      = SIMPAD_UCB1X00_GPIO_BASE,
 };
 
 static struct mcp_plat_data simpad_mcp_data = {
        .mccr0          = MCCR0_ADM,
        .sclk_rate      = 11981000,
-       .gpio_base      = SIMPAD_UCB1X00_GPIO_BASE,
+       .codec_pdata    = &simpad_ucb1x00_data,
 };
 
 
@@ -376,6 +374,7 @@ static int __init simpad_init(void)
 
        pm_power_off = simpad_power_off;
 
+       sa11x0_ppc_configure_mcp();
        sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
                              ARRAY_SIZE(simpad_flash_resources));
        sa11x0_register_mcp(&simpad_mcp_data);
@@ -394,6 +393,7 @@ MACHINE_START(SIMPAD, "Simpad")
        /* Maintainer: Holger Freyther */
        .atag_offset    = 0x100,
        .map_io         = simpad_map_io,
+       .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
        .restart        = sa11x0_restart,
index e822331..30cc672 100644 (file)
  *
  * Causes sa11x0 to enter sleep state
  *
+ * Must be aligned to a cacheline.
  */
-
+       .balign 32
 ENTRY(sa1100_finish_suspend)
        @ disable clock switching
        mcr     p15, 0, r1, c15, c2, 2
 
-        @ Adjust memory timing before lowering CPU clock
-       @ Clock speed adjustment without changing memory timing makes
-       @ CPU hang in some cases
-        ldr     r0, =MDREFR
-        ldr     r1, [r0]
-        orr     r1, r1, #MDREFR_K1DB2
-        str     r1, [r0]
+       ldr     r6, =MDREFR
+       ldr     r4, [r6]
+       orr     r4, r4, #MDREFR_K1DB2
+       ldr     r5, =PPCR
+
+       @ Pre-load __udelay into the I-cache
+       mov     r0, #1
+       bl      __udelay
+       mov     r0, r0
+
+       @ The following must all exist in a single cache line to
+       @ avoid accessing memory until this sequence is complete,
+       @ otherwise we occasionally hang.
+
+       @ Adjust memory timing before lowering CPU clock
+       str     r4, [r6]
 
        @ delay 90us and set CPU PLL to lowest speed
        @ fixes resume problem on high speed SA1110
        mov     r0, #90
        bl      __udelay
-       ldr     r0, =PPCR
        mov     r1, #0
-       str     r1, [r0]
+       str     r1, [r5]
        mov     r0, #90
        bl      __udelay
 
@@ -85,12 +94,10 @@ ENTRY(sa1100_finish_suspend)
        bic     r5, r5, #FMsk(MSC_RT)
        bic     r5, r5, #FMsk(MSC_RT)<<16
 
-       ldr     r6, =MDREFR
-
        ldr     r7, [r6]
-bic    r7, r7, #0x0000FF00
-bic    r7, r7, #0x000000F0
-orr    r8, r7, #MDREFR_SLFRSH
+       bic     r7, r7, #0x0000FF00
+       bic     r7, r7, #0x000000F0
+       orr     r8, r7, #MDREFR_SLFRSH
 
        ldr     r9, =MDCNFG
        ldr     r10, [r9]
index b20ff93..e22fca9 100644 (file)
@@ -19,8 +19,8 @@
 #include <linux/init.h>
 #include <linux/io.h>
 
-#include <asm/irq.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <asm/hardware/ssp.h>
 
 #define TIMEOUT 100000
index 69e3353..6af26e8 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 
 static u32 notrace sa1100_read_sched_clock(void)
 {
index 6fcf304..a83cf51 100644 (file)
@@ -662,6 +662,7 @@ static struct sh_dmae_pdata usb_dma0_platform_data = {
        .dmaor_is_32bit = 1,
        .needs_tend_set = 1,
        .no_dmars       = 1,
+       .slave_only     = 1,
 };
 
 static struct resource sh7372_usb_dmae0_resources[] = {
@@ -723,6 +724,7 @@ static struct sh_dmae_pdata usb_dma1_platform_data = {
        .dmaor_is_32bit = 1,
        .needs_tend_set = 1,
        .no_dmars       = 1,
+       .slave_only     = 1,
 };
 
 static struct resource sh7372_usb_dmae1_resources[] = {
index ba15937..80632e8 100644 (file)
@@ -225,8 +225,7 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
                if ((area->flags & VM_ARM_MTYPE_MASK) != VM_ARM_MTYPE(mtype))
                        continue;
                if (__phys_to_pfn(area->phys_addr) > pfn ||
-                   __pfn_to_phys(pfn) + offset + size-1 >
-                   area->phys_addr + area->size-1)
+                   __pfn_to_phys(pfn) + size-1 > area->phys_addr + area->size-1)
                        continue;
                /* we can drop the lock here as we know *area is static */
                read_unlock(&vmlist_lock);
index 197e96f..3dea723 100644 (file)
@@ -8,6 +8,7 @@ config AVR32
        select HAVE_KPROBES
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_PROBE
+       select GENERIC_ATOMIC64
        select HARDIRQS_SW_RESEND
        select GENERIC_IRQ_SHOW
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
index d4fc1a9..604cd9d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/cache.h>
 #include <linux/of_platform.h>
 #include <linux/dma-mapping.h>
-#include <linux/cpu.h>
 #include <asm/cacheflush.h>
 #include <asm/entry.h>
 #include <asm/cpuinfo.h>
@@ -227,23 +226,5 @@ static int __init setup_bus_notifier(void)
 
        return 0;
 }
-arch_initcall(setup_bus_notifier);
-
-static DEFINE_PER_CPU(struct cpu, cpu_devices);
-
-static int __init topology_init(void)
-{
-       int i, ret;
-
-       for_each_present_cpu(i) {
-               struct cpu *c = &per_cpu(cpu_devices, i);
 
-               ret = register_cpu(c, i);
-               if (ret)
-                       printk(KERN_WARNING "topology_init: register_cpu %d "
-                                               "failed (%d)\n", i, ret);
-       }
-
-       return 0;
-}
-subsys_initcall(topology_init);
+arch_initcall(setup_bus_notifier);
index c4c1312..5ab6e89 100644 (file)
@@ -2356,6 +2356,7 @@ config PCI
        depends on HW_HAS_PCI
        select PCI_DOMAINS
        select GENERIC_PCI_IOMAP
+       select NO_GENERIC_PCI_IOPORT_MAP
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
index 2635b1a..fd35daa 100644 (file)
@@ -10,8 +10,8 @@
 #include <linux/module.h>
 #include <asm/io.h>
 
-static void __iomem *ioport_map_pci(struct pci_dev *dev,
-                                     unsigned long port, unsigned int nr)
+void __iomem *__pci_ioport_map(struct pci_dev *dev,
+                              unsigned long port, unsigned int nr)
 {
        struct pci_controller *ctrl = dev->bus->sysdata;
        unsigned long base = ctrl->io_map_base;
index 3c8db65..713fb58 100644 (file)
@@ -859,6 +859,7 @@ config PCI
        depends on SYS_SUPPORTS_PCI
        select PCI_DOMAINS
        select GENERIC_PCI_IOMAP
+       select NO_GENERIC_PCI_IOPORT_MAP
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
index 8f18dd0..1e7b0e2 100644 (file)
@@ -356,8 +356,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 
 #ifndef CONFIG_GENERIC_IOMAP
 
-static void __iomem *ioport_map_pci(struct pci_dev *dev,
-                                   unsigned long port, unsigned int nr)
+void __iomem *__pci_ioport_map(struct pci_dev *dev,
+                              unsigned long port, unsigned int nr)
 {
        struct pci_channel *chan = dev->sysdata;
 
index 9665799..ca5580e 100644 (file)
@@ -33,6 +33,7 @@ config SPARC
 config SPARC32
        def_bool !64BIT
        select GENERIC_ATOMIC64
+       select CLZ_TAB
 
 config SPARC64
        def_bool 64BIT
index 681b368..d74bc09 100644 (file)
@@ -17,23 +17,9 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-       .data
-       .align 8
-       .globl  __clz_tab
-__clz_tab:
-       .byte   0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
-       .byte   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6
-       .byte   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-       .byte   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-       .byte   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
-       .byte   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
-       .byte   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
-       .byte   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
-       .size    __clz_tab,256
-       .global .udiv
-
        .text
        .align 4
+       .global .udiv
        .globl __divdi3
 __divdi3:
        save %sp,-104,%sp
index 0c9fa27..b3b7332 100644 (file)
@@ -145,13 +145,13 @@ extern void __add_wrong_size(void)
 
 #ifdef __HAVE_ARCH_CMPXCHG
 #define cmpxchg(ptr, old, new)                                         \
-       __cmpxchg((ptr), (old), (new), sizeof(*ptr))
+       __cmpxchg(ptr, old, new, sizeof(*(ptr)))
 
 #define sync_cmpxchg(ptr, old, new)                                    \
-       __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
+       __sync_cmpxchg(ptr, old, new, sizeof(*(ptr)))
 
 #define cmpxchg_local(ptr, old, new)                                   \
-       __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
+       __cmpxchg_local(ptr, old, new, sizeof(*(ptr)))
 #endif
 
 /*
index ab4092e..7b9cfc4 100644 (file)
@@ -190,6 +190,9 @@ struct x86_emulate_ops {
        int (*intercept)(struct x86_emulate_ctxt *ctxt,
                         struct x86_instruction_info *info,
                         enum x86_intercept_stage stage);
+
+       bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
+                        u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
 };
 
 typedef u32 __attribute__((vector_size(16))) sse128_t;
@@ -298,6 +301,19 @@ struct x86_emulate_ctxt {
 #define X86EMUL_MODE_PROT     (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \
                               X86EMUL_MODE_PROT64)
 
+/* CPUID vendors */
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65
+
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273
+
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69
+
 enum x86_intercept_stage {
        X86_ICTP_NONE = 0,   /* Allow zero-init to not match anything */
        X86_ICPT_PRE_EXCEPT,
index 1aae78f..4025fe4 100644 (file)
@@ -252,7 +252,8 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
        unsigned short ss;
        unsigned long sp;
 #endif
-       printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+       printk(KERN_DEFAULT
+              "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
 #ifdef CONFIG_PREEMPT
        printk("PREEMPT ");
 #endif
index 6d728d9..17107bd 100644 (file)
@@ -129,7 +129,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
        if (!stack) {
                if (regs)
                        stack = (unsigned long *)regs->sp;
-               else if (task && task != current)
+               else if (task != current)
                        stack = (unsigned long *)task->thread.sp;
                else
                        stack = &dummy;
@@ -269,11 +269,11 @@ void show_registers(struct pt_regs *regs)
                unsigned char c;
                u8 *ip;
 
-               printk(KERN_EMERG "Stack:\n");
+               printk(KERN_DEFAULT "Stack:\n");
                show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
-                                  0, KERN_EMERG);
+                                  0, KERN_DEFAULT);
 
-               printk(KERN_EMERG "Code: ");
+               printk(KERN_DEFAULT "Code: ");
 
                ip = (u8 *)regs->ip - code_prologue;
                if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
index 37a458b..d840e69 100644 (file)
@@ -39,6 +39,14 @@ static int reboot_mode;
 enum reboot_type reboot_type = BOOT_ACPI;
 int reboot_force;
 
+/* This variable is used privately to keep track of whether or not
+ * reboot_type is still set to its default value (i.e., reboot= hasn't
+ * been set on the command line).  This is needed so that we can
+ * suppress DMI scanning for reboot quirks.  Without it, it's
+ * impossible to override a faulty reboot quirk without recompiling.
+ */
+static int reboot_default = 1;
+
 #if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
 static int reboot_cpu = -1;
 #endif
@@ -67,6 +75,12 @@ bool port_cf9_safe = false;
 static int __init reboot_setup(char *str)
 {
        for (;;) {
+               /* Having anything passed on the command line via
+                * reboot= will cause us to disable DMI checking
+                * below.
+                */
+               reboot_default = 0;
+
                switch (*str) {
                case 'w':
                        reboot_mode = 0x1234;
@@ -295,14 +309,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
                },
        },
-       {       /* Handle problems with rebooting on VersaLogic Menlow boards */
-               .callback = set_bios_reboot,
-               .ident = "VersaLogic Menlow based board",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "VersaLogic Corporation"),
-                       DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"),
-               },
-       },
        { /* Handle reboot issue on Acer Aspire one */
                .callback = set_kbd_reboot,
                .ident = "Acer Aspire One A110",
@@ -316,7 +322,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
 
 static int __init reboot_init(void)
 {
-       dmi_check_system(reboot_dmi_table);
+       /* Only do the DMI check if reboot_type hasn't been overridden
+        * on the command line
+        */
+       if (reboot_default) {
+               dmi_check_system(reboot_dmi_table);
+       }
        return 0;
 }
 core_initcall(reboot_init);
@@ -465,7 +476,12 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
 
 static int __init pci_reboot_init(void)
 {
-       dmi_check_system(pci_reboot_dmi_table);
+       /* Only do the DMI check if reboot_type hasn't been overridden
+        * on the command line
+        */
+       if (reboot_default) {
+               dmi_check_system(pci_reboot_dmi_table);
+       }
        return 0;
 }
 core_initcall(pci_reboot_init);
index 05a562b..0982507 100644 (file)
@@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
        ss->p = 1;
 }
 
+static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
+{
+       struct x86_emulate_ops *ops = ctxt->ops;
+       u32 eax, ebx, ecx, edx;
+
+       /*
+        * syscall should always be enabled in longmode - so only become
+        * vendor specific (cpuid) if other modes are active...
+        */
+       if (ctxt->mode == X86EMUL_MODE_PROT64)
+               return true;
+
+       eax = 0x00000000;
+       ecx = 0x00000000;
+       if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) {
+               /*
+                * Intel ("GenuineIntel")
+                * remark: Intel CPUs only support "syscall" in 64bit
+                * longmode. Also an 64bit guest with a
+                * 32bit compat-app running will #UD !! While this
+                * behaviour can be fixed (by emulating) into AMD
+                * response - CPUs of AMD can't behave like Intel.
+                */
+               if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx &&
+                   ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx &&
+                   edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx)
+                       return false;
+
+               /* AMD ("AuthenticAMD") */
+               if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx &&
+                   ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx &&
+                   edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx)
+                       return true;
+
+               /* AMD ("AMDisbetter!") */
+               if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx &&
+                   ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
+                   edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
+                       return true;
+       }
+
+       /* default: (not Intel, not AMD), apply Intel's stricter rules... */
+       return false;
+}
+
 static int em_syscall(struct x86_emulate_ctxt *ctxt)
 {
        struct x86_emulate_ops *ops = ctxt->ops;
@@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
            ctxt->mode == X86EMUL_MODE_VM86)
                return emulate_ud(ctxt);
 
+       if (!(em_syscall_is_enabled(ctxt)))
+               return emulate_ud(ctxt);
+
        ops->get_msr(ctxt, MSR_EFER, &efer);
        setup_syscalls_segments(ctxt, &cs, &ss);
 
+       if (!(efer & EFER_SCE))
+               return emulate_ud(ctxt);
+
        ops->get_msr(ctxt, MSR_STAR, &msr_data);
        msr_data >>= 32;
        cs_sel = (u16)(msr_data & 0xfffc);
index 14d6cad..9cbfc06 100644 (file)
@@ -1495,6 +1495,8 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
 
 int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
+       bool pr = false;
+
        switch (msr) {
        case MSR_EFER:
                return set_efer(vcpu, data);
@@ -1635,6 +1637,18 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
                pr_unimpl(vcpu, "unimplemented perfctr wrmsr: "
                        "0x%x data 0x%llx\n", msr, data);
                break;
+       case MSR_P6_PERFCTR0:
+       case MSR_P6_PERFCTR1:
+               pr = true;
+       case MSR_P6_EVNTSEL0:
+       case MSR_P6_EVNTSEL1:
+               if (kvm_pmu_msr(vcpu, msr))
+                       return kvm_pmu_set_msr(vcpu, msr, data);
+
+               if (pr || data != 0)
+                       pr_unimpl(vcpu, "disabled perfctr wrmsr: "
+                               "0x%x data 0x%llx\n", msr, data);
+               break;
        case MSR_K7_CLK_CTL:
                /*
                 * Ignore all writes to this no longer documented MSR.
@@ -1835,6 +1849,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        case MSR_FAM10H_MMIO_CONF_BASE:
                data = 0;
                break;
+       case MSR_P6_PERFCTR0:
+       case MSR_P6_PERFCTR1:
+       case MSR_P6_EVNTSEL0:
+       case MSR_P6_EVNTSEL1:
+               if (kvm_pmu_msr(vcpu, msr))
+                       return kvm_pmu_get_msr(vcpu, msr, pdata);
+               data = 0;
+               break;
        case MSR_IA32_UCODE_REV:
                data = 0x100000000ULL;
                break;
@@ -4180,6 +4202,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
        return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);
 }
 
+static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
+                              u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
+{
+       struct kvm_cpuid_entry2 *cpuid = NULL;
+
+       if (eax && ecx)
+               cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt),
+                                           *eax, *ecx);
+
+       if (cpuid) {
+               *eax = cpuid->eax;
+               *ecx = cpuid->ecx;
+               if (ebx)
+                       *ebx = cpuid->ebx;
+               if (edx)
+                       *edx = cpuid->edx;
+               return true;
+       }
+
+       return false;
+}
+
 static struct x86_emulate_ops emulate_ops = {
        .read_std            = kvm_read_guest_virt_system,
        .write_std           = kvm_write_guest_virt_system,
@@ -4211,6 +4255,7 @@ static struct x86_emulate_ops emulate_ops = {
        .get_fpu             = emulator_get_fpu,
        .put_fpu             = emulator_put_fpu,
        .intercept           = emulator_intercept,
+       .get_cpuid           = emulator_get_cpuid,
 };
 
 static void cache_all_regs(struct kvm_vcpu *vcpu)
index 9d74824..f0b4caf 100644 (file)
@@ -673,7 +673,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
 
        stackend = end_of_stack(tsk);
        if (tsk != &init_task && *stackend != STACK_END_MAGIC)
-               printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
+               printk(KERN_EMERG "Thread overran stack, or stack corrupted\n");
 
        tsk->thread.cr2         = address;
        tsk->thread.trap_no     = 14;
@@ -684,7 +684,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
                sig = 0;
 
        /* Executive summary in case the body of the oops scrolled away */
-       printk(KERN_EMERG "CR2: %016lx\n", address);
+       printk(KERN_DEFAULT "CR2: %016lx\n", address);
 
        oops_end(flags, regs, sig);
 }
index 5fb8c27..405a8c4 100644 (file)
@@ -118,7 +118,4 @@ extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
 /* Don't build bcopy at all ...  */
 #define __HAVE_ARCH_BCOPY
 
-#define __HAVE_ARCH_MEMSCAN
-#define memscan memchr
-
 #endif /* _XTENSA_STRING_H */
index 2b805d7..8ae05ce 100644 (file)
@@ -579,13 +579,6 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
                goto err_free_cpumask;
        }
 
-       /*
-        * Do not start hotplugged CPUs now, but when they
-        * are onlined the first time
-        */
-       if (pr->flags.need_hotplug_init)
-               return 0;
-
        /*
         * Do not start hotplugged CPUs now, but when they
         * are onlined the first time
index 3fd31de..a6278e7 100644 (file)
@@ -380,6 +380,7 @@ static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr,
        rbdc = __rbd_client_find(opt);
        if (rbdc) {
                ceph_destroy_options(opt);
+               kfree(rbd_opts);
 
                /* using an existing client */
                kref_get(&rbdc->kref);
@@ -406,15 +407,15 @@ done_err:
 
 /*
  * Destroy ceph client
+ *
+ * Caller must hold node_lock.
  */
 static void rbd_client_release(struct kref *kref)
 {
        struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref);
 
        dout("rbd_release_client %p\n", rbdc);
-       spin_lock(&node_lock);
        list_del(&rbdc->node);
-       spin_unlock(&node_lock);
 
        ceph_destroy_client(rbdc->client);
        kfree(rbdc->rbd_opts);
@@ -427,7 +428,9 @@ static void rbd_client_release(struct kref *kref)
  */
 static void rbd_put_client(struct rbd_device *rbd_dev)
 {
+       spin_lock(&node_lock);
        kref_put(&rbd_dev->rbd_client->kref, rbd_client_release);
+       spin_unlock(&node_lock);
        rbd_dev->rbd_client = NULL;
        rbd_dev->client = NULL;
 }
index f1a2749..4a6c46d 100644 (file)
@@ -252,6 +252,15 @@ config EP93XX_DMA
        help
          Enable support for the Cirrus Logic EP93xx M2P/M2M DMA controller.
 
+config DMA_SA11X0
+       tristate "SA-11x0 DMA support"
+       depends on ARCH_SA1100
+       select DMA_ENGINE
+       help
+         Support the DMA engine found on Intel StrongARM SA-1100 and
+         SA-1110 SoCs.  This DMA engine can only be used with on-chip
+         devices.
+
 config DMA_ENGINE
        bool
 
index 009a222..86b795b 100644 (file)
@@ -27,3 +27,4 @@ obj-$(CONFIG_PL330_DMA) += pl330.o
 obj-$(CONFIG_PCH_DMA) += pch_dma.o
 obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
 obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
+obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
index 97f87b2..f4aed5f 100644 (file)
@@ -1343,7 +1343,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
 
                tasklet_init(&atchan->tasklet, atc_tasklet,
                                (unsigned long)atchan);
-               atc_enable_irq(atchan);
+               atc_enable_chan_irq(atdma, i);
        }
 
        /* set base routines */
@@ -1410,7 +1410,7 @@ static int __exit at_dma_remove(struct platform_device *pdev)
                struct at_dma_chan      *atchan = to_at_dma_chan(chan);
 
                /* Disable interrupts */
-               atc_disable_irq(atchan);
+               atc_disable_chan_irq(atdma, chan->chan_id);
                tasklet_disable(&atchan->tasklet);
 
                tasklet_kill(&atchan->tasklet);
index dcaedfc..a8d3277 100644 (file)
@@ -327,28 +327,27 @@ static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
 }
 
 
-static void atc_setup_irq(struct at_dma_chan *atchan, int on)
+static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on)
 {
-       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
-       u32             ebci;
+       u32 ebci;
 
        /* enable interrupts on buffer transfer completion & error */
-       ebci =    AT_DMA_BTC(atchan->chan_common.chan_id)
-               | AT_DMA_ERR(atchan->chan_common.chan_id);
+       ebci =    AT_DMA_BTC(chan_id)
+               | AT_DMA_ERR(chan_id);
        if (on)
                dma_writel(atdma, EBCIER, ebci);
        else
                dma_writel(atdma, EBCIDR, ebci);
 }
 
-static inline void atc_enable_irq(struct at_dma_chan *atchan)
+static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id)
 {
-       atc_setup_irq(atchan, 1);
+       atc_setup_irq(atdma, chan_id, 1);
 }
 
-static inline void atc_disable_irq(struct at_dma_chan *atchan)
+static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id)
 {
-       atc_setup_irq(atchan, 0);
+       atc_setup_irq(atdma, chan_id, 0);
 }
 
 
index 2b8661b..24225f0 100644 (file)
@@ -599,7 +599,7 @@ static int dmatest_add_channel(struct dma_chan *chan)
        }
        if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
                cnt = dmatest_add_threads(dtc, DMA_PQ);
-               thread_count += cnt > 0 ?: 0;
+               thread_count += cnt > 0 ? cnt : 0;
        }
 
        pr_info("dmatest: Started %u threads using %s\n",
index a8af379..8bc5acf 100644 (file)
@@ -1102,11 +1102,13 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
        case DMA_SLAVE_CONFIG:
                if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
                        sdmac->per_address = dmaengine_cfg->src_addr;
-                       sdmac->watermark_level = dmaengine_cfg->src_maxburst;
+                       sdmac->watermark_level = dmaengine_cfg->src_maxburst *
+                                               dmaengine_cfg->src_addr_width;
                        sdmac->word_size = dmaengine_cfg->src_addr_width;
                } else {
                        sdmac->per_address = dmaengine_cfg->dst_addr;
-                       sdmac->watermark_level = dmaengine_cfg->dst_maxburst;
+                       sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
+                                               dmaengine_cfg->dst_addr_width;
                        sdmac->word_size = dmaengine_cfg->dst_addr_width;
                }
                sdmac->direction = dmaengine_cfg->direction;
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
new file mode 100644 (file)
index 0000000..16a6b48
--- /dev/null
@@ -0,0 +1,1109 @@
+/*
+ * SA11x0 DMAengine support
+ *
+ * Copyright (C) 2012 Russell King
+ *   Derived in part from arch/arm/mach-sa1100/dma.c,
+ *   Copyright (C) 2000, 2001 by Nicolas Pitre
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sa11x0-dma.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define NR_PHY_CHAN    6
+#define DMA_ALIGN      3
+#define DMA_MAX_SIZE   0x1fff
+#define DMA_CHUNK_SIZE 0x1000
+
+#define DMA_DDAR       0x00
+#define DMA_DCSR_S     0x04
+#define DMA_DCSR_C     0x08
+#define DMA_DCSR_R     0x0c
+#define DMA_DBSA       0x10
+#define DMA_DBTA       0x14
+#define DMA_DBSB       0x18
+#define DMA_DBTB       0x1c
+#define DMA_SIZE       0x20
+
+#define DCSR_RUN       (1 << 0)
+#define DCSR_IE                (1 << 1)
+#define DCSR_ERROR     (1 << 2)
+#define DCSR_DONEA     (1 << 3)
+#define DCSR_STRTA     (1 << 4)
+#define DCSR_DONEB     (1 << 5)
+#define DCSR_STRTB     (1 << 6)
+#define DCSR_BIU       (1 << 7)
+
+#define DDAR_RW                (1 << 0)        /* 0 = W, 1 = R */
+#define DDAR_E         (1 << 1)        /* 0 = LE, 1 = BE */
+#define DDAR_BS                (1 << 2)        /* 0 = BS4, 1 = BS8 */
+#define DDAR_DW                (1 << 3)        /* 0 = 8b, 1 = 16b */
+#define DDAR_Ser0UDCTr (0x0 << 4)
+#define DDAR_Ser0UDCRc (0x1 << 4)
+#define DDAR_Ser1SDLCTr        (0x2 << 4)
+#define DDAR_Ser1SDLCRc        (0x3 << 4)
+#define DDAR_Ser1UARTTr        (0x4 << 4)
+#define DDAR_Ser1UARTRc        (0x5 << 4)
+#define DDAR_Ser2ICPTr (0x6 << 4)
+#define DDAR_Ser2ICPRc (0x7 << 4)
+#define DDAR_Ser3UARTTr        (0x8 << 4)
+#define DDAR_Ser3UARTRc        (0x9 << 4)
+#define DDAR_Ser4MCP0Tr        (0xa << 4)
+#define DDAR_Ser4MCP0Rc        (0xb << 4)
+#define DDAR_Ser4MCP1Tr        (0xc << 4)
+#define DDAR_Ser4MCP1Rc        (0xd << 4)
+#define DDAR_Ser4SSPTr (0xe << 4)
+#define DDAR_Ser4SSPRc (0xf << 4)
+
+struct sa11x0_dma_sg {
+       u32                     addr;
+       u32                     len;
+};
+
+struct sa11x0_dma_desc {
+       struct dma_async_tx_descriptor tx;
+       u32                     ddar;
+       size_t                  size;
+
+       /* maybe protected by c->lock */
+       struct list_head        node;
+       unsigned                sglen;
+       struct sa11x0_dma_sg    sg[0];
+};
+
+struct sa11x0_dma_phy;
+
+struct sa11x0_dma_chan {
+       struct dma_chan         chan;
+       spinlock_t              lock;
+       dma_cookie_t            lc;
+
+       /* protected by c->lock */
+       struct sa11x0_dma_phy   *phy;
+       enum dma_status         status;
+       struct list_head        desc_submitted;
+       struct list_head        desc_issued;
+
+       /* protected by d->lock */
+       struct list_head        node;
+
+       u32                     ddar;
+       const char              *name;
+};
+
+struct sa11x0_dma_phy {
+       void __iomem            *base;
+       struct sa11x0_dma_dev   *dev;
+       unsigned                num;
+
+       struct sa11x0_dma_chan  *vchan;
+
+       /* Protected by c->lock */
+       unsigned                sg_load;
+       struct sa11x0_dma_desc  *txd_load;
+       unsigned                sg_done;
+       struct sa11x0_dma_desc  *txd_done;
+#ifdef CONFIG_PM_SLEEP
+       u32                     dbs[2];
+       u32                     dbt[2];
+       u32                     dcsr;
+#endif
+};
+
+struct sa11x0_dma_dev {
+       struct dma_device       slave;
+       void __iomem            *base;
+       spinlock_t              lock;
+       struct tasklet_struct   task;
+       struct list_head        chan_pending;
+       struct list_head        desc_complete;
+       struct sa11x0_dma_phy   phy[NR_PHY_CHAN];
+};
+
+static struct sa11x0_dma_chan *to_sa11x0_dma_chan(struct dma_chan *chan)
+{
+       return container_of(chan, struct sa11x0_dma_chan, chan);
+}
+
+static struct sa11x0_dma_dev *to_sa11x0_dma(struct dma_device *dmadev)
+{
+       return container_of(dmadev, struct sa11x0_dma_dev, slave);
+}
+
+static struct sa11x0_dma_desc *to_sa11x0_dma_tx(struct dma_async_tx_descriptor *tx)
+{
+       return container_of(tx, struct sa11x0_dma_desc, tx);
+}
+
+static struct sa11x0_dma_desc *sa11x0_dma_next_desc(struct sa11x0_dma_chan *c)
+{
+       if (list_empty(&c->desc_issued))
+               return NULL;
+
+       return list_first_entry(&c->desc_issued, struct sa11x0_dma_desc, node);
+}
+
+static void sa11x0_dma_start_desc(struct sa11x0_dma_phy *p, struct sa11x0_dma_desc *txd)
+{
+       list_del(&txd->node);
+       p->txd_load = txd;
+       p->sg_load = 0;
+
+       dev_vdbg(p->dev->slave.dev, "pchan %u: txd %p[%x]: starting: DDAR:%x\n",
+               p->num, txd, txd->tx.cookie, txd->ddar);
+}
+
+static void noinline sa11x0_dma_start_sg(struct sa11x0_dma_phy *p,
+       struct sa11x0_dma_chan *c)
+{
+       struct sa11x0_dma_desc *txd = p->txd_load;
+       struct sa11x0_dma_sg *sg;
+       void __iomem *base = p->base;
+       unsigned dbsx, dbtx;
+       u32 dcsr;
+
+       if (!txd)
+               return;
+
+       dcsr = readl_relaxed(base + DMA_DCSR_R);
+
+       /* Don't try to load the next transfer if both buffers are started */
+       if ((dcsr & (DCSR_STRTA | DCSR_STRTB)) == (DCSR_STRTA | DCSR_STRTB))
+               return;
+
+       if (p->sg_load == txd->sglen) {
+               struct sa11x0_dma_desc *txn = sa11x0_dma_next_desc(c);
+
+               /*
+                * We have reached the end of the current descriptor.
+                * Peek at the next descriptor, and if compatible with
+                * the current, start processing it.
+                */
+               if (txn && txn->ddar == txd->ddar) {
+                       txd = txn;
+                       sa11x0_dma_start_desc(p, txn);
+               } else {
+                       p->txd_load = NULL;
+                       return;
+               }
+       }
+
+       sg = &txd->sg[p->sg_load++];
+
+       /* Select buffer to load according to channel status */
+       if (((dcsr & (DCSR_BIU | DCSR_STRTB)) == (DCSR_BIU | DCSR_STRTB)) ||
+           ((dcsr & (DCSR_BIU | DCSR_STRTA)) == 0)) {
+               dbsx = DMA_DBSA;
+               dbtx = DMA_DBTA;
+               dcsr = DCSR_STRTA | DCSR_IE | DCSR_RUN;
+       } else {
+               dbsx = DMA_DBSB;
+               dbtx = DMA_DBTB;
+               dcsr = DCSR_STRTB | DCSR_IE | DCSR_RUN;
+       }
+
+       writel_relaxed(sg->addr, base + dbsx);
+       writel_relaxed(sg->len, base + dbtx);
+       writel(dcsr, base + DMA_DCSR_S);
+
+       dev_dbg(p->dev->slave.dev, "pchan %u: load: DCSR:%02x DBS%c:%08x DBT%c:%08x\n",
+               p->num, dcsr,
+               'A' + (dbsx == DMA_DBSB), sg->addr,
+               'A' + (dbtx == DMA_DBTB), sg->len);
+}
+
+static void noinline sa11x0_dma_complete(struct sa11x0_dma_phy *p,
+       struct sa11x0_dma_chan *c)
+{
+       struct sa11x0_dma_desc *txd = p->txd_done;
+
+       if (++p->sg_done == txd->sglen) {
+               struct sa11x0_dma_dev *d = p->dev;
+
+               dev_vdbg(d->slave.dev, "pchan %u: txd %p[%x]: completed\n",
+                       p->num, p->txd_done, p->txd_done->tx.cookie);
+
+               c->lc = txd->tx.cookie;
+
+               spin_lock(&d->lock);
+               list_add_tail(&txd->node, &d->desc_complete);
+               spin_unlock(&d->lock);
+
+               p->sg_done = 0;
+               p->txd_done = p->txd_load;
+
+               tasklet_schedule(&d->task);
+       }
+
+       sa11x0_dma_start_sg(p, c);
+}
+
+static irqreturn_t sa11x0_dma_irq(int irq, void *dev_id)
+{
+       struct sa11x0_dma_phy *p = dev_id;
+       struct sa11x0_dma_dev *d = p->dev;
+       struct sa11x0_dma_chan *c;
+       u32 dcsr;
+
+       dcsr = readl_relaxed(p->base + DMA_DCSR_R);
+       if (!(dcsr & (DCSR_ERROR | DCSR_DONEA | DCSR_DONEB)))
+               return IRQ_NONE;
+
+       /* Clear reported status bits */
+       writel_relaxed(dcsr & (DCSR_ERROR | DCSR_DONEA | DCSR_DONEB),
+               p->base + DMA_DCSR_C);
+
+       dev_dbg(d->slave.dev, "pchan %u: irq: DCSR:%02x\n", p->num, dcsr);
+
+       if (dcsr & DCSR_ERROR) {
+               dev_err(d->slave.dev, "pchan %u: error. DCSR:%02x DDAR:%08x DBSA:%08x DBTA:%08x DBSB:%08x DBTB:%08x\n",
+                       p->num, dcsr,
+                       readl_relaxed(p->base + DMA_DDAR),
+                       readl_relaxed(p->base + DMA_DBSA),
+                       readl_relaxed(p->base + DMA_DBTA),
+                       readl_relaxed(p->base + DMA_DBSB),
+                       readl_relaxed(p->base + DMA_DBTB));
+       }
+
+       c = p->vchan;
+       if (c) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&c->lock, flags);
+               /*
+                * Now that we're holding the lock, check that the vchan
+                * really is associated with this pchan before touching the
+                * hardware.  This should always succeed, because we won't
+                * change p->vchan or c->phy while the channel is actively
+                * transferring.
+                */
+               if (c->phy == p) {
+                       if (dcsr & DCSR_DONEA)
+                               sa11x0_dma_complete(p, c);
+                       if (dcsr & DCSR_DONEB)
+                               sa11x0_dma_complete(p, c);
+               }
+               spin_unlock_irqrestore(&c->lock, flags);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void sa11x0_dma_start_txd(struct sa11x0_dma_chan *c)
+{
+       struct sa11x0_dma_desc *txd = sa11x0_dma_next_desc(c);
+
+       /* If the issued list is empty, we have no further txds to process */
+       if (txd) {
+               struct sa11x0_dma_phy *p = c->phy;
+
+               sa11x0_dma_start_desc(p, txd);
+               p->txd_done = txd;
+               p->sg_done = 0;
+
+               /* The channel should not have any transfers started */
+               WARN_ON(readl_relaxed(p->base + DMA_DCSR_R) &
+                                     (DCSR_STRTA | DCSR_STRTB));
+
+               /* Clear the run and start bits before changing DDAR */
+               writel_relaxed(DCSR_RUN | DCSR_STRTA | DCSR_STRTB,
+                              p->base + DMA_DCSR_C);
+               writel_relaxed(txd->ddar, p->base + DMA_DDAR);
+
+               /* Try to start both buffers */
+               sa11x0_dma_start_sg(p, c);
+               sa11x0_dma_start_sg(p, c);
+       }
+}
+
+static void sa11x0_dma_tasklet(unsigned long arg)
+{
+       struct sa11x0_dma_dev *d = (struct sa11x0_dma_dev *)arg;
+       struct sa11x0_dma_phy *p;
+       struct sa11x0_dma_chan *c;
+       struct sa11x0_dma_desc *txd, *txn;
+       LIST_HEAD(head);
+       unsigned pch, pch_alloc = 0;
+
+       dev_dbg(d->slave.dev, "tasklet enter\n");
+
+       /* Get the completed tx descriptors */
+       spin_lock_irq(&d->lock);
+       list_splice_init(&d->desc_complete, &head);
+       spin_unlock_irq(&d->lock);
+
+       list_for_each_entry(txd, &head, node) {
+               c = to_sa11x0_dma_chan(txd->tx.chan);
+
+               dev_dbg(d->slave.dev, "vchan %p: txd %p[%x] completed\n",
+                       c, txd, txd->tx.cookie);
+
+               spin_lock_irq(&c->lock);
+               p = c->phy;
+               if (p) {
+                       if (!p->txd_done)
+                               sa11x0_dma_start_txd(c);
+                       if (!p->txd_done) {
+                               /* No current txd associated with this channel */
+                               dev_dbg(d->slave.dev, "pchan %u: free\n", p->num);
+
+                               /* Mark this channel free */
+                               c->phy = NULL;
+                               p->vchan = NULL;
+                       }
+               }
+               spin_unlock_irq(&c->lock);
+       }
+
+       spin_lock_irq(&d->lock);
+       for (pch = 0; pch < NR_PHY_CHAN; pch++) {
+               p = &d->phy[pch];
+
+               if (p->vchan == NULL && !list_empty(&d->chan_pending)) {
+                       c = list_first_entry(&d->chan_pending,
+                               struct sa11x0_dma_chan, node);
+                       list_del_init(&c->node);
+
+                       pch_alloc |= 1 << pch;
+
+                       /* Mark this channel allocated */
+                       p->vchan = c;
+
+                       dev_dbg(d->slave.dev, "pchan %u: alloc vchan %p\n", pch, c);
+               }
+       }
+       spin_unlock_irq(&d->lock);
+
+       for (pch = 0; pch < NR_PHY_CHAN; pch++) {
+               if (pch_alloc & (1 << pch)) {
+                       p = &d->phy[pch];
+                       c = p->vchan;
+
+                       spin_lock_irq(&c->lock);
+                       c->phy = p;
+
+                       sa11x0_dma_start_txd(c);
+                       spin_unlock_irq(&c->lock);
+               }
+       }
+
+       /* Now free the completed tx descriptor, and call their callbacks */
+       list_for_each_entry_safe(txd, txn, &head, node) {
+               dma_async_tx_callback callback = txd->tx.callback;
+               void *callback_param = txd->tx.callback_param;
+
+               dev_dbg(d->slave.dev, "txd %p[%x]: callback and free\n",
+                       txd, txd->tx.cookie);
+
+               kfree(txd);
+
+               if (callback)
+                       callback(callback_param);
+       }
+
+       dev_dbg(d->slave.dev, "tasklet exit\n");
+}
+
+
+static void sa11x0_dma_desc_free(struct sa11x0_dma_dev *d, struct list_head *head)
+{
+       struct sa11x0_dma_desc *txd, *txn;
+
+       list_for_each_entry_safe(txd, txn, head, node) {
+               dev_dbg(d->slave.dev, "txd %p: freeing\n", txd);
+               kfree(txd);
+       }
+}
+
+static int sa11x0_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+       return 0;
+}
+
+static void sa11x0_dma_free_chan_resources(struct dma_chan *chan)
+{
+       struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
+       struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
+       unsigned long flags;
+       LIST_HEAD(head);
+
+       spin_lock_irqsave(&c->lock, flags);
+       spin_lock(&d->lock);
+       list_del_init(&c->node);
+       spin_unlock(&d->lock);
+
+       list_splice_tail_init(&c->desc_submitted, &head);
+       list_splice_tail_init(&c->desc_issued, &head);
+       spin_unlock_irqrestore(&c->lock, flags);
+
+       sa11x0_dma_desc_free(d, &head);
+}
+
+static dma_addr_t sa11x0_dma_pos(struct sa11x0_dma_phy *p)
+{
+       unsigned reg;
+       u32 dcsr;
+
+       dcsr = readl_relaxed(p->base + DMA_DCSR_R);
+
+       if ((dcsr & (DCSR_BIU | DCSR_STRTA)) == DCSR_STRTA ||
+           (dcsr & (DCSR_BIU | DCSR_STRTB)) == DCSR_BIU)
+               reg = DMA_DBSA;
+       else
+               reg = DMA_DBSB;
+
+       return readl_relaxed(p->base + reg);
+}
+
+static enum dma_status sa11x0_dma_tx_status(struct dma_chan *chan,
+       dma_cookie_t cookie, struct dma_tx_state *state)
+{
+       struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
+       struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
+       struct sa11x0_dma_phy *p;
+       struct sa11x0_dma_desc *txd;
+       dma_cookie_t last_used, last_complete;
+       unsigned long flags;
+       enum dma_status ret;
+       size_t bytes = 0;
+
+       last_used = c->chan.cookie;
+       last_complete = c->lc;
+
+       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       if (ret == DMA_SUCCESS) {
+               dma_set_tx_state(state, last_complete, last_used, 0);
+               return ret;
+       }
+
+       spin_lock_irqsave(&c->lock, flags);
+       p = c->phy;
+       ret = c->status;
+       if (p) {
+               dma_addr_t addr = sa11x0_dma_pos(p);
+
+               dev_vdbg(d->slave.dev, "tx_status: addr:%x\n", addr);
+
+               txd = p->txd_done;
+               if (txd) {
+                       unsigned i;
+
+                       for (i = 0; i < txd->sglen; i++) {
+                               dev_vdbg(d->slave.dev, "tx_status: [%u] %x+%x\n",
+                                       i, txd->sg[i].addr, txd->sg[i].len);
+                               if (addr >= txd->sg[i].addr &&
+                                   addr < txd->sg[i].addr + txd->sg[i].len) {
+                                       unsigned len;
+
+                                       len = txd->sg[i].len -
+                                               (addr - txd->sg[i].addr);
+                                       dev_vdbg(d->slave.dev, "tx_status: [%u] +%x\n",
+                                               i, len);
+                                       bytes += len;
+                                       i++;
+                                       break;
+                               }
+                       }
+                       for (; i < txd->sglen; i++) {
+                               dev_vdbg(d->slave.dev, "tx_status: [%u] %x+%x ++\n",
+                                       i, txd->sg[i].addr, txd->sg[i].len);
+                               bytes += txd->sg[i].len;
+                       }
+               }
+               if (txd != p->txd_load && p->txd_load)
+                       bytes += p->txd_load->size;
+       }
+       list_for_each_entry(txd, &c->desc_issued, node) {
+               bytes += txd->size;
+       }
+       spin_unlock_irqrestore(&c->lock, flags);
+
+       dma_set_tx_state(state, last_complete, last_used, bytes);
+
+       dev_vdbg(d->slave.dev, "tx_status: bytes 0x%zx\n", bytes);
+
+       return ret;
+}
+
+/*
+ * Move pending txds to the issued list, and re-init pending list.
+ * If not already pending, add this channel to the list of pending
+ * channels and trigger the tasklet to run.
+ */
+static void sa11x0_dma_issue_pending(struct dma_chan *chan)
+{
+       struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
+       struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
+       unsigned long flags;
+
+       spin_lock_irqsave(&c->lock, flags);
+       list_splice_tail_init(&c->desc_submitted, &c->desc_issued);
+       if (!list_empty(&c->desc_issued)) {
+               spin_lock(&d->lock);
+               if (!c->phy && list_empty(&c->node)) {
+                       list_add_tail(&c->node, &d->chan_pending);
+                       tasklet_schedule(&d->task);
+                       dev_dbg(d->slave.dev, "vchan %p: issued\n", c);
+               }
+               spin_unlock(&d->lock);
+       } else
+               dev_dbg(d->slave.dev, "vchan %p: nothing to issue\n", c);
+       spin_unlock_irqrestore(&c->lock, flags);
+}
+
+static dma_cookie_t sa11x0_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+       struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(tx->chan);
+       struct sa11x0_dma_desc *txd = to_sa11x0_dma_tx(tx);
+       unsigned long flags;
+
+       spin_lock_irqsave(&c->lock, flags);
+       c->chan.cookie += 1;
+       if (c->chan.cookie < 0)
+               c->chan.cookie = 1;
+       txd->tx.cookie = c->chan.cookie;
+
+       list_add_tail(&txd->node, &c->desc_submitted);
+       spin_unlock_irqrestore(&c->lock, flags);
+
+       dev_dbg(tx->chan->device->dev, "vchan %p: txd %p[%x]: submitted\n",
+               c, txd, txd->tx.cookie);
+
+       return txd->tx.cookie;
+}
+
+static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg(
+       struct dma_chan *chan, struct scatterlist *sg, unsigned int sglen,
+       enum dma_transfer_direction dir, unsigned long flags)
+{
+       struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
+       struct sa11x0_dma_desc *txd;
+       struct scatterlist *sgent;
+       unsigned i, j = sglen;
+       size_t size = 0;
+
+       /* SA11x0 channels can only operate in their native direction */
+       if (dir != (c->ddar & DDAR_RW ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV)) {
+               dev_err(chan->device->dev, "vchan %p: bad DMA direction: DDAR:%08x dir:%u\n",
+                       c, c->ddar, dir);
+               return NULL;
+       }
+
+       /* Do not allow zero-sized txds */
+       if (sglen == 0)
+               return NULL;
+
+       for_each_sg(sg, sgent, sglen, i) {
+               dma_addr_t addr = sg_dma_address(sgent);
+               unsigned int len = sg_dma_len(sgent);
+
+               if (len > DMA_MAX_SIZE)
+                       j += DIV_ROUND_UP(len, DMA_MAX_SIZE & ~DMA_ALIGN) - 1;
+               if (addr & DMA_ALIGN) {
+                       dev_dbg(chan->device->dev, "vchan %p: bad buffer alignment: %08x\n",
+                               c, addr);
+                       return NULL;
+               }
+       }
+
+       txd = kzalloc(sizeof(*txd) + j * sizeof(txd->sg[0]), GFP_ATOMIC);
+       if (!txd) {
+               dev_dbg(chan->device->dev, "vchan %p: kzalloc failed\n", c);
+               return NULL;
+       }
+
+       j = 0;
+       for_each_sg(sg, sgent, sglen, i) {
+               dma_addr_t addr = sg_dma_address(sgent);
+               unsigned len = sg_dma_len(sgent);
+
+               size += len;
+
+               do {
+                       unsigned tlen = len;
+
+                       /*
+                        * Check whether the transfer will fit.  If not, try
+                        * to split the transfer up such that we end up with
+                        * equal chunks - but make sure that we preserve the
+                        * alignment.  This avoids small segments.
+                        */
+                       if (tlen > DMA_MAX_SIZE) {
+                               unsigned mult = DIV_ROUND_UP(tlen,
+                                       DMA_MAX_SIZE & ~DMA_ALIGN);
+
+                               tlen = (tlen / mult) & ~DMA_ALIGN;
+                       }
+
+                       txd->sg[j].addr = addr;
+                       txd->sg[j].len = tlen;
+
+                       addr += tlen;
+                       len -= tlen;
+                       j++;
+               } while (len);
+       }
+
+       dma_async_tx_descriptor_init(&txd->tx, &c->chan);
+       txd->tx.flags = flags;
+       txd->tx.tx_submit = sa11x0_dma_tx_submit;
+       txd->ddar = c->ddar;
+       txd->size = size;
+       txd->sglen = j;
+
+       dev_dbg(chan->device->dev, "vchan %p: txd %p: size %u nr %u\n",
+               c, txd, txd->size, txd->sglen);
+
+       return &txd->tx;
+}
+
+static int sa11x0_dma_slave_config(struct sa11x0_dma_chan *c, struct dma_slave_config *cfg)
+{
+       u32 ddar = c->ddar & ((0xf << 4) | DDAR_RW);
+       dma_addr_t addr;
+       enum dma_slave_buswidth width;
+       u32 maxburst;
+
+       if (ddar & DDAR_RW) {
+               addr = cfg->src_addr;
+               width = cfg->src_addr_width;
+               maxburst = cfg->src_maxburst;
+       } else {
+               addr = cfg->dst_addr;
+               width = cfg->dst_addr_width;
+               maxburst = cfg->dst_maxburst;
+       }
+
+       if ((width != DMA_SLAVE_BUSWIDTH_1_BYTE &&
+            width != DMA_SLAVE_BUSWIDTH_2_BYTES) ||
+           (maxburst != 4 && maxburst != 8))
+               return -EINVAL;
+
+       if (width == DMA_SLAVE_BUSWIDTH_2_BYTES)
+               ddar |= DDAR_DW;
+       if (maxburst == 8)
+               ddar |= DDAR_BS;
+
+       dev_dbg(c->chan.device->dev, "vchan %p: dma_slave_config addr %x width %u burst %u\n",
+               c, addr, width, maxburst);
+
+       c->ddar = ddar | (addr & 0xf0000000) | (addr & 0x003ffffc) << 6;
+
+       return 0;
+}
+
+static int sa11x0_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+       unsigned long arg)
+{
+       struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
+       struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
+       struct sa11x0_dma_phy *p;
+       LIST_HEAD(head);
+       unsigned long flags;
+       int ret;
+
+       switch (cmd) {
+       case DMA_SLAVE_CONFIG:
+               return sa11x0_dma_slave_config(c, (struct dma_slave_config *)arg);
+
+       case DMA_TERMINATE_ALL:
+               dev_dbg(d->slave.dev, "vchan %p: terminate all\n", c);
+               /* Clear the tx descriptor lists */
+               spin_lock_irqsave(&c->lock, flags);
+               list_splice_tail_init(&c->desc_submitted, &head);
+               list_splice_tail_init(&c->desc_issued, &head);
+
+               p = c->phy;
+               if (p) {
+                       struct sa11x0_dma_desc *txd, *txn;
+
+                       dev_dbg(d->slave.dev, "pchan %u: terminating\n", p->num);
+                       /* vchan is assigned to a pchan - stop the channel */
+                       writel(DCSR_RUN | DCSR_IE |
+                               DCSR_STRTA | DCSR_DONEA |
+                               DCSR_STRTB | DCSR_DONEB,
+                               p->base + DMA_DCSR_C);
+
+                       list_for_each_entry_safe(txd, txn, &d->desc_complete, node)
+                               if (txd->tx.chan == &c->chan)
+                                       list_move(&txd->node, &head);
+
+                       if (p->txd_load) {
+                               if (p->txd_load != p->txd_done)
+                                       list_add_tail(&p->txd_load->node, &head);
+                               p->txd_load = NULL;
+                       }
+                       if (p->txd_done) {
+                               list_add_tail(&p->txd_done->node, &head);
+                               p->txd_done = NULL;
+                       }
+                       c->phy = NULL;
+                       spin_lock(&d->lock);
+                       p->vchan = NULL;
+                       spin_unlock(&d->lock);
+                       tasklet_schedule(&d->task);
+               }
+               spin_unlock_irqrestore(&c->lock, flags);
+               sa11x0_dma_desc_free(d, &head);
+               ret = 0;
+               break;
+
+       case DMA_PAUSE:
+               dev_dbg(d->slave.dev, "vchan %p: pause\n", c);
+               spin_lock_irqsave(&c->lock, flags);
+               if (c->status == DMA_IN_PROGRESS) {
+                       c->status = DMA_PAUSED;
+
+                       p = c->phy;
+                       if (p) {
+                               writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_C);
+                       } else {
+                               spin_lock(&d->lock);
+                               list_del_init(&c->node);
+                               spin_unlock(&d->lock);
+                       }
+               }
+               spin_unlock_irqrestore(&c->lock, flags);
+               ret = 0;
+               break;
+
+       case DMA_RESUME:
+               dev_dbg(d->slave.dev, "vchan %p: resume\n", c);
+               spin_lock_irqsave(&c->lock, flags);
+               if (c->status == DMA_PAUSED) {
+                       c->status = DMA_IN_PROGRESS;
+
+                       p = c->phy;
+                       if (p) {
+                               writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_S);
+                       } else if (!list_empty(&c->desc_issued)) {
+                               spin_lock(&d->lock);
+                               list_add_tail(&c->node, &d->chan_pending);
+                               spin_unlock(&d->lock);
+                       }
+               }
+               spin_unlock_irqrestore(&c->lock, flags);
+               ret = 0;
+               break;
+
+       default:
+               ret = -ENXIO;
+               break;
+       }
+
+       return ret;
+}
+
+struct sa11x0_dma_channel_desc {
+       u32 ddar;
+       const char *name;
+};
+
+#define CD(d1, d2) { .ddar = DDAR_##d1 | d2, .name = #d1 }
+static const struct sa11x0_dma_channel_desc chan_desc[] = {
+       CD(Ser0UDCTr, 0),
+       CD(Ser0UDCRc, DDAR_RW),
+       CD(Ser1SDLCTr, 0),
+       CD(Ser1SDLCRc, DDAR_RW),
+       CD(Ser1UARTTr, 0),
+       CD(Ser1UARTRc, DDAR_RW),
+       CD(Ser2ICPTr, 0),
+       CD(Ser2ICPRc, DDAR_RW),
+       CD(Ser3UARTTr, 0),
+       CD(Ser3UARTRc, DDAR_RW),
+       CD(Ser4MCP0Tr, 0),
+       CD(Ser4MCP0Rc, DDAR_RW),
+       CD(Ser4MCP1Tr, 0),
+       CD(Ser4MCP1Rc, DDAR_RW),
+       CD(Ser4SSPTr, 0),
+       CD(Ser4SSPRc, DDAR_RW),
+};
+
+static int __devinit sa11x0_dma_init_dmadev(struct dma_device *dmadev,
+       struct device *dev)
+{
+       unsigned i;
+
+       dmadev->chancnt = ARRAY_SIZE(chan_desc);
+       INIT_LIST_HEAD(&dmadev->channels);
+       dmadev->dev = dev;
+       dmadev->device_alloc_chan_resources = sa11x0_dma_alloc_chan_resources;
+       dmadev->device_free_chan_resources = sa11x0_dma_free_chan_resources;
+       dmadev->device_control = sa11x0_dma_control;
+       dmadev->device_tx_status = sa11x0_dma_tx_status;
+       dmadev->device_issue_pending = sa11x0_dma_issue_pending;
+
+       for (i = 0; i < dmadev->chancnt; i++) {
+               struct sa11x0_dma_chan *c;
+
+               c = kzalloc(sizeof(*c), GFP_KERNEL);
+               if (!c) {
+                       dev_err(dev, "no memory for channel %u\n", i);
+                       return -ENOMEM;
+               }
+
+               c->chan.device = dmadev;
+               c->status = DMA_IN_PROGRESS;
+               c->ddar = chan_desc[i].ddar;
+               c->name = chan_desc[i].name;
+               spin_lock_init(&c->lock);
+               INIT_LIST_HEAD(&c->desc_submitted);
+               INIT_LIST_HEAD(&c->desc_issued);
+               INIT_LIST_HEAD(&c->node);
+               list_add_tail(&c->chan.device_node, &dmadev->channels);
+       }
+
+       return dma_async_device_register(dmadev);
+}
+
+static int sa11x0_dma_request_irq(struct platform_device *pdev, int nr,
+       void *data)
+{
+       int irq = platform_get_irq(pdev, nr);
+
+       if (irq <= 0)
+               return -ENXIO;
+
+       return request_irq(irq, sa11x0_dma_irq, 0, dev_name(&pdev->dev), data);
+}
+
+static void sa11x0_dma_free_irq(struct platform_device *pdev, int nr,
+       void *data)
+{
+       int irq = platform_get_irq(pdev, nr);
+       if (irq > 0)
+               free_irq(irq, data);
+}
+
+static void sa11x0_dma_free_channels(struct dma_device *dmadev)
+{
+       struct sa11x0_dma_chan *c, *cn;
+
+       list_for_each_entry_safe(c, cn, &dmadev->channels, chan.device_node) {
+               list_del(&c->chan.device_node);
+               kfree(c);
+       }
+}
+
+static int __devinit sa11x0_dma_probe(struct platform_device *pdev)
+{
+       struct sa11x0_dma_dev *d;
+       struct resource *res;
+       unsigned i;
+       int ret;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENXIO;
+
+       d = kzalloc(sizeof(*d), GFP_KERNEL);
+       if (!d) {
+               ret = -ENOMEM;
+               goto err_alloc;
+       }
+
+       spin_lock_init(&d->lock);
+       INIT_LIST_HEAD(&d->chan_pending);
+       INIT_LIST_HEAD(&d->desc_complete);
+
+       d->base = ioremap(res->start, resource_size(res));
+       if (!d->base) {
+               ret = -ENOMEM;
+               goto err_ioremap;
+       }
+
+       tasklet_init(&d->task, sa11x0_dma_tasklet, (unsigned long)d);
+
+       for (i = 0; i < NR_PHY_CHAN; i++) {
+               struct sa11x0_dma_phy *p = &d->phy[i];
+
+               p->dev = d;
+               p->num = i;
+               p->base = d->base + i * DMA_SIZE;
+               writel_relaxed(DCSR_RUN | DCSR_IE | DCSR_ERROR |
+                       DCSR_DONEA | DCSR_STRTA | DCSR_DONEB | DCSR_STRTB,
+                       p->base + DMA_DCSR_C);
+               writel_relaxed(0, p->base + DMA_DDAR);
+
+               ret = sa11x0_dma_request_irq(pdev, i, p);
+               if (ret) {
+                       while (i) {
+                               i--;
+                               sa11x0_dma_free_irq(pdev, i, &d->phy[i]);
+                       }
+                       goto err_irq;
+               }
+       }
+
+       dma_cap_set(DMA_SLAVE, d->slave.cap_mask);
+       d->slave.device_prep_slave_sg = sa11x0_dma_prep_slave_sg;
+       ret = sa11x0_dma_init_dmadev(&d->slave, &pdev->dev);
+       if (ret) {
+               dev_warn(d->slave.dev, "failed to register slave async device: %d\n",
+                       ret);
+               goto err_slave_reg;
+       }
+
+       platform_set_drvdata(pdev, d);
+       return 0;
+
+ err_slave_reg:
+       sa11x0_dma_free_channels(&d->slave);
+       for (i = 0; i < NR_PHY_CHAN; i++)
+               sa11x0_dma_free_irq(pdev, i, &d->phy[i]);
+ err_irq:
+       tasklet_kill(&d->task);
+       iounmap(d->base);
+ err_ioremap:
+       kfree(d);
+ err_alloc:
+       return ret;
+}
+
+static int __devexit sa11x0_dma_remove(struct platform_device *pdev)
+{
+       struct sa11x0_dma_dev *d = platform_get_drvdata(pdev);
+       unsigned pch;
+
+       dma_async_device_unregister(&d->slave);
+
+       sa11x0_dma_free_channels(&d->slave);
+       for (pch = 0; pch < NR_PHY_CHAN; pch++)
+               sa11x0_dma_free_irq(pdev, pch, &d->phy[pch]);
+       tasklet_kill(&d->task);
+       iounmap(d->base);
+       kfree(d);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sa11x0_dma_suspend(struct device *dev)
+{
+       struct sa11x0_dma_dev *d = dev_get_drvdata(dev);
+       unsigned pch;
+
+       for (pch = 0; pch < NR_PHY_CHAN; pch++) {
+               struct sa11x0_dma_phy *p = &d->phy[pch];
+               u32 dcsr, saved_dcsr;
+
+               dcsr = saved_dcsr = readl_relaxed(p->base + DMA_DCSR_R);
+               if (dcsr & DCSR_RUN) {
+                       writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_C);
+                       dcsr = readl_relaxed(p->base + DMA_DCSR_R);
+               }
+
+               saved_dcsr &= DCSR_RUN | DCSR_IE;
+               if (dcsr & DCSR_BIU) {
+                       p->dbs[0] = readl_relaxed(p->base + DMA_DBSB);
+                       p->dbt[0] = readl_relaxed(p->base + DMA_DBTB);
+                       p->dbs[1] = readl_relaxed(p->base + DMA_DBSA);
+                       p->dbt[1] = readl_relaxed(p->base + DMA_DBTA);
+                       saved_dcsr |= (dcsr & DCSR_STRTA ? DCSR_STRTB : 0) |
+                                     (dcsr & DCSR_STRTB ? DCSR_STRTA : 0);
+               } else {
+                       p->dbs[0] = readl_relaxed(p->base + DMA_DBSA);
+                       p->dbt[0] = readl_relaxed(p->base + DMA_DBTA);
+                       p->dbs[1] = readl_relaxed(p->base + DMA_DBSB);
+                       p->dbt[1] = readl_relaxed(p->base + DMA_DBTB);
+                       saved_dcsr |= dcsr & (DCSR_STRTA | DCSR_STRTB);
+               }
+               p->dcsr = saved_dcsr;
+
+               writel(DCSR_STRTA | DCSR_STRTB, p->base + DMA_DCSR_C);
+       }
+
+       return 0;
+}
+
+static int sa11x0_dma_resume(struct device *dev)
+{
+       struct sa11x0_dma_dev *d = dev_get_drvdata(dev);
+       unsigned pch;
+
+       for (pch = 0; pch < NR_PHY_CHAN; pch++) {
+               struct sa11x0_dma_phy *p = &d->phy[pch];
+               struct sa11x0_dma_desc *txd = NULL;
+               u32 dcsr = readl_relaxed(p->base + DMA_DCSR_R);
+
+               WARN_ON(dcsr & (DCSR_BIU | DCSR_STRTA | DCSR_STRTB | DCSR_RUN));
+
+               if (p->txd_done)
+                       txd = p->txd_done;
+               else if (p->txd_load)
+                       txd = p->txd_load;
+
+               if (!txd)
+                       continue;
+
+               writel_relaxed(txd->ddar, p->base + DMA_DDAR);
+
+               writel_relaxed(p->dbs[0], p->base + DMA_DBSA);
+               writel_relaxed(p->dbt[0], p->base + DMA_DBTA);
+               writel_relaxed(p->dbs[1], p->base + DMA_DBSB);
+               writel_relaxed(p->dbt[1], p->base + DMA_DBTB);
+               writel_relaxed(p->dcsr, p->base + DMA_DCSR_S);
+       }
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops sa11x0_dma_pm_ops = {
+       .suspend_noirq = sa11x0_dma_suspend,
+       .resume_noirq = sa11x0_dma_resume,
+       .freeze_noirq = sa11x0_dma_suspend,
+       .thaw_noirq = sa11x0_dma_resume,
+       .poweroff_noirq = sa11x0_dma_suspend,
+       .restore_noirq = sa11x0_dma_resume,
+};
+
+static struct platform_driver sa11x0_dma_driver = {
+       .driver = {
+               .name   = "sa11x0-dma",
+               .owner  = THIS_MODULE,
+               .pm     = &sa11x0_dma_pm_ops,
+       },
+       .probe          = sa11x0_dma_probe,
+       .remove         = __devexit_p(sa11x0_dma_remove),
+};
+
+bool sa11x0_dma_filter_fn(struct dma_chan *chan, void *param)
+{
+       if (chan->device->dev->driver == &sa11x0_dma_driver.driver) {
+               struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
+               const char *p = param;
+
+               return !strcmp(c->name, p);
+       }
+       return false;
+}
+EXPORT_SYMBOL(sa11x0_dma_filter_fn);
+
+static int __init sa11x0_dma_init(void)
+{
+       return platform_driver_register(&sa11x0_dma_driver);
+}
+subsys_initcall(sa11x0_dma_init);
+
+static void __exit sa11x0_dma_exit(void)
+{
+       platform_driver_unregister(&sa11x0_dma_driver);
+}
+module_exit(sa11x0_dma_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("SA-11x0 DMA driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sa11x0-dma");
index 54043cd..812fd76 100644 (file)
@@ -1262,7 +1262,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
 
        INIT_LIST_HEAD(&shdev->common.channels);
 
-       dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
+       if (!pdata->slave_only)
+               dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
        if (pdata->slave && pdata->slave_num)
                dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
 
index 6628fea..7f5f0da 100644 (file)
@@ -263,6 +263,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
 static char ohci_driver_name[] = KBUILD_MODNAME;
 
 #define PCI_DEVICE_ID_AGERE_FW643      0x5901
+#define PCI_DEVICE_ID_CREATIVE_SB1394  0x4001
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW        0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22     0x8009
 #define PCI_DEVICE_ID_TI_TSB12LV26     0x8020
@@ -289,6 +290,9 @@ static const struct {
        {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
                QUIRK_NO_MSI},
 
+       {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID,
+               QUIRK_RESET_PACKET},
+
        {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
                QUIRK_NO_MSI},
 
@@ -299,7 +303,7 @@ static const struct {
                QUIRK_NO_MSI},
 
        {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
-               QUIRK_CYCLE_TIMER},
+               QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
 
        {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
                QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
index 5b69480..ddfacc5 100644 (file)
@@ -96,7 +96,7 @@ static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
 };
 
 static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
-       "gpi000", "gpio01", "gpio02", "gpio03",
+       "gpio00", "gpio01", "gpio02", "gpio03",
        "gpio04", "gpio05"
 };
 
index 03d6dd5..f0febe5 100644 (file)
@@ -448,6 +448,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
                chip->reg = chip->base;
                chip->ch = i;
                mutex_init(&chip->lock);
+               spin_lock_init(&chip->spinlock);
                ioh_gpio_setup(chip, num_ports[i]);
                ret = gpiochip_add(&chip->gpio);
                if (ret) {
index 68fa55e..e8729cc 100644 (file)
@@ -392,6 +392,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
        chip->reg = chip->base;
        pci_set_drvdata(pdev, chip);
        mutex_init(&chip->lock);
+       spin_lock_init(&chip->spinlock);
        pch_gpio_setup(chip);
        ret = gpiochip_add(&chip->gpio);
        if (ret) {
index 7eecf69..8ea3b33 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 
 static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
index a766177..0a79a11 100644 (file)
@@ -2387,27 +2387,30 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
 };
 
 #if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF)
-static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np,
-                             const void *gpio_spec, u32 *flags)
+static int exynos4_gpio_xlate(struct gpio_chip *gc,
+                       const struct of_phandle_args *gpiospec, u32 *flags)
 {
-       const __be32 *gpio = gpio_spec;
-       const u32 n = be32_to_cpup(gpio);
-       unsigned int pin = gc->base + be32_to_cpu(gpio[0]);
+       unsigned int pin;
 
        if (WARN_ON(gc->of_gpio_n_cells < 4))
                return -EINVAL;
 
-       if (n > gc->ngpio)
+       if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
                return -EINVAL;
 
-       if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1]))))
+       if (gpiospec->args[0] > gc->ngpio)
+               return -EINVAL;
+
+       pin = gc->base + gpiospec->args[0];
+
+       if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
                pr_warn("gpio_xlate: failed to set pin function\n");
-       if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2])))
+       if (s3c_gpio_setpull(pin, gpiospec->args[2]))
                pr_warn("gpio_xlate: failed to set pin pull up/down\n");
-       if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3])))
+       if (s5p_gpio_set_drvstr(pin, gpiospec->args[3]))
                pr_warn("gpio_xlate: failed to set pin drive strength\n");
 
-       return n;
+       return gpiospec->args[0];
 }
 
 static const struct of_device_id exynos4_gpio_dt_match[] __initdata = {
index 1e382ad..a37c31e 100644 (file)
@@ -54,9 +54,10 @@ struct bit_entry {
 int bit_table(struct drm_device *, u8 id, struct bit_entry *);
 
 enum dcb_gpio_tag {
-       DCB_GPIO_TVDAC0 = 0xc,
+       DCB_GPIO_PANEL_POWER = 0x01,
+       DCB_GPIO_TVDAC0 = 0x0c,
        DCB_GPIO_TVDAC1 = 0x2d,
-       DCB_GPIO_PWM_FAN = 0x9,
+       DCB_GPIO_PWM_FAN = 0x09,
        DCB_GPIO_FAN_SENSE = 0x3d,
        DCB_GPIO_UNUSED = 0xff
 };
index 3cb52bc..795a9e3 100644 (file)
@@ -219,6 +219,16 @@ nouveau_display_init(struct drm_device *dev)
        if (ret)
                return ret;
 
+       /* power on internal panel if it's not already.  the init tables of
+        * some vbios default this to off for some reason, causing the
+        * panel to not work after resume
+        */
+       if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) {
+               nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true);
+               msleep(300);
+       }
+
+       /* enable polling for external displays */
        drm_kms_helper_poll_enable(dev);
 
        /* enable hotplug interrupts */
index e4a7cfe..81d7962 100644 (file)
@@ -124,7 +124,7 @@ MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n");
 int nouveau_ctxfw;
 module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
 
-MODULE_PARM_DESC(ctxfw, "Santise DCB table according to MXM-SIS\n");
+MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS\n");
 int nouveau_mxmdcb = 1;
 module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400);
 
index 5f0bc57..7ce3fde 100644 (file)
@@ -379,6 +379,25 @@ retry:
        return 0;
 }
 
+static int
+validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo)
+{
+       struct nouveau_fence *fence = NULL;
+       int ret = 0;
+
+       spin_lock(&nvbo->bo.bdev->fence_lock);
+       if (nvbo->bo.sync_obj)
+               fence = nouveau_fence_ref(nvbo->bo.sync_obj);
+       spin_unlock(&nvbo->bo.bdev->fence_lock);
+
+       if (fence) {
+               ret = nouveau_fence_sync(fence, chan);
+               nouveau_fence_unref(&fence);
+       }
+
+       return ret;
+}
+
 static int
 validate_list(struct nouveau_channel *chan, struct list_head *list,
              struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)
@@ -393,7 +412,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
        list_for_each_entry(nvbo, list, entry) {
                struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
 
-               ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
+               ret = validate_sync(chan, nvbo);
                if (unlikely(ret)) {
                        NV_ERROR(dev, "fail pre-validate sync\n");
                        return ret;
@@ -416,7 +435,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
                        return ret;
                }
 
-               ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
+               ret = validate_sync(chan, nvbo);
                if (unlikely(ret)) {
                        NV_ERROR(dev, "fail post-validate sync\n");
                        return ret;
index 8bccddf..e5a64f0 100644 (file)
@@ -656,7 +656,16 @@ nouveau_mxm_init(struct drm_device *dev)
 
        if (mxm_shadow(dev, mxm[0])) {
                MXM_MSG(dev, "failed to locate valid SIS\n");
+#if 0
+               /* we should, perhaps, fall back to some kind of limited
+                * mode here if the x86 vbios hasn't already done the
+                * work for us (so we prevent loading with completely
+                * whacked vbios tables).
+                */
                return -EINVAL;
+#else
+               return 0;
+#endif
        }
 
        MXM_MSG(dev, "MXMS Version %d.%d\n",
index 0393721..ec5481d 100644 (file)
@@ -495,9 +495,9 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nv50_pm_state *info;
        struct pll_lims pll;
-       int ret = -EINVAL;
+       int clk, ret = -EINVAL;
        int N, M, P1, P2;
-       u32 clk, out;
+       u32 out;
 
        if (dev_priv->chipset == 0xaa ||
            dev_priv->chipset == 0xac)
index 8919352..742f17f 100644 (file)
@@ -1184,7 +1184,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
 
        WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
-              crtc->mode.vdisplay);
+              target_fb->height);
        x &= ~3;
        y &= ~1;
        WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
@@ -1353,7 +1353,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
 
        WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
-              crtc->mode.vdisplay);
+              target_fb->height);
        x &= ~3;
        y &= ~1;
        WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
index a71557c..552b436 100644 (file)
@@ -564,9 +564,21 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
            ENCODER_OBJECT_ID_NUTMEG)
                panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
        else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
-                ENCODER_OBJECT_ID_TRAVIS)
-               panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
-       else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+                ENCODER_OBJECT_ID_TRAVIS) {
+               u8 id[6];
+               int i;
+               for (i = 0; i < 6; i++)
+                       id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i);
+               if (id[0] == 0x73 &&
+                   id[1] == 0x69 &&
+                   id[2] == 0x76 &&
+                   id[3] == 0x61 &&
+                   id[4] == 0x72 &&
+                   id[5] == 0x54)
+                       panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
+               else
+                       panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+       } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
                u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
                if (tmp & 1)
                        panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
index d996f43..accc032 100644 (file)
@@ -468,27 +468,42 @@ set_default_state(struct radeon_device *rdev)
        radeon_ring_write(ring, sq_stack_resource_mgmt_2);
 }
 
+#define I2F_MAX_BITS 15
+#define I2F_MAX_INPUT  ((1 << I2F_MAX_BITS) - 1)
+#define I2F_SHIFT (24 - I2F_MAX_BITS)
+
+/*
+ * Converts unsigned integer into 32-bit IEEE floating point representation.
+ * Conversion is not universal and only works for the range from 0
+ * to 2^I2F_MAX_BITS-1. Currently we only use it with inputs between
+ * 0 and 16384 (inclusive), so I2F_MAX_BITS=15 is enough. If necessary,
+ * I2F_MAX_BITS can be increased, but that will add to the loop iterations
+ * and slow us down. Conversion is done by shifting the input and counting
+ * down until the first 1 reaches bit position 23. The resulting counter
+ * and the shifted input are, respectively, the exponent and the fraction.
+ * The sign is always zero.
+ */
 static uint32_t i2f(uint32_t input)
 {
        u32 result, i, exponent, fraction;
 
-       if ((input & 0x3fff) == 0)
-               result = 0; /* 0 is a special case */
+       WARN_ON_ONCE(input > I2F_MAX_INPUT);
+
+       if ((input & I2F_MAX_INPUT) == 0)
+               result = 0;
        else {
-               exponent = 140; /* exponent biased by 127; */
-               fraction = (input & 0x3fff) << 10; /* cheat and only
-                                                     handle numbers below 2^^15 */
-               for (i = 0; i < 14; i++) {
+               exponent = 126 + I2F_MAX_BITS;
+               fraction = (input & I2F_MAX_INPUT) << I2F_SHIFT;
+
+               for (i = 0; i < I2F_MAX_BITS; i++) {
                        if (fraction & 0x800000)
                                break;
                        else {
-                               fraction = fraction << 1; /* keep
-                                                            shifting left until top bit = 1 */
+                               fraction = fraction << 1;
                                exponent = exponent - 1;
                        }
                }
-               result = exponent << 23 | (fraction & 0x7fffff); /* mask
-                                                                   off top bit; assumed 1 */
+               result = exponent << 23 | (fraction & 0x7fffff);
        }
        return result;
 }
index 13ac63b..98724fc 100644 (file)
@@ -59,8 +59,9 @@ static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
 
        obj = (union acpi_object *)buffer.pointer;
        memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
+       len = obj->buffer.length;
        kfree(buffer.pointer);
-       return obj->buffer.length;
+       return len;
 }
 
 bool radeon_atrm_supported(struct pci_dev *pdev)
index cec51a5..49f7cb7 100644 (file)
@@ -883,6 +883,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
        if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                return 0;
 
+       drm_kms_helper_poll_disable(dev);
+
        /* turn off display hw */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
@@ -972,6 +974,8 @@ int radeon_resume_kms(struct drm_device *dev)
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
        }
+
+       drm_kms_helper_poll_enable(dev);
        return 0;
 }
 
index e2a393f..98a8ad6 100644 (file)
@@ -958,6 +958,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
        i2c->rec = *rec;
        i2c->adapter.owner = THIS_MODULE;
        i2c->adapter.class = I2C_CLASS_DDC;
+       i2c->adapter.dev.parent = &dev->pdev->dev;
        i2c->dev = dev;
        snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
                 "Radeon aux bus %s", name);
index 0c33ae9..4066324 100644 (file)
@@ -548,6 +548,7 @@ static int mousevsc_remove(struct hv_device *dev)
        struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
 
        vmbus_close(dev->channel);
+       hid_hw_stop(input_dev->hid_device);
        hid_destroy_device(input_dev->hid_device);
        mousevsc_free_device(input_dev);
 
index b47e58b..acab74c 100644 (file)
@@ -531,7 +531,6 @@ static int wacom_probe(struct hid_device *hdev,
        wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
        wdata->battery.use_for_apm = 0;
 
-       power_supply_powers(&wdata->battery, &hdev->dev);
 
        ret = power_supply_register(&hdev->dev, &wdata->battery);
        if (ret) {
@@ -540,6 +539,8 @@ static int wacom_probe(struct hid_device *hdev,
                goto err_battery;
        }
 
+       power_supply_powers(&wdata->battery, &hdev->dev);
+
        wdata->ac.properties = wacom_ac_props;
        wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
        wdata->ac.get_property = wacom_ac_get_property;
@@ -547,14 +548,14 @@ static int wacom_probe(struct hid_device *hdev,
        wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
        wdata->ac.use_for_apm = 0;
 
-       power_supply_powers(&wdata->battery, &hdev->dev);
-
        ret = power_supply_register(&hdev->dev, &wdata->ac);
        if (ret) {
                hid_warn(hdev,
                         "can't create ac battery attribute, err: %d\n", ret);
                goto err_ac;
        }
+
+       power_supply_powers(&wdata->ac, &hdev->dev);
 #endif
        return 0;
 
index fc253b4..cac3589 100644 (file)
@@ -1226,14 +1226,14 @@ static int wiimote_hid_probe(struct hid_device *hdev,
        wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
        wdata->battery.use_for_apm = 0;
 
-       power_supply_powers(&wdata->battery, &hdev->dev);
-
        ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
        if (ret) {
                hid_err(hdev, "Cannot register battery device\n");
                goto err_battery;
        }
 
+       power_supply_powers(&wdata->battery, &hdev->dev);
+
        ret = wiimote_leds_create(wdata);
        if (ret)
                goto err_free;
index 7c297d3..b1ec0e2 100644 (file)
@@ -922,11 +922,11 @@ void hiddev_disconnect(struct hid_device *hid)
        struct hiddev *hiddev = hid->hiddev;
        struct usbhid_device *usbhid = hid->driver_data;
 
+       usb_deregister_dev(usbhid->intf, &hiddev_class);
+
        mutex_lock(&hiddev->existancelock);
        hiddev->exist = 0;
 
-       usb_deregister_dev(usbhid->intf, &hiddev_class);
-
        if (hiddev->open) {
                mutex_unlock(&hiddev->existancelock);
                usbhid_close(hiddev->hid);
index 2dfae7d..4d383e7 100644 (file)
@@ -1920,9 +1920,26 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
                fan4min = 0;
                fan5pin = 0;
        } else if (sio_data->kind == nct6776) {
-               fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
-               fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
-               fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+               bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
+
+               superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
+               regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
+
+               if (regval & 0x80)
+                       fan3pin = gpok;
+               else
+                       fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+
+               if (regval & 0x40)
+                       fan4pin = gpok;
+               else
+                       fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
+
+               if (regval & 0x20)
+                       fan5pin = gpok;
+               else
+                       fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+
                fan4min = fan4pin;
        } else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
                fan3pin = 1;
index f713eac..801df60 100644 (file)
@@ -1018,7 +1018,7 @@ omap_i2c_probe(struct platform_device *pdev)
                goto err_release_region;
        }
 
-       match = of_match_device(omap_i2c_of_match, &pdev->dev);
+       match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev);
        if (match) {
                u32 freq = 100000; /* default to 100000 Hz */
 
index b37b0c0..5034a87 100644 (file)
@@ -808,9 +808,12 @@ static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf,
                return PTR_ERR(ctx);
 
        if (cmd.conn_param.valid) {
-               ctx->uid = cmd.uid;
                ucma_copy_conn_param(&conn_param, &cmd.conn_param);
+               mutex_lock(&file->mut);
                ret = rdma_accept(ctx->cm_id, &conn_param);
+               if (!ret)
+                       ctx->uid = cmd.uid;
+               mutex_unlock(&file->mut);
        } else
                ret = rdma_accept(ctx->cm_id, NULL);
 
index b930da4..4d27e4c 100644 (file)
@@ -1485,6 +1485,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
                qp->event_handler = attr.event_handler;
                qp->qp_context    = attr.qp_context;
                qp->qp_type       = attr.qp_type;
+               atomic_set(&qp->usecnt, 0);
                atomic_inc(&pd->usecnt);
                atomic_inc(&attr.send_cq->usecnt);
                if (attr.recv_cq)
index 602b1bd..575b780 100644 (file)
@@ -421,6 +421,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
                qp->uobject    = NULL;
                qp->qp_type    = qp_init_attr->qp_type;
 
+               atomic_set(&qp->usecnt, 0);
                if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
                        qp->event_handler = __ib_shared_qp_event_handler;
                        qp->qp_context = qp;
@@ -430,7 +431,6 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
                        qp->xrcd = qp_init_attr->xrcd;
                        atomic_inc(&qp_init_attr->xrcd->usecnt);
                        INIT_LIST_HEAD(&qp->open_list);
-                       atomic_set(&qp->usecnt, 0);
 
                        real_qp = qp;
                        qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
index b7d4216..a4de9d5 100644 (file)
@@ -89,7 +89,7 @@ static int create_file(const char *name, umode_t mode,
                error = ipathfs_mknod(parent->d_inode, *dentry,
                                      mode, fops, data);
        else
-               error = PTR_ERR(dentry);
+               error = PTR_ERR(*dentry);
        mutex_unlock(&parent->d_inode->i_mutex);
 
        return error;
index 95c94d8..259b067 100644 (file)
@@ -257,12 +257,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
                        return IB_MAD_RESULT_SUCCESS;
 
                /*
-                * Don't process SMInfo queries or vendor-specific
-                * MADs -- the SMA can't handle them.
+                * Don't process SMInfo queries -- the SMA can't handle them.
                 */
-               if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO ||
-                   ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) ==
-                    IB_SMP_ATTR_VENDOR_MASK))
+               if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
                        return IB_MAD_RESULT_SUCCESS;
        } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
                   in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1   ||
index 7013da5..7140199 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 568b4f1..c438e46 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 425065b..a4972ab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -233,6 +233,7 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
        u8 *start_ptr = &start_addr;
        u8 **start_buff = &start_ptr;
        u16 buff_len = 0;
+       struct ietf_mpa_v1 *mpa_frame;
 
        skb = dev_alloc_skb(MAX_CM_BUFFER);
        if (!skb) {
@@ -242,6 +243,8 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
 
        /* send an MPA reject frame */
        cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY);
+       mpa_frame = (struct ietf_mpa_v1 *)*start_buff;
+       mpa_frame->flags |= IETF_MPA_FLAGS_REJECT;
        form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);
 
        cm_node->state = NES_CM_STATE_FIN_WAIT1;
@@ -1360,8 +1363,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
                                if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
                                            neigh->ha, ETH_ALEN)) {
                                        /* Mac address same as in nes_arp_table */
-                                       ip_rt_put(rt);
-                                       return rc;
+                                       goto out;
                                }
 
                                nes_manage_arp_cache(nesvnic->netdev,
@@ -1377,6 +1379,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
                        neigh_event_send(neigh, NULL);
                }
        }
+
+out:
        rcu_read_unlock();
        ip_rt_put(rt);
        return rc;
index bdfa1fb..4646e66 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index b4393a1..a69eef1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 055f4b5..d42c9f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 0b590e1..d748e4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+* Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
index b3b2a24..3ba7be3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel-NE, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 8c8af25..4f7f701 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2010 Intel-NE, Inc.  All rights reserved.
+* Copyright (c) 2006 - 2011 Intel-NE, Inc.  All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
index 4b3fa71..f3a3ecf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 71e133a..4926de7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
index 8b4c2ff..e98f4fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 5095bc4..0927b5c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -3427,6 +3427,8 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
                        set_wqe_32bit_value(wqe->wqe_words,
                                            NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,
                                            ib_wr->wr.fast_reg.length);
+                       set_wqe_32bit_value(wqe->wqe_words,
+                                           NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0);
                        set_wqe_32bit_value(wqe->wqe_words,
                                            NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,
                                            ib_wr->wr.fast_reg.rkey);
@@ -3724,7 +3726,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
                                                entry->opcode = IB_WC_SEND;
                                                break;
                                        case NES_IWARP_SQ_OP_LOCINV:
-                                               entry->opcode = IB_WR_LOCAL_INV;
+                                               entry->opcode = IB_WC_LOCAL_INV;
                                                break;
                                        case NES_IWARP_SQ_OP_FAST_REG:
                                                entry->opcode = IB_WC_FAST_REG_MR;
index fe6b6e9..0eff7c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 4f18e2d..d0c64d5 100644 (file)
@@ -2105,7 +2105,7 @@ static void alloc_dummy_hdrq(struct qib_devdata *dd)
        dd->cspec->dummy_hdrq = dma_alloc_coherent(&dd->pcidev->dev,
                                        dd->rcd[0]->rcvhdrq_size,
                                        &dd->cspec->dummy_hdrq_phys,
-                                       GFP_KERNEL | __GFP_COMP);
+                                       GFP_ATOMIC | __GFP_COMP);
        if (!dd->cspec->dummy_hdrq) {
                qib_devinfo(dd->pcidev, "Couldn't allocate dummy hdrq\n");
                /* fallback to just 0'ing */
index f695061..0fde788 100644 (file)
@@ -560,7 +560,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
  * BIOS may not set PCIe bus-utilization parameters for best performance.
  * Check and optionally adjust them to maximize our throughput.
  */
-static int qib_pcie_caps = 0x51;
+static int qib_pcie_caps;
 module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO);
 MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)");
 
index cd5d05e..2b73d43 100644 (file)
@@ -69,8 +69,8 @@ MODULE_LICENSE("Dual BSD/GPL");
  */
 
 static u64 srpt_service_guid;
-static spinlock_t srpt_dev_lock;       /* Protects srpt_dev_list. */
-static struct list_head srpt_dev_list; /* List of srpt_device structures. */
+static DEFINE_SPINLOCK(srpt_dev_lock); /* Protects srpt_dev_list. */
+static LIST_HEAD(srpt_dev_list);       /* List of srpt_device structures. */
 
 static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE;
 module_param(srp_max_req_size, int, 0444);
@@ -687,6 +687,7 @@ err:
        while (--i >= 0)
                srpt_free_ioctx(sdev, ring[i], dma_size, dir);
        kfree(ring);
+       ring = NULL;
 out:
        return ring;
 }
@@ -2595,7 +2596,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
        }
 
        ch->sess = transport_init_session();
-       if (!ch->sess) {
+       if (IS_ERR(ch->sess)) {
                rej->reason = __constant_cpu_to_be32(
                                SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
                pr_debug("Failed to create session\n");
@@ -3264,8 +3265,7 @@ static void srpt_add_one(struct ib_device *device)
        for (i = 0; i < sdev->srq_size; ++i)
                srpt_post_recv(sdev, sdev->ioctx_ring[i]);
 
-       WARN_ON(sdev->device->phys_port_cnt
-               > sizeof(sdev->port)/sizeof(sdev->port[0]));
+       WARN_ON(sdev->device->phys_port_cnt > ARRAY_SIZE(sdev->port));
 
        for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
                sport = &sdev->port[i - 1];
@@ -4010,13 +4010,10 @@ static int __init srpt_init_module(void)
                goto out;
        }
 
-       spin_lock_init(&srpt_dev_lock);
-       INIT_LIST_HEAD(&srpt_dev_list);
-
-       ret = -ENODEV;
        srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt");
-       if (!srpt_target) {
+       if (IS_ERR(srpt_target)) {
                printk(KERN_ERR "couldn't register\n");
+               ret = PTR_ERR(srpt_target);
                goto out;
        }
 
index b4b4bbc..61e52b8 100644 (file)
@@ -35,7 +35,6 @@
 #ifndef IB_SRPT_H
 #define IB_SRPT_H
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/wait.h>
index 76457d5..afc166f 100644 (file)
@@ -386,7 +386,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
        struct evdev_client *client = file->private_data;
        struct evdev *evdev = client->evdev;
        struct input_event event;
-       int retval;
+       int retval = 0;
 
        if (count < input_event_size())
                return -EINVAL;
index eeafc30..9d639fa 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <mach/jornada720.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 
 MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>");
 MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver");
index a588578..67bec14 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/i2c/twl.h>
 #include <linux/slab.h>
 
-
 /*
  * The TWL4030 family chips include a keypad controller that supports
  * up to an 8x8 switch matrix.  The controller can issue system wakeup
@@ -302,7 +301,7 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)
        if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0)
                return -EIO;
 
-       /* Set timeout period to 100 ms */
+       /* Set timeout period to 200 ms */
        i = KEYP_PERIOD_US(200000, PTV_PRESCALER);
        if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0)
                return -EIO;
@@ -466,4 +465,3 @@ MODULE_AUTHOR("Texas Instruments");
 MODULE_DESCRIPTION("TWL4030 Keypad Driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:twl4030_keypad");
-
index b4cfc6c..5ec774d 100644 (file)
@@ -512,6 +512,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
                },
        },
+       {
+               /* Lenovo Ideapad U455 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
+               },
+       },
        { }
 };
 
index 8b44ddc..58b2244 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 
-#include <asm/irq.h>
 #include <mach/hardware.h>
 #include <asm/hardware/iomd.h>
 #include <asm/system.h>
@@ -46,6 +45,11 @@ MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:kart");
 
+struct rpckbd_data {
+       int tx_irq;
+       int rx_irq;
+};
+
 static int rpckbd_write(struct serio *port, unsigned char val)
 {
        while (!(iomd_readb(IOMD_KCTRL) & (1 << 7)))
@@ -78,19 +82,21 @@ static irqreturn_t rpckbd_tx(int irq, void *dev_id)
 
 static int rpckbd_open(struct serio *port)
 {
+       struct rpckbd_data *rpckbd = port->port_data;
+
        /* Reset the keyboard state machine. */
        iomd_writeb(0, IOMD_KCTRL);
        iomd_writeb(8, IOMD_KCTRL);
        iomd_readb(IOMD_KARTRX);
 
-       if (request_irq(IRQ_KEYBOARDRX, rpckbd_rx, 0, "rpckbd", port) != 0) {
+       if (request_irq(rpckbd->rx_irq, rpckbd_rx, 0, "rpckbd", port) != 0) {
                printk(KERN_ERR "rpckbd.c: Could not allocate keyboard receive IRQ\n");
                return -EBUSY;
        }
 
-       if (request_irq(IRQ_KEYBOARDTX, rpckbd_tx, 0, "rpckbd", port) != 0) {
+       if (request_irq(rpckbd->tx_irq, rpckbd_tx, 0, "rpckbd", port) != 0) {
                printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n");
-               free_irq(IRQ_KEYBOARDRX, port);
+               free_irq(rpckbd->rx_irq, port);
                return -EBUSY;
        }
 
@@ -99,8 +105,10 @@ static int rpckbd_open(struct serio *port)
 
 static void rpckbd_close(struct serio *port)
 {
-       free_irq(IRQ_KEYBOARDRX, port);
-       free_irq(IRQ_KEYBOARDTX, port);
+       struct rpckbd_data *rpckbd = port->port_data;
+
+       free_irq(rpckbd->rx_irq, port);
+       free_irq(rpckbd->tx_irq, port);
 }
 
 /*
@@ -109,17 +117,35 @@ static void rpckbd_close(struct serio *port)
  */
 static int __devinit rpckbd_probe(struct platform_device *dev)
 {
+       struct rpckbd_data *rpckbd;
        struct serio *serio;
+       int tx_irq, rx_irq;
+
+       rx_irq = platform_get_irq(dev, 0);
+       if (rx_irq <= 0)
+               return rx_irq < 0 ? rx_irq : -ENXIO;
+
+       tx_irq = platform_get_irq(dev, 1);
+       if (tx_irq <= 0)
+               return tx_irq < 0 ? tx_irq : -ENXIO;
 
        serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
-       if (!serio)
+       rpckbd = kzalloc(sizeof(*rpckbd), GFP_KERNEL);
+       if (!serio || !rpckbd) {
+               kfree(rpckbd);
+               kfree(serio);
                return -ENOMEM;
+       }
+
+       rpckbd->rx_irq = rx_irq;
+       rpckbd->tx_irq = tx_irq;
 
        serio->id.type          = SERIO_8042;
        serio->write            = rpckbd_write;
        serio->open             = rpckbd_open;
        serio->close            = rpckbd_close;
        serio->dev.parent       = &dev->dev;
+       serio->port_data        = rpckbd;
        strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name));
        strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys));
 
@@ -131,7 +157,11 @@ static int __devinit rpckbd_probe(struct platform_device *dev)
 static int __devexit rpckbd_remove(struct platform_device *dev)
 {
        struct serio *serio = platform_get_drvdata(dev);
+       struct rpckbd_data *rpckbd = serio->port_data;
+
        serio_unregister_port(serio);
+       kfree(rpckbd);
+
        return 0;
 }
 
index 44fc8b4..5ebabe3 100644 (file)
 
 #include <asm/hardware/sa1111.h>
 
+#define PS2CR          0x0000
+#define PS2STAT                0x0004
+#define PS2DATA                0x0008
+#define PS2CLKDIV      0x000c
+#define PS2PRECNT      0x0010
+
+#define PS2CR_ENA      0x08
+#define PS2CR_FKD      0x02
+#define PS2CR_FKC      0x01
+
+#define PS2STAT_STP    0x0100
+#define PS2STAT_TXE    0x0080
+#define PS2STAT_TXB    0x0040
+#define PS2STAT_RXF    0x0020
+#define PS2STAT_RXB    0x0010
+#define PS2STAT_ENA    0x0008
+#define PS2STAT_RXP    0x0004
+#define PS2STAT_KBD    0x0002
+#define PS2STAT_KBC    0x0001
+
 struct ps2if {
        struct serio            *io;
        struct sa1111_dev       *dev;
@@ -45,22 +65,22 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id)
        struct ps2if *ps2if = dev_id;
        unsigned int scancode, flag, status;
 
-       status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
+       status = sa1111_readl(ps2if->base + PS2STAT);
        while (status & PS2STAT_RXF) {
                if (status & PS2STAT_STP)
-                       sa1111_writel(PS2STAT_STP, ps2if->base + SA1111_PS2STAT);
+                       sa1111_writel(PS2STAT_STP, ps2if->base + PS2STAT);
 
                flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) |
                       (status & PS2STAT_RXP ? 0 : SERIO_PARITY);
 
-               scancode = sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff;
+               scancode = sa1111_readl(ps2if->base + PS2DATA) & 0xff;
 
                if (hweight8(scancode) & 1)
                        flag ^= SERIO_PARITY;
 
                serio_interrupt(ps2if->io, scancode, flag);
 
-               status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
+               status = sa1111_readl(ps2if->base + PS2STAT);
         }
 
         return IRQ_HANDLED;
@@ -75,12 +95,12 @@ static irqreturn_t ps2_txint(int irq, void *dev_id)
        unsigned int status;
 
        spin_lock(&ps2if->lock);
-       status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
+       status = sa1111_readl(ps2if->base + PS2STAT);
        if (ps2if->head == ps2if->tail) {
                disable_irq_nosync(irq);
                /* done */
        } else if (status & PS2STAT_TXE) {
-               sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
+               sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA);
                ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
        }
        spin_unlock(&ps2if->lock);
@@ -103,8 +123,8 @@ static int ps2_write(struct serio *io, unsigned char val)
        /*
         * If the TX register is empty, we can go straight out.
         */
-       if (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) {
-               sa1111_writel(val, ps2if->base + SA1111_PS2DATA);
+       if (sa1111_readl(ps2if->base + PS2STAT) & PS2STAT_TXE) {
+               sa1111_writel(val, ps2if->base + PS2DATA);
        } else {
                if (ps2if->head == ps2if->tail)
                        enable_irq(ps2if->dev->irq[1]);
@@ -124,13 +144,16 @@ static int ps2_open(struct serio *io)
        struct ps2if *ps2if = io->port_data;
        int ret;
 
-       sa1111_enable_device(ps2if->dev);
+       ret = sa1111_enable_device(ps2if->dev);
+       if (ret)
+               return ret;
 
        ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
                          SA1111_DRIVER_NAME(ps2if->dev), ps2if);
        if (ret) {
                printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
                        ps2if->dev->irq[0], ret);
+               sa1111_disable_device(ps2if->dev);
                return ret;
        }
 
@@ -140,6 +163,7 @@ static int ps2_open(struct serio *io)
                printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
                        ps2if->dev->irq[1], ret);
                free_irq(ps2if->dev->irq[0], ps2if);
+               sa1111_disable_device(ps2if->dev);
                return ret;
        }
 
@@ -147,7 +171,7 @@ static int ps2_open(struct serio *io)
 
        enable_irq_wake(ps2if->dev->irq[0]);
 
-       sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR);
+       sa1111_writel(PS2CR_ENA, ps2if->base + PS2CR);
        return 0;
 }
 
@@ -155,7 +179,7 @@ static void ps2_close(struct serio *io)
 {
        struct ps2if *ps2if = io->port_data;
 
-       sa1111_writel(0, ps2if->base + SA1111_PS2CR);
+       sa1111_writel(0, ps2if->base + PS2CR);
 
        disable_irq_wake(ps2if->dev->irq[0]);
 
@@ -175,7 +199,7 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if)
        int maxread = 100;
 
        while (maxread--) {
-               if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff)
+               if ((sa1111_readl(ps2if->base + PS2DATA) & 0xff) == 0xff)
                        break;
        }
 }
@@ -185,11 +209,11 @@ static unsigned int __devinit ps2_test_one(struct ps2if *ps2if,
 {
        unsigned int val;
 
-       sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR);
+       sa1111_writel(PS2CR_ENA | mask, ps2if->base + PS2CR);
 
        udelay(2);
 
-       val = sa1111_readl(ps2if->base + SA1111_PS2STAT);
+       val = sa1111_readl(ps2if->base + PS2STAT);
        return val & (PS2STAT_KBC | PS2STAT_KBD);
 }
 
@@ -220,7 +244,7 @@ static int __devinit ps2_test(struct ps2if *ps2if)
                ret = -ENODEV;
        }
 
-       sa1111_writel(0, ps2if->base + SA1111_PS2CR);
+       sa1111_writel(0, ps2if->base + PS2CR);
 
        return ret;
 }
@@ -274,8 +298,8 @@ static int __devinit ps2_probe(struct sa1111_dev *dev)
        sa1111_enable_device(ps2if->dev);
 
        /* Incoming clock is 8MHz */
-       sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV);
-       sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT);
+       sa1111_writel(0, ps2if->base + PS2CLKDIV);
+       sa1111_writel(127, ps2if->base + PS2PRECNT);
 
        /*
         * Flush any pending input.
@@ -330,6 +354,7 @@ static int __devexit ps2_remove(struct sa1111_dev *dev)
 static struct sa1111_driver ps2_driver = {
        .drv = {
                .name   = "sa1111-ps2",
+               .owner  = THIS_MODULE,
        },
        .devid          = SA1111_DEVID_PS2,
        .probe          = ps2_probe,
index 8250299..4494233 100644 (file)
@@ -164,7 +164,8 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,
        struct serio_raw_client *client = file->private_data;
        struct serio_raw *serio_raw = client->serio_raw;
        char uninitialized_var(c);
-       ssize_t retval = 0;
+       ssize_t read = 0;
+       int retval;
 
        if (serio_raw->dead)
                return -ENODEV;
@@ -180,13 +181,15 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,
        if (serio_raw->dead)
                return -ENODEV;
 
-       while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
-               if (put_user(c, buffer++))
-                       return -EFAULT;
-               retval++;
+       while (read < count && serio_raw_fetch_byte(serio_raw, &c)) {
+               if (put_user(c, buffer++)) {
+                       retval = -EFAULT;
+                       break;
+               }
+               read++;
        }
 
-       return retval;
+       return read ?: retval;
 }
 
 static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
index c3848ad..d9be6ea 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <mach/hardware.h>
 #include <mach/jornada720.h>
+#include <mach/irqs.h>
 
 MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
 MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver");
index cce1f03..f75e060 100644 (file)
@@ -2863,6 +2863,9 @@ static unsigned device_dma_ops_init(void)
 
        for_each_pci_dev(pdev) {
                if (!check_device(&pdev->dev)) {
+
+                       iommu_ignore_device(&pdev->dev);
+
                        unhandled += 1;
                        continue;
                }
index 08a90b8..cee307e 100644 (file)
@@ -482,23 +482,19 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
 
        priv = domain->priv;
 
-       if (!priv) {
-               ret = -ENODEV;
+       if (!priv)
                goto fail;
-       }
 
        fl_table = priv->pgtable;
 
        if (len != SZ_16M && len != SZ_1M &&
            len != SZ_64K && len != SZ_4K) {
                pr_debug("Bad length: %d\n", len);
-               ret = -EINVAL;
                goto fail;
        }
 
        if (!fl_table) {
                pr_debug("Null page table\n");
-               ret = -EINVAL;
                goto fail;
        }
 
@@ -507,7 +503,6 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
 
        if (*fl_pte == 0) {
                pr_debug("First level PTE is 0\n");
-               ret = -ENODEV;
                goto fail;
        }
 
index 45e6878..e59c166 100644 (file)
@@ -164,8 +164,8 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
 
        if (drvdata->mode == LM3530_BL_MODE_ALS) {
                if (pltfm->als_vmax == 0) {
-                       pltfm->als_vmin = als_vmin = 0;
-                       pltfm->als_vmin = als_vmax = LM3530_ALS_WINDOW_mV;
+                       pltfm->als_vmin = 0;
+                       pltfm->als_vmax = LM3530_ALS_WINDOW_mV;
                }
 
                als_vmin = pltfm->als_vmin;
index c2907d8..86cb7e5 100644 (file)
@@ -56,7 +56,8 @@ struct raid_dev {
 struct raid_set {
        struct dm_target *ti;
 
-       uint64_t print_flags;
+       uint32_t bitmap_loaded;
+       uint32_t print_flags;
 
        struct mddev md;
        struct raid_type *raid_type;
@@ -1085,7 +1086,7 @@ static int raid_status(struct dm_target *ti, status_type_t type,
                                raid_param_cnt += 2;
                }
 
-               raid_param_cnt += (hweight64(rs->print_flags & ~DMPF_REBUILD) * 2);
+               raid_param_cnt += (hweight32(rs->print_flags & ~DMPF_REBUILD) * 2);
                if (rs->print_flags & (DMPF_SYNC | DMPF_NOSYNC))
                        raid_param_cnt--;
 
@@ -1197,7 +1198,12 @@ static void raid_resume(struct dm_target *ti)
 {
        struct raid_set *rs = ti->private;
 
-       bitmap_load(&rs->md);
+       if (!rs->bitmap_loaded) {
+               bitmap_load(&rs->md);
+               rs->bitmap_loaded = 1;
+       } else
+               md_wakeup_thread(rs->md.thread);
+
        mddev_resume(&rs->md);
 }
 
index 9417ae2..ce88755 100644 (file)
@@ -7333,7 +7333,8 @@ void md_do_sync(struct mddev *mddev)
                                        printk(KERN_INFO
                                               "md: checkpointing %s of %s.\n",
                                               desc, mdname(mddev));
-                                       mddev->recovery_cp = mddev->curr_resync;
+                                       mddev->recovery_cp =
+                                               mddev->curr_resync_completed;
                                }
                        } else
                                mddev->recovery_cp = MaxSector;
@@ -7351,9 +7352,9 @@ void md_do_sync(struct mddev *mddev)
                        rcu_read_unlock();
                }
        }
+ skip:
        set_bit(MD_CHANGE_DEVS, &mddev->flags);
 
- skip:
        if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
                /* We completed so min/max setting can be forgotten if used. */
                if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
index cd13e9f..28a301b 100644 (file)
@@ -847,8 +847,9 @@ config MCP_SA11X0
 
 # Chip drivers
 config MCP_UCB1200
-       tristate "Support for UCB1200 / UCB1300"
-       depends on MCP
+       bool "Support for UCB1200 / UCB1300"
+       depends on MCP_SA11X0
+       select MCP
 
 config MCP_UCB1200_TS
        tristate "Touchscreen interface support"
index 86cc3f7..6acf2e0 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/string.h>
 #include <linux/mfd/mcp.h>
 
-#include <mach/dma.h>
 #include <asm/system.h>
 
 
@@ -48,39 +47,11 @@ static int mcp_bus_remove(struct device *dev)
        return 0;
 }
 
-static int mcp_bus_suspend(struct device *dev, pm_message_t state)
-{
-       struct mcp *mcp = to_mcp(dev);
-       int ret = 0;
-
-       if (dev->driver) {
-               struct mcp_driver *drv = to_mcp_driver(dev->driver);
-
-               ret = drv->suspend(mcp, state);
-       }
-       return ret;
-}
-
-static int mcp_bus_resume(struct device *dev)
-{
-       struct mcp *mcp = to_mcp(dev);
-       int ret = 0;
-
-       if (dev->driver) {
-               struct mcp_driver *drv = to_mcp_driver(dev->driver);
-
-               ret = drv->resume(mcp);
-       }
-       return ret;
-}
-
 static struct bus_type mcp_bus_type = {
        .name           = "mcp",
        .match          = mcp_bus_match,
        .probe          = mcp_bus_probe,
        .remove         = mcp_bus_remove,
-       .suspend        = mcp_bus_suspend,
-       .resume         = mcp_bus_resume,
 };
 
 /**
@@ -208,6 +179,7 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size)
        mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL);
        if (mcp) {
                spin_lock_init(&mcp->lock);
+               device_initialize(&mcp->attached_device);
                mcp->attached_device.parent = parent;
                mcp->attached_device.bus = &mcp_bus_type;
                mcp->attached_device.dma_mask = parent->dma_mask;
@@ -217,18 +189,25 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size)
 }
 EXPORT_SYMBOL(mcp_host_alloc);
 
-int mcp_host_register(struct mcp *mcp)
+int mcp_host_add(struct mcp *mcp, void *pdata)
 {
+       mcp->attached_device.platform_data = pdata;
        dev_set_name(&mcp->attached_device, "mcp0");
-       return device_register(&mcp->attached_device);
+       return device_add(&mcp->attached_device);
+}
+EXPORT_SYMBOL(mcp_host_add);
+
+void mcp_host_del(struct mcp *mcp)
+{
+       device_del(&mcp->attached_device);
 }
-EXPORT_SYMBOL(mcp_host_register);
+EXPORT_SYMBOL(mcp_host_del);
 
-void mcp_host_unregister(struct mcp *mcp)
+void mcp_host_free(struct mcp *mcp)
 {
-       device_unregister(&mcp->attached_device);
+       put_device(&mcp->attached_device);
 }
-EXPORT_SYMBOL(mcp_host_unregister);
+EXPORT_SYMBOL(mcp_host_free);
 
 int mcp_driver_register(struct mcp_driver *mcpdrv)
 {
index 02c53a0..1c0ceac 100644 (file)
  */
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
+#include <linux/pm.h>
 #include <linux/mfd/mcp.h>
 
-#include <mach/dma.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/system.h>
 #include <mach/mcp.h>
 
-#include <mach/assabet.h>
-
+#define DRIVER_NAME "sa11x0-mcp"
 
 struct mcp_sa11x0 {
-       u32     mccr0;
-       u32     mccr1;
+       void __iomem    *base0;
+       void __iomem    *base1;
+       u32             mccr0;
+       u32             mccr1;
 };
 
+/* Register offsets */
+#define MCCR0(m)       ((m)->base0 + 0x00)
+#define MCDR0(m)       ((m)->base0 + 0x08)
+#define MCDR1(m)       ((m)->base0 + 0x0c)
+#define MCDR2(m)       ((m)->base0 + 0x10)
+#define MCSR(m)                ((m)->base0 + 0x18)
+#define MCCR1(m)       ((m)->base1 + 0x00)
+
 #define priv(mcp)      ((struct mcp_sa11x0 *)mcp_priv(mcp))
 
 static void
 mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
 {
-       unsigned int mccr0;
+       struct mcp_sa11x0 *m = priv(mcp);
 
        divisor /= 32;
 
-       mccr0 = Ser4MCCR0 & ~0x00007f00;
-       mccr0 |= divisor << 8;
-       Ser4MCCR0 = mccr0;
+       m->mccr0 &= ~0x00007f00;
+       m->mccr0 |= divisor << 8;
+       writel_relaxed(m->mccr0, MCCR0(m));
 }
 
 static void
 mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
 {
-       unsigned int mccr0;
+       struct mcp_sa11x0 *m = priv(mcp);
 
        divisor /= 32;
 
-       mccr0 = Ser4MCCR0 & ~0x0000007f;
-       mccr0 |= divisor;
-       Ser4MCCR0 = mccr0;
+       m->mccr0 &= ~0x0000007f;
+       m->mccr0 |= divisor;
+       writel_relaxed(m->mccr0, MCCR0(m));
 }
 
 /*
@@ -69,14 +79,15 @@ mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
 static void
 mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
 {
+       struct mcp_sa11x0 *m = priv(mcp);
        int ret = -ETIME;
        int i;
 
-       Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
+       writel_relaxed(reg << 17 | MCDR2_Wr | (val & 0xffff), MCDR2(m));
 
        for (i = 0; i < 2; i++) {
                udelay(mcp->rw_timeout);
-               if (Ser4MCSR & MCSR_CWC) {
+               if (readl_relaxed(MCSR(m)) & MCSR_CWC) {
                        ret = 0;
                        break;
                }
@@ -95,15 +106,16 @@ mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
 static unsigned int
 mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
 {
+       struct mcp_sa11x0 *m = priv(mcp);
        int ret = -ETIME;
        int i;
 
-       Ser4MCDR2 = reg << 17 | MCDR2_Rd;
+       writel_relaxed(reg << 17 | MCDR2_Rd, MCDR2(m));
 
        for (i = 0; i < 2; i++) {
                udelay(mcp->rw_timeout);
-               if (Ser4MCSR & MCSR_CRC) {
-                       ret = Ser4MCDR2 & 0xffff;
+               if (readl_relaxed(MCSR(m)) & MCSR_CRC) {
+                       ret = readl_relaxed(MCDR2(m)) & 0xffff;
                        break;
                }
        }
@@ -116,13 +128,19 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
 
 static void mcp_sa11x0_enable(struct mcp *mcp)
 {
-       Ser4MCSR = -1;
-       Ser4MCCR0 |= MCCR0_MCE;
+       struct mcp_sa11x0 *m = priv(mcp);
+
+       writel(-1, MCSR(m));
+       m->mccr0 |= MCCR0_MCE;
+       writel_relaxed(m->mccr0, MCCR0(m));
 }
 
 static void mcp_sa11x0_disable(struct mcp *mcp)
 {
-       Ser4MCCR0 &= ~MCCR0_MCE;
+       struct mcp_sa11x0 *m = priv(mcp);
+
+       m->mccr0 &= ~MCCR0_MCE;
+       writel_relaxed(m->mccr0, MCCR0(m));
 }
 
 /*
@@ -137,55 +155,64 @@ static struct mcp_ops mcp_sa11x0 = {
        .disable                = mcp_sa11x0_disable,
 };
 
-static int mcp_sa11x0_probe(struct platform_device *pdev)
+static int mcp_sa11x0_probe(struct platform_device *dev)
 {
-       struct mcp_plat_data *data = pdev->dev.platform_data;
+       struct mcp_plat_data *data = dev->dev.platform_data;
+       struct resource *mem0, *mem1;
+       struct mcp_sa11x0 *m;
        struct mcp *mcp;
        int ret;
 
        if (!data)
                return -ENODEV;
 
-       if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
-               return -EBUSY;
+       mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
+       if (!mem0 || !mem1)
+               return -ENXIO;
+
+       if (!request_mem_region(mem0->start, resource_size(mem0),
+                               DRIVER_NAME)) {
+               ret = -EBUSY;
+               goto err_mem0;
+       }
 
-       mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
+       if (!request_mem_region(mem1->start, resource_size(mem1),
+                               DRIVER_NAME)) {
+               ret = -EBUSY;
+               goto err_mem1;
+       }
+
+       mcp = mcp_host_alloc(&dev->dev, sizeof(struct mcp_sa11x0));
        if (!mcp) {
                ret = -ENOMEM;
-               goto release;
+               goto err_alloc;
        }
 
        mcp->owner              = THIS_MODULE;
        mcp->ops                = &mcp_sa11x0;
        mcp->sclk_rate          = data->sclk_rate;
-       mcp->dma_audio_rd       = DMA_Ser4MCP0Rd;
-       mcp->dma_audio_wr       = DMA_Ser4MCP0Wr;
-       mcp->dma_telco_rd       = DMA_Ser4MCP1Rd;
-       mcp->dma_telco_wr       = DMA_Ser4MCP1Wr;
-       mcp->gpio_base          = data->gpio_base;
 
-       platform_set_drvdata(pdev, mcp);
+       m = priv(mcp);
+       m->mccr0 = data->mccr0 | 0x7f7f;
+       m->mccr1 = data->mccr1;
 
-       if (machine_is_assabet()) {
-               ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
+       m->base0 = ioremap(mem0->start, resource_size(mem0));
+       m->base1 = ioremap(mem1->start, resource_size(mem1));
+       if (!m->base0 || !m->base1) {
+               ret = -ENOMEM;
+               goto err_ioremap;
        }
 
-       /*
-        * Setup the PPC unit correctly.
-        */
-       PPDR &= ~PPC_RXD4;
-       PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
-       PSDR |= PPC_RXD4;
-       PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-       PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+       platform_set_drvdata(dev, mcp);
 
        /*
         * Initialise device.  Note that we initially
         * set the sampling rate to minimum.
         */
-       Ser4MCSR = -1;
-       Ser4MCCR1 = data->mccr1;
-       Ser4MCCR0 = data->mccr0 | 0x7f7f;
+       writel_relaxed(-1, MCSR(m));
+       writel_relaxed(m->mccr1, MCCR1(m));
+       writel_relaxed(m->mccr0, MCCR0(m));
 
        /*
         * Calculate the read/write timeout (us) from the bit clock
@@ -195,62 +222,90 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
        mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
                          mcp->sclk_rate;
 
-       ret = mcp_host_register(mcp);
+       ret = mcp_host_add(mcp, data->codec_pdata);
        if (ret == 0)
-               goto out;
+               return 0;
 
- release:
-       release_mem_region(0x80060000, 0x60);
-       platform_set_drvdata(pdev, NULL);
+       platform_set_drvdata(dev, NULL);
 
- out:
+ err_ioremap:
+       iounmap(m->base1);
+       iounmap(m->base0);
+       mcp_host_free(mcp);
+ err_alloc:
+       release_mem_region(mem1->start, resource_size(mem1));
+ err_mem1:
+       release_mem_region(mem0->start, resource_size(mem0));
+ err_mem0:
        return ret;
 }
 
 static int mcp_sa11x0_remove(struct platform_device *dev)
 {
        struct mcp *mcp = platform_get_drvdata(dev);
+       struct mcp_sa11x0 *m = priv(mcp);
+       struct resource *mem0, *mem1;
+
+       if (m->mccr0 & MCCR0_MCE)
+               dev_warn(&dev->dev,
+                        "device left active (missing disable call?)\n");
+
+       mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
 
        platform_set_drvdata(dev, NULL);
-       mcp_host_unregister(mcp);
-       release_mem_region(0x80060000, 0x60);
+       mcp_host_del(mcp);
+       iounmap(m->base1);
+       iounmap(m->base0);
+       mcp_host_free(mcp);
+       release_mem_region(mem1->start, resource_size(mem1));
+       release_mem_region(mem0->start, resource_size(mem0));
 
        return 0;
 }
 
-static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int mcp_sa11x0_suspend(struct device *dev)
 {
-       struct mcp *mcp = platform_get_drvdata(dev);
+       struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev));
+
+       if (m->mccr0 & MCCR0_MCE)
+               dev_warn(dev, "device left active (missing disable call?)\n");
 
-       priv(mcp)->mccr0 = Ser4MCCR0;
-       priv(mcp)->mccr1 = Ser4MCCR1;
-       Ser4MCCR0 &= ~MCCR0_MCE;
+       writel(m->mccr0 & ~MCCR0_MCE, MCCR0(m));
 
        return 0;
 }
 
-static int mcp_sa11x0_resume(struct platform_device *dev)
+static int mcp_sa11x0_resume(struct device *dev)
 {
-       struct mcp *mcp = platform_get_drvdata(dev);
+       struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev));
 
-       Ser4MCCR1 = priv(mcp)->mccr1;
-       Ser4MCCR0 = priv(mcp)->mccr0;
+       writel_relaxed(m->mccr1, MCCR1(m));
+       writel_relaxed(m->mccr0, MCCR0(m));
 
        return 0;
 }
-
-/*
- * The driver for the SA11x0 MCP port.
- */
-MODULE_ALIAS("platform:sa11x0-mcp");
+#endif
+
+static const struct dev_pm_ops mcp_sa11x0_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+       .suspend = mcp_sa11x0_suspend,
+       .freeze = mcp_sa11x0_suspend,
+       .poweroff = mcp_sa11x0_suspend,
+       .resume_noirq = mcp_sa11x0_resume,
+       .thaw_noirq = mcp_sa11x0_resume,
+       .restore_noirq = mcp_sa11x0_resume,
+#endif
+};
 
 static struct platform_driver mcp_sa11x0_driver = {
        .probe          = mcp_sa11x0_probe,
        .remove         = mcp_sa11x0_remove,
-       .suspend        = mcp_sa11x0_suspend,
-       .resume         = mcp_sa11x0_resume,
        .driver         = {
-               .name   = "sa11x0-mcp",
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &mcp_sa11x0_pm_ops,
        },
 };
 
@@ -259,6 +314,7 @@ static struct platform_driver mcp_sa11x0_driver = {
  */
 module_platform_driver(mcp_sa11x0_driver);
 
+MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
 MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
 MODULE_LICENSE("GPL");
index dda8629..b2d8e51 100644 (file)
@@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
                /* Default PLL configuration after power up */
                twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
                twl6040->sysclk = 19200000;
+               twl6040->mclk = 32768;
        } else {
                /* already powered-down */
                if (!twl6040->power_count) {
@@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
                        twl6040_power_down(twl6040);
                }
                twl6040->sysclk = 0;
+               twl6040->mclk = 0;
        }
 
 out:
@@ -324,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
        hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
        lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
 
+       /* Force full reconfiguration when switching between PLL */
+       if (pll_id != twl6040->pll) {
+               twl6040->sysclk = 0;
+               twl6040->mclk = 0;
+       }
+
        switch (pll_id) {
        case TWL6040_SYSCLK_SEL_LPPLL:
                /* low-power PLL divider */
-               switch (freq_out) {
-               case 17640000:
-                       lppllctl |= TWL6040_LPLLFIN;
-                       break;
-               case 19200000:
-                       lppllctl &= ~TWL6040_LPLLFIN;
-                       break;
-               default:
-                       dev_err(twl6040->dev,
-                               "freq_out %d not supported\n", freq_out);
-                       ret = -EINVAL;
-                       goto pll_out;
+               /* Change the sysclk configuration only if it has been canged */
+               if (twl6040->sysclk != freq_out) {
+                       switch (freq_out) {
+                       case 17640000:
+                               lppllctl |= TWL6040_LPLLFIN;
+                               break;
+                       case 19200000:
+                               lppllctl &= ~TWL6040_LPLLFIN;
+                               break;
+                       default:
+                               dev_err(twl6040->dev,
+                                       "freq_out %d not supported\n",
+                                       freq_out);
+                               ret = -EINVAL;
+                               goto pll_out;
+                       }
+                       twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+                                         lppllctl);
                }
-               twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+
+               /* The PLL in use has not been change, we can exit */
+               if (twl6040->pll == pll_id)
+                       break;
 
                switch (freq_in) {
                case 32768:
@@ -371,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
                        goto pll_out;
                }
 
-               hppllctl &= ~TWL6040_MCLK_MSK;
+               if (twl6040->mclk != freq_in) {
+                       hppllctl &= ~TWL6040_MCLK_MSK;
+
+                       switch (freq_in) {
+                       case 12000000:
+                               /* PLL enabled, active mode */
+                               hppllctl |= TWL6040_MCLK_12000KHZ |
+                                           TWL6040_HPLLENA;
+                               break;
+                       case 19200000:
+                               /*
+                               * PLL disabled
+                               * (enable PLL if MCLK jitter quality
+                               *  doesn't meet specification)
+                               */
+                               hppllctl |= TWL6040_MCLK_19200KHZ;
+                               break;
+                       case 26000000:
+                               /* PLL enabled, active mode */
+                               hppllctl |= TWL6040_MCLK_26000KHZ |
+                                           TWL6040_HPLLENA;
+                               break;
+                       case 38400000:
+                               /* PLL enabled, active mode */
+                               hppllctl |= TWL6040_MCLK_38400KHZ |
+                                           TWL6040_HPLLENA;
+                               break;
+                       default:
+                               dev_err(twl6040->dev,
+                                       "freq_in %d not supported\n", freq_in);
+                               ret = -EINVAL;
+                               goto pll_out;
+                       }
 
-               switch (freq_in) {
-               case 12000000:
-                       /* PLL enabled, active mode */
-                       hppllctl |= TWL6040_MCLK_12000KHZ |
-                                   TWL6040_HPLLENA;
-                       break;
-               case 19200000:
                        /*
-                        * PLL disabled
-                        * (enable PLL if MCLK jitter quality
-                        *  doesn't meet specification)
+                        * enable clock slicer to ensure input waveform is
+                        * square
                         */
-                       hppllctl |= TWL6040_MCLK_19200KHZ;
-                       break;
-               case 26000000:
-                       /* PLL enabled, active mode */
-                       hppllctl |= TWL6040_MCLK_26000KHZ |
-                                   TWL6040_HPLLENA;
-                       break;
-               case 38400000:
-                       /* PLL enabled, active mode */
-                       hppllctl |= TWL6040_MCLK_38400KHZ |
-                                   TWL6040_HPLLENA;
-                       break;
-               default:
-                       dev_err(twl6040->dev,
-                               "freq_in %d not supported\n", freq_in);
-                       ret = -EINVAL;
-                       goto pll_out;
-               }
+                       hppllctl |= TWL6040_HPLLSQRENA;
 
-               /* enable clock slicer to ensure input waveform is square */
-               hppllctl |= TWL6040_HPLLSQRENA;
-
-               twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl);
-               usleep_range(500, 700);
-               lppllctl |= TWL6040_HPLLSEL;
-               twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
-               lppllctl &= ~TWL6040_LPLLENA;
-               twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+                       twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
+                                         hppllctl);
+                       usleep_range(500, 700);
+                       lppllctl |= TWL6040_HPLLSEL;
+                       twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+                                         lppllctl);
+                       lppllctl &= ~TWL6040_LPLLENA;
+                       twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+                                         lppllctl);
+               }
                break;
        default:
                dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
@@ -421,6 +446,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
        }
 
        twl6040->sysclk = freq_out;
+       twl6040->mclk = freq_in;
        twl6040->pll = pll_id;
 
 pll_out:
index cea9da6..b63c075 100644 (file)
  */
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
 #include <linux/fs.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
 #include <linux/proc_fs.h>
-#include <linux/device.h>
 #include <linux/mfd/ucb1x00.h>
 
-#include <mach/dma.h>
-
-
 #define UCB1X00_ATTR(name,input)\
 static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \
                           char *buf)   \
@@ -38,14 +39,45 @@ UCB1X00_ATTR(batt_temp, UCB_ADC_INP_AD2);
 
 static int ucb1x00_assabet_add(struct ucb1x00_dev *dev)
 {
-       device_create_file(&dev->ucb->dev, &dev_attr_vbatt);
-       device_create_file(&dev->ucb->dev, &dev_attr_vcharger);
-       device_create_file(&dev->ucb->dev, &dev_attr_batt_temp);
+       struct ucb1x00 *ucb = dev->ucb;
+       struct platform_device *pdev;
+       struct gpio_keys_platform_data keys;
+       static struct gpio_keys_button buttons[6];
+       unsigned i;
+
+       memset(buttons, 0, sizeof(buttons));
+       memset(&keys, 0, sizeof(keys));
+
+       for (i = 0; i < ARRAY_SIZE(buttons); i++) {
+               buttons[i].code = BTN_0 + i;
+               buttons[i].gpio = ucb->gpio.base + i;
+               buttons[i].type = EV_KEY;
+               buttons[i].can_disable = true;
+       }
+
+       keys.buttons = buttons;
+       keys.nbuttons = ARRAY_SIZE(buttons);
+       keys.poll_interval = 50;
+       keys.name = "ucb1x00";
+
+       pdev = platform_device_register_data(&ucb->dev, "gpio-keys", -1,
+               &keys, sizeof(keys));
+
+       device_create_file(&ucb->dev, &dev_attr_vbatt);
+       device_create_file(&ucb->dev, &dev_attr_vcharger);
+       device_create_file(&ucb->dev, &dev_attr_batt_temp);
+
+       dev->priv = pdev;
        return 0;
 }
 
 static void ucb1x00_assabet_remove(struct ucb1x00_dev *dev)
 {
+       struct platform_device *pdev = dev->priv;
+
+       if (!IS_ERR(pdev))
+               platform_device_unregister(pdev);
+
        device_remove_file(&dev->ucb->dev, &dev_attr_batt_temp);
        device_remove_file(&dev->ucb->dev, &dev_attr_vcharger);
        device_remove_file(&dev->ucb->dev, &dev_attr_vbatt);
index febc90c..70f02da 100644 (file)
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/mfd/ucb1x00.h>
+#include <linux/pm.h>
 #include <linux/gpio.h>
-#include <linux/semaphore.h>
-
-#include <mach/dma.h>
-#include <mach/hardware.h>
 
 static DEFINE_MUTEX(ucb1x00_mutex);
 static LIST_HEAD(ucb1x00_drivers);
@@ -102,7 +100,7 @@ void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear)
  *     ucb1x00_enable must have been called to enable the comms
  *     before using this function.
  *
- *     This function does not take any semaphores or spinlocks.
+ *     This function does not take any mutexes or spinlocks.
  */
 unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
 {
@@ -120,14 +118,22 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
        else
                ucb->io_out &= ~(1 << offset);
 
+       ucb1x00_enable(ucb);
        ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
+       ucb1x00_disable(ucb);
        spin_unlock_irqrestore(&ucb->io_lock, flags);
 }
 
 static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
        struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
-       return ucb1x00_reg_read(ucb, UCB_IO_DATA) & (1 << offset);
+       unsigned val;
+
+       ucb1x00_enable(ucb);
+       val = ucb1x00_reg_read(ucb, UCB_IO_DATA);
+       ucb1x00_disable(ucb);
+
+       return val & (1 << offset);
 }
 
 static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -137,7 +143,9 @@ static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 
        spin_lock_irqsave(&ucb->io_lock, flags);
        ucb->io_dir &= ~(1 << offset);
+       ucb1x00_enable(ucb);
        ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
+       ucb1x00_disable(ucb);
        spin_unlock_irqrestore(&ucb->io_lock, flags);
 
        return 0;
@@ -157,6 +165,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
        else
                ucb->io_out &= ~mask;
 
+       ucb1x00_enable(ucb);
        if (old != ucb->io_out)
                ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
 
@@ -164,11 +173,19 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
                ucb->io_dir |= mask;
                ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
        }
+       ucb1x00_disable(ucb);
        spin_unlock_irqrestore(&ucb->io_lock, flags);
 
        return 0;
 }
 
+static int ucb1x00_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
+
+       return ucb->irq_base > 0 ? ucb->irq_base + offset : -ENXIO;
+}
+
 /*
  * UCB1300 data sheet says we must:
  *  1. enable ADC      => 5us (including reference startup time)
@@ -186,7 +203,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
  *     Any code wishing to use the ADC converter must call this
  *     function prior to using it.
  *
- *     This function takes the ADC semaphore to prevent two or more
+ *     This function takes the ADC mutex to prevent two or more
  *     concurrent uses, and therefore may sleep.  As a result, it
  *     can only be called from process context, not interrupt
  *     context.
@@ -196,7 +213,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
  */
 void ucb1x00_adc_enable(struct ucb1x00 *ucb)
 {
-       down(&ucb->adc_sem);
+       mutex_lock(&ucb->adc_mutex);
 
        ucb->adc_cr |= UCB_ADC_ENA;
 
@@ -218,7 +235,7 @@ void ucb1x00_adc_enable(struct ucb1x00 *ucb)
  *     complete (2 frames max without sync).
  *
  *     If called for a synchronised ADC conversion, it may sleep
- *     with the ADC semaphore held.
+ *     with the ADC mutex held.
  */
 unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
 {
@@ -246,7 +263,7 @@ unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
  *     ucb1x00_adc_disable - disable the ADC converter
  *     @ucb: UCB1x00 structure describing chip
  *
- *     Disable the ADC converter and release the ADC semaphore.
+ *     Disable the ADC converter and release the ADC mutex.
  */
 void ucb1x00_adc_disable(struct ucb1x00 *ucb)
 {
@@ -254,7 +271,7 @@ void ucb1x00_adc_disable(struct ucb1x00 *ucb)
        ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
        ucb1x00_disable(ucb);
 
-       up(&ucb->adc_sem);
+       mutex_unlock(&ucb->adc_mutex);
 }
 
 /*
@@ -265,10 +282,9 @@ void ucb1x00_adc_disable(struct ucb1x00 *ucb)
  * SIBCLK to talk to the chip.  We leave the clock running until
  * we have finished processing all interrupts from the chip.
  */
-static irqreturn_t ucb1x00_irq(int irqnr, void *devid)
+static void ucb1x00_irq(unsigned int irq, struct irq_desc *desc)
 {
-       struct ucb1x00 *ucb = devid;
-       struct ucb1x00_irq *irq;
+       struct ucb1x00 *ucb = irq_desc_get_handler_data(desc);
        unsigned int isr, i;
 
        ucb1x00_enable(ucb);
@@ -276,157 +292,104 @@ static irqreturn_t ucb1x00_irq(int irqnr, void *devid)
        ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
        ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
 
-       for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
-               if (isr & 1 && irq->fn)
-                       irq->fn(i, irq->devid);
+       for (i = 0; i < 16 && isr; i++, isr >>= 1, irq++)
+               if (isr & 1)
+                       generic_handle_irq(ucb->irq_base + i);
        ucb1x00_disable(ucb);
-
-       return IRQ_HANDLED;
 }
 
-/**
- *     ucb1x00_hook_irq - hook a UCB1x00 interrupt
- *     @ucb:   UCB1x00 structure describing chip
- *     @idx:   interrupt index
- *     @fn:    function to call when interrupt is triggered
- *     @devid: device id to pass to interrupt handler
- *
- *     Hook the specified interrupt.  You can only register one handler
- *     for each interrupt source.  The interrupt source is not enabled
- *     by this function; use ucb1x00_enable_irq instead.
- *
- *     Interrupt handlers will be called with other interrupts enabled.
- *
- *     Returns zero on success, or one of the following errors:
- *      -EINVAL if the interrupt index is invalid
- *      -EBUSY if the interrupt has already been hooked
- */
-int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid)
+static void ucb1x00_irq_update(struct ucb1x00 *ucb, unsigned mask)
 {
-       struct ucb1x00_irq *irq;
-       int ret = -EINVAL;
-
-       if (idx < 16) {
-               irq = ucb->irq_handler + idx;
-               ret = -EBUSY;
-
-               spin_lock_irq(&ucb->lock);
-               if (irq->fn == NULL) {
-                       irq->devid = devid;
-                       irq->fn = fn;
-                       ret = 0;
-               }
-               spin_unlock_irq(&ucb->lock);
-       }
-       return ret;
+       ucb1x00_enable(ucb);
+       if (ucb->irq_ris_enbl & mask)
+               ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
+                                 ucb->irq_mask);
+       if (ucb->irq_fal_enbl & mask)
+               ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
+                                 ucb->irq_mask);
+       ucb1x00_disable(ucb);
 }
 
-/**
- *     ucb1x00_enable_irq - enable an UCB1x00 interrupt source
- *     @ucb: UCB1x00 structure describing chip
- *     @idx: interrupt index
- *     @edges: interrupt edges to enable
- *
- *     Enable the specified interrupt to trigger on %UCB_RISING,
- *     %UCB_FALLING or both edges.  The interrupt should have been
- *     hooked by ucb1x00_hook_irq.
- */
-void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
+static void ucb1x00_irq_noop(struct irq_data *data)
 {
-       unsigned long flags;
+}
 
-       if (idx < 16) {
-               spin_lock_irqsave(&ucb->lock, flags);
+static void ucb1x00_irq_mask(struct irq_data *data)
+{
+       struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
+       unsigned mask = 1 << (data->irq - ucb->irq_base);
 
-               ucb1x00_enable(ucb);
-               if (edges & UCB_RISING) {
-                       ucb->irq_ris_enbl |= 1 << idx;
-                       ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-               }
-               if (edges & UCB_FALLING) {
-                       ucb->irq_fal_enbl |= 1 << idx;
-                       ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
-               }
-               ucb1x00_disable(ucb);
-               spin_unlock_irqrestore(&ucb->lock, flags);
-       }
+       raw_spin_lock(&ucb->irq_lock);
+       ucb->irq_mask &= ~mask;
+       ucb1x00_irq_update(ucb, mask);
+       raw_spin_unlock(&ucb->irq_lock);
 }
 
-/**
- *     ucb1x00_disable_irq - disable an UCB1x00 interrupt source
- *     @ucb: UCB1x00 structure describing chip
- *     @edges: interrupt edges to disable
- *
- *     Disable the specified interrupt triggering on the specified
- *     (%UCB_RISING, %UCB_FALLING or both) edges.
- */
-void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
+static void ucb1x00_irq_unmask(struct irq_data *data)
 {
-       unsigned long flags;
+       struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
+       unsigned mask = 1 << (data->irq - ucb->irq_base);
 
-       if (idx < 16) {
-               spin_lock_irqsave(&ucb->lock, flags);
-
-               ucb1x00_enable(ucb);
-               if (edges & UCB_RISING) {
-                       ucb->irq_ris_enbl &= ~(1 << idx);
-                       ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-               }
-               if (edges & UCB_FALLING) {
-                       ucb->irq_fal_enbl &= ~(1 << idx);
-                       ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
-               }
-               ucb1x00_disable(ucb);
-               spin_unlock_irqrestore(&ucb->lock, flags);
-       }
+       raw_spin_lock(&ucb->irq_lock);
+       ucb->irq_mask |= mask;
+       ucb1x00_irq_update(ucb, mask);
+       raw_spin_unlock(&ucb->irq_lock);
 }
 
-/**
- *     ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt
- *     @ucb: UCB1x00 structure describing chip
- *     @idx: interrupt index
- *     @devid: device id.
- *
- *     Disable the interrupt source and remove the handler.  devid must
- *     match the devid passed when hooking the interrupt.
- *
- *     Returns zero on success, or one of the following errors:
- *      -EINVAL if the interrupt index is invalid
- *      -ENOENT if devid does not match
- */
-int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid)
+static int ucb1x00_irq_set_type(struct irq_data *data, unsigned int type)
 {
-       struct ucb1x00_irq *irq;
-       int ret;
+       struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
+       unsigned mask = 1 << (data->irq - ucb->irq_base);
 
-       if (idx >= 16)
-               goto bad;
+       raw_spin_lock(&ucb->irq_lock);
+       if (type & IRQ_TYPE_EDGE_RISING)
+               ucb->irq_ris_enbl |= mask;
+       else
+               ucb->irq_ris_enbl &= ~mask;
 
-       irq = ucb->irq_handler + idx;
-       ret = -ENOENT;
+       if (type & IRQ_TYPE_EDGE_FALLING)
+               ucb->irq_fal_enbl |= mask;
+       else
+               ucb->irq_fal_enbl &= ~mask;
+       if (ucb->irq_mask & mask) {
+               ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
+                                 ucb->irq_mask);
+               ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
+                                 ucb->irq_mask);
+       }
+       raw_spin_unlock(&ucb->irq_lock);
 
-       spin_lock_irq(&ucb->lock);
-       if (irq->devid == devid) {
-               ucb->irq_ris_enbl &= ~(1 << idx);
-               ucb->irq_fal_enbl &= ~(1 << idx);
+       return 0;
+}
 
-               ucb1x00_enable(ucb);
-               ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-               ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
-               ucb1x00_disable(ucb);
+static int ucb1x00_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+       struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
+       struct ucb1x00_plat_data *pdata = ucb->mcp->attached_device.platform_data;
+       unsigned mask = 1 << (data->irq - ucb->irq_base);
 
-               irq->fn = NULL;
-               irq->devid = NULL;
-               ret = 0;
-       }
-       spin_unlock_irq(&ucb->lock);
-       return ret;
+       if (!pdata || !pdata->can_wakeup)
+               return -EINVAL;
 
-bad:
-       printk(KERN_ERR "Freeing bad UCB1x00 irq %d\n", idx);
-       return -EINVAL;
+       raw_spin_lock(&ucb->irq_lock);
+       if (on)
+               ucb->irq_wake |= mask;
+       else
+               ucb->irq_wake &= ~mask;
+       raw_spin_unlock(&ucb->irq_lock);
+
+       return 0;
 }
 
+static struct irq_chip ucb1x00_irqchip = {
+       .name = "ucb1x00",
+       .irq_ack = ucb1x00_irq_noop,
+       .irq_mask = ucb1x00_irq_mask,
+       .irq_unmask = ucb1x00_irq_unmask,
+       .irq_set_type = ucb1x00_irq_set_type,
+       .irq_set_wake = ucb1x00_irq_set_wake,
+};
+
 static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv)
 {
        struct ucb1x00_dev *dev;
@@ -440,8 +403,8 @@ static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv)
                ret = drv->add(dev);
 
                if (ret == 0) {
-                       list_add(&dev->dev_node, &ucb->devs);
-                       list_add(&dev->drv_node, &drv->devs);
+                       list_add_tail(&dev->dev_node, &ucb->devs);
+                       list_add_tail(&dev->drv_node, &drv->devs);
                } else {
                        kfree(dev);
                }
@@ -533,98 +496,126 @@ static struct class ucb1x00_class = {
 
 static int ucb1x00_probe(struct mcp *mcp)
 {
-       struct ucb1x00 *ucb;
+       struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data;
        struct ucb1x00_driver *drv;
-       unsigned int id;
+       struct ucb1x00 *ucb;
+       unsigned id, i, irq_base;
        int ret = -ENODEV;
-       int temp;
+
+       /* Tell the platform to deassert the UCB1x00 reset */
+       if (pdata && pdata->reset)
+               pdata->reset(UCB_RST_PROBE);
 
        mcp_enable(mcp);
        id = mcp_reg_read(mcp, UCB_ID);
+       mcp_disable(mcp);
 
        if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) {
                printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
-               goto err_disable;
+               goto out;
        }
 
        ucb = kzalloc(sizeof(struct ucb1x00), GFP_KERNEL);
        ret = -ENOMEM;
        if (!ucb)
-               goto err_disable;
-
+               goto out;
 
+       device_initialize(&ucb->dev);
        ucb->dev.class = &ucb1x00_class;
        ucb->dev.parent = &mcp->attached_device;
        dev_set_name(&ucb->dev, "ucb1x00");
 
-       spin_lock_init(&ucb->lock);
+       raw_spin_lock_init(&ucb->irq_lock);
        spin_lock_init(&ucb->io_lock);
-       sema_init(&ucb->adc_sem, 1);
+       mutex_init(&ucb->adc_mutex);
 
        ucb->id  = id;
        ucb->mcp = mcp;
+
+       ret = device_add(&ucb->dev);
+       if (ret)
+               goto err_dev_add;
+
+       ucb1x00_enable(ucb);
        ucb->irq = ucb1x00_detect_irq(ucb);
+       ucb1x00_disable(ucb);
        if (ucb->irq == NO_IRQ) {
-               printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
+               dev_err(&ucb->dev, "IRQ probe failed\n");
                ret = -ENODEV;
-               goto err_free;
+               goto err_no_irq;
        }
 
        ucb->gpio.base = -1;
-       if (mcp->gpio_base != 0) {
+       irq_base = pdata ? pdata->irq_base : 0;
+       ucb->irq_base = irq_alloc_descs(-1, irq_base, 16, -1);
+       if (ucb->irq_base < 0) {
+               dev_err(&ucb->dev, "unable to allocate 16 irqs: %d\n",
+                       ucb->irq_base);
+               goto err_irq_alloc;
+       }
+
+       for (i = 0; i < 16; i++) {
+               unsigned irq = ucb->irq_base + i;
+
+               irq_set_chip_and_handler(irq, &ucb1x00_irqchip, handle_edge_irq);
+               irq_set_chip_data(irq, ucb);
+               set_irq_flags(irq, IRQF_VALID | IRQ_NOREQUEST);
+       }
+
+       irq_set_irq_type(ucb->irq, IRQ_TYPE_EDGE_RISING);
+       irq_set_handler_data(ucb->irq, ucb);
+       irq_set_chained_handler(ucb->irq, ucb1x00_irq);
+
+       if (pdata && pdata->gpio_base) {
                ucb->gpio.label = dev_name(&ucb->dev);
-               ucb->gpio.base = mcp->gpio_base;
+               ucb->gpio.dev = &ucb->dev;
+               ucb->gpio.owner = THIS_MODULE;
+               ucb->gpio.base = pdata->gpio_base;
                ucb->gpio.ngpio = 10;
                ucb->gpio.set = ucb1x00_gpio_set;
                ucb->gpio.get = ucb1x00_gpio_get;
                ucb->gpio.direction_input = ucb1x00_gpio_direction_input;
                ucb->gpio.direction_output = ucb1x00_gpio_direction_output;
+               ucb->gpio.to_irq = ucb1x00_to_irq;
                ret = gpiochip_add(&ucb->gpio);
                if (ret)
-                       goto err_free;
+                       goto err_gpio_add;
        } else
                dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");
 
-       ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
-                         "UCB1x00", ucb);
-       if (ret) {
-               printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
-                       ucb->irq, ret);
-               goto err_gpio;
-       }
-
        mcp_set_drvdata(mcp, ucb);
 
-       ret = device_register(&ucb->dev);
-       if (ret)
-               goto err_irq;
-
+       if (pdata)
+               device_set_wakeup_capable(&ucb->dev, pdata->can_wakeup);
 
        INIT_LIST_HEAD(&ucb->devs);
        mutex_lock(&ucb1x00_mutex);
-       list_add(&ucb->node, &ucb1x00_devices);
+       list_add_tail(&ucb->node, &ucb1x00_devices);
        list_for_each_entry(drv, &ucb1x00_drivers, node) {
                ucb1x00_add_dev(ucb, drv);
        }
        mutex_unlock(&ucb1x00_mutex);
 
-       goto out;
+       return ret;
 
- err_irq:
-       free_irq(ucb->irq, ucb);
- err_gpio:
-       if (ucb->gpio.base != -1)
-               temp = gpiochip_remove(&ucb->gpio);
- err_free:
-       kfree(ucb);
- err_disable:
-       mcp_disable(mcp);
+ err_gpio_add:
+       irq_set_chained_handler(ucb->irq, NULL);
+ err_irq_alloc:
+       if (ucb->irq_base > 0)
+               irq_free_descs(ucb->irq_base, 16);
+ err_no_irq:
+       device_del(&ucb->dev);
+ err_dev_add:
+       put_device(&ucb->dev);
  out:
+       if (pdata && pdata->reset)
+               pdata->reset(UCB_RST_PROBE_FAIL);
        return ret;
 }
 
 static void ucb1x00_remove(struct mcp *mcp)
 {
+       struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data;
        struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
        struct list_head *l, *n;
        int ret;
@@ -643,8 +634,12 @@ static void ucb1x00_remove(struct mcp *mcp)
                        dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret);
        }
 
-       free_irq(ucb->irq, ucb);
+       irq_set_chained_handler(ucb->irq, NULL);
+       irq_free_descs(ucb->irq_base, 16);
        device_unregister(&ucb->dev);
+
+       if (pdata && pdata->reset)
+               pdata->reset(UCB_RST_REMOVE);
 }
 
 int ucb1x00_register_driver(struct ucb1x00_driver *drv)
@@ -653,7 +648,7 @@ int ucb1x00_register_driver(struct ucb1x00_driver *drv)
 
        INIT_LIST_HEAD(&drv->devs);
        mutex_lock(&ucb1x00_mutex);
-       list_add(&drv->node, &ucb1x00_drivers);
+       list_add_tail(&drv->node, &ucb1x00_drivers);
        list_for_each_entry(ucb, &ucb1x00_devices, node) {
                ucb1x00_add_dev(ucb, drv);
        }
@@ -674,44 +669,86 @@ void ucb1x00_unregister_driver(struct ucb1x00_driver *drv)
        mutex_unlock(&ucb1x00_mutex);
 }
 
-static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state)
+static int ucb1x00_suspend(struct device *dev)
 {
-       struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
-       struct ucb1x00_dev *dev;
+       struct ucb1x00_plat_data *pdata = dev->platform_data;
+       struct ucb1x00 *ucb = dev_get_drvdata(dev);
+       struct ucb1x00_dev *udev;
 
        mutex_lock(&ucb1x00_mutex);
-       list_for_each_entry(dev, &ucb->devs, dev_node) {
-               if (dev->drv->suspend)
-                       dev->drv->suspend(dev, state);
+       list_for_each_entry(udev, &ucb->devs, dev_node) {
+               if (udev->drv->suspend)
+                       udev->drv->suspend(udev);
        }
        mutex_unlock(&ucb1x00_mutex);
+
+       if (ucb->irq_wake) {
+               unsigned long flags;
+
+               raw_spin_lock_irqsave(&ucb->irq_lock, flags);
+               ucb1x00_enable(ucb);
+               ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
+                                 ucb->irq_wake);
+               ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
+                                 ucb->irq_wake);
+               ucb1x00_disable(ucb);
+               raw_spin_unlock_irqrestore(&ucb->irq_lock, flags);
+
+               enable_irq_wake(ucb->irq);
+       } else if (pdata && pdata->reset)
+               pdata->reset(UCB_RST_SUSPEND);
+
        return 0;
 }
 
-static int ucb1x00_resume(struct mcp *mcp)
+static int ucb1x00_resume(struct device *dev)
 {
-       struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
-       struct ucb1x00_dev *dev;
+       struct ucb1x00_plat_data *pdata = dev->platform_data;
+       struct ucb1x00 *ucb = dev_get_drvdata(dev);
+       struct ucb1x00_dev *udev;
+
+       if (!ucb->irq_wake && pdata && pdata->reset)
+               pdata->reset(UCB_RST_RESUME);
 
+       ucb1x00_enable(ucb);
        ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
        ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
+
+       if (ucb->irq_wake) {
+               unsigned long flags;
+
+               raw_spin_lock_irqsave(&ucb->irq_lock, flags);
+               ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
+                                 ucb->irq_mask);
+               ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
+                                 ucb->irq_mask);
+               raw_spin_unlock_irqrestore(&ucb->irq_lock, flags);
+
+               disable_irq_wake(ucb->irq);
+       }
+       ucb1x00_disable(ucb);
+
        mutex_lock(&ucb1x00_mutex);
-       list_for_each_entry(dev, &ucb->devs, dev_node) {
-               if (dev->drv->resume)
-                       dev->drv->resume(dev);
+       list_for_each_entry(udev, &ucb->devs, dev_node) {
+               if (udev->drv->resume)
+                       udev->drv->resume(udev);
        }
        mutex_unlock(&ucb1x00_mutex);
        return 0;
 }
 
+static const struct dev_pm_ops ucb1x00_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(ucb1x00_suspend, ucb1x00_resume)
+};
+
 static struct mcp_driver ucb1x00_driver = {
        .drv            = {
                .name   = "ucb1x00",
+               .owner  = THIS_MODULE,
+               .pm     = &ucb1x00_pm_ops,
        },
        .probe          = ucb1x00_probe,
        .remove         = ucb1x00_remove,
-       .suspend        = ucb1x00_suspend,
-       .resume         = ucb1x00_resume,
 };
 
 static int __init ucb1x00_init(void)
@@ -742,14 +779,10 @@ EXPORT_SYMBOL(ucb1x00_adc_enable);
 EXPORT_SYMBOL(ucb1x00_adc_read);
 EXPORT_SYMBOL(ucb1x00_adc_disable);
 
-EXPORT_SYMBOL(ucb1x00_hook_irq);
-EXPORT_SYMBOL(ucb1x00_free_irq);
-EXPORT_SYMBOL(ucb1x00_enable_irq);
-EXPORT_SYMBOL(ucb1x00_disable_irq);
-
 EXPORT_SYMBOL(ucb1x00_register_driver);
 EXPORT_SYMBOL(ucb1x00_unregister_driver);
 
+MODULE_ALIAS("mcp:ucb1x00");
 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
 MODULE_DESCRIPTION("UCB1x00 core driver");
 MODULE_LICENSE("GPL");
index 63a3cbd..1e0e20c 100644 (file)
@@ -20,8 +20,9 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
-#include <linux/smp.h>
+#include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/string.h>
@@ -32,7 +33,6 @@
 #include <linux/kthread.h>
 #include <linux/mfd/ucb1x00.h>
 
-#include <mach/dma.h>
 #include <mach/collie.h>
 #include <asm/mach-types.h>
 
@@ -42,6 +42,8 @@ struct ucb1x00_ts {
        struct input_dev        *idev;
        struct ucb1x00          *ucb;
 
+       spinlock_t              irq_lock;
+       unsigned                irq_disabled;
        wait_queue_head_t       irq_wait;
        struct task_struct      *rtask;
        u16                     x_res;
@@ -238,7 +240,12 @@ static int ucb1x00_thread(void *_ts)
                if (ucb1x00_ts_pen_down(ts)) {
                        set_current_state(TASK_INTERRUPTIBLE);
 
-                       ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING);
+                       spin_lock_irq(&ts->irq_lock);
+                       if (ts->irq_disabled) {
+                               ts->irq_disabled = 0;
+                               enable_irq(ts->ucb->irq_base + UCB_IRQ_TSPX);
+                       }
+                       spin_unlock_irq(&ts->irq_lock);
                        ucb1x00_disable(ts->ucb);
 
                        /*
@@ -281,23 +288,37 @@ static int ucb1x00_thread(void *_ts)
  * We only detect touch screen _touches_ with this interrupt
  * handler, and even then we just schedule our task.
  */
-static void ucb1x00_ts_irq(int idx, void *id)
+static irqreturn_t ucb1x00_ts_irq(int irq, void *id)
 {
        struct ucb1x00_ts *ts = id;
 
-       ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
+       spin_lock(&ts->irq_lock);
+       ts->irq_disabled = 1;
+       disable_irq_nosync(ts->ucb->irq_base + UCB_IRQ_TSPX);
+       spin_unlock(&ts->irq_lock);
        wake_up(&ts->irq_wait);
+
+       return IRQ_HANDLED;
 }
 
 static int ucb1x00_ts_open(struct input_dev *idev)
 {
        struct ucb1x00_ts *ts = input_get_drvdata(idev);
+       unsigned long flags = 0;
        int ret = 0;
 
        BUG_ON(ts->rtask);
 
+       if (machine_is_collie())
+               flags = IRQF_TRIGGER_RISING;
+       else
+               flags = IRQF_TRIGGER_FALLING;
+
+       ts->irq_disabled = 0;
+
        init_waitqueue_head(&ts->irq_wait);
-       ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
+       ret = request_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ucb1x00_ts_irq,
+                         flags, "ucb1x00-ts", ts);
        if (ret < 0)
                goto out;
 
@@ -314,7 +335,7 @@ static int ucb1x00_ts_open(struct input_dev *idev)
        if (!IS_ERR(ts->rtask)) {
                ret = 0;
        } else {
-               ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
+               free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts);
                ts->rtask = NULL;
                ret = -EFAULT;
        }
@@ -334,7 +355,7 @@ static void ucb1x00_ts_close(struct input_dev *idev)
                kthread_stop(ts->rtask);
 
        ucb1x00_enable(ts->ucb);
-       ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
+       free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts);
        ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
        ucb1x00_disable(ts->ucb);
 }
@@ -359,11 +380,13 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
        ts->ucb = dev->ucb;
        ts->idev = idev;
        ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
+       spin_lock_init(&ts->irq_lock);
 
        idev->name       = "Touchscreen panel";
        idev->id.product = ts->ucb->id;
        idev->open       = ucb1x00_ts_open;
        idev->close      = ucb1x00_ts_close;
+       idev->dev.parent = &ts->ucb->dev;
 
        idev->evbit[0]   = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
        idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
index 150cd70..28adefe 100644 (file)
@@ -354,6 +354,7 @@ static void lkdtm_do_action(enum ctype which)
 static void lkdtm_handler(void)
 {
        unsigned long flags;
+       bool do_it = false;
 
        spin_lock_irqsave(&count_lock, flags);
        count--;
@@ -361,10 +362,13 @@ static void lkdtm_handler(void)
                        cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
 
        if (count == 0) {
-               lkdtm_do_action(cptype);
+               do_it = true;
                count = cpoint_count;
        }
        spin_unlock_irqrestore(&count_lock, flags);
+
+       if (do_it)
+               lkdtm_do_action(cptype);
 }
 
 static int lkdtm_register_cpoint(enum cname which)
index 5028219..cbc3b78 100644 (file)
 #include <asm/sizes.h>
 #include <asm/mach/flash.h>
 
-#if 0
-/*
- * This is here for documentation purposes only - until these people
- * submit their machine types.  It will be gone January 2005.
- */
-static struct mtd_partition consus_partitions[] = {
-       {
-               .name           = "Consus boot firmware",
-               .offset         = 0,
-               .size           = 0x00040000,
-               .mask_flags     = MTD_WRITABLE, /* force read-only */
-       }, {
-               .name           = "Consus kernel",
-               .offset         = 0x00040000,
-               .size           = 0x00100000,
-               .mask_flags     = 0,
-       }, {
-               .name           = "Consus disk",
-               .offset         = 0x00140000,
-               /* The rest (up to 16M) for jffs.  We could put 0 and
-                  make it find the size automatically, but right now
-                  i have 32 megs.  jffs will use all 32 megs if given
-                  the chance, and this leads to horrible problems
-                  when you try to re-flash the image because blob
-                  won't erase the whole partition. */
-               .size           = 0x01000000 - 0x00140000,
-               .mask_flags     = 0,
-       }, {
-               /* this disk is a secondary disk, which can be used as
-                  needed, for simplicity, make it the size of the other
-                  consus partition, although realistically it could be
-                  the remainder of the disk (depending on the file
-                  system used) */
-                .name          = "Consus disk2",
-                .offset        = 0x01000000,
-                .size          = 0x01000000 - 0x00140000,
-                .mask_flags    = 0,
-       }
-};
-
-/* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */
-static struct mtd_partition frodo_partitions[] =
-{
-       {
-               .name           = "bootloader",
-               .size           = 0x00040000,
-               .offset         = 0x00000000,
-               .mask_flags     = MTD_WRITEABLE
-       }, {
-               .name           = "bootloader params",
-               .size           = 0x00040000,
-               .offset         = MTDPART_OFS_APPEND,
-               .mask_flags     = MTD_WRITEABLE
-       }, {
-               .name           = "kernel",
-               .size           = 0x00100000,
-               .offset         = MTDPART_OFS_APPEND,
-               .mask_flags     = MTD_WRITEABLE
-       }, {
-               .name           = "ramdisk",
-               .size           = 0x00400000,
-               .offset         = MTDPART_OFS_APPEND,
-               .mask_flags     = MTD_WRITEABLE
-       }, {
-               .name           = "file system",
-               .size           = MTDPART_SIZ_FULL,
-               .offset         = MTDPART_OFS_APPEND
-       }
-};
-
-static struct mtd_partition jornada56x_partitions[] = {
-       {
-               .name           = "bootldr",
-               .size           = 0x00040000,
-               .offset         = 0,
-               .mask_flags     = MTD_WRITEABLE,
-       }, {
-               .name           = "rootfs",
-               .size           = MTDPART_SIZ_FULL,
-               .offset         = MTDPART_OFS_APPEND,
-       }
-};
-
-static void jornada56x_set_vpp(int vpp)
-{
-       if (vpp)
-               GPSR = GPIO_GPIO26;
-       else
-               GPCR = GPIO_GPIO26;
-       GPDR |= GPIO_GPIO26;
-}
-
-/*
- * Machine        Phys          Size    set_vpp
- * Consus    : SA1100_CS0_PHYS SZ_32M
- * Frodo     : SA1100_CS0_PHYS SZ_32M
- * Jornada56x: SA1100_CS0_PHYS SZ_32M jornada56x_set_vpp
- */
-#endif
-
 struct sa_subdev_info {
        char name[16];
        struct map_info map;
@@ -373,21 +273,9 @@ static int __exit sa1100_mtd_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static void sa1100_mtd_shutdown(struct platform_device *dev)
-{
-       struct sa_info *info = platform_get_drvdata(dev);
-       if (info && mtd_suspend(info->mtd) == 0)
-               mtd_resume(info->mtd);
-}
-#else
-#define sa1100_mtd_shutdown NULL
-#endif
-
 static struct platform_driver sa1100_mtd_driver = {
        .probe          = sa1100_mtd_probe,
        .remove         = __exit_p(sa1100_mtd_remove),
-       .shutdown       = sa1100_mtd_shutdown,
        .driver         = {
                .name   = "sa1100-mtd",
                .owner  = THIS_MODULE,
index 6ae9ca0..9a9ce71 100644 (file)
@@ -119,7 +119,7 @@ static int mtd_cls_suspend(struct device *dev, pm_message_t state)
 {
        struct mtd_info *mtd = dev_get_drvdata(dev);
 
-       return mtd_suspend(mtd);
+       return mtd ? mtd_suspend(mtd) : 0;
 }
 
 static int mtd_cls_resume(struct device *dev)
index 4dd056e..35b4fb5 100644 (file)
@@ -161,6 +161,37 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
                 !!host->board->rdy_pin_active_low;
 }
 
+/*
+ * Minimal-overhead PIO for data access.
+ */
+static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
+{
+       struct nand_chip        *nand_chip = mtd->priv;
+
+       __raw_readsb(nand_chip->IO_ADDR_R, buf, len);
+}
+
+static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
+{
+       struct nand_chip        *nand_chip = mtd->priv;
+
+       __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
+}
+
+static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
+{
+       struct nand_chip        *nand_chip = mtd->priv;
+
+       __raw_writesb(nand_chip->IO_ADDR_W, buf, len);
+}
+
+static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
+{
+       struct nand_chip        *nand_chip = mtd->priv;
+
+       __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
+}
+
 static void dma_complete_func(void *completion)
 {
        complete(completion);
@@ -235,27 +266,33 @@ err_buf:
 static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
        struct nand_chip *chip = mtd->priv;
+       struct atmel_nand_host *host = chip->priv;
 
        if (use_dma && len > mtd->oobsize)
                /* only use DMA for bigger than oob size: better performances */
                if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
                        return;
 
-       /* if no DMA operation possible, use PIO */
-       memcpy_fromio(buf, chip->IO_ADDR_R, len);
+       if (host->board->bus_width_16)
+               atmel_read_buf16(mtd, buf, len);
+       else
+               atmel_read_buf8(mtd, buf, len);
 }
 
 static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
        struct nand_chip *chip = mtd->priv;
+       struct atmel_nand_host *host = chip->priv;
 
        if (use_dma && len > mtd->oobsize)
                /* only use DMA for bigger than oob size: better performances */
                if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
                        return;
 
-       /* if no DMA operation possible, use PIO */
-       memcpy_toio(chip->IO_ADDR_W, buf, len);
+       if (host->board->bus_width_16)
+               atmel_write_buf16(mtd, buf, len);
+       else
+               atmel_write_buf8(mtd, buf, len);
 }
 
 /*
index 7f68042..7db6555 100644 (file)
@@ -69,17 +69,19 @@ static int clear_poll_bit(void __iomem *addr, u32 mask)
  *  [1] enable the module.
  *  [2] reset the module.
  *
- * In most of the cases, it's ok. But there is a hardware bug in the BCH block.
+ * In most of the cases, it's ok.
+ * But in MX23, there is a hardware bug in the BCH block (see erratum #2847).
  * If you try to soft reset the BCH block, it becomes unusable until
  * the next hard reset. This case occurs in the NAND boot mode. When the board
  * boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
  * So If the driver tries to reset the BCH again, the BCH will not work anymore.
- * You will see a DMA timeout in this case.
+ * You will see a DMA timeout in this case. The bug has been fixed
+ * in the following chips, such as MX28.
  *
  * To avoid this bug, just add a new parameter `just_enable` for
  * the mxs_reset_block(), and rewrite it here.
  */
-int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
+static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
 {
        int ret;
        int timeout = 0x400;
@@ -206,7 +208,15 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        if (ret)
                goto err_out;
 
-       ret = gpmi_reset_block(r->bch_regs, true);
+       /*
+       * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
+       * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
+       * On the other hand, the MX28 needs the reset, because one case has been
+       * seen where the BCH produced ECC errors constantly after 10000
+       * consecutive reboots. The latter case has not been seen on the MX23 yet,
+       * still we don't know if it could happen there as well.
+       */
+       ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
        if (ret)
                goto err_out;
 
index 35b4565..8a393f9 100644 (file)
@@ -2588,7 +2588,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
        instr->state = MTD_ERASING;
 
        while (len) {
-               /* Heck if we have a bad block, we do not erase bad blocks! */
+               /* Check if we have a bad block, we do not erase bad blocks! */
                if (nand_block_checkbad(mtd, ((loff_t) page) <<
                                        chip->page_shift, 0, allowbbt)) {
                        pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
index 64ad3ed..0dba050 100644 (file)
@@ -2281,7 +2281,7 @@ static int __devinit smc_drv_probe(struct platform_device *pdev)
        if (ret)
                goto out_release_io;
 #if defined(CONFIG_SA1100_ASSABET)
-       NCR_0 |= NCR_ENET_OSC_EN;
+       neponset_ncr_set(NCR_ENET_OSC_EN);
 #endif
        platform_set_drvdata(pdev, ndev);
        ret = smc_enable_device(pdev);
index e535137..4680478 100644 (file)
@@ -356,7 +356,7 @@ config VLSI_FIR
 
 config SA1100_FIR
        tristate "SA1100 Internal IR"
-       depends on ARCH_SA1100 && IRDA
+       depends on ARCH_SA1100 && IRDA && DMA_SA11X0
 
 config VIA_FIR
        tristate "VIA VT8231/VT1211 SIR/MIR/FIR"
index da27050..a0d1913 100644 (file)
@@ -15,7 +15,7 @@
  *  This driver takes one kernel command line parameter, sa1100ir=, with
  *  the following options:
  *     max_rate:baudrate       - set the maximum baud rate
- *     power_leve:level        - set the transmitter power level
+ *     power_level:level       - set the transmitter power level
  *     tx_lpm:0|1              - set transmit low power mode
  */
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/sa11x0-dma.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/wrapper.h>
 #include <net/irda/irda_device.h>
 
-#include <asm/irq.h>
-#include <mach/dma.h>
 #include <mach/hardware.h>
 #include <asm/mach/irda.h>
 
@@ -44,8 +44,15 @@ static int power_level = 3;
 static int tx_lpm;
 static int max_rate = 4000000;
 
+struct sa1100_buf {
+       struct device           *dev;
+       struct sk_buff          *skb;
+       struct scatterlist      sg;
+       struct dma_chan         *chan;
+       dma_cookie_t            cookie;
+};
+
 struct sa1100_irda {
-       unsigned char           hscr0;
        unsigned char           utcr4;
        unsigned char           power;
        unsigned char           open;
@@ -53,12 +60,8 @@ struct sa1100_irda {
        int                     speed;
        int                     newspeed;
 
-       struct sk_buff          *txskb;
-       struct sk_buff          *rxskb;
-       dma_addr_t              txbuf_dma;
-       dma_addr_t              rxbuf_dma;
-       dma_regs_t              *txdma;
-       dma_regs_t              *rxdma;
+       struct sa1100_buf       dma_rx;
+       struct sa1100_buf       dma_tx;
 
        struct device           *dev;
        struct irda_platform_data *pdata;
@@ -67,23 +70,103 @@ struct sa1100_irda {
 
        iobuff_t                tx_buff;
        iobuff_t                rx_buff;
+
+       int (*tx_start)(struct sk_buff *, struct net_device *, struct sa1100_irda *);
+       irqreturn_t (*irq)(struct net_device *, struct sa1100_irda *);
 };
 
+static int sa1100_irda_set_speed(struct sa1100_irda *, int);
+
 #define IS_FIR(si)             ((si)->speed >= 4000000)
 
 #define HPSIR_MAX_RXLEN                2047
 
+static struct dma_slave_config sa1100_irda_sir_tx = {
+       .direction      = DMA_TO_DEVICE,
+       .dst_addr       = __PREG(Ser2UTDR),
+       .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
+       .dst_maxburst   = 4,
+};
+
+static struct dma_slave_config sa1100_irda_fir_rx = {
+       .direction      = DMA_FROM_DEVICE,
+       .src_addr       = __PREG(Ser2HSDR),
+       .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
+       .src_maxburst   = 8,
+};
+
+static struct dma_slave_config sa1100_irda_fir_tx = {
+       .direction      = DMA_TO_DEVICE,
+       .dst_addr       = __PREG(Ser2HSDR),
+       .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
+       .dst_maxburst   = 8,
+};
+
+static unsigned sa1100_irda_dma_xferred(struct sa1100_buf *buf)
+{
+       struct dma_chan *chan = buf->chan;
+       struct dma_tx_state state;
+       enum dma_status status;
+
+       status = chan->device->device_tx_status(chan, buf->cookie, &state);
+       if (status != DMA_PAUSED)
+               return 0;
+
+       return sg_dma_len(&buf->sg) - state.residue;
+}
+
+static int sa1100_irda_dma_request(struct device *dev, struct sa1100_buf *buf,
+       const char *name, struct dma_slave_config *cfg)
+{
+       dma_cap_mask_t m;
+       int ret;
+
+       dma_cap_zero(m);
+       dma_cap_set(DMA_SLAVE, m);
+
+       buf->chan = dma_request_channel(m, sa11x0_dma_filter_fn, (void *)name);
+       if (!buf->chan) {
+               dev_err(dev, "unable to request DMA channel for %s\n",
+                       name);
+               return -ENOENT;
+       }
+
+       ret = dmaengine_slave_config(buf->chan, cfg);
+       if (ret)
+               dev_warn(dev, "DMA slave_config for %s returned %d\n",
+                       name, ret);
+
+       buf->dev = buf->chan->device->dev;
+
+       return 0;
+}
+
+static void sa1100_irda_dma_start(struct sa1100_buf *buf,
+       enum dma_transfer_direction dir, dma_async_tx_callback cb, void *cb_p)
+{
+       struct dma_async_tx_descriptor *desc;
+       struct dma_chan *chan = buf->chan;
+
+       desc = chan->device->device_prep_slave_sg(chan, &buf->sg, 1, dir,
+                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (desc) {
+               desc->callback = cb;
+               desc->callback_param = cb_p;
+               buf->cookie = dmaengine_submit(desc);
+               dma_async_issue_pending(chan);
+       }
+}
+
 /*
  * Allocate and map the receive buffer, unless it is already allocated.
  */
 static int sa1100_irda_rx_alloc(struct sa1100_irda *si)
 {
-       if (si->rxskb)
+       if (si->dma_rx.skb)
                return 0;
 
-       si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);
-
-       if (!si->rxskb) {
+       si->dma_rx.skb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);
+       if (!si->dma_rx.skb) {
                printk(KERN_ERR "sa1100_ir: out of memory for RX SKB\n");
                return -ENOMEM;
        }
@@ -92,11 +175,14 @@ static int sa1100_irda_rx_alloc(struct sa1100_irda *si)
         * Align any IP headers that may be contained
         * within the frame.
         */
-       skb_reserve(si->rxskb, 1);
+       skb_reserve(si->dma_rx.skb, 1);
+
+       sg_set_buf(&si->dma_rx.sg, si->dma_rx.skb->data, HPSIR_MAX_RXLEN);
+       if (dma_map_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, DMA_FROM_DEVICE) == 0) {
+               dev_kfree_skb_any(si->dma_rx.skb);
+               return -ENOMEM;
+       }
 
-       si->rxbuf_dma = dma_map_single(si->dev, si->rxskb->data,
-                                       HPSIR_MAX_RXLEN,
-                                       DMA_FROM_DEVICE);
        return 0;
 }
 
@@ -106,7 +192,7 @@ static int sa1100_irda_rx_alloc(struct sa1100_irda *si)
  */
 static void sa1100_irda_rx_dma_start(struct sa1100_irda *si)
 {
-       if (!si->rxskb) {
+       if (!si->dma_rx.skb) {
                printk(KERN_ERR "sa1100_ir: rx buffer went missing\n");
                return;
        }
@@ -114,254 +200,87 @@ static void sa1100_irda_rx_dma_start(struct sa1100_irda *si)
        /*
         * First empty receive FIFO
         */
-       Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
+       Ser2HSCR0 = HSCR0_HSSP;
 
        /*
         * Enable the DMA, receiver and receive interrupt.
         */
-       sa1100_clear_dma(si->rxdma);
-       sa1100_start_dma(si->rxdma, si->rxbuf_dma, HPSIR_MAX_RXLEN);
-       Ser2HSCR0 = si->hscr0 | HSCR0_HSSP | HSCR0_RXE;
+       dmaengine_terminate_all(si->dma_rx.chan);
+       sa1100_irda_dma_start(&si->dma_rx, DMA_DEV_TO_MEM, NULL, NULL);
+
+       Ser2HSCR0 = HSCR0_HSSP | HSCR0_RXE;
 }
 
-/*
- * Set the IrDA communications speed.
- */
-static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed)
+static void sa1100_irda_check_speed(struct sa1100_irda *si)
 {
-       unsigned long flags;
-       int brd, ret = -EINVAL;
-
-       switch (speed) {
-       case 9600:      case 19200:     case 38400:
-       case 57600:     case 115200:
-               brd = 3686400 / (16 * speed) - 1;
-
-               /*
-                * Stop the receive DMA.
-                */
-               if (IS_FIR(si))
-                       sa1100_stop_dma(si->rxdma);
-
-               local_irq_save(flags);
-
-               Ser2UTCR3 = 0;
-               Ser2HSCR0 = HSCR0_UART;
-
-               Ser2UTCR1 = brd >> 8;
-               Ser2UTCR2 = brd;
-
-               /*
-                * Clear status register
-                */
-               Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
-               Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;
-
-               if (si->pdata->set_speed)
-                       si->pdata->set_speed(si->dev, speed);
-
-               si->speed = speed;
-
-               local_irq_restore(flags);
-               ret = 0;
-               break;
-
-       case 4000000:
-               local_irq_save(flags);
-
-               si->hscr0 = 0;
-
-               Ser2HSSR0 = 0xff;
-               Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
-               Ser2UTCR3 = 0;
-
-               si->speed = speed;
-
-               if (si->pdata->set_speed)
-                       si->pdata->set_speed(si->dev, speed);
-
-               sa1100_irda_rx_alloc(si);
-               sa1100_irda_rx_dma_start(si);
-
-               local_irq_restore(flags);
-
-               break;
-
-       default:
-               break;
+       if (si->newspeed) {
+               sa1100_irda_set_speed(si, si->newspeed);
+               si->newspeed = 0;
        }
-
-       return ret;
 }
 
 /*
- * Control the power state of the IrDA transmitter.
- * State:
- *  0 - off
- *  1 - short range, lowest power
- *  2 - medium range, medium power
- *  3 - maximum range, high power
- *
- * Currently, only assabet is known to support this.
+ * HP-SIR format support.
  */
-static int
-__sa1100_irda_set_power(struct sa1100_irda *si, unsigned int state)
-{
-       int ret = 0;
-       if (si->pdata->set_power)
-               ret = si->pdata->set_power(si->dev, state);
-       return ret;
-}
-
-static inline int
-sa1100_set_power(struct sa1100_irda *si, unsigned int state)
+static void sa1100_irda_sirtxdma_irq(void *id)
 {
-       int ret;
-
-       ret = __sa1100_irda_set_power(si, state);
-       if (ret == 0)
-               si->power = state;
-
-       return ret;
-}
+       struct net_device *dev = id;
+       struct sa1100_irda *si = netdev_priv(dev);
 
-static int sa1100_irda_startup(struct sa1100_irda *si)
-{
-       int ret;
+       dma_unmap_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, DMA_TO_DEVICE);
+       dev_kfree_skb(si->dma_tx.skb);
+       si->dma_tx.skb = NULL;
 
-       /*
-        * Ensure that the ports for this device are setup correctly.
-        */
-       if (si->pdata->startup) {
-               ret = si->pdata->startup(si->dev);
-               if (ret)
-                       return ret;
-       }
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes += sg_dma_len(&si->dma_tx.sg);
 
-       /*
-        * Configure PPC for IRDA - we want to drive TXD2 low.
-        * We also want to drive this pin low during sleep.
-        */
-       PPSR &= ~PPC_TXD2;
-       PSDR &= ~PPC_TXD2;
-       PPDR |= PPC_TXD2;
-
-       /*
-        * Enable HP-SIR modulation, and ensure that the port is disabled.
-        */
-       Ser2UTCR3 = 0;
-       Ser2HSCR0 = HSCR0_UART;
-       Ser2UTCR4 = si->utcr4;
-       Ser2UTCR0 = UTCR0_8BitData;
-       Ser2HSCR2 = HSCR2_TrDataH | HSCR2_RcDataL;
+       /* We need to ensure that the transmitter has finished. */
+       do
+               rmb();
+       while (Ser2UTSR1 & UTSR1_TBY);
 
        /*
-        * Clear status register
+        * Ok, we've finished transmitting.  Now enable the receiver.
+        * Sometimes we get a receive IRQ immediately after a transmit...
         */
        Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
+       Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;
 
-       ret = sa1100_irda_set_speed(si, si->speed = 9600);
-       if (ret) {
-               Ser2UTCR3 = 0;
-               Ser2HSCR0 = 0;
+       sa1100_irda_check_speed(si);
 
-               if (si->pdata->shutdown)
-                       si->pdata->shutdown(si->dev);
-       }
-
-       return ret;
-}
-
-static void sa1100_irda_shutdown(struct sa1100_irda *si)
-{
-       /*
-        * Stop all DMA activity.
-        */
-       sa1100_stop_dma(si->rxdma);
-       sa1100_stop_dma(si->txdma);
-
-       /* Disable the port. */
-       Ser2UTCR3 = 0;
-       Ser2HSCR0 = 0;
-
-       if (si->pdata->shutdown)
-               si->pdata->shutdown(si->dev);
+       /* I'm hungry! */
+       netif_wake_queue(dev);
 }
 
-#ifdef CONFIG_PM
-/*
- * Suspend the IrDA interface.
- */
-static int sa1100_irda_suspend(struct platform_device *pdev, pm_message_t state)
+static int sa1100_irda_sir_tx_start(struct sk_buff *skb, struct net_device *dev,
+       struct sa1100_irda *si)
 {
-       struct net_device *dev = platform_get_drvdata(pdev);
-       struct sa1100_irda *si;
-
-       if (!dev)
-               return 0;
-
-       si = netdev_priv(dev);
-       if (si->open) {
-               /*
-                * Stop the transmit queue
-                */
-               netif_device_detach(dev);
-               disable_irq(dev->irq);
-               sa1100_irda_shutdown(si);
-               __sa1100_irda_set_power(si, 0);
+       si->tx_buff.data = si->tx_buff.head;
+       si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data,
+                                         si->tx_buff.truesize);
+
+       si->dma_tx.skb = skb;
+       sg_set_buf(&si->dma_tx.sg, si->tx_buff.data, si->tx_buff.len);
+       if (dma_map_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, DMA_TO_DEVICE) == 0) {
+               si->dma_tx.skb = NULL;
+               netif_wake_queue(dev);
+               dev->stats.tx_dropped++;
+               return NETDEV_TX_OK;
        }
 
-       return 0;
-}
-
-/*
- * Resume the IrDA interface.
- */
-static int sa1100_irda_resume(struct platform_device *pdev)
-{
-       struct net_device *dev = platform_get_drvdata(pdev);
-       struct sa1100_irda *si;
-
-       if (!dev)
-               return 0;
-
-       si = netdev_priv(dev);
-       if (si->open) {
-               /*
-                * If we missed a speed change, initialise at the new speed
-                * directly.  It is debatable whether this is actually
-                * required, but in the interests of continuing from where
-                * we left off it is desirable.  The converse argument is
-                * that we should re-negotiate at 9600 baud again.
-                */
-               if (si->newspeed) {
-                       si->speed = si->newspeed;
-                       si->newspeed = 0;
-               }
-
-               sa1100_irda_startup(si);
-               __sa1100_irda_set_power(si, si->power);
-               enable_irq(dev->irq);
+       sa1100_irda_dma_start(&si->dma_tx, DMA_MEM_TO_DEV, sa1100_irda_sirtxdma_irq, dev);
 
-               /*
-                * This automatically wakes up the queue
-                */
-               netif_device_attach(dev);
-       }
+       /*
+        * The mean turn-around time is enforced by XBOF padding,
+        * so we don't have to do anything special here.
+        */
+       Ser2UTCR3 = UTCR3_TXE;
 
-       return 0;
+       return NETDEV_TX_OK;
 }
-#else
-#define sa1100_irda_suspend    NULL
-#define sa1100_irda_resume     NULL
-#endif
 
-/*
- * HP-SIR format interrupt service routines.
- */
-static void sa1100_irda_hpsir_irq(struct net_device *dev)
+static irqreturn_t sa1100_irda_sir_irq(struct net_device *dev, struct sa1100_irda *si)
 {
-       struct sa1100_irda *si = netdev_priv(dev);
        int status;
 
        status = Ser2UTSR0;
@@ -414,51 +333,96 @@ static void sa1100_irda_hpsir_irq(struct net_device *dev)
 
        }
 
-       if (status & UTSR0_TFS && si->tx_buff.len) {
-               /*
-                * Transmitter FIFO is not full
-                */
-               do {
-                       Ser2UTDR = *si->tx_buff.data++;
-                       si->tx_buff.len -= 1;
-               } while (Ser2UTSR1 & UTSR1_TNF && si->tx_buff.len);
+       return IRQ_HANDLED;
+}
 
-               if (si->tx_buff.len == 0) {
-                       dev->stats.tx_packets++;
-                       dev->stats.tx_bytes += si->tx_buff.data -
-                                             si->tx_buff.head;
+/*
+ * FIR format support.
+ */
+static void sa1100_irda_firtxdma_irq(void *id)
+{
+       struct net_device *dev = id;
+       struct sa1100_irda *si = netdev_priv(dev);
+       struct sk_buff *skb;
 
-                       /*
-                        * We need to ensure that the transmitter has
-                        * finished.
-                        */
-                       do
-                               rmb();
-                       while (Ser2UTSR1 & UTSR1_TBY);
+       /*
+        * Wait for the transmission to complete.  Unfortunately,
+        * the hardware doesn't give us an interrupt to indicate
+        * "end of frame".
+        */
+       do
+               rmb();
+       while (!(Ser2HSSR0 & HSSR0_TUR) || Ser2HSSR1 & HSSR1_TBY);
 
-                       /*
-                        * Ok, we've finished transmitting.  Now enable
-                        * the receiver.  Sometimes we get a receive IRQ
-                        * immediately after a transmit...
-                        */
-                       Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
-                       Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;
+       /*
+        * Clear the transmit underrun bit.
+        */
+       Ser2HSSR0 = HSSR0_TUR;
 
-                       if (si->newspeed) {
-                               sa1100_irda_set_speed(si, si->newspeed);
-                               si->newspeed = 0;
-                       }
+       /*
+        * Do we need to change speed?  Note that we're lazy
+        * here - we don't free the old dma_rx.skb.  We don't need
+        * to allocate a buffer either.
+        */
+       sa1100_irda_check_speed(si);
 
-                       /* I'm hungry! */
-                       netif_wake_queue(dev);
-               }
+       /*
+        * Start reception.  This disables the transmitter for
+        * us.  This will be using the existing RX buffer.
+        */
+       sa1100_irda_rx_dma_start(si);
+
+       /* Account and free the packet. */
+       skb = si->dma_tx.skb;
+       if (skb) {
+               dma_unmap_sg(si->dma_tx.dev, &si->dma_tx.sg, 1,
+                            DMA_TO_DEVICE);
+               dev->stats.tx_packets ++;
+               dev->stats.tx_bytes += skb->len;
+               dev_kfree_skb_irq(skb);
+               si->dma_tx.skb = NULL;
        }
+
+       /*
+        * Make sure that the TX queue is available for sending
+        * (for retries).  TX has priority over RX at all times.
+        */
+       netif_wake_queue(dev);
+}
+
+static int sa1100_irda_fir_tx_start(struct sk_buff *skb, struct net_device *dev,
+       struct sa1100_irda *si)
+{
+       int mtt = irda_get_mtt(skb);
+
+       si->dma_tx.skb = skb;
+       sg_set_buf(&si->dma_tx.sg, skb->data, skb->len);
+       if (dma_map_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, DMA_TO_DEVICE) == 0) {
+               si->dma_tx.skb = NULL;
+               netif_wake_queue(dev);
+               dev->stats.tx_dropped++;
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
+
+       sa1100_irda_dma_start(&si->dma_tx, DMA_MEM_TO_DEV, sa1100_irda_firtxdma_irq, dev);
+
+       /*
+        * If we have a mean turn-around time, impose the specified
+        * specified delay.  We could shorten this by timing from
+        * the point we received the packet.
+        */
+       if (mtt)
+               udelay(mtt);
+
+       Ser2HSCR0 = HSCR0_HSSP | HSCR0_TXE;
+
+       return NETDEV_TX_OK;
 }
 
 static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev)
 {
-       struct sk_buff *skb = si->rxskb;
-       dma_addr_t dma_addr;
+       struct sk_buff *skb = si->dma_rx.skb;
        unsigned int len, stat, data;
 
        if (!skb) {
@@ -469,11 +433,10 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
        /*
         * Get the current data position.
         */
-       dma_addr = sa1100_get_dma_pos(si->rxdma);
-       len = dma_addr - si->rxbuf_dma;
+       len = sa1100_irda_dma_xferred(&si->dma_rx);
        if (len > HPSIR_MAX_RXLEN)
                len = HPSIR_MAX_RXLEN;
-       dma_unmap_single(si->dev, si->rxbuf_dma, len, DMA_FROM_DEVICE);
+       dma_unmap_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, DMA_FROM_DEVICE);
 
        do {
                /*
@@ -501,7 +464,7 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
        } while (Ser2HSSR0 & HSSR0_EIF);
 
        if (stat & HSSR1_EOF) {
-               si->rxskb = NULL;
+               si->dma_rx.skb = NULL;
 
                skb_put(skb, len);
                skb->dev = dev;
@@ -518,28 +481,23 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
                netif_rx(skb);
        } else {
                /*
-                * Remap the buffer.
+                * Remap the buffer - it was previously mapped, and we
+                * hope that this succeeds.
                 */
-               si->rxbuf_dma = dma_map_single(si->dev, si->rxskb->data,
-                                               HPSIR_MAX_RXLEN,
-                                               DMA_FROM_DEVICE);
+               dma_map_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, DMA_FROM_DEVICE);
        }
 }
 
 /*
- * FIR format interrupt service routine.  We only have to
- * handle RX events; transmit events go via the TX DMA handler.
- *
- * No matter what, we disable RX, process, and the restart RX.
+ * We only have to handle RX events here; transmit events go via the TX
+ * DMA handler. We disable RX, process, and the restart RX.
  */
-static void sa1100_irda_fir_irq(struct net_device *dev)
+static irqreturn_t sa1100_irda_fir_irq(struct net_device *dev, struct sa1100_irda *si)
 {
-       struct sa1100_irda *si = netdev_priv(dev);
-
        /*
         * Stop RX DMA
         */
-       sa1100_stop_dma(si->rxdma);
+       dmaengine_pause(si->dma_rx.chan);
 
        /*
         * Framing error - we throw away the packet completely.
@@ -555,7 +513,7 @@ static void sa1100_irda_fir_irq(struct net_device *dev)
                /*
                 * Clear out the DMA...
                 */
-               Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
+               Ser2HSCR0 = HSCR0_HSSP;
 
                /*
                 * Clear selected status bits now, so we
@@ -577,74 +535,124 @@ static void sa1100_irda_fir_irq(struct net_device *dev)
         * No matter what happens, we must restart reception.
         */
        sa1100_irda_rx_dma_start(si);
+
+       return IRQ_HANDLED;
 }
 
-static irqreturn_t sa1100_irda_irq(int irq, void *dev_id)
+/*
+ * Set the IrDA communications speed.
+ */
+static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed)
 {
-       struct net_device *dev = dev_id;
-       if (IS_FIR(((struct sa1100_irda *)netdev_priv(dev))))
-               sa1100_irda_fir_irq(dev);
-       else
-               sa1100_irda_hpsir_irq(dev);
-       return IRQ_HANDLED;
+       unsigned long flags;
+       int brd, ret = -EINVAL;
+
+       switch (speed) {
+       case 9600:      case 19200:     case 38400:
+       case 57600:     case 115200:
+               brd = 3686400 / (16 * speed) - 1;
+
+               /* Stop the receive DMA, and configure transmit. */
+               if (IS_FIR(si)) {
+                       dmaengine_terminate_all(si->dma_rx.chan);
+                       dmaengine_slave_config(si->dma_tx.chan,
+                                               &sa1100_irda_sir_tx);
+               }
+
+               local_irq_save(flags);
+
+               Ser2UTCR3 = 0;
+               Ser2HSCR0 = HSCR0_UART;
+
+               Ser2UTCR1 = brd >> 8;
+               Ser2UTCR2 = brd;
+
+               /*
+                * Clear status register
+                */
+               Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
+               Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;
+
+               if (si->pdata->set_speed)
+                       si->pdata->set_speed(si->dev, speed);
+
+               si->speed = speed;
+               si->tx_start = sa1100_irda_sir_tx_start;
+               si->irq = sa1100_irda_sir_irq;
+
+               local_irq_restore(flags);
+               ret = 0;
+               break;
+
+       case 4000000:
+               if (!IS_FIR(si))
+                       dmaengine_slave_config(si->dma_tx.chan,
+                                               &sa1100_irda_fir_tx);
+
+               local_irq_save(flags);
+
+               Ser2HSSR0 = 0xff;
+               Ser2HSCR0 = HSCR0_HSSP;
+               Ser2UTCR3 = 0;
+
+               si->speed = speed;
+               si->tx_start = sa1100_irda_fir_tx_start;
+               si->irq = sa1100_irda_fir_irq;
+
+               if (si->pdata->set_speed)
+                       si->pdata->set_speed(si->dev, speed);
+
+               sa1100_irda_rx_alloc(si);
+               sa1100_irda_rx_dma_start(si);
+
+               local_irq_restore(flags);
+
+               break;
+
+       default:
+               break;
+       }
+
+       return ret;
 }
 
 /*
- * TX DMA completion handler.
+ * Control the power state of the IrDA transmitter.
+ * State:
+ *  0 - off
+ *  1 - short range, lowest power
+ *  2 - medium range, medium power
+ *  3 - maximum range, high power
+ *
+ * Currently, only assabet is known to support this.
  */
-static void sa1100_irda_txdma_irq(void *id)
+static int
+__sa1100_irda_set_power(struct sa1100_irda *si, unsigned int state)
 {
-       struct net_device *dev = id;
-       struct sa1100_irda *si = netdev_priv(dev);
-       struct sk_buff *skb = si->txskb;
-
-       si->txskb = NULL;
-
-       /*
-        * Wait for the transmission to complete.  Unfortunately,
-        * the hardware doesn't give us an interrupt to indicate
-        * "end of frame".
-        */
-       do
-               rmb();
-       while (!(Ser2HSSR0 & HSSR0_TUR) || Ser2HSSR1 & HSSR1_TBY);
+       int ret = 0;
+       if (si->pdata->set_power)
+               ret = si->pdata->set_power(si->dev, state);
+       return ret;
+}
 
-       /*
-        * Clear the transmit underrun bit.
-        */
-       Ser2HSSR0 = HSSR0_TUR;
+static inline int
+sa1100_set_power(struct sa1100_irda *si, unsigned int state)
+{
+       int ret;
 
-       /*
-        * Do we need to change speed?  Note that we're lazy
-        * here - we don't free the old rxskb.  We don't need
-        * to allocate a buffer either.
-        */
-       if (si->newspeed) {
-               sa1100_irda_set_speed(si, si->newspeed);
-               si->newspeed = 0;
-       }
+       ret = __sa1100_irda_set_power(si, state);
+       if (ret == 0)
+               si->power = state;
 
-       /*
-        * Start reception.  This disables the transmitter for
-        * us.  This will be using the existing RX buffer.
-        */
-       sa1100_irda_rx_dma_start(si);
+       return ret;
+}
 
-       /*
-        * Account and free the packet.
-        */
-       if (skb) {
-               dma_unmap_single(si->dev, si->txbuf_dma, skb->len, DMA_TO_DEVICE);
-               dev->stats.tx_packets ++;
-               dev->stats.tx_bytes += skb->len;
-               dev_kfree_skb_irq(skb);
-       }
+static irqreturn_t sa1100_irda_irq(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       struct sa1100_irda *si = netdev_priv(dev);
 
-       /*
-        * Make sure that the TX queue is available for sending
-        * (for retries).  TX has priority over RX at all times.
-        */
-       netif_wake_queue(dev);
+       return si->irq(dev, si);
 }
 
 static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -660,62 +668,19 @@ static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
        if (speed != si->speed && speed != -1)
                si->newspeed = speed;
 
-       /*
-        * If this is an empty frame, we can bypass a lot.
-        */
+       /* If this is an empty frame, we can bypass a lot. */
        if (skb->len == 0) {
-               if (si->newspeed) {
-                       si->newspeed = 0;
-                       sa1100_irda_set_speed(si, speed);
-               }
+               sa1100_irda_check_speed(si);
                dev_kfree_skb(skb);
                return NETDEV_TX_OK;
        }
 
-       if (!IS_FIR(si)) {
-               netif_stop_queue(dev);
-
-               si->tx_buff.data = si->tx_buff.head;
-               si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data,
-                                                 si->tx_buff.truesize);
-
-               /*
-                * Set the transmit interrupt enable.  This will fire
-                * off an interrupt immediately.  Note that we disable
-                * the receiver so we won't get spurious characteres
-                * received.
-                */
-               Ser2UTCR3 = UTCR3_TIE | UTCR3_TXE;
-
-               dev_kfree_skb(skb);
-       } else {
-               int mtt = irda_get_mtt(skb);
-
-               /*
-                * We must not be transmitting...
-                */
-               BUG_ON(si->txskb);
-
-               netif_stop_queue(dev);
-
-               si->txskb = skb;
-               si->txbuf_dma = dma_map_single(si->dev, skb->data,
-                                        skb->len, DMA_TO_DEVICE);
-
-               sa1100_start_dma(si->txdma, si->txbuf_dma, skb->len);
-
-               /*
-                * If we have a mean turn-around time, impose the specified
-                * specified delay.  We could shorten this by timing from
-                * the point we received the packet.
-                */
-               if (mtt)
-                       udelay(mtt);
+       netif_stop_queue(dev);
 
-               Ser2HSCR0 = si->hscr0 | HSCR0_HSSP | HSCR0_TXE;
-       }
+       /* We must not already have a skb to transmit... */
+       BUG_ON(si->dma_tx.skb);
 
-       return NETDEV_TX_OK;
+       return si->tx_start(skb, dev, si);
 }
 
 static int
@@ -762,6 +727,69 @@ sa1100_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
        return ret;
 }
 
+static int sa1100_irda_startup(struct sa1100_irda *si)
+{
+       int ret;
+
+       /*
+        * Ensure that the ports for this device are setup correctly.
+        */
+       if (si->pdata->startup) {
+               ret = si->pdata->startup(si->dev);
+               if (ret)
+                       return ret;
+       }
+
+       /*
+        * Configure PPC for IRDA - we want to drive TXD2 low.
+        * We also want to drive this pin low during sleep.
+        */
+       PPSR &= ~PPC_TXD2;
+       PSDR &= ~PPC_TXD2;
+       PPDR |= PPC_TXD2;
+
+       /*
+        * Enable HP-SIR modulation, and ensure that the port is disabled.
+        */
+       Ser2UTCR3 = 0;
+       Ser2HSCR0 = HSCR0_UART;
+       Ser2UTCR4 = si->utcr4;
+       Ser2UTCR0 = UTCR0_8BitData;
+       Ser2HSCR2 = HSCR2_TrDataH | HSCR2_RcDataL;
+
+       /*
+        * Clear status register
+        */
+       Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
+
+       ret = sa1100_irda_set_speed(si, si->speed = 9600);
+       if (ret) {
+               Ser2UTCR3 = 0;
+               Ser2HSCR0 = 0;
+
+               if (si->pdata->shutdown)
+                       si->pdata->shutdown(si->dev);
+       }
+
+       return ret;
+}
+
+static void sa1100_irda_shutdown(struct sa1100_irda *si)
+{
+       /*
+        * Stop all DMA activity.
+        */
+       dmaengine_terminate_all(si->dma_rx.chan);
+       dmaengine_terminate_all(si->dma_tx.chan);
+
+       /* Disable the port. */
+       Ser2UTCR3 = 0;
+       Ser2HSCR0 = 0;
+
+       if (si->pdata->shutdown)
+               si->pdata->shutdown(si->dev);
+}
+
 static int sa1100_irda_start(struct net_device *dev)
 {
        struct sa1100_irda *si = netdev_priv(dev);
@@ -769,25 +797,16 @@ static int sa1100_irda_start(struct net_device *dev)
 
        si->speed = 9600;
 
-       err = request_irq(dev->irq, sa1100_irda_irq, 0, dev->name, dev);
-       if (err)
-               goto err_irq;
-
-       err = sa1100_request_dma(DMA_Ser2HSSPRd, "IrDA receive",
-                                NULL, NULL, &si->rxdma);
+       err = sa1100_irda_dma_request(si->dev, &si->dma_rx, "Ser2ICPRc",
+                               &sa1100_irda_fir_rx);
        if (err)
                goto err_rx_dma;
 
-       err = sa1100_request_dma(DMA_Ser2HSSPWr, "IrDA transmit",
-                                sa1100_irda_txdma_irq, dev, &si->txdma);
+       err = sa1100_irda_dma_request(si->dev, &si->dma_tx, "Ser2ICPTr",
+                               &sa1100_irda_sir_tx);
        if (err)
                goto err_tx_dma;
 
-       /*
-        * The interrupt must remain disabled for now.
-        */
-       disable_irq(dev->irq);
-
        /*
         * Setup the serial port for the specified speed.
         */
@@ -803,44 +822,60 @@ static int sa1100_irda_start(struct net_device *dev)
        if (!si->irlap)
                goto err_irlap;
 
+       err = request_irq(dev->irq, sa1100_irda_irq, 0, dev->name, dev);
+       if (err)
+               goto err_irq;
+
        /*
         * Now enable the interrupt and start the queue
         */
        si->open = 1;
        sa1100_set_power(si, power_level); /* low power mode */
-       enable_irq(dev->irq);
+
        netif_start_queue(dev);
        return 0;
 
+err_irq:
+       irlap_close(si->irlap);
 err_irlap:
        si->open = 0;
        sa1100_irda_shutdown(si);
 err_startup:
-       sa1100_free_dma(si->txdma);
+       dma_release_channel(si->dma_tx.chan);
 err_tx_dma:
-       sa1100_free_dma(si->rxdma);
+       dma_release_channel(si->dma_rx.chan);
 err_rx_dma:
-       free_irq(dev->irq, dev);
-err_irq:
        return err;
 }
 
 static int sa1100_irda_stop(struct net_device *dev)
 {
        struct sa1100_irda *si = netdev_priv(dev);
+       struct sk_buff *skb;
 
-       disable_irq(dev->irq);
+       netif_stop_queue(dev);
+
+       si->open = 0;
        sa1100_irda_shutdown(si);
 
        /*
-        * If we have been doing DMA receive, make sure we
+        * If we have been doing any DMA activity, make sure we
         * tidy that up cleanly.
         */
-       if (si->rxskb) {
-               dma_unmap_single(si->dev, si->rxbuf_dma, HPSIR_MAX_RXLEN,
-                                DMA_FROM_DEVICE);
-               dev_kfree_skb(si->rxskb);
-               si->rxskb = NULL;
+       skb = si->dma_rx.skb;
+       if (skb) {
+               dma_unmap_sg(si->dma_rx.dev, &si->dma_rx.sg, 1,
+                            DMA_FROM_DEVICE);
+               dev_kfree_skb(skb);
+               si->dma_rx.skb = NULL;
+       }
+
+       skb = si->dma_tx.skb;
+       if (skb) {
+               dma_unmap_sg(si->dma_tx.dev, &si->dma_tx.sg, 1,
+                            DMA_TO_DEVICE);
+               dev_kfree_skb(skb);
+               si->dma_tx.skb = NULL;
        }
 
        /* Stop IrLAP */
@@ -849,14 +884,11 @@ static int sa1100_irda_stop(struct net_device *dev)
                si->irlap = NULL;
        }
 
-       netif_stop_queue(dev);
-       si->open = 0;
-
        /*
         * Free resources
         */
-       sa1100_free_dma(si->txdma);
-       sa1100_free_dma(si->rxdma);
+       dma_release_channel(si->dma_tx.chan);
+       dma_release_channel(si->dma_rx.chan);
        free_irq(dev->irq, dev);
 
        sa1100_set_power(si, 0);
@@ -888,11 +920,15 @@ static int sa1100_irda_probe(struct platform_device *pdev)
        struct net_device *dev;
        struct sa1100_irda *si;
        unsigned int baudrate_mask;
-       int err;
+       int err, irq;
 
        if (!pdev->dev.platform_data)
                return -EINVAL;
 
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0)
+               return irq < 0 ? irq : -ENXIO;
+
        err = request_mem_region(__PREG(Ser2UTCR0), 0x24, "IrDA") ? 0 : -EBUSY;
        if (err)
                goto err_mem_1;
@@ -907,22 +943,27 @@ static int sa1100_irda_probe(struct platform_device *pdev)
        if (!dev)
                goto err_mem_4;
 
+       SET_NETDEV_DEV(dev, &pdev->dev);
+
        si = netdev_priv(dev);
        si->dev = &pdev->dev;
        si->pdata = pdev->dev.platform_data;
 
+       sg_init_table(&si->dma_rx.sg, 1);
+       sg_init_table(&si->dma_tx.sg, 1);
+
        /*
         * Initialise the HP-SIR buffers
         */
        err = sa1100_irda_init_iobuf(&si->rx_buff, 14384);
        if (err)
                goto err_mem_5;
-       err = sa1100_irda_init_iobuf(&si->tx_buff, 4000);
+       err = sa1100_irda_init_iobuf(&si->tx_buff, IRDA_SIR_MAX_FRAME);
        if (err)
                goto err_mem_5;
 
        dev->netdev_ops = &sa1100_irda_netdev_ops;
-       dev->irq        = IRQ_Ser2ICP;
+       dev->irq        = irq;
 
        irda_init_max_qos_capabilies(&si->qos);
 
@@ -996,6 +1037,74 @@ static int sa1100_irda_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+/*
+ * Suspend the IrDA interface.
+ */
+static int sa1100_irda_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct sa1100_irda *si;
+
+       if (!dev)
+               return 0;
+
+       si = netdev_priv(dev);
+       if (si->open) {
+               /*
+                * Stop the transmit queue
+                */
+               netif_device_detach(dev);
+               disable_irq(dev->irq);
+               sa1100_irda_shutdown(si);
+               __sa1100_irda_set_power(si, 0);
+       }
+
+       return 0;
+}
+
+/*
+ * Resume the IrDA interface.
+ */
+static int sa1100_irda_resume(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct sa1100_irda *si;
+
+       if (!dev)
+               return 0;
+
+       si = netdev_priv(dev);
+       if (si->open) {
+               /*
+                * If we missed a speed change, initialise at the new speed
+                * directly.  It is debatable whether this is actually
+                * required, but in the interests of continuing from where
+                * we left off it is desirable.  The converse argument is
+                * that we should re-negotiate at 9600 baud again.
+                */
+               if (si->newspeed) {
+                       si->speed = si->newspeed;
+                       si->newspeed = 0;
+               }
+
+               sa1100_irda_startup(si);
+               __sa1100_irda_set_power(si, si->power);
+               enable_irq(dev->irq);
+
+               /*
+                * This automatically wakes up the queue
+                */
+               netif_device_attach(dev);
+       }
+
+       return 0;
+}
+#else
+#define sa1100_irda_suspend    NULL
+#define sa1100_irda_resume     NULL
+#endif
+
 static struct platform_driver sa1100ir_driver = {
        .probe          = sa1100_irda_probe,
        .remove         = sa1100_irda_remove,
index 749c2a1..1932029 100644 (file)
@@ -1269,10 +1269,8 @@ static int pcmcia_bus_add(struct pcmcia_socket *skt)
 
 static int pcmcia_bus_early_resume(struct pcmcia_socket *skt)
 {
-       if (!verify_cis_cache(skt)) {
-               pcmcia_put_socket(skt);
+       if (!verify_cis_cache(skt))
                return 0;
-       }
 
        dev_dbg(&skt->dev, "cis mismatch - different card\n");
 
index c95639b..4300a7f 100644 (file)
@@ -94,12 +94,7 @@ neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_sta
 
        ret = sa1111_pcmcia_configure_socket(skt, state);
        if (ret == 0) {
-               unsigned long flags;
-
-               local_irq_save(flags);
-               NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set;
-
-               local_irq_restore(flags);
+               neponset_ncr_frob(ncr_mask, ncr_set);
                sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
        }
 
index 27f2fe3..33568e1 100644 (file)
 
 #include "sa1111_generic.h"
 
+/*
+ * These are offsets from the above base.
+ */
+#define PCCR   0x0000
+#define PCSSR  0x0004
+#define PCSR   0x0008
+
+#define PCSR_S0_READY  (1<<0)
+#define PCSR_S1_READY  (1<<1)
+#define PCSR_S0_DETECT (1<<2)
+#define PCSR_S1_DETECT (1<<3)
+#define PCSR_S0_VS1    (1<<4)
+#define PCSR_S0_VS2    (1<<5)
+#define PCSR_S1_VS1    (1<<6)
+#define PCSR_S1_VS2    (1<<7)
+#define PCSR_S0_WP     (1<<8)
+#define PCSR_S1_WP     (1<<9)
+#define PCSR_S0_BVD1   (1<<10)
+#define PCSR_S0_BVD2   (1<<11)
+#define PCSR_S1_BVD1   (1<<12)
+#define PCSR_S1_BVD2   (1<<13)
+
+#define PCCR_S0_RST    (1<<0)
+#define PCCR_S1_RST    (1<<1)
+#define PCCR_S0_FLT    (1<<2)
+#define PCCR_S1_FLT    (1<<3)
+#define PCCR_S0_PWAITEN        (1<<4)
+#define PCCR_S1_PWAITEN        (1<<5)
+#define PCCR_S0_PSE    (1<<6)
+#define PCCR_S1_PSE    (1<<7)
+
+#define PCSSR_S0_SLEEP (1<<0)
+#define PCSSR_S1_SLEEP (1<<1)
+
 #define IDX_IRQ_S0_READY_NINT  (0)
 #define IDX_IRQ_S0_CD_VALID    (1)
 #define IDX_IRQ_S0_BVD1_STSCHG (2)
@@ -49,7 +83,7 @@ static void sa1111_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
 {
        struct sa1111_pcmcia_socket *s = to_skt(skt);
-       unsigned long status = sa1111_readl(s->dev->mapbase + SA1111_PCSR);
+       unsigned long status = sa1111_readl(s->dev->mapbase + PCSR);
 
        switch (skt->nr) {
        case 0:
@@ -105,10 +139,10 @@ int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s
                pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT;
 
        local_irq_save(flags);
-       val = sa1111_readl(s->dev->mapbase + SA1111_PCCR);
+       val = sa1111_readl(s->dev->mapbase + PCCR);
        val &= ~pccr_skt_mask;
        val |= pccr_set_mask & pccr_skt_mask;
-       sa1111_writel(val, s->dev->mapbase + SA1111_PCCR);
+       sa1111_writel(val, s->dev->mapbase + PCCR);
        local_irq_restore(flags);
 
        return 0;
@@ -163,12 +197,18 @@ int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops,
 static int pcmcia_probe(struct sa1111_dev *dev)
 {
        void __iomem *base;
+       int ret;
+
+       ret = sa1111_enable_device(dev);
+       if (ret)
+               return ret;
 
        dev_set_drvdata(&dev->dev, NULL);
 
-       if (!request_mem_region(dev->res.start, 512,
-                               SA1111_DRIVER_NAME(dev)))
+       if (!request_mem_region(dev->res.start, 512, SA1111_DRIVER_NAME(dev))) {
+               sa1111_disable_device(dev);
                return -EBUSY;
+       }
 
        base = dev->mapbase;
 
@@ -181,8 +221,8 @@ static int pcmcia_probe(struct sa1111_dev *dev)
        /*
         * Initialise the suspend state.
         */
-       sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + SA1111_PCSSR);
-       sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + SA1111_PCCR);
+       sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + PCSSR);
+       sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + PCCR);
 
 #ifdef CONFIG_SA1100_BADGE4
        pcmcia_badge4_init(&dev->dev);
@@ -212,6 +252,7 @@ static int __devexit pcmcia_remove(struct sa1111_dev *dev)
        }
 
        release_mem_region(dev->res.start, 512);
+       sa1111_disable_device(dev);
        return 0;
 }
 
index cb9a585..e8f1add 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/bitops.h>
 
 #include <mach/hardware.h>
-#include <asm/irq.h>
+#include <mach/irqs.h>
 
 #ifdef CONFIG_ARCH_PXA
 #include <mach/regs-rtc.h>
index a750aa7..2a28b4a 100644 (file)
@@ -305,7 +305,7 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
        info->base = base;
 
        info->info.scsi.io_base         = base + 0x2000;
-       info->info.scsi.irq             = NO_IRQ;
+       info->info.scsi.irq             = 0;
        info->info.scsi.dma             = NO_DMA;
        info->info.scsi.io_shift        = 5;
        info->info.ifcfg.clockrate      = 24; /* MHz */
index e85c40b..6206a66 100644 (file)
@@ -2176,7 +2176,7 @@ static void fas216_done(FAS216_Info *info, unsigned int result)
        fn = (void (*)(FAS216_Info *, struct scsi_cmnd *, unsigned int))SCpnt->host_scribble;
        fn(info, SCpnt, result);
 
-       if (info->scsi.irq != NO_IRQ) {
+       if (info->scsi.irq) {
                spin_lock_irqsave(&info->host_lock, flags);
                if (info->scsi.phase == PHASE_IDLE)
                        fas216_kick(info);
@@ -2276,7 +2276,7 @@ static int fas216_noqueue_command_lck(struct scsi_cmnd *SCpnt,
         * We should only be using this if we don't have an interrupt.
         * Provide some "incentive" to use the queueing code.
         */
-       BUG_ON(info->scsi.irq != NO_IRQ);
+       BUG_ON(info->scsi.irq);
 
        info->internal_done = 0;
        fas216_queue_command_lck(SCpnt, fas216_internal_done);
index 84b7127..df2e1b3 100644 (file)
 #ifndef FAS216_H
 #define FAS216_H
 
-#ifndef NO_IRQ
-#define NO_IRQ 255
-#endif
-
 #include <scsi/scsi_eh.h>
 
 #include "queue.h"
index 3f9a47e..8293658 100644 (file)
@@ -299,7 +299,7 @@ config SPI_S3C24XX_FIQ
 
 config SPI_S3C64XX
        tristate "Samsung S3C64XX series type SPI"
-       depends on (ARCH_S3C64XX || ARCH_S5P64X0)
+       depends on (ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS)
        select S3C64XX_DMA if ARCH_S3C64XX
        help
          SPI driver for Samsung S3C64XX and newer SoCs.
index 2a6429d..10182eb 100644 (file)
@@ -1720,7 +1720,7 @@ static int pch_spi_resume(struct pci_dev *pdev)
 
 #endif
 
-static struct pci_driver pch_spi_pcidev = {
+static struct pci_driver pch_spi_pcidev_driver = {
        .name = "pch_spi",
        .id_table = pch_spi_pcidev_id,
        .probe = pch_spi_probe,
@@ -1736,7 +1736,7 @@ static int __init pch_spi_init(void)
        if (ret)
                return ret;
 
-       ret = pci_register_driver(&pch_spi_pcidev);
+       ret = pci_register_driver(&pch_spi_pcidev_driver);
        if (ret)
                return ret;
 
@@ -1746,7 +1746,7 @@ module_init(pch_spi_init);
 
 static void __exit pch_spi_exit(void)
 {
-       pci_unregister_driver(&pch_spi_pcidev);
+       pci_unregister_driver(&pch_spi_pcidev_driver);
        platform_driver_unregister(&pch_spi_pd_driver);
 }
 module_exit(pch_spi_exit);
index 70e006b..5443e25 100644 (file)
@@ -1279,3 +1279,4 @@ static struct usb_driver go7007_usb_driver = {
 };
 
 module_usb_driver(go7007_usb_driver);
+MODULE_LICENSE("GPL v2");
index ac44af1..4426290 100644 (file)
@@ -1061,7 +1061,7 @@ attach_cmd:
        if (ret < 0)
                return iscsit_add_reject_from_cmd(
                                ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                               1, 1, buf, cmd);
+                               1, 0, buf, cmd);
        /*
         * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
         * the Immediate Bit is not set, and no Immediate
@@ -3164,6 +3164,30 @@ static int iscsit_send_task_mgt_rsp(
        return 0;
 }
 
+static bool iscsit_check_inaddr_any(struct iscsi_np *np)
+{
+       bool ret = false;
+
+       if (np->np_sockaddr.ss_family == AF_INET6) {
+               const struct sockaddr_in6 sin6 = {
+                       .sin6_addr = IN6ADDR_ANY_INIT };
+               struct sockaddr_in6 *sock_in6 =
+                        (struct sockaddr_in6 *)&np->np_sockaddr;
+
+               if (!memcmp(sock_in6->sin6_addr.s6_addr,
+                               sin6.sin6_addr.s6_addr, 16))
+                       ret = true;
+       } else {
+               struct sockaddr_in * sock_in =
+                       (struct sockaddr_in *)&np->np_sockaddr;
+
+               if (sock_in->sin_addr.s_addr == INADDR_ANY)
+                       ret = true;
+       }
+
+       return ret;
+}
+
 static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
 {
        char *payload = NULL;
@@ -3213,12 +3237,17 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
                        spin_lock(&tpg->tpg_np_lock);
                        list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
                                                tpg_np_list) {
+                               struct iscsi_np *np = tpg_np->tpg_np;
+                               bool inaddr_any = iscsit_check_inaddr_any(np);
+
                                len = sprintf(buf, "TargetAddress="
                                        "%s%s%s:%hu,%hu",
-                                       (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
-                                       "[" : "", tpg_np->tpg_np->np_ip,
-                                       (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
-                                       "]" : "", tpg_np->tpg_np->np_port,
+                                       (np->np_sockaddr.ss_family == AF_INET6) ?
+                                       "[" : "", (inaddr_any == false) ?
+                                               np->np_ip : conn->local_ip,
+                                       (np->np_sockaddr.ss_family == AF_INET6) ?
+                                       "]" : "", (inaddr_any == false) ?
+                                               np->np_port : conn->local_port,
                                        tpg->tpgt);
                                len += 1;
 
index 3468caa..6b35b37 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/configfs.h>
 #include <linux/export.h>
+#include <linux/inet.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
 #include <target/target_core_fabric_configfs.h>
index f1a02da..0ec3b77 100644 (file)
@@ -508,6 +508,7 @@ struct iscsi_conn {
        u16                     cid;
        /* Remote TCP Port */
        u16                     login_port;
+       u16                     local_port;
        int                     net_size;
        u32                     auth_id;
 #define CONNFLAG_SCTP_STRUCT_FILE                      0x01
@@ -527,6 +528,7 @@ struct iscsi_conn {
        unsigned char           bad_hdr[ISCSI_HDR_LEN];
 #define IPV6_ADDRESS_SPACE                             48
        unsigned char           login_ip[IPV6_ADDRESS_SPACE];
+       unsigned char           local_ip[IPV6_ADDRESS_SPACE];
        int                     conn_usage_count;
        int                     conn_waiting_on_uc;
        atomic_t                check_immediate_queue;
@@ -561,8 +563,8 @@ struct iscsi_conn {
        struct hash_desc        conn_tx_hash;
        /* Used for scheduling TX and RX connection kthreads */
        cpumask_var_t           conn_cpumask;
-       int                     conn_rx_reset_cpumask:1;
-       int                     conn_tx_reset_cpumask:1;
+       unsigned int            conn_rx_reset_cpumask:1;
+       unsigned int            conn_tx_reset_cpumask:1;
        /* list_head of struct iscsi_cmd for this connection */
        struct list_head        conn_cmd_list;
        struct list_head        immed_queue_list;
index 255c0d6..27901e3 100644 (file)
@@ -1238,7 +1238,7 @@ void iscsit_mod_dataout_timer(struct iscsi_cmd *cmd)
 {
        struct iscsi_conn *conn = cmd->conn;
        struct iscsi_session *sess = conn->sess;
-       struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
+       struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
 
        spin_lock_bh(&cmd->dataout_timeout_lock);
        if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) {
@@ -1261,7 +1261,7 @@ void iscsit_start_dataout_timer(
        struct iscsi_conn *conn)
 {
        struct iscsi_session *sess = conn->sess;
-       struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
+       struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
 
        if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING)
                return;
index 373b0cc..38cb7ce 100644 (file)
@@ -615,8 +615,8 @@ static int iscsi_post_login_handler(
                }
 
                pr_debug("iSCSI Login successful on CID: %hu from %s to"
-                       " %s:%hu,%hu\n", conn->cid, conn->login_ip, np->np_ip,
-                               np->np_port, tpg->tpgt);
+                       " %s:%hu,%hu\n", conn->cid, conn->login_ip,
+                       conn->local_ip, conn->local_port, tpg->tpgt);
 
                list_add_tail(&conn->conn_list, &sess->sess_conn_list);
                atomic_inc(&sess->nconn);
@@ -658,7 +658,8 @@ static int iscsi_post_login_handler(
        sess->session_state = TARG_SESS_STATE_LOGGED_IN;
 
        pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n",
-               conn->cid, conn->login_ip, np->np_ip, np->np_port, tpg->tpgt);
+               conn->cid, conn->login_ip, conn->local_ip, conn->local_port,
+               tpg->tpgt);
 
        spin_lock_bh(&sess->conn_lock);
        list_add_tail(&conn->conn_list, &sess->sess_conn_list);
@@ -841,6 +842,14 @@ int iscsi_target_setup_login_socket(
                goto fail;
        }
 
+       ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND,
+                       (char *)&opt, sizeof(opt));
+       if (ret < 0) {
+               pr_err("kernel_setsockopt() for IP_FREEBIND"
+                       " failed\n");
+               goto fail;
+       }
+
        ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len);
        if (ret < 0) {
                pr_err("kernel_bind() failed: %d\n", ret);
@@ -1020,6 +1029,18 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
                                &sock_in6.sin6_addr.in6_u);
                conn->login_port = ntohs(sock_in6.sin6_port);
+
+               if (conn->sock->ops->getname(conn->sock,
+                               (struct sockaddr *)&sock_in6, &err, 0) < 0) {
+                       pr_err("sock_ops->getname() failed.\n");
+                       iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+                                       ISCSI_LOGIN_STATUS_TARGET_ERROR);
+                       goto new_sess_out;
+               }
+               snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
+                               &sock_in6.sin6_addr.in6_u);
+               conn->local_port = ntohs(sock_in6.sin6_port);
+
        } else {
                memset(&sock_in, 0, sizeof(struct sockaddr_in));
 
@@ -1032,6 +1053,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                }
                sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr);
                conn->login_port = ntohs(sock_in.sin_port);
+
+               if (conn->sock->ops->getname(conn->sock,
+                               (struct sockaddr *)&sock_in, &err, 0) < 0) {
+                       pr_err("sock_ops->getname() failed.\n");
+                       iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+                                       ISCSI_LOGIN_STATUS_TARGET_ERROR);
+                       goto new_sess_out;
+               }
+               sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr);
+               conn->local_port = ntohs(sock_in.sin_port);
        }
 
        conn->network_transport = np->np_network_transport;
@@ -1039,7 +1070,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
        pr_debug("Received iSCSI login request from %s on %s Network"
                        " Portal %s:%hu\n", conn->login_ip,
                (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP",
-                       np->np_ip, np->np_port);
+                       conn->local_ip, conn->local_port);
 
        pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");
        conn->conn_state        = TARG_CONN_STATE_IN_LOGIN;
index a05ca1c..11287e1 100644 (file)
@@ -849,6 +849,17 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
        case ISCSI_OP_SCSI_TMFUNC:
                transport_generic_free_cmd(&cmd->se_cmd, 1);
                break;
+       case ISCSI_OP_REJECT:
+               /*
+                * Handle special case for REJECT when iscsi_add_reject*() has
+                * overwritten the original iscsi_opcode assignment, and the
+                * associated cmd->se_cmd needs to be released.
+                */
+               if (cmd->se_cmd.se_tfo != NULL) {
+                       transport_generic_free_cmd(&cmd->se_cmd, 1);
+                       break;
+               }
+               /* Fall-through */
        default:
                iscsit_release_cmd(cmd);
                break;
index 1b1edd1..01a2691 100644 (file)
@@ -78,7 +78,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
        list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
@@ -163,7 +163,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
        buf[2] = ((rd_len >> 8) & 0xff);
        buf[3] = (rd_len & 0xff);
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
@@ -194,7 +194,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
                cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                return -EINVAL;
        }
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        /*
         * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
@@ -351,7 +351,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
        }
 
 out:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
        return 0;
index 2f2235e..f3d71fa 100644 (file)
@@ -83,7 +83,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        if (dev == tpg->tpg_virt_lun0.lun_se_dev) {
                buf[0] = 0x3f; /* Not connected */
@@ -134,7 +134,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
        buf[4] = 31; /* Set additional length to 31 */
 
 out:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        return 0;
 }
 
@@ -698,6 +698,13 @@ int target_emulate_inquiry(struct se_task *task)
        int p, ret;
 
        if (!(cdb[1] & 0x1)) {
+               if (cdb[2]) {
+                       pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
+                              cdb[2]);
+                       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+                       return -EINVAL;
+               }
+
                ret = target_emulate_inquiry_std(cmd);
                goto out;
        }
@@ -716,7 +723,7 @@ int target_emulate_inquiry(struct se_task *task)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        buf[0] = dev->transport->get_device_type(dev);
 
@@ -729,11 +736,11 @@ int target_emulate_inquiry(struct se_task *task)
        }
 
        pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
-       cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
        ret = -EINVAL;
 
 out_unmap:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 out:
        if (!ret) {
                task->task_scsi_status = GOOD;
@@ -755,7 +762,7 @@ int target_emulate_readcapacity(struct se_task *task)
        else
                blocks = (u32)blocks_long;
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        buf[0] = (blocks >> 24) & 0xff;
        buf[1] = (blocks >> 16) & 0xff;
@@ -771,7 +778,7 @@ int target_emulate_readcapacity(struct se_task *task)
        if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
                put_unaligned_be32(0xFFFFFFFF, &buf[0]);
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
@@ -785,7 +792,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
        unsigned char *buf;
        unsigned long long blocks = dev->transport->get_blocks(dev);
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        buf[0] = (blocks >> 56) & 0xff;
        buf[1] = (blocks >> 48) & 0xff;
@@ -806,7 +813,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
        if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
                buf[14] = 0x80;
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
@@ -1019,9 +1026,9 @@ int target_emulate_modesense(struct se_task *task)
                        offset = cmd->data_length;
        }
 
-       rbuf = transport_kmap_first_data_page(cmd);
+       rbuf = transport_kmap_data_sg(cmd);
        memcpy(rbuf, buf, offset);
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
@@ -1043,7 +1050,7 @@ int target_emulate_request_sense(struct se_task *task)
                return -ENOSYS;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
                /*
@@ -1051,11 +1058,8 @@ int target_emulate_request_sense(struct se_task *task)
                 */
                buf[0] = 0x70;
                buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
-               /*
-                * Make sure request data length is enough for additional
-                * sense data.
-                */
-               if (cmd->data_length <= 18) {
+
+               if (cmd->data_length < 18) {
                        buf[7] = 0x00;
                        err = -EINVAL;
                        goto end;
@@ -1072,11 +1076,8 @@ int target_emulate_request_sense(struct se_task *task)
                 */
                buf[0] = 0x70;
                buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
-               /*
-                * Make sure request data length is enough for additional
-                * sense data.
-                */
-               if (cmd->data_length <= 18) {
+
+               if (cmd->data_length < 18) {
                        buf[7] = 0x00;
                        err = -EINVAL;
                        goto end;
@@ -1089,7 +1090,7 @@ int target_emulate_request_sense(struct se_task *task)
        }
 
 end:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
        return 0;
@@ -1123,7 +1124,7 @@ int target_emulate_unmap(struct se_task *task)
        dl = get_unaligned_be16(&cdb[0]);
        bd_dl = get_unaligned_be16(&cdb[2]);
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        ptr = &buf[offset];
        pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
@@ -1147,7 +1148,7 @@ int target_emulate_unmap(struct se_task *task)
        }
 
 err:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        if (!ret) {
                task->task_scsi_status = GOOD;
                transport_complete_task(task, 1);
index 0955bb8..6e043ee 100644 (file)
@@ -1704,13 +1704,15 @@ static ssize_t target_core_store_dev_alias(
                return -EINVAL;
        }
 
-       se_dev->su_dev_flags |= SDF_USING_ALIAS;
        read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN,
                        "%s", page);
-
+       if (!read_bytes)
+               return -EINVAL;
        if (se_dev->se_dev_alias[read_bytes - 1] == '\n')
                se_dev->se_dev_alias[read_bytes - 1] = '\0';
 
+       se_dev->su_dev_flags |= SDF_USING_ALIAS;
+
        pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n",
                config_item_name(&hba->hba_group.cg_item),
                config_item_name(&se_dev->se_dev_group.cg_item),
@@ -1753,13 +1755,15 @@ static ssize_t target_core_store_dev_udev_path(
                return -EINVAL;
        }
 
-       se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
        read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN,
                        "%s", page);
-
+       if (!read_bytes)
+               return -EINVAL;
        if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n')
                se_dev->se_dev_udev_path[read_bytes - 1] = '\0';
 
+       se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
+
        pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n",
                config_item_name(&hba->hba_group.cg_item),
                config_item_name(&se_dev->se_dev_group.cg_item),
index 0c5992f..edbcabb 100644 (file)
@@ -320,11 +320,12 @@ int core_free_device_list_for_node(
 void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd)
 {
        struct se_dev_entry *deve;
+       unsigned long flags;
 
-       spin_lock_irq(&se_nacl->device_list_lock);
+       spin_lock_irqsave(&se_nacl->device_list_lock, flags);
        deve = &se_nacl->device_list[se_cmd->orig_fe_lun];
        deve->deve_cmds--;
-       spin_unlock_irq(&se_nacl->device_list_lock);
+       spin_unlock_irqrestore(&se_nacl->device_list_lock, flags);
 }
 
 void core_update_device_list_access(
@@ -656,7 +657,7 @@ int target_report_luns(struct se_task *se_task)
        unsigned char *buf;
        u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
 
-       buf = transport_kmap_first_data_page(se_cmd);
+       buf = (unsigned char *) transport_kmap_data_sg(se_cmd);
 
        /*
         * If no struct se_session pointer is present, this struct se_cmd is
@@ -694,7 +695,7 @@ int target_report_luns(struct se_task *se_task)
         * See SPC3 r07, page 159.
         */
 done:
-       transport_kunmap_first_data_page(se_cmd);
+       transport_kunmap_data_sg(se_cmd);
        lun_count *= 8;
        buf[0] = ((lun_count >> 24) & 0xff);
        buf[1] = ((lun_count >> 16) & 0xff);
@@ -1294,24 +1295,26 @@ struct se_lun *core_dev_add_lun(
 {
        struct se_lun *lun_p;
        u32 lun_access = 0;
+       int rc;
 
        if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {
                pr_err("Unable to export struct se_device while dev_access_obj: %d\n",
                        atomic_read(&dev->dev_access_obj.obj_access_count));
-               return NULL;
+               return ERR_PTR(-EACCES);
        }
 
        lun_p = core_tpg_pre_addlun(tpg, lun);
-       if ((IS_ERR(lun_p)) || !lun_p)
-               return NULL;
+       if (IS_ERR(lun_p))
+               return lun_p;
 
        if (dev->dev_flags & DF_READ_ONLY)
                lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
        else
                lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
 
-       if (core_tpg_post_addlun(tpg, lun_p, lun_access, dev) < 0)
-               return NULL;
+       rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev);
+       if (rc < 0)
+               return ERR_PTR(rc);
 
        pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"
                " CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(),
@@ -1348,11 +1351,10 @@ int core_dev_del_lun(
        u32 unpacked_lun)
 {
        struct se_lun *lun;
-       int ret = 0;
 
-       lun = core_tpg_pre_dellun(tpg, unpacked_lun, &ret);
-       if (!lun)
-               return ret;
+       lun = core_tpg_pre_dellun(tpg, unpacked_lun);
+       if (IS_ERR(lun))
+               return PTR_ERR(lun);
 
        core_tpg_post_dellun(tpg, lun);
 
index 4f77cce..9a2ce11 100644 (file)
@@ -766,9 +766,9 @@ static int target_fabric_port_link(
 
        lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev,
                                lun->unpacked_lun);
-       if (IS_ERR(lun_p) || !lun_p) {
+       if (IS_ERR(lun_p)) {
                pr_err("core_dev_add_lun() failed\n");
-               ret = -EINVAL;
+               ret = PTR_ERR(lun_p);
                goto out;
        }
 
index cc8e6b5..8572eae 100644 (file)
@@ -129,7 +129,7 @@ static struct se_device *iblock_create_virtdevice(
        /*
         * These settings need to be made tunable..
         */
-       ib_dev->ibd_bio_set = bioset_create(32, 64);
+       ib_dev->ibd_bio_set = bioset_create(32, 0);
        if (!ib_dev->ibd_bio_set) {
                pr_err("IBLOCK: Unable to create bioset()\n");
                return ERR_PTR(-ENOMEM);
@@ -181,7 +181,7 @@ static struct se_device *iblock_create_virtdevice(
                 */
                dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1;
                dev->se_sub_dev->se_dev_attrib.unmap_granularity =
-                               q->limits.discard_granularity;
+                               q->limits.discard_granularity >> 9;
                dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment =
                                q->limits.discard_alignment;
 
@@ -488,6 +488,13 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
        struct iblock_req *ib_req = IBLOCK_REQ(task);
        struct bio *bio;
 
+       /*
+        * Only allocate as many vector entries as the bio code allows us to,
+        * we'll loop later on until we have handled the whole request.
+        */
+       if (sg_num > BIO_MAX_PAGES)
+               sg_num = BIO_MAX_PAGES;
+
        bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
        if (!bio) {
                pr_err("Unable to allocate memory for bio\n");
index 26f135e..4500136 100644 (file)
@@ -90,7 +90,7 @@ void  core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
 struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32);
 int    core_tpg_post_addlun(struct se_portal_group *, struct se_lun *,
                u32, void *);
-struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32, int *);
+struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun);
 int    core_tpg_post_dellun(struct se_portal_group *, struct se_lun *);
 
 /* target_core_transport.c */
index 429ad72..b7c7793 100644 (file)
@@ -478,6 +478,7 @@ static int core_scsi3_pr_seq_non_holder(
        case READ_MEDIA_SERIAL_NUMBER:
        case REPORT_LUNS:
        case REQUEST_SENSE:
+       case PERSISTENT_RESERVE_IN:
                ret = 0; /*/ Allowed CDBs */
                break;
        default:
@@ -1534,7 +1535,7 @@ static int core_scsi3_decode_spec_i_port(
        tidh_new->dest_local_nexus = 1;
        list_add_tail(&tidh_new->dest_list, &tid_dest_list);
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        /*
         * For a PERSISTENT RESERVE OUT specify initiator ports payload,
         * first extract TransportID Parameter Data Length, and make sure
@@ -1785,7 +1786,7 @@ static int core_scsi3_decode_spec_i_port(
 
        }
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        /*
         * Go ahead and create a registrations from tid_dest_list for the
@@ -1833,7 +1834,7 @@ static int core_scsi3_decode_spec_i_port(
 
        return 0;
 out:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        /*
         * For the failure case, release everything from tid_dest_list
         * including *dest_pr_reg and the configfs dependances..
@@ -3120,7 +3121,7 @@ static int core_scsi3_pro_preempt(
                        if (!calling_it_nexus)
                                core_scsi3_ua_allocate(pr_reg_nacl,
                                        pr_res_mapped_lun, 0x2A,
-                                       ASCQ_2AH_RESERVATIONS_PREEMPTED);
+                                       ASCQ_2AH_REGISTRATIONS_PREEMPTED);
                }
                spin_unlock(&pr_tmpl->registration_lock);
                /*
@@ -3233,7 +3234,7 @@ static int core_scsi3_pro_preempt(
                 *    additional sense code set to REGISTRATIONS PREEMPTED;
                 */
                core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A,
-                               ASCQ_2AH_RESERVATIONS_PREEMPTED);
+                               ASCQ_2AH_REGISTRATIONS_PREEMPTED);
        }
        spin_unlock(&pr_tmpl->registration_lock);
        /*
@@ -3410,14 +3411,14 @@ static int core_scsi3_emulate_pro_register_and_move(
         * will be moved to for the TransportID containing SCSI initiator WWN
         * information.
         */
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        rtpi = (buf[18] & 0xff) << 8;
        rtpi |= buf[19] & 0xff;
        tid_len = (buf[20] & 0xff) << 24;
        tid_len |= (buf[21] & 0xff) << 16;
        tid_len |= (buf[22] & 0xff) << 8;
        tid_len |= buf[23] & 0xff;
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        buf = NULL;
 
        if ((tid_len + 24) != cmd->data_length) {
@@ -3469,7 +3470,7 @@ static int core_scsi3_emulate_pro_register_and_move(
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        proto_ident = (buf[24] & 0x0f);
 #if 0
        pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
@@ -3503,7 +3504,7 @@ static int core_scsi3_emulate_pro_register_and_move(
                goto out;
        }
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        buf = NULL;
 
        pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s"
@@ -3768,13 +3769,13 @@ after_iport_check:
                                        " REGISTER_AND_MOVE\n");
        }
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        core_scsi3_put_pr_reg(dest_pr_reg);
        return 0;
 out:
        if (buf)
-               transport_kunmap_first_data_page(cmd);
+               transport_kunmap_data_sg(cmd);
        if (dest_se_deve)
                core_scsi3_lunacl_undepend_item(dest_se_deve);
        if (dest_node_acl)
@@ -3848,7 +3849,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
        scope = (cdb[2] & 0xf0);
        type = (cdb[2] & 0x0f);
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        /*
         * From PERSISTENT_RESERVE_OUT parameter list (payload)
         */
@@ -3866,7 +3867,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
                aptpl = (buf[17] & 0x01);
                unreg = (buf[17] & 0x02);
        }
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        buf = NULL;
 
        /*
@@ -3966,7 +3967,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
        buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
        buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
@@ -4000,7 +4001,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
        buf[6] = ((add_len >> 8) & 0xff);
        buf[7] = (add_len & 0xff);
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        return 0;
 }
@@ -4026,7 +4027,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
        buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
        buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
@@ -4085,7 +4086,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 
 err:
        spin_unlock(&se_dev->dev_reservation_lock);
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        return 0;
 }
@@ -4109,7 +4110,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        buf[0] = ((add_len << 8) & 0xff);
        buf[1] = (add_len & 0xff);
@@ -4141,7 +4142,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
        buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */
        buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        return 0;
 }
@@ -4171,7 +4172,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
        buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
@@ -4292,7 +4293,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
        buf[6] = ((add_len >> 8) & 0xff);
        buf[7] = (add_len & 0xff);
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        return 0;
 }
index d35467d..8d4def3 100644 (file)
@@ -693,7 +693,7 @@ static int pscsi_transport_complete(struct se_task *task)
 
                if (task->task_se_cmd->se_deve->lun_flags &
                                TRANSPORT_LUNFLAGS_READ_ONLY) {
-                       unsigned char *buf = transport_kmap_first_data_page(task->task_se_cmd);
+                       unsigned char *buf = transport_kmap_data_sg(task->task_se_cmd);
 
                        if (cdb[0] == MODE_SENSE_10) {
                                if (!(buf[3] & 0x80))
@@ -703,7 +703,7 @@ static int pscsi_transport_complete(struct se_task *task)
                                        buf[2] |= 0x80;
                        }
 
-                       transport_kunmap_first_data_page(task->task_se_cmd);
+                       transport_kunmap_data_sg(task->task_se_cmd);
                }
        }
 after_mode_sense:
index b766802..06336ec 100644 (file)
@@ -807,8 +807,7 @@ static void core_tpg_shutdown_lun(
 
 struct se_lun *core_tpg_pre_dellun(
        struct se_portal_group *tpg,
-       u32 unpacked_lun,
-       int *ret)
+       u32 unpacked_lun)
 {
        struct se_lun *lun;
 
index d3ddd13..58cea07 100644 (file)
@@ -1255,32 +1255,34 @@ static void core_setup_task_attr_emulation(struct se_device *dev)
 static void scsi_dump_inquiry(struct se_device *dev)
 {
        struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn;
+       char buf[17];
        int i, device_type;
        /*
         * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer
         */
-       pr_debug("  Vendor: ");
        for (i = 0; i < 8; i++)
                if (wwn->vendor[i] >= 0x20)
-                       pr_debug("%c", wwn->vendor[i]);
+                       buf[i] = wwn->vendor[i];
                else
-                       pr_debug(" ");
+                       buf[i] = ' ';
+       buf[i] = '\0';
+       pr_debug("  Vendor: %s\n", buf);
 
-       pr_debug("  Model: ");
        for (i = 0; i < 16; i++)
                if (wwn->model[i] >= 0x20)
-                       pr_debug("%c", wwn->model[i]);
+                       buf[i] = wwn->model[i];
                else
-                       pr_debug(" ");
+                       buf[i] = ' ';
+       buf[i] = '\0';
+       pr_debug("  Model: %s\n", buf);
 
-       pr_debug("  Revision: ");
        for (i = 0; i < 4; i++)
                if (wwn->revision[i] >= 0x20)
-                       pr_debug("%c", wwn->revision[i]);
+                       buf[i] = wwn->revision[i];
                else
-                       pr_debug(" ");
-
-       pr_debug("\n");
+                       buf[i] = ' ';
+       buf[i] = '\0';
+       pr_debug("  Revision: %s\n", buf);
 
        device_type = dev->transport->get_device_type(dev);
        pr_debug("  Type:   %s ", scsi_device_type(device_type));
@@ -1655,7 +1657,7 @@ EXPORT_SYMBOL(transport_handle_cdb_direct);
  * This may only be called from process context, and also currently
  * assumes internal allocation of fabric payload buffer by target-core.
  **/
-int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
+void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
                unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,
                u32 data_length, int task_attr, int data_dir, int flags)
 {
@@ -1688,15 +1690,21 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
        /*
         * Locate se_lun pointer and attach it to struct se_cmd
         */
-       if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0)
-               goto out_check_cond;
+       if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) {
+               transport_send_check_condition_and_sense(se_cmd,
+                               se_cmd->scsi_sense_reason, 0);
+               target_put_sess_cmd(se_sess, se_cmd);
+               return;
+       }
        /*
         * Sanitize CDBs via transport_generic_cmd_sequencer() and
         * allocate the necessary tasks to complete the received CDB+data
         */
        rc = transport_generic_allocate_tasks(se_cmd, cdb);
-       if (rc != 0)
-               goto out_check_cond;
+       if (rc != 0) {
+               transport_generic_request_failure(se_cmd);
+               return;
+       }
        /*
         * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend
         * for immediate execution of READs, otherwise wait for
@@ -1704,12 +1712,7 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
         * when fabric has filled the incoming buffer.
         */
        transport_handle_cdb_direct(se_cmd);
-       return 0;
-
-out_check_cond:
-       transport_send_check_condition_and_sense(se_cmd,
-                               se_cmd->scsi_sense_reason, 0);
-       return 0;
+       return;
 }
 EXPORT_SYMBOL(target_submit_cmd);
 
@@ -2694,7 +2697,7 @@ static int transport_generic_cmd_sequencer(
                        cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 
                        if (target_check_write_same_discard(&cdb[10], dev) < 0)
-                               goto out_invalid_cdb_field;
+                               goto out_unsupported_cdb;
                        if (!passthrough)
                                cmd->execute_task = target_emulate_write_same;
                        break;
@@ -2977,7 +2980,7 @@ static int transport_generic_cmd_sequencer(
                cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 
                if (target_check_write_same_discard(&cdb[1], dev) < 0)
-                       goto out_invalid_cdb_field;
+                       goto out_unsupported_cdb;
                if (!passthrough)
                        cmd->execute_task = target_emulate_write_same;
                break;
@@ -3000,7 +3003,7 @@ static int transport_generic_cmd_sequencer(
                 * of byte 1 bit 3 UNMAP instead of original reserved field
                 */
                if (target_check_write_same_discard(&cdb[1], dev) < 0)
-                       goto out_invalid_cdb_field;
+                       goto out_unsupported_cdb;
                if (!passthrough)
                        cmd->execute_task = target_emulate_write_same;
                break;
@@ -3082,11 +3085,6 @@ static int transport_generic_cmd_sequencer(
             (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
                goto out_unsupported_cdb;
 
-       /* Let's limit control cdbs to a page, for simplicity's sake. */
-       if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
-           size > PAGE_SIZE)
-               goto out_invalid_cdb_field;
-
        transport_set_supported_SAM_opcode(cmd);
        return ret;
 
@@ -3490,9 +3488,11 @@ int transport_generic_map_mem_to_cmd(
 }
 EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
 
-void *transport_kmap_first_data_page(struct se_cmd *cmd)
+void *transport_kmap_data_sg(struct se_cmd *cmd)
 {
        struct scatterlist *sg = cmd->t_data_sg;
+       struct page **pages;
+       int i;
 
        BUG_ON(!sg);
        /*
@@ -3500,15 +3500,41 @@ void *transport_kmap_first_data_page(struct se_cmd *cmd)
         * tcm_loop who may be using a contig buffer from the SCSI midlayer for
         * control CDBs passed as SGLs via transport_generic_map_mem_to_cmd()
         */
-       return kmap(sg_page(sg)) + sg->offset;
+       if (!cmd->t_data_nents)
+               return NULL;
+       else if (cmd->t_data_nents == 1)
+               return kmap(sg_page(sg)) + sg->offset;
+
+       /* >1 page. use vmap */
+       pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL);
+       if (!pages)
+               return NULL;
+
+       /* convert sg[] to pages[] */
+       for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) {
+               pages[i] = sg_page(sg);
+       }
+
+       cmd->t_data_vmap = vmap(pages, cmd->t_data_nents,  VM_MAP, PAGE_KERNEL);
+       kfree(pages);
+       if (!cmd->t_data_vmap)
+               return NULL;
+
+       return cmd->t_data_vmap + cmd->t_data_sg[0].offset;
 }
-EXPORT_SYMBOL(transport_kmap_first_data_page);
+EXPORT_SYMBOL(transport_kmap_data_sg);
 
-void transport_kunmap_first_data_page(struct se_cmd *cmd)
+void transport_kunmap_data_sg(struct se_cmd *cmd)
 {
-       kunmap(sg_page(cmd->t_data_sg));
+       if (!cmd->t_data_nents)
+               return;
+       else if (cmd->t_data_nents == 1)
+               kunmap(sg_page(cmd->t_data_sg));
+
+       vunmap(cmd->t_data_vmap);
+       cmd->t_data_vmap = NULL;
 }
-EXPORT_SYMBOL(transport_kunmap_first_data_page);
+EXPORT_SYMBOL(transport_kunmap_data_sg);
 
 static int
 transport_generic_get_mem(struct se_cmd *cmd)
@@ -3516,6 +3542,7 @@ transport_generic_get_mem(struct se_cmd *cmd)
        u32 length = cmd->data_length;
        unsigned int nents;
        struct page *page;
+       gfp_t zero_flag;
        int i = 0;
 
        nents = DIV_ROUND_UP(length, PAGE_SIZE);
@@ -3526,9 +3553,11 @@ transport_generic_get_mem(struct se_cmd *cmd)
        cmd->t_data_nents = nents;
        sg_init_table(cmd->t_data_sg, nents);
 
+       zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB ? 0 : __GFP_ZERO;
+
        while (length) {
                u32 page_len = min_t(u32, length, PAGE_SIZE);
-               page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               page = alloc_page(GFP_KERNEL | zero_flag);
                if (!page)
                        goto out;
 
@@ -3756,6 +3785,11 @@ transport_allocate_control_task(struct se_cmd *cmd)
        struct se_task *task;
        unsigned long flags;
 
+       /* Workaround for handling zero-length control CDBs */
+       if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
+           !cmd->data_length)
+               return 0;
+
        task = transport_generic_get_task(cmd, cmd->data_direction);
        if (!task)
                return -ENOMEM;
@@ -3827,6 +3861,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
        else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) {
                cmd->t_state = TRANSPORT_COMPLETE;
                atomic_set(&cmd->t_transport_active, 1);
+
+               if (cmd->t_task_cdb[0] == REQUEST_SENSE) {
+                       u8 ua_asc = 0, ua_ascq = 0;
+
+                       core_scsi3_ua_clear_for_request_sense(cmd,
+                                       &ua_asc, &ua_ascq);
+               }
+
                INIT_WORK(&cmd->work, target_complete_ok_work);
                queue_work(target_completion_wq, &cmd->work);
                return 0;
@@ -4448,8 +4490,8 @@ int transport_send_check_condition_and_sense(
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
                buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
-               /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               /* ILLEGAL REQUEST */
+               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN CDB */
                buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24;
                break;
@@ -4457,8 +4499,8 @@ int transport_send_check_condition_and_sense(
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
                buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
-               /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               /* ILLEGAL REQUEST */
+               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN PARAMETER LIST */
                buffer[offset+SPC_ASC_KEY_OFFSET] = 0x26;
                break;
index addc18f..9e7e26c 100644 (file)
@@ -540,7 +540,6 @@ static void ft_send_work(struct work_struct *work)
        int data_dir = 0;
        u32 data_len;
        int task_attr;
-       int ret;
 
        fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
        if (!fcp)
@@ -603,14 +602,10 @@ static void ft_send_work(struct work_struct *work)
         * Use a single se_cmd->cmd_kref as we expect to release se_cmd
         * directly from ft_check_stop_free callback in response path.
         */
-       ret = target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb,
+       target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb,
                                &cmd->ft_sense_buffer[0], cmd->lun, data_len,
                                task_attr, data_dir, 0);
-       pr_debug("r_ctl %x alloc target_submit_cmd %d\n", fh->fh_r_ctl, ret);
-       if (ret < 0) {
-               ft_dump_cmd(cmd, __func__);
-               return;
-       }
+       pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);
        return;
 
 err:
index ef7a21a..2ca5959 100644 (file)
@@ -38,6 +38,7 @@
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <asm/mach/serial_sa1100.h>
 
 /* We've been assigned a range on the "Low-density serial ports" major */
index 5e096f4..65447c5 100644 (file)
@@ -1463,7 +1463,6 @@ compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,
        if (!perm && op->op != KD_FONT_OP_GET)
                return -EPERM;
        op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
-       op->flags |= KD_FONT_FLAG_OLD;
        i = con_font_op(vc, op);
        if (i)
                return i;
index 4bde4f9..e1004fb 100644 (file)
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <mach/assabet.h>
-#include <mach/badge4.h>
 #include <asm/hardware/sa1111.h>
 
 #ifndef CONFIG_SA1111
 #error "This file is SA-1111 bus glue.  CONFIG_SA1111 must be defined."
 #endif
 
-extern int usb_disabled(void);
+#define USB_STATUS     0x0118
+#define USB_RESET      0x011c
+#define USB_IRQTEST    0x0120
+
+#define USB_RESET_FORCEIFRESET (1 << 0)
+#define USB_RESET_FORCEHCRESET (1 << 1)
+#define USB_RESET_CLKGENRESET  (1 << 2)
+#define USB_RESET_SIMSCALEDOWN (1 << 3)
+#define USB_RESET_USBINTTEST   (1 << 4)
+#define USB_RESET_SLEEPSTBYEN  (1 << 5)
+#define USB_RESET_PWRSENSELOW  (1 << 6)
+#define USB_RESET_PWRCTRLLOW   (1 << 7)
+
+#define USB_STATUS_IRQHCIRMTWKUP  (1 <<  7)
+#define USB_STATUS_IRQHCIBUFFACC  (1 <<  8)
+#define USB_STATUS_NIRQHCIM       (1 <<  9)
+#define USB_STATUS_NHCIMFCLR      (1 << 10)
+#define USB_STATUS_USBPWRSENSE    (1 << 11)
 
-/*-------------------------------------------------------------------------*/
+#if 0
+static void dump_hci_status(struct usb_hcd *hcd, const char *label)
+{
+       unsigned long status = sa1111_readl(hcd->regs + USB_STATUS);
+
+       dbg("%s USB_STATUS = { %s%s%s%s%s}", label,
+            ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""),
+            ((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""),
+            ((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "),
+            ((status & USB_STATUS_NHCIMFCLR) ? "" : "HCIMFCLR "),
+            ((status & USB_STATUS_USBPWRSENSE) ? "USBPWRSENSE " : ""));
+}
+#endif
 
-static void sa1111_start_hc(struct sa1111_dev *dev)
+static int ohci_sa1111_reset(struct usb_hcd *hcd)
 {
-       unsigned int usb_rst = 0;
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+       ohci_hcd_init(ohci);
+       return ohci_init(ohci);
+}
 
-       printk(KERN_DEBUG "%s: starting SA-1111 OHCI USB Controller\n",
-              __FILE__);
+static int __devinit ohci_sa1111_start(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       int ret;
 
-#ifdef CONFIG_SA1100_BADGE4
-       if (machine_is_badge4()) {
-               badge4_set_5V(BADGE4_5V_USB, 1);
+       ret = ohci_run(ohci);
+       if (ret < 0) {
+               ohci_err(ohci, "can't start\n");
+               ohci_stop(hcd);
        }
+       return ret;
+}
+
+static const struct hc_driver ohci_sa1111_hc_driver = {
+       .description =          hcd_name,
+       .product_desc =         "SA-1111 OHCI",
+       .hcd_priv_size =        sizeof(struct ohci_hcd),
+
+       /*
+        * generic hardware linkage
+        */
+       .irq =                  ohci_irq,
+       .flags =                HCD_USB11 | HCD_MEMORY,
+
+       /*
+        * basic lifecycle operations
+        */
+       .reset =                ohci_sa1111_reset,
+       .start =                ohci_sa1111_start,
+       .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue =          ohci_urb_enqueue,
+       .urb_dequeue =          ohci_urb_dequeue,
+       .endpoint_disable =     ohci_endpoint_disable,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number =     ohci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data =      ohci_hub_status_data,
+       .hub_control =          ohci_hub_control,
+#ifdef CONFIG_PM
+       .bus_suspend =          ohci_bus_suspend,
+       .bus_resume =           ohci_bus_resume,
 #endif
+       .start_port_reset =     ohci_start_port_reset,
+};
+
+static int sa1111_start_hc(struct sa1111_dev *dev)
+{
+       unsigned int usb_rst = 0;
+       int ret;
+
+       dev_dbg(&dev->dev, "starting SA-1111 OHCI USB Controller\n");
 
        if (machine_is_xp860() ||
            machine_has_neponset() ||
@@ -51,220 +137,121 @@ static void sa1111_start_hc(struct sa1111_dev *dev)
         * host controller in reset.
         */
        sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET,
-                     dev->mapbase + SA1111_USB_RESET);
+                     dev->mapbase + USB_RESET);
 
        /*
         * Now, carefully enable the USB clock, and take
         * the USB host controller out of reset.
         */
-       sa1111_enable_device(dev);
-       udelay(11);
-       sa1111_writel(usb_rst, dev->mapbase + SA1111_USB_RESET);
+       ret = sa1111_enable_device(dev);
+       if (ret == 0) {
+               udelay(11);
+               sa1111_writel(usb_rst, dev->mapbase + USB_RESET);
+       }
+
+       return ret;
 }
 
 static void sa1111_stop_hc(struct sa1111_dev *dev)
 {
        unsigned int usb_rst;
-       printk(KERN_DEBUG "%s: stopping SA-1111 OHCI USB Controller\n",
-              __FILE__);
+
+       dev_dbg(&dev->dev, "stopping SA-1111 OHCI USB Controller\n");
 
        /*
         * Put the USB host controller into reset.
         */
-       usb_rst = sa1111_readl(dev->mapbase + SA1111_USB_RESET);
+       usb_rst = sa1111_readl(dev->mapbase + USB_RESET);
        sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET,
-                     dev->mapbase + SA1111_USB_RESET);
+                     dev->mapbase + USB_RESET);
 
        /*
         * Stop the USB clock.
         */
        sa1111_disable_device(dev);
-
-#ifdef CONFIG_SA1100_BADGE4
-       if (machine_is_badge4()) {
-               /* Disable power to the USB bus */
-               badge4_set_5V(BADGE4_5V_USB, 0);
-       }
-#endif
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-#if 0
-static void dump_hci_status(struct usb_hcd *hcd, const char *label)
-{
-       unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
-
-       dbg ("%s USB_STATUS = { %s%s%s%s%s}", label,
-            ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""),
-            ((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""),
-            ((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "),
-            ((status & USB_STATUS_NHCIMFCLR) ? "" : "HCIMFCLR "),
-            ((status & USB_STATUS_USBPWRSENSE) ? "USBPWRSENSE " : ""));
 }
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
 
 /**
- * usb_hcd_sa1111_probe - initialize SA-1111-based HCDs
- * Context: !in_interrupt()
+ * ohci_hcd_sa1111_probe - initialize SA-1111-based HCDs
  *
  * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- * Store this function in the HCD's struct pci_driver as probe().
+ * then invokes the start() method for the HCD associated with it.
  */
-int usb_hcd_sa1111_probe (const struct hc_driver *driver,
-                         struct sa1111_dev *dev)
+static int ohci_hcd_sa1111_probe(struct sa1111_dev *dev)
 {
        struct usb_hcd *hcd;
-       int retval;
+       int ret;
 
-       hcd = usb_create_hcd (driver, &dev->dev, "sa1111");
+       if (usb_disabled())
+               return -ENODEV;
+
+       hcd = usb_create_hcd(&ohci_sa1111_hc_driver, &dev->dev, "sa1111");
        if (!hcd)
                return -ENOMEM;
+
        hcd->rsrc_start = dev->res.start;
        hcd->rsrc_len = resource_size(&dev->res);
 
        if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
                dbg("request_mem_region failed");
-               retval = -EBUSY;
+               ret = -EBUSY;
                goto err1;
        }
+
        hcd->regs = dev->mapbase;
 
-       sa1111_start_hc(dev);
-       ohci_hcd_init(hcd_to_ohci(hcd));
+       ret = sa1111_start_hc(dev);
+       if (ret)
+               goto err2;
 
-       retval = usb_add_hcd(hcd, dev->irq[1], 0);
-       if (retval == 0)
-               return retval;
+       ret = usb_add_hcd(hcd, dev->irq[1], 0);
+       if (ret == 0)
+               return ret;
 
        sa1111_stop_hc(dev);
+ err2:
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  err1:
        usb_put_hcd(hcd);
-       return retval;
+       return ret;
 }
 
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
 /**
- * usb_hcd_sa1111_remove - shutdown processing for SA-1111-based HCDs
+ * ohci_hcd_sa1111_remove - shutdown processing for SA-1111-based HCDs
  * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_sa1111_probe(), first invoking
- * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
  *
+ * Reverses the effect of ohci_hcd_sa1111_probe(), first invoking
+ * the HCD's stop() method.
  */
-void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev)
+static int ohci_hcd_sa1111_remove(struct sa1111_dev *dev)
 {
+       struct usb_hcd *hcd = sa1111_get_drvdata(dev);
+
        usb_remove_hcd(hcd);
        sa1111_stop_hc(dev);
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
-}
-
-/*-------------------------------------------------------------------------*/
 
-static int __devinit
-ohci_sa1111_start (struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
-       int             ret;
-
-       if ((ret = ohci_init(ohci)) < 0)
-               return ret;
-
-       if ((ret = ohci_run (ohci)) < 0) {
-               err ("can't start %s", hcd->self.bus_name);
-               ohci_stop (hcd);
-               return ret;
-       }
        return 0;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ohci_sa1111_hc_driver = {
-       .description =          hcd_name,
-       .product_desc =         "SA-1111 OHCI",
-       .hcd_priv_size =        sizeof(struct ohci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ohci_irq,
-       .flags =                HCD_USB11 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .start =                ohci_sa1111_start,
-       .stop =                 ohci_stop,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ohci_urb_enqueue,
-       .urb_dequeue =          ohci_urb_dequeue,
-       .endpoint_disable =     ohci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ohci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ohci_hub_status_data,
-       .hub_control =          ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend =          ohci_bus_suspend,
-       .bus_resume =           ohci_bus_resume,
-#endif
-       .start_port_reset =     ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_hcd_sa1111_drv_probe(struct sa1111_dev *dev)
-{
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, dev);
-       return ret;
-}
-
-static int ohci_hcd_sa1111_drv_remove(struct sa1111_dev *dev)
+static void ohci_hcd_sa1111_shutdown(struct sa1111_dev *dev)
 {
        struct usb_hcd *hcd = sa1111_get_drvdata(dev);
 
-       usb_hcd_sa1111_remove(hcd, dev);
-       return 0;
+       if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+               hcd->driver->shutdown(hcd);
+               sa1111_stop_hc(dev);
+       }
 }
 
 static struct sa1111_driver ohci_hcd_sa1111_driver = {
        .drv = {
                .name   = "sa1111-ohci",
+               .owner  = THIS_MODULE,
        },
        .devid          = SA1111_DEVID_USB,
-       .probe          = ohci_hcd_sa1111_drv_probe,
-       .remove         = ohci_hcd_sa1111_drv_remove,
+       .probe          = ohci_hcd_sa1111_probe,
+       .remove         = ohci_hcd_sa1111_remove,
+       .shutdown       = ohci_hcd_sa1111_shutdown,
 };
-
index 0d7b20d..e40c00f 100644 (file)
@@ -1108,7 +1108,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
         */
        lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
 
-       sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
+       sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);
        lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
        if (sinfo->atmel_lcdfb_power_control)
                sinfo->atmel_lcdfb_power_control(0);
index acf292b..6af3f16 100644 (file)
@@ -1432,7 +1432,7 @@ static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
        struct fsl_diu_data *data;
 
        data = dev_get_drvdata(&ofdev->dev);
-       disable_lcdc(data->fsl_diu_info[0]);
+       disable_lcdc(data->fsl_diu_info);
 
        return 0;
 }
@@ -1442,7 +1442,7 @@ static int fsl_diu_resume(struct platform_device *ofdev)
        struct fsl_diu_data *data;
 
        data = dev_get_drvdata(&ofdev->dev);
-       enable_lcdc(data->fsl_diu_info[0]);
+       enable_lcdc(data->fsl_diu_info);
 
        return 0;
 }
index c6afa33..02fd226 100644 (file)
@@ -529,7 +529,6 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
        if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
                ERR_MSG("Could not allocate cmap for intelfb_info.\n");
                goto err_out_cmap;
-               return -ENODEV;
        }
 
        dinfo = info->par;
index a5ec7f3..e1626a1 100644 (file)
@@ -401,7 +401,7 @@ void dispc_runtime_put(void)
 
        DSSDBG("dispc_runtime_put\n");
 
-       r = pm_runtime_put(&dispc.pdev->dev);
+       r = pm_runtime_put_sync(&dispc.pdev->dev);
        WARN_ON(r < 0);
 }
 
index d4d676c..52f36ec 100644 (file)
@@ -1079,7 +1079,7 @@ void dsi_runtime_put(struct platform_device *dsidev)
 
        DSSDBG("dsi_runtime_put\n");
 
-       r = pm_runtime_put(&dsi->pdev->dev);
+       r = pm_runtime_put_sync(&dsi->pdev->dev);
        WARN_ON(r < 0);
 }
 
index 1703345..77c2b5a 100644 (file)
@@ -720,7 +720,7 @@ void dss_runtime_put(void)
 
        DSSDBG("dss_runtime_put\n");
 
-       r = pm_runtime_put(&dss.pdev->dev);
+       r = pm_runtime_put_sync(&dss.pdev->dev);
        WARN_ON(r < 0);
 }
 
index b4c270e..d7aa3b0 100644 (file)
@@ -176,7 +176,7 @@ static void hdmi_runtime_put(void)
 
        DSSDBG("hdmi_runtime_put\n");
 
-       r = pm_runtime_put(&hdmi.pdev->dev);
+       r = pm_runtime_put_sync(&hdmi.pdev->dev);
        WARN_ON(r < 0);
 }
 
@@ -497,6 +497,7 @@ bool omapdss_hdmi_detect(void)
 
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 {
+       struct omap_dss_hdmi_data *priv = dssdev->data;
        int r = 0;
 
        DSSDBG("ENTER hdmi_display_enable\n");
@@ -509,6 +510,8 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
                goto err0;
        }
 
+       hdmi.ip_data.hpd_gpio = priv->hpd_gpio;
+
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
index 814bb95..55f3980 100644 (file)
@@ -140,7 +140,7 @@ static void rfbi_runtime_put(void)
 
        DSSDBG("rfbi_runtime_put\n");
 
-       r = pm_runtime_put(&rfbi.pdev->dev);
+       r = pm_runtime_put_sync(&rfbi.pdev->dev);
        WARN_ON(r < 0);
 }
 
index 7503f7f..50dadba 100644 (file)
@@ -126,6 +126,10 @@ struct hdmi_ip_data {
        const struct ti_hdmi_ip_ops *ops;
        struct hdmi_config cfg;
        struct hdmi_pll_info pll_data;
+
+       /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */
+       int hpd_gpio;
+       bool phy_tx_enabled;
 };
 int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
 void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
index 9af81f1..2d72334 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/seq_file.h>
+#include <linux/gpio.h>
 
 #include "ti_hdmi_4xxx_ip.h"
 #include "dss.h"
@@ -223,6 +224,49 @@ void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)
        hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
 }
 
+static int hdmi_check_hpd_state(struct hdmi_ip_data *ip_data)
+{
+       unsigned long flags;
+       bool hpd;
+       int r;
+       /* this should be in ti_hdmi_4xxx_ip private data */
+       static DEFINE_SPINLOCK(phy_tx_lock);
+
+       spin_lock_irqsave(&phy_tx_lock, flags);
+
+       hpd = gpio_get_value(ip_data->hpd_gpio);
+
+       if (hpd == ip_data->phy_tx_enabled) {
+               spin_unlock_irqrestore(&phy_tx_lock, flags);
+               return 0;
+       }
+
+       if (hpd)
+               r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
+       else
+               r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
+
+       if (r) {
+               DSSERR("Failed to %s PHY TX power\n",
+                               hpd ? "enable" : "disable");
+               goto err;
+       }
+
+       ip_data->phy_tx_enabled = hpd;
+err:
+       spin_unlock_irqrestore(&phy_tx_lock, flags);
+       return r;
+}
+
+static irqreturn_t hpd_irq_handler(int irq, void *data)
+{
+       struct hdmi_ip_data *ip_data = data;
+
+       hdmi_check_hpd_state(ip_data);
+
+       return IRQ_HANDLED;
+}
+
 int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
 {
        u16 r = 0;
@@ -232,10 +276,6 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
        if (r)
                return r;
 
-       r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
-       if (r)
-               return r;
-
        /*
         * Read address 0 in order to get the SCP reset done completed
         * Dummy access performed to make sure reset is done
@@ -257,12 +297,32 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
        /* Write to phy address 3 to change the polarity control */
        REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
 
+       r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio),
+                       NULL, hpd_irq_handler,
+                       IRQF_DISABLED | IRQF_TRIGGER_RISING |
+                       IRQF_TRIGGER_FALLING, "hpd", ip_data);
+       if (r) {
+               DSSERR("HPD IRQ request failed\n");
+               hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+               return r;
+       }
+
+       r = hdmi_check_hpd_state(ip_data);
+       if (r) {
+               free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
+               hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+               return r;
+       }
+
        return 0;
 }
 
 void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data)
 {
+       free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
+
        hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+       ip_data->phy_tx_enabled = false;
 }
 
 static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data)
index b3e9f90..5c3d0f9 100644 (file)
@@ -401,7 +401,7 @@ static void venc_runtime_put(void)
 
        DSSDBG("venc_runtime_put\n");
 
-       r = pm_runtime_put(&venc.pdev->dev);
+       r = pm_runtime_put_sync(&venc.pdev->dev);
        WARN_ON(r < 0);
 }
 
index 98d55d0..b632584 100644 (file)
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/cpufreq.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/mutex.h>
 #include <linux/io.h>
 
+#include <video/sa1100fb.h>
+
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <mach/assabet.h>
 #include <mach/shannon.h>
 
-/*
- * debugging?
- */
-#define DEBUG 0
 /*
  * Complain if VAR is out of range.
  */
 #define DEBUG_VAR 1
 
-#undef ASSABET_PAL_VIDEO
-
 #include "sa1100fb.h"
 
-extern void (*sa1100fb_backlight_power)(int on);
-extern void (*sa1100fb_lcd_power)(int on);
-
-static struct sa1100fb_rgb rgb_4 = {
+static const struct sa1100fb_rgb rgb_4 = {
        .red    = { .offset = 0,  .length = 4, },
        .green  = { .offset = 0,  .length = 4, },
        .blue   = { .offset = 0,  .length = 4, },
        .transp = { .offset = 0,  .length = 0, },
 };
 
-static struct sa1100fb_rgb rgb_8 = {
+static const struct sa1100fb_rgb rgb_8 = {
        .red    = { .offset = 0,  .length = 8, },
        .green  = { .offset = 0,  .length = 8, },
        .blue   = { .offset = 0,  .length = 8, },
        .transp = { .offset = 0,  .length = 0, },
 };
 
-static struct sa1100fb_rgb def_rgb_16 = {
+static const struct sa1100fb_rgb def_rgb_16 = {
        .red    = { .offset = 11, .length = 5, },
        .green  = { .offset = 5,  .length = 6, },
        .blue   = { .offset = 0,  .length = 5, },
        .transp = { .offset = 0,  .length = 0, },
 };
 
-#ifdef CONFIG_SA1100_ASSABET
-#ifndef ASSABET_PAL_VIDEO
-/*
- * The assabet uses a sharp LQ039Q2DS54 LCD module.  It is actually
- * takes an RGB666 signal, but we provide it with an RGB565 signal
- * instead (def_rgb_16).
- */
-static struct sa1100fb_mach_info lq039q2ds54_info __initdata = {
-       .pixclock       = 171521,       .bpp            = 16,
-       .xres           = 320,          .yres           = 240,
-
-       .hsync_len      = 5,            .vsync_len      = 1,
-       .left_margin    = 61,           .upper_margin   = 3,
-       .right_margin   = 9,            .lower_margin   = 0,
-
-       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-
-       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-};
-#else
-static struct sa1100fb_mach_info pal_info __initdata = {
-       .pixclock       = 67797,        .bpp            = 16,
-       .xres           = 640,          .yres           = 512,
-
-       .hsync_len      = 64,           .vsync_len      = 6,
-       .left_margin    = 125,          .upper_margin   = 70,
-       .right_margin   = 115,          .lower_margin   = 36,
-
-       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
-};
-#endif
-#endif
-
-#ifdef CONFIG_SA1100_H3600
-static struct sa1100fb_mach_info h3600_info __initdata = {
-       .pixclock       = 174757,       .bpp            = 16,
-       .xres           = 320,          .yres           = 240,
-
-       .hsync_len      = 3,            .vsync_len      = 3,
-       .left_margin    = 12,           .upper_margin   = 10,
-       .right_margin   = 17,           .lower_margin   = 1,
-
-       .cmap_static    = 1,
-
-       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-};
-
-static struct sa1100fb_rgb h3600_rgb_16 = {
-       .red    = { .offset = 12, .length = 4, },
-       .green  = { .offset = 7,  .length = 4, },
-       .blue   = { .offset = 1,  .length = 4, },
-       .transp = { .offset = 0,  .length = 0, },
-};
-#endif
-
-#ifdef CONFIG_SA1100_H3100
-static struct sa1100fb_mach_info h3100_info __initdata = {
-       .pixclock       = 406977,       .bpp            = 4,
-       .xres           = 320,          .yres           = 240,
-
-       .hsync_len      = 26,           .vsync_len      = 41,
-       .left_margin    = 4,            .upper_margin   = 0,
-       .right_margin   = 4,            .lower_margin   = 0,
-
-       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-       .cmap_greyscale = 1,
-       .cmap_inverse   = 1,
-
-       .lccr0          = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
-       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-};
-#endif
-
-#ifdef CONFIG_SA1100_COLLIE
-static struct sa1100fb_mach_info collie_info __initdata = {
-       .pixclock       = 171521,       .bpp            = 16,
-       .xres           = 320,          .yres           = 240,
-
-       .hsync_len      = 5,            .vsync_len      = 1,
-       .left_margin    = 11,           .upper_margin   = 2,
-       .right_margin   = 30,           .lower_margin   = 0,
-
-       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-
-       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-};
-#endif
-
-#ifdef LART_GREY_LCD
-static struct sa1100fb_mach_info lart_grey_info __initdata = {
-       .pixclock       = 150000,       .bpp            = 4,
-       .xres           = 320,          .yres           = 240,
-
-       .hsync_len      = 1,            .vsync_len      = 1,
-       .left_margin    = 4,            .upper_margin   = 0,
-       .right_margin   = 2,            .lower_margin   = 0,
-
-       .cmap_greyscale = 1,
-       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-
-       .lccr0          = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
-       .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
-};
-#endif
-#ifdef LART_COLOR_LCD
-static struct sa1100fb_mach_info lart_color_info __initdata = {
-       .pixclock       = 150000,       .bpp            = 16,
-       .xres           = 320,          .yres           = 240,
-
-       .hsync_len      = 2,            .vsync_len      = 3,
-       .left_margin    = 69,           .upper_margin   = 14,
-       .right_margin   = 8,            .lower_margin   = 4,
-
-       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-       .lccr3          = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
-};
-#endif
-#ifdef LART_VIDEO_OUT
-static struct sa1100fb_mach_info lart_video_info __initdata = {
-       .pixclock       = 39721,        .bpp            = 16,
-       .xres           = 640,          .yres           = 480,
-
-       .hsync_len      = 95,           .vsync_len      = 2,
-       .left_margin    = 40,           .upper_margin   = 32,
-       .right_margin   = 24,           .lower_margin   = 11,
-
-       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-
-       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-       .lccr3          = LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
-};
-#endif
-
-#ifdef LART_KIT01_LCD
-static struct sa1100fb_mach_info lart_kit01_info __initdata = {
-       .pixclock       = 63291,        .bpp            = 16,
-       .xres           = 640,          .yres           = 480,
-
-       .hsync_len      = 64,           .vsync_len      = 3,
-       .left_margin    = 122,          .upper_margin   = 45,
-       .right_margin   = 10,           .lower_margin   = 10,
-
-       .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-       .lccr3          = LCCR3_OutEnH | LCCR3_PixFlEdg
-};
-#endif
-
-#ifdef CONFIG_SA1100_SHANNON
-static struct sa1100fb_mach_info shannon_info __initdata = {
-       .pixclock       = 152500,       .bpp            = 8,
-       .xres           = 640,          .yres           = 480,
-
-       .hsync_len      = 4,            .vsync_len      = 3,
-       .left_margin    = 2,            .upper_margin   = 0,
-       .right_margin   = 1,            .lower_margin   = 0,
-
-       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-
-       .lccr0          = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
-       .lccr3          = LCCR3_ACBsDiv(512),
-};
-#endif
-
 
 
-static struct sa1100fb_mach_info * __init
-sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
-{
-       struct sa1100fb_mach_info *inf = NULL;
-
-       /*
-        *            R        G       B       T
-        * default  {11,5}, { 5,6}, { 0,5}, { 0,0}
-        * h3600    {12,4}, { 7,4}, { 1,4}, { 0,0}
-        * freebird { 8,4}, { 4,4}, { 0,4}, {12,4}
-        */
-#ifdef CONFIG_SA1100_ASSABET
-       if (machine_is_assabet()) {
-#ifndef ASSABET_PAL_VIDEO
-               inf = &lq039q2ds54_info;
-#else
-               inf = &pal_info;
-#endif
-       }
-#endif
-#ifdef CONFIG_SA1100_H3100
-       if (machine_is_h3100()) {
-               inf = &h3100_info;
-       }
-#endif
-#ifdef CONFIG_SA1100_H3600
-       if (machine_is_h3600()) {
-               inf = &h3600_info;
-               fbi->rgb[RGB_16] = &h3600_rgb_16;
-       }
-#endif
-#ifdef CONFIG_SA1100_COLLIE
-       if (machine_is_collie()) {
-               inf = &collie_info;
-       }
-#endif
-#ifdef CONFIG_SA1100_LART
-       if (machine_is_lart()) {
-#ifdef LART_GREY_LCD
-               inf = &lart_grey_info;
-#endif
-#ifdef LART_COLOR_LCD
-               inf = &lart_color_info;
-#endif
-#ifdef LART_VIDEO_OUT
-               inf = &lart_video_info;
-#endif
-#ifdef LART_KIT01_LCD
-               inf = &lart_kit01_info;
-#endif
-       }
-#endif
-#ifdef CONFIG_SA1100_SHANNON
-       if (machine_is_shannon()) {
-               inf = &shannon_info;
-       }
-#endif
-       return inf;
-}
-
 static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);
 static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state);
 
@@ -533,7 +299,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
         * is what you poke into the framebuffer to produce the
         * colour you requested.
         */
-       if (fbi->cmap_inverse) {
+       if (fbi->inf->cmap_inverse) {
                red   = 0xffff - red;
                green = 0xffff - green;
                blue  = 0xffff - blue;
@@ -607,14 +373,14 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
                var->xres = MIN_XRES;
        if (var->yres < MIN_YRES)
                var->yres = MIN_YRES;
-       if (var->xres > fbi->max_xres)
-               var->xres = fbi->max_xres;
-       if (var->yres > fbi->max_yres)
-               var->yres = fbi->max_yres;
+       if (var->xres > fbi->inf->xres)
+               var->xres = fbi->inf->xres;
+       if (var->yres > fbi->inf->yres)
+               var->yres = fbi->inf->yres;
        var->xres_virtual = max(var->xres_virtual, var->xres);
        var->yres_virtual = max(var->yres_virtual, var->yres);
 
-       DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
+       dev_dbg(fbi->dev, "var->bits_per_pixel=%d\n", var->bits_per_pixel);
        switch (var->bits_per_pixel) {
        case 4:
                rgbidx = RGB_4;
@@ -638,16 +404,16 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        var->blue   = fbi->rgb[rgbidx]->blue;
        var->transp = fbi->rgb[rgbidx]->transp;
 
-       DPRINTK("RGBT length = %d:%d:%d:%d\n",
+       dev_dbg(fbi->dev, "RGBT length = %d:%d:%d:%d\n",
                var->red.length, var->green.length, var->blue.length,
                var->transp.length);
 
-       DPRINTK("RGBT offset = %d:%d:%d:%d\n",
+       dev_dbg(fbi->dev, "RGBT offset = %d:%d:%d:%d\n",
                var->red.offset, var->green.offset, var->blue.offset,
                var->transp.offset);
 
 #ifdef CONFIG_CPU_FREQ
-       printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n",
+       dev_dbg(fbi->dev, "dma period = %d ps, clock = %d kHz\n",
                sa1100fb_display_dma_period(var),
                cpufreq_get(smp_processor_id()));
 #endif
@@ -655,22 +421,10 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        return 0;
 }
 
-static inline void sa1100fb_set_truecolor(u_int is_true_color)
+static void sa1100fb_set_visual(struct sa1100fb_info *fbi, u32 visual)
 {
-       if (machine_is_assabet()) {
-#if 1          // phase 4 or newer Assabet's
-               if (is_true_color)
-                       ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
-               else
-                       ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
-#else
-               // older Assabet's
-               if (is_true_color)
-                       ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
-               else
-                       ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
-#endif
-       }
+       if (fbi->inf->set_visual)
+               fbi->inf->set_visual(visual);
 }
 
 /*
@@ -683,11 +437,11 @@ static int sa1100fb_set_par(struct fb_info *info)
        struct fb_var_screeninfo *var = &info->var;
        unsigned long palette_mem_size;
 
-       DPRINTK("set_par\n");
+       dev_dbg(fbi->dev, "set_par\n");
 
        if (var->bits_per_pixel == 16)
                fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
-       else if (!fbi->cmap_static)
+       else if (!fbi->inf->cmap_static)
                fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
        else {
                /*
@@ -704,7 +458,7 @@ static int sa1100fb_set_par(struct fb_info *info)
 
        palette_mem_size = fbi->palette_size * sizeof(u16);
 
-       DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
+       dev_dbg(fbi->dev, "palette_mem_size = 0x%08lx\n", palette_mem_size);
 
        fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
        fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
@@ -712,7 +466,7 @@ static int sa1100fb_set_par(struct fb_info *info)
        /*
         * Set (any) board control register to handle new color depth
         */
-       sa1100fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
+       sa1100fb_set_visual(fbi, fbi->fb.fix.visual);
        sa1100fb_activate_var(var, fbi);
 
        return 0;
@@ -728,7 +482,7 @@ sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
        /*
         * Make sure the user isn't doing something stupid.
         */
-       if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->cmap_static))
+       if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->inf->cmap_static))
                return -EINVAL;
 
        return gen_set_cmap(cmap, kspc, con, info);
@@ -775,7 +529,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
        struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
        int i;
 
-       DPRINTK("sa1100fb_blank: blank=%d\n", blank);
+       dev_dbg(fbi->dev, "sa1100fb_blank: blank=%d\n", blank);
 
        switch (blank) {
        case FB_BLANK_POWERDOWN:
@@ -863,43 +617,43 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
        u_int half_screen_size, yres, pcd;
        u_long flags;
 
-       DPRINTK("Configuring SA1100 LCD\n");
+       dev_dbg(fbi->dev, "Configuring SA1100 LCD\n");
 
-       DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n",
+       dev_dbg(fbi->dev, "var: xres=%d hslen=%d lm=%d rm=%d\n",
                var->xres, var->hsync_len,
                var->left_margin, var->right_margin);
-       DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n",
+       dev_dbg(fbi->dev, "var: yres=%d vslen=%d um=%d bm=%d\n",
                var->yres, var->vsync_len,
                var->upper_margin, var->lower_margin);
 
 #if DEBUG_VAR
        if (var->xres < 16        || var->xres > 1024)
-               printk(KERN_ERR "%s: invalid xres %d\n",
+               dev_err(fbi->dev, "%s: invalid xres %d\n",
                        fbi->fb.fix.id, var->xres);
        if (var->hsync_len < 1    || var->hsync_len > 64)
-               printk(KERN_ERR "%s: invalid hsync_len %d\n",
+               dev_err(fbi->dev, "%s: invalid hsync_len %d\n",
                        fbi->fb.fix.id, var->hsync_len);
        if (var->left_margin < 1  || var->left_margin > 255)
-               printk(KERN_ERR "%s: invalid left_margin %d\n",
+               dev_err(fbi->dev, "%s: invalid left_margin %d\n",
                        fbi->fb.fix.id, var->left_margin);
        if (var->right_margin < 1 || var->right_margin > 255)
-               printk(KERN_ERR "%s: invalid right_margin %d\n",
+               dev_err(fbi->dev, "%s: invalid right_margin %d\n",
                        fbi->fb.fix.id, var->right_margin);
        if (var->yres < 1         || var->yres > 1024)
-               printk(KERN_ERR "%s: invalid yres %d\n",
+               dev_err(fbi->dev, "%s: invalid yres %d\n",
                        fbi->fb.fix.id, var->yres);
        if (var->vsync_len < 1    || var->vsync_len > 64)
-               printk(KERN_ERR "%s: invalid vsync_len %d\n",
+               dev_err(fbi->dev, "%s: invalid vsync_len %d\n",
                        fbi->fb.fix.id, var->vsync_len);
        if (var->upper_margin < 0 || var->upper_margin > 255)
-               printk(KERN_ERR "%s: invalid upper_margin %d\n",
+               dev_err(fbi->dev, "%s: invalid upper_margin %d\n",
                        fbi->fb.fix.id, var->upper_margin);
        if (var->lower_margin < 0 || var->lower_margin > 255)
-               printk(KERN_ERR "%s: invalid lower_margin %d\n",
+               dev_err(fbi->dev, "%s: invalid lower_margin %d\n",
                        fbi->fb.fix.id, var->lower_margin);
 #endif
 
-       new_regs.lccr0 = fbi->lccr0 |
+       new_regs.lccr0 = fbi->inf->lccr0 |
                LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
                LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
 
@@ -914,7 +668,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
         * the YRES parameter.
         */
        yres = var->yres;
-       if (fbi->lccr0 & LCCR0_Dual)
+       if (fbi->inf->lccr0 & LCCR0_Dual)
                yres /= 2;
 
        new_regs.lccr2 =
@@ -924,14 +678,14 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
                LCCR2_EndFrmDel(var->lower_margin);
 
        pcd = get_pcd(var->pixclock, cpufreq_get(0));
-       new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->lccr3 |
+       new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->inf->lccr3 |
                (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
                (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
 
-       DPRINTK("nlccr0 = 0x%08lx\n", new_regs.lccr0);
-       DPRINTK("nlccr1 = 0x%08lx\n", new_regs.lccr1);
-       DPRINTK("nlccr2 = 0x%08lx\n", new_regs.lccr2);
-       DPRINTK("nlccr3 = 0x%08lx\n", new_regs.lccr3);
+       dev_dbg(fbi->dev, "nlccr0 = 0x%08lx\n", new_regs.lccr0);
+       dev_dbg(fbi->dev, "nlccr1 = 0x%08lx\n", new_regs.lccr1);
+       dev_dbg(fbi->dev, "nlccr2 = 0x%08lx\n", new_regs.lccr2);
+       dev_dbg(fbi->dev, "nlccr3 = 0x%08lx\n", new_regs.lccr3);
 
        half_screen_size = var->bits_per_pixel;
        half_screen_size = half_screen_size * var->xres * var->yres / 16;
@@ -951,9 +705,12 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
         * Only update the registers if the controller is enabled
         * and something has changed.
         */
-       if ((LCCR0 != fbi->reg_lccr0)       || (LCCR1 != fbi->reg_lccr1) ||
-           (LCCR2 != fbi->reg_lccr2)       || (LCCR3 != fbi->reg_lccr3) ||
-           (DBAR1 != fbi->dbar1) || (DBAR2 != fbi->dbar2))
+       if (readl_relaxed(fbi->base + LCCR0) != fbi->reg_lccr0 ||
+           readl_relaxed(fbi->base + LCCR1) != fbi->reg_lccr1 ||
+           readl_relaxed(fbi->base + LCCR2) != fbi->reg_lccr2 ||
+           readl_relaxed(fbi->base + LCCR3) != fbi->reg_lccr3 ||
+           readl_relaxed(fbi->base + DBAR1) != fbi->dbar1 ||
+           readl_relaxed(fbi->base + DBAR2) != fbi->dbar2)
                sa1100fb_schedule_work(fbi, C_REENABLE);
 
        return 0;
@@ -967,18 +724,18 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
  */
 static inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on)
 {
-       DPRINTK("backlight o%s\n", on ? "n" : "ff");
+       dev_dbg(fbi->dev, "backlight o%s\n", on ? "n" : "ff");
 
-       if (sa1100fb_backlight_power)
-               sa1100fb_backlight_power(on);
+       if (fbi->inf->backlight_power)
+               fbi->inf->backlight_power(on);
 }
 
 static inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on)
 {
-       DPRINTK("LCD power o%s\n", on ? "n" : "ff");
+       dev_dbg(fbi->dev, "LCD power o%s\n", on ? "n" : "ff");
 
-       if (sa1100fb_lcd_power)
-               sa1100fb_lcd_power(on);
+       if (fbi->inf->lcd_power)
+               fbi->inf->lcd_power(on);
 }
 
 static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
@@ -1008,14 +765,25 @@ static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
        }
 
        if (mask) {
+               unsigned long flags;
+
+               /*
+                * SA-1100 requires the GPIO direction register set
+                * appropriately for the alternate function.  Hence
+                * we set it here via bitmask rather than excessive
+                * fiddling via the GPIO subsystem - and even then
+                * we'll still have to deal with GAFR.
+                */
+               local_irq_save(flags);
                GPDR |= mask;
                GAFR |= mask;
+               local_irq_restore(flags);
        }
 }
 
 static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
 {
-       DPRINTK("Enabling LCD controller\n");
+       dev_dbg(fbi->dev, "Enabling LCD controller\n");
 
        /*
         * Make sure the mode bits are present in the first palette entry
@@ -1024,43 +792,46 @@ static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
        fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var);
 
        /* Sequence from 11.7.10 */
-       LCCR3 = fbi->reg_lccr3;
-       LCCR2 = fbi->reg_lccr2;
-       LCCR1 = fbi->reg_lccr1;
-       LCCR0 = fbi->reg_lccr0 & ~LCCR0_LEN;
-       DBAR1 = fbi->dbar1;
-       DBAR2 = fbi->dbar2;
-       LCCR0 |= LCCR0_LEN;
-
-       if (machine_is_shannon()) {
-               GPDR |= SHANNON_GPIO_DISP_EN;
-               GPSR |= SHANNON_GPIO_DISP_EN;
-       }
-
-       DPRINTK("DBAR1 = 0x%08x\n", DBAR1);
-       DPRINTK("DBAR2 = 0x%08x\n", DBAR2);
-       DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
-       DPRINTK("LCCR1 = 0x%08x\n", LCCR1);
-       DPRINTK("LCCR2 = 0x%08x\n", LCCR2);
-       DPRINTK("LCCR3 = 0x%08x\n", LCCR3);
+       writel_relaxed(fbi->reg_lccr3, fbi->base + LCCR3);
+       writel_relaxed(fbi->reg_lccr2, fbi->base + LCCR2);
+       writel_relaxed(fbi->reg_lccr1, fbi->base + LCCR1);
+       writel_relaxed(fbi->reg_lccr0 & ~LCCR0_LEN, fbi->base + LCCR0);
+       writel_relaxed(fbi->dbar1, fbi->base + DBAR1);
+       writel_relaxed(fbi->dbar2, fbi->base + DBAR2);
+       writel_relaxed(fbi->reg_lccr0 | LCCR0_LEN, fbi->base + LCCR0);
+
+       if (machine_is_shannon())
+               gpio_set_value(SHANNON_GPIO_DISP_EN, 1);
+
+       dev_dbg(fbi->dev, "DBAR1: 0x%08x\n", readl_relaxed(fbi->base + DBAR1));
+       dev_dbg(fbi->dev, "DBAR2: 0x%08x\n", readl_relaxed(fbi->base + DBAR2));
+       dev_dbg(fbi->dev, "LCCR0: 0x%08x\n", readl_relaxed(fbi->base + LCCR0));
+       dev_dbg(fbi->dev, "LCCR1: 0x%08x\n", readl_relaxed(fbi->base + LCCR1));
+       dev_dbg(fbi->dev, "LCCR2: 0x%08x\n", readl_relaxed(fbi->base + LCCR2));
+       dev_dbg(fbi->dev, "LCCR3: 0x%08x\n", readl_relaxed(fbi->base + LCCR3));
 }
 
 static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
 {
        DECLARE_WAITQUEUE(wait, current);
+       u32 lccr0;
 
-       DPRINTK("Disabling LCD controller\n");
+       dev_dbg(fbi->dev, "Disabling LCD controller\n");
 
-       if (machine_is_shannon()) {
-               GPCR |= SHANNON_GPIO_DISP_EN;
-       }       
+       if (machine_is_shannon())
+               gpio_set_value(SHANNON_GPIO_DISP_EN, 0);
 
        set_current_state(TASK_UNINTERRUPTIBLE);
        add_wait_queue(&fbi->ctrlr_wait, &wait);
 
-       LCSR = 0xffffffff;      /* Clear LCD Status Register */
-       LCCR0 &= ~LCCR0_LDM;    /* Enable LCD Disable Done Interrupt */
-       LCCR0 &= ~LCCR0_LEN;    /* Disable LCD Controller */
+       /* Clear LCD Status Register */
+       writel_relaxed(~0, fbi->base + LCSR);
+
+       lccr0 = readl_relaxed(fbi->base + LCCR0);
+       lccr0 &= ~LCCR0_LDM;    /* Enable LCD Disable Done Interrupt */
+       writel_relaxed(lccr0, fbi->base + LCCR0);
+       lccr0 &= ~LCCR0_LEN;    /* Disable LCD Controller */
+       writel_relaxed(lccr0, fbi->base + LCCR0);
 
        schedule_timeout(20 * HZ / 1000);
        remove_wait_queue(&fbi->ctrlr_wait, &wait);
@@ -1072,14 +843,15 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
 static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id)
 {
        struct sa1100fb_info *fbi = dev_id;
-       unsigned int lcsr = LCSR;
+       unsigned int lcsr = readl_relaxed(fbi->base + LCSR);
 
        if (lcsr & LCSR_LDD) {
-               LCCR0 |= LCCR0_LDM;
+               u32 lccr0 = readl_relaxed(fbi->base + LCCR0) | LCCR0_LDM;
+               writel_relaxed(lccr0, fbi->base + LCCR0);
                wake_up(&fbi->ctrlr_wait);
        }
 
-       LCSR = lcsr;
+       writel_relaxed(lcsr, fbi->base + LCSR);
        return IRQ_HANDLED;
 }
 
@@ -1268,7 +1040,7 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
        switch (val) {
        case CPUFREQ_ADJUST:
        case CPUFREQ_INCOMPATIBLE:
-               printk(KERN_DEBUG "min dma period: %d ps, "
+               dev_dbg(fbi->dev, "min dma period: %d ps, "
                        "new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
                        policy->max);
                /* todo: fill in min/max values */
@@ -1318,7 +1090,7 @@ static int sa1100fb_resume(struct platform_device *dev)
  *      cache.  Once this area is remapped, all virtual memory
  *      access to the video memory should occur at the new region.
  */
-static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
+static int __devinit sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
 {
        /*
         * We reserve one page for the palette, plus the size
@@ -1344,7 +1116,7 @@ static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
 }
 
 /* Fake monspecs to fill in fbinfo structure */
-static struct fb_monspecs monspecs __initdata = {
+static struct fb_monspecs monspecs __devinitdata = {
        .hfmin  = 30000,
        .hfmax  = 70000,
        .vfmin  = 50,
@@ -1352,10 +1124,11 @@ static struct fb_monspecs monspecs __initdata = {
 };
 
 
-static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
+static struct sa1100fb_info * __devinit sa1100fb_init_fbinfo(struct device *dev)
 {
-       struct sa1100fb_mach_info *inf;
+       struct sa1100fb_mach_info *inf = dev->platform_data;
        struct sa1100fb_info *fbi;
+       unsigned i;
 
        fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
                      GFP_KERNEL);
@@ -1390,8 +1163,6 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
        fbi->rgb[RGB_8]         = &rgb_8;
        fbi->rgb[RGB_16]        = &def_rgb_16;
 
-       inf = sa1100fb_get_machine_info(fbi);
-
        /*
         * People just don't seem to get this.  We don't support
         * anything but correct entries now, so panic if someone
@@ -1402,13 +1173,10 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
                panic("sa1100fb error: invalid LCCR3 fields set or zero "
                        "pixclock.");
 
-       fbi->max_xres                   = inf->xres;
        fbi->fb.var.xres                = inf->xres;
        fbi->fb.var.xres_virtual        = inf->xres;
-       fbi->max_yres                   = inf->yres;
        fbi->fb.var.yres                = inf->yres;
        fbi->fb.var.yres_virtual        = inf->yres;
-       fbi->max_bpp                    = inf->bpp;
        fbi->fb.var.bits_per_pixel      = inf->bpp;
        fbi->fb.var.pixclock            = inf->pixclock;
        fbi->fb.var.hsync_len           = inf->hsync_len;
@@ -1419,14 +1187,16 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
        fbi->fb.var.lower_margin        = inf->lower_margin;
        fbi->fb.var.sync                = inf->sync;
        fbi->fb.var.grayscale           = inf->cmap_greyscale;
-       fbi->cmap_inverse               = inf->cmap_inverse;
-       fbi->cmap_static                = inf->cmap_static;
-       fbi->lccr0                      = inf->lccr0;
-       fbi->lccr3                      = inf->lccr3;
        fbi->state                      = C_STARTUP;
        fbi->task_state                 = (u_char)-1;
-       fbi->fb.fix.smem_len            = fbi->max_xres * fbi->max_yres *
-                                         fbi->max_bpp / 8;
+       fbi->fb.fix.smem_len            = inf->xres * inf->yres *
+                                         inf->bpp / 8;
+       fbi->inf                        = inf;
+
+       /* Copy the RGB bitfield overrides */
+       for (i = 0; i < NR_RGB; i++)
+               if (inf->rgb[i])
+                       fbi->rgb[i] = inf->rgb[i];
 
        init_waitqueue_head(&fbi->ctrlr_wait);
        INIT_WORK(&fbi->task, sa1100fb_task);
@@ -1438,13 +1208,20 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
 static int __devinit sa1100fb_probe(struct platform_device *pdev)
 {
        struct sa1100fb_info *fbi;
+       struct resource *res;
        int ret, irq;
 
+       if (!pdev->dev.platform_data) {
+               dev_err(&pdev->dev, "no platform LCD data\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
+       if (irq < 0 || !res)
                return -EINVAL;
 
-       if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
+       if (!request_mem_region(res->start, resource_size(res), "LCD"))
                return -EBUSY;
 
        fbi = sa1100fb_init_fbinfo(&pdev->dev);
@@ -1452,6 +1229,10 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
        if (!fbi)
                goto failed;
 
+       fbi->base = ioremap(res->start, resource_size(res));
+       if (!fbi->base)
+               goto failed;
+
        /* Initialize video memory */
        ret = sa1100fb_map_video_memory(fbi);
        if (ret)
@@ -1459,14 +1240,16 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
 
        ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi);
        if (ret) {
-               printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
+               dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
                goto failed;
        }
 
-#ifdef ASSABET_PAL_VIDEO
-       if (machine_is_assabet())
-               ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
-#endif
+       if (machine_is_shannon()) {
+               ret = gpio_request_one(SHANNON_GPIO_DISP_EN,
+                       GPIOF_OUT_INIT_LOW, "display enable");
+               if (ret)
+                       goto err_free_irq;
+       }
 
        /*
         * This makes sure that our colour bitfield
@@ -1478,7 +1261,7 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
 
        ret = register_framebuffer(&fbi->fb);
        if (ret < 0)
-               goto err_free_irq;
+               goto err_reg_fb;
 
 #ifdef CONFIG_CPU_FREQ
        fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
@@ -1490,12 +1273,17 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
        /* This driver cannot be unloaded at the moment */
        return 0;
 
+ err_reg_fb:
+       if (machine_is_shannon())
+               gpio_free(SHANNON_GPIO_DISP_EN);
  err_free_irq:
        free_irq(irq, fbi);
  failed:
+       if (fbi)
+               iounmap(fbi->base);
        platform_set_drvdata(pdev, NULL);
        kfree(fbi);
-       release_mem_region(0xb0100000, 0x10000);
+       release_mem_region(res->start, resource_size(res));
        return ret;
 }
 
@@ -1505,6 +1293,7 @@ static struct platform_driver sa1100fb_driver = {
        .resume         = sa1100fb_resume,
        .driver         = {
                .name   = "sa11x0-fb",
+               .owner  = THIS_MODULE,
        },
 };
 
index 1c3b459..fc5d429 100644 (file)
  * for more details.
  */
 
-/*
- * These are the bitfields for each
- * display depth that we support.
- */
-struct sa1100fb_rgb {
-       struct fb_bitfield      red;
-       struct fb_bitfield      green;
-       struct fb_bitfield      blue;
-       struct fb_bitfield      transp;
-};
-
-/*
- * This structure describes the machine which we are running on.
- */
-struct sa1100fb_mach_info {
-       u_long          pixclock;
-
-       u_short         xres;
-       u_short         yres;
-
-       u_char          bpp;
-       u_char          hsync_len;
-       u_char          left_margin;
-       u_char          right_margin;
-
-       u_char          vsync_len;
-       u_char          upper_margin;
-       u_char          lower_margin;
-       u_char          sync;
-
-       u_int           cmap_greyscale:1,
-                       cmap_inverse:1,
-                       cmap_static:1,
-                       unused:29;
-
-       u_int           lccr0;
-       u_int           lccr3;
-};
+#define LCCR0           0x0000          /* LCD Control Reg. 0 */
+#define LCSR            0x0004          /* LCD Status Reg. */
+#define DBAR1           0x0010          /* LCD DMA Base Address Reg. channel 1 */
+#define DCAR1           0x0014          /* LCD DMA Current Address Reg. channel 1 */
+#define DBAR2           0x0018          /* LCD DMA Base Address Reg.  channel 2 */
+#define DCAR2           0x001C          /* LCD DMA Current Address Reg. channel 2 */
+#define LCCR1           0x0020          /* LCD Control Reg. 1 */
+#define LCCR2           0x0024          /* LCD Control Reg. 2 */
+#define LCCR3           0x0028          /* LCD Control Reg. 3 */
 
 /* Shadows for LCD controller registers */
 struct sa1100fb_lcd_reg {
@@ -57,19 +28,11 @@ struct sa1100fb_lcd_reg {
        unsigned long lccr3;
 };
 
-#define RGB_4  (0)
-#define RGB_8  (1)
-#define RGB_16 (2)
-#define NR_RGB 3
-
 struct sa1100fb_info {
        struct fb_info          fb;
        struct device           *dev;
-       struct sa1100fb_rgb     *rgb[NR_RGB];
-
-       u_int                   max_bpp;
-       u_int                   max_xres;
-       u_int                   max_yres;
+       const struct sa1100fb_rgb *rgb[NR_RGB];
+       void __iomem            *base;
 
        /*
         * These are the addresses we mapped
@@ -88,12 +51,6 @@ struct sa1100fb_info {
        dma_addr_t              dbar1;
        dma_addr_t              dbar2;
 
-       u_int                   lccr0;
-       u_int                   lccr3;
-       u_int                   cmap_inverse:1,
-                               cmap_static:1,
-                               unused:30;
-
        u_int                   reg_lccr0;
        u_int                   reg_lccr1;
        u_int                   reg_lccr2;
@@ -109,6 +66,8 @@ struct sa1100fb_info {
        struct notifier_block   freq_transition;
        struct notifier_block   freq_policy;
 #endif
+
+       const struct sa1100fb_mach_info *inf;
 };
 
 #define TO_INF(ptr,member)     container_of(ptr,struct sa1100fb_info,member)
@@ -129,15 +88,6 @@ struct sa1100fb_info {
 
 #define SA1100_NAME    "SA1100"
 
-/*
- *  Debug macros 
- */
-#if DEBUG
-#  define DPRINTK(fmt, args...)        printk("%s: " fmt, __func__ , ## args)
-#else
-#  define DPRINTK(fmt, args...)
-#endif
-
 /*
  * Minimum X and Y resolutions
  */
index b60fc8b..620daad 100644 (file)
@@ -641,10 +641,10 @@ static int __cap_is_valid(struct ceph_cap *cap)
        unsigned long ttl;
        u32 gen;
 
-       spin_lock(&cap->session->s_cap_lock);
+       spin_lock(&cap->session->s_gen_ttl_lock);
        gen = cap->session->s_cap_gen;
        ttl = cap->session->s_cap_ttl;
-       spin_unlock(&cap->session->s_cap_lock);
+       spin_unlock(&cap->session->s_gen_ttl_lock);
 
        if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) {
                dout("__cap_is_valid %p cap %p issued %s "
index 618246b..3e8094b 100644 (file)
@@ -975,10 +975,10 @@ static int dentry_lease_is_valid(struct dentry *dentry)
        di = ceph_dentry(dentry);
        if (di->lease_session) {
                s = di->lease_session;
-               spin_lock(&s->s_cap_lock);
+               spin_lock(&s->s_gen_ttl_lock);
                gen = s->s_cap_gen;
                ttl = s->s_cap_ttl;
-               spin_unlock(&s->s_cap_lock);
+               spin_unlock(&s->s_gen_ttl_lock);
 
                if (di->lease_gen == gen &&
                    time_before(jiffies, dentry->d_time) &&
index 23ab6a3..866e8d7 100644 (file)
@@ -262,6 +262,7 @@ static int parse_reply_info(struct ceph_msg *msg,
        /* trace */
        ceph_decode_32_safe(&p, end, len, bad);
        if (len > 0) {
+               ceph_decode_need(&p, end, len, bad);
                err = parse_reply_info_trace(&p, p+len, info, features);
                if (err < 0)
                        goto out_bad;
@@ -270,6 +271,7 @@ static int parse_reply_info(struct ceph_msg *msg,
        /* extra */
        ceph_decode_32_safe(&p, end, len, bad);
        if (len > 0) {
+               ceph_decode_need(&p, end, len, bad);
                err = parse_reply_info_extra(&p, p+len, info, features);
                if (err < 0)
                        goto out_bad;
@@ -398,9 +400,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
        s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS;
        s->s_con.peer_name.num = cpu_to_le64(mds);
 
-       spin_lock_init(&s->s_cap_lock);
+       spin_lock_init(&s->s_gen_ttl_lock);
        s->s_cap_gen = 0;
        s->s_cap_ttl = 0;
+
+       spin_lock_init(&s->s_cap_lock);
        s->s_renew_requested = 0;
        s->s_renew_seq = 0;
        INIT_LIST_HEAD(&s->s_caps);
@@ -2326,10 +2330,10 @@ static void handle_session(struct ceph_mds_session *session,
        case CEPH_SESSION_STALE:
                pr_info("mds%d caps went stale, renewing\n",
                        session->s_mds);
-               spin_lock(&session->s_cap_lock);
+               spin_lock(&session->s_gen_ttl_lock);
                session->s_cap_gen++;
                session->s_cap_ttl = 0;
-               spin_unlock(&session->s_cap_lock);
+               spin_unlock(&session->s_gen_ttl_lock);
                send_renew_caps(mdsc, session);
                break;
 
index a50ca0e..8c7c04e 100644 (file)
@@ -117,10 +117,13 @@ struct ceph_mds_session {
        void             *s_authorizer_buf, *s_authorizer_reply_buf;
        size_t            s_authorizer_buf_len, s_authorizer_reply_buf_len;
 
-       /* protected by s_cap_lock */
-       spinlock_t        s_cap_lock;
+       /* protected by s_gen_ttl_lock */
+       spinlock_t        s_gen_ttl_lock;
        u32               s_cap_gen;  /* inc each time we get mds stale msg */
        unsigned long     s_cap_ttl;  /* when session caps expire */
+
+       /* protected by s_cap_lock */
+       spinlock_t        s_cap_lock;
        struct list_head  s_caps;     /* all caps issued by this session */
        int               s_nr_caps, s_trim_caps;
        int               s_num_cap_releases;
index 857214a..a76f697 100644 (file)
@@ -111,8 +111,10 @@ static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
 }
 
 static struct ceph_vxattr_cb ceph_file_vxattrs[] = {
+       { true, "ceph.file.layout", ceph_vxattrcb_layout},
+       /* The following extended attribute name is deprecated */
        { true, "ceph.layout", ceph_vxattrcb_layout},
-       { NULL, NULL }
+       { true, NULL, NULL }
 };
 
 static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode)
index 0554b00..2b243af 100644 (file)
@@ -139,7 +139,7 @@ config CIFS_DFS_UPCALL
            points. If unsure, say N.
 
 config CIFS_FSCACHE
-         bool "Provide CIFS client caching support (EXPERIMENTAL)"
+         bool "Provide CIFS client caching support"
          depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
          help
            Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
@@ -147,7 +147,7 @@ config CIFS_FSCACHE
            manager. If unsure, say N.
 
 config CIFS_ACL
-         bool "Provide CIFS ACL support (EXPERIMENTAL)"
+         bool "Provide CIFS ACL support"
          depends on CIFS_XATTR && KEYS
          help
            Allows to fetch CIFS/NTFS ACL from the server.  The DACL blob
index 986709a..9c28865 100644 (file)
@@ -2142,14 +2142,14 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
 
        len = delim - payload;
        if (len > MAX_USERNAME_SIZE || len <= 0) {
-               cFYI(1, "Bad value from username search (len=%ld)", len);
+               cFYI(1, "Bad value from username search (len=%zd)", len);
                rc = -EINVAL;
                goto out_key_put;
        }
 
        vol->username = kstrndup(payload, len, GFP_KERNEL);
        if (!vol->username) {
-               cFYI(1, "Unable to allocate %ld bytes for username", len);
+               cFYI(1, "Unable to allocate %zd bytes for username", len);
                rc = -ENOMEM;
                goto out_key_put;
        }
@@ -2157,7 +2157,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
 
        len = key->datalen - (len + 1);
        if (len > MAX_PASSWORD_SIZE || len <= 0) {
-               cFYI(1, "Bad len for password search (len=%ld)", len);
+               cFYI(1, "Bad len for password search (len=%zd)", len);
                rc = -EINVAL;
                kfree(vol->username);
                vol->username = NULL;
@@ -2167,7 +2167,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
        ++delim;
        vol->password = kstrndup(delim, len, GFP_KERNEL);
        if (!vol->password) {
-               cFYI(1, "Unable to allocate %ld bytes for password", len);
+               cFYI(1, "Unable to allocate %zd bytes for password", len);
                rc = -ENOMEM;
                kfree(vol->username);
                vol->username = NULL;
@@ -3857,10 +3857,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
        struct smb_vol *vol_info;
 
        vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
-       if (vol_info == NULL) {
-               tcon = ERR_PTR(-ENOMEM);
-               goto out;
-       }
+       if (vol_info == NULL)
+               return ERR_PTR(-ENOMEM);
 
        vol_info->local_nls = cifs_sb->local_nls;
        vol_info->linux_uid = fsuid;
index d85efad..551d0c2 100644 (file)
@@ -246,16 +246,15 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
        /* copy user */
        /* BB what about null user mounts - check that we do this BB */
        /* copy user */
-       if (ses->user_name != NULL)
+       if (ses->user_name != NULL) {
                strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE);
+               bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
+       }
        /* else null user mount */
-
-       bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
        *bcc_ptr = 0;
        bcc_ptr++; /* account for null termination */
 
        /* copy domain */
-
        if (ses->domainName != NULL) {
                strncpy(bcc_ptr, ses->domainName, 256);
                bcc_ptr += strnlen(ses->domainName, 256);
@@ -395,6 +394,10 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
        ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
        tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
        tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
+       if (tioffset > blob_len || tioffset + tilen > blob_len) {
+               cERROR(1, "tioffset + tilen too high %u + %u", tioffset, tilen);
+               return -EINVAL;
+       }
        if (tilen) {
                ses->auth_key.response = kmalloc(tilen, GFP_KERNEL);
                if (!ses->auth_key.response) {
index aeb135c..92ce83a 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1071,6 +1071,21 @@ void set_task_comm(struct task_struct *tsk, char *buf)
        perf_event_comm(tsk);
 }
 
+static void filename_to_taskname(char *tcomm, const char *fn, unsigned int len)
+{
+       int i, ch;
+
+       /* Copies the binary name from after last slash */
+       for (i = 0; (ch = *(fn++)) != '\0';) {
+               if (ch == '/')
+                       i = 0; /* overwrite what we wrote */
+               else
+                       if (i < len - 1)
+                               tcomm[i++] = ch;
+       }
+       tcomm[i] = '\0';
+}
+
 int flush_old_exec(struct linux_binprm * bprm)
 {
        int retval;
@@ -1085,6 +1100,7 @@ int flush_old_exec(struct linux_binprm * bprm)
 
        set_mm_exe_file(bprm->mm, bprm->file);
 
+       filename_to_taskname(bprm->tcomm, bprm->filename, sizeof(bprm->tcomm));
        /*
         * Release all of the old mmap stuff
         */
@@ -1116,10 +1132,6 @@ EXPORT_SYMBOL(would_dump);
 
 void setup_new_exec(struct linux_binprm * bprm)
 {
-       int i, ch;
-       const char *name;
-       char tcomm[sizeof(current->comm)];
-
        arch_pick_mmap_layout(current->mm);
 
        /* This is the point of no return */
@@ -1130,18 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm)
        else
                set_dumpable(current->mm, suid_dumpable);
 
-       name = bprm->filename;
-
-       /* Copies the binary name from after last slash */
-       for (i=0; (ch = *(name++)) != '\0';) {
-               if (ch == '/')
-                       i = 0; /* overwrite what we wrote */
-               else
-                       if (i < (sizeof(tcomm) - 1))
-                               tcomm[i++] = ch;
-       }
-       tcomm[i] = '\0';
-       set_task_comm(current, tcomm);
+       set_task_comm(current, bprm->tcomm);
 
        /* Set the new mm task size. We have to do that late because it may
         * depend on TIF_32BIT which is only updated in flush_thread() on
index a01cdad..eafb8d3 100644 (file)
@@ -335,7 +335,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
        void *ebuf;
        uint32_t ofs;
        size_t retlen;
-       int ret = -EIO;
+       int ret;
        unsigned long *wordebuf;
 
        ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen,
index e97404d..9c50144 100644 (file)
@@ -152,9 +152,6 @@ static struct page *logfs_mtd_find_first_sb(struct super_block *sb, u64 *ofs)
        filler_t *filler = logfs_mtd_readpage;
        struct mtd_info *mtd = super->s_mtd;
 
-       if (!mtd_can_have_bb(mtd))
-               return NULL;
-
        *ofs = 0;
        while (mtd_block_isbad(mtd, *ofs)) {
                *ofs += mtd->erasesize;
@@ -172,9 +169,6 @@ static struct page *logfs_mtd_find_last_sb(struct super_block *sb, u64 *ofs)
        filler_t *filler = logfs_mtd_readpage;
        struct mtd_info *mtd = super->s_mtd;
 
-       if (!mtd_can_have_bb(mtd))
-               return NULL;
-
        *ofs = mtd->size - mtd->erasesize;
        while (mtd_block_isbad(mtd, *ofs)) {
                *ofs -= mtd->erasesize;
index 8866496..2a70fce 100644 (file)
@@ -603,6 +603,8 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
        nsegs = argv[4].v_nmembs;
        if (argv[4].v_size != argsz[4])
                goto out;
+       if (nsegs > UINT_MAX / sizeof(__u64))
+               goto out;
 
        /*
         * argv[4] points to segment numbers this ioctl cleans.  We
index 9cde9ed..d4548dd 100644 (file)
@@ -198,26 +198,6 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
        return result;
 }
 
-static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
-{
-       struct mm_struct *mm;
-       int err;
-
-       err =  mutex_lock_killable(&task->signal->cred_guard_mutex);
-       if (err)
-               return ERR_PTR(err);
-
-       mm = get_task_mm(task);
-       if (mm && mm != current->mm &&
-                       !ptrace_may_access(task, mode)) {
-               mmput(mm);
-               mm = ERR_PTR(-EACCES);
-       }
-       mutex_unlock(&task->signal->cred_guard_mutex);
-
-       return mm;
-}
-
 struct mm_struct *mm_for_maps(struct task_struct *task)
 {
        return mm_access(task, PTRACE_MODE_READ);
@@ -711,6 +691,13 @@ static int mem_open(struct inode* inode, struct file* file)
        if (IS_ERR(mm))
                return PTR_ERR(mm);
 
+       if (mm) {
+               /* ensure this mm_struct can't be freed */
+               atomic_inc(&mm->mm_count);
+               /* but do not pin its memory */
+               mmput(mm);
+       }
+
        /* OK to pass negative loff_t, we can catch out-of-range */
        file->f_mode |= FMODE_UNSIGNED_OFFSET;
        file->private_data = mm;
@@ -718,57 +705,13 @@ static int mem_open(struct inode* inode, struct file* file)
        return 0;
 }
 
-static ssize_t mem_read(struct file * file, char __user * buf,
-                       size_t count, loff_t *ppos)
+static ssize_t mem_rw(struct file *file, char __user *buf,
+                       size_t count, loff_t *ppos, int write)
 {
-       int ret;
-       char *page;
-       unsigned long src = *ppos;
        struct mm_struct *mm = file->private_data;
-
-       if (!mm)
-               return 0;
-
-       page = (char *)__get_free_page(GFP_TEMPORARY);
-       if (!page)
-               return -ENOMEM;
-
-       ret = 0;
-       while (count > 0) {
-               int this_len, retval;
-
-               this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
-               retval = access_remote_vm(mm, src, page, this_len, 0);
-               if (!retval) {
-                       if (!ret)
-                               ret = -EIO;
-                       break;
-               }
-
-               if (copy_to_user(buf, page, retval)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               ret += retval;
-               src += retval;
-               buf += retval;
-               count -= retval;
-       }
-       *ppos = src;
-
-       free_page((unsigned long) page);
-       return ret;
-}
-
-static ssize_t mem_write(struct file * file, const char __user *buf,
-                        size_t count, loff_t *ppos)
-{
-       int copied;
+       unsigned long addr = *ppos;
+       ssize_t copied;
        char *page;
-       unsigned long dst = *ppos;
-       struct mm_struct *mm = file->private_data;
 
        if (!mm)
                return 0;
@@ -778,31 +721,54 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
                return -ENOMEM;
 
        copied = 0;
+       if (!atomic_inc_not_zero(&mm->mm_users))
+               goto free;
+
        while (count > 0) {
-               int this_len, retval;
+               int this_len = min_t(int, count, PAGE_SIZE);
 
-               this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
-               if (copy_from_user(page, buf, this_len)) {
+               if (write && copy_from_user(page, buf, this_len)) {
                        copied = -EFAULT;
                        break;
                }
-               retval = access_remote_vm(mm, dst, page, this_len, 1);
-               if (!retval) {
+
+               this_len = access_remote_vm(mm, addr, page, this_len, write);
+               if (!this_len) {
                        if (!copied)
                                copied = -EIO;
                        break;
                }
-               copied += retval;
-               buf += retval;
-               dst += retval;
-               count -= retval;                        
+
+               if (!write && copy_to_user(buf, page, this_len)) {
+                       copied = -EFAULT;
+                       break;
+               }
+
+               buf += this_len;
+               addr += this_len;
+               copied += this_len;
+               count -= this_len;
        }
-       *ppos = dst;
+       *ppos = addr;
 
+       mmput(mm);
+free:
        free_page((unsigned long) page);
        return copied;
 }
 
+static ssize_t mem_read(struct file *file, char __user *buf,
+                       size_t count, loff_t *ppos)
+{
+       return mem_rw(file, buf, count, ppos, 0);
+}
+
+static ssize_t mem_write(struct file *file, const char __user *buf,
+                        size_t count, loff_t *ppos)
+{
+       return mem_rw(file, (char __user*)buf, count, ppos, 1);
+}
+
 loff_t mem_lseek(struct file *file, loff_t offset, int orig)
 {
        switch (orig) {
@@ -822,8 +788,8 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig)
 static int mem_release(struct inode *inode, struct file *file)
 {
        struct mm_struct *mm = file->private_data;
-
-       mmput(mm);
+       if (mm)
+               mmdrop(mm);
        return 0;
 }
 
index 8de4b73..e58fcf8 100644 (file)
@@ -15,6 +15,16 @@ struct pci_dev;
 #ifdef CONFIG_PCI
 /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
 extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+/* Create a virtual mapping cookie for a port on a given PCI device.
+ * Do not call this directly, it exists to make it easier for architectures
+ * to override */
+#ifdef CONFIG_NO_GENERIC_PCI_IOPORT_MAP
+extern void __iomem *__pci_ioport_map(struct pci_dev *dev, unsigned long port,
+                                     unsigned int nr);
+#else
+#define __pci_ioport_map(dev, port, nr) ioport_map((port), (nr))
+#endif
+
 #else
 static inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
 {
index fd88a39..0092102 100644 (file)
@@ -18,7 +18,7 @@ struct pt_regs;
 #define BINPRM_BUF_SIZE 128
 
 #ifdef __KERNEL__
-#include <linux/list.h>
+#include <linux/sched.h>
 
 #define CORENAME_MAX_SIZE 128
 
@@ -58,6 +58,7 @@ struct linux_binprm {
        unsigned interp_flags;
        unsigned interp_data;
        unsigned long loader, exec;
+       char tcomm[TASK_COMM_LEN];
 };
 
 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
index b5ca4b2..004ff33 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _GPIO_KEYS_H
 #define _GPIO_KEYS_H
 
+struct device;
+
 struct gpio_keys_button {
        /* Configuration parameters */
        unsigned int code;      /* input event code (KEY_*, SW_*) */
old mode 100755 (executable)
new mode 100644 (file)
index f88c1cc..a9e8bd1 100644 (file)
@@ -10,8 +10,6 @@
 #ifndef MCP_H
 #define MCP_H
 
-#include <mach/dma.h>
-
 struct mcp_ops;
 
 struct mcp {
@@ -21,12 +19,7 @@ struct mcp {
        int             use_count;
        unsigned int    sclk_rate;
        unsigned int    rw_timeout;
-       dma_device_t    dma_audio_rd;
-       dma_device_t    dma_audio_wr;
-       dma_device_t    dma_telco_rd;
-       dma_device_t    dma_telco_wr;
        struct device   attached_device;
-       int             gpio_base;
 };
 
 struct mcp_ops {
@@ -47,15 +40,14 @@ void mcp_disable(struct mcp *);
 #define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
 
 struct mcp *mcp_host_alloc(struct device *, size_t);
-int mcp_host_register(struct mcp *);
-void mcp_host_unregister(struct mcp *);
+int mcp_host_add(struct mcp *, void *);
+void mcp_host_del(struct mcp *);
+void mcp_host_free(struct mcp *);
 
 struct mcp_driver {
        struct device_driver drv;
        int (*probe)(struct mcp *);
        void (*remove)(struct mcp *);
-       int (*suspend)(struct mcp *, pm_message_t);
-       int (*resume)(struct mcp *);
 };
 
 int mcp_driver_register(struct mcp_driver *);
index 2463c26..9bc9ac6 100644 (file)
@@ -187,8 +187,10 @@ struct twl6040 {
        int rev;
        u8 vibra_ctrl_cache[2];
 
+       /* PLL configuration */
        int pll;
        unsigned int sysclk;
+       unsigned int mclk;
 
        unsigned int irq;
        unsigned int irq_base;
index 4321f04..28af417 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <linux/mfd/mcp.h>
 #include <linux/gpio.h>
-#include <linux/semaphore.h>
+#include <linux/mutex.h>
 
 #define UCB_IO_DATA    0x00
 #define UCB_IO_DIR     0x01
 #define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
 #define UCB_MODE_AUD_OFF_CAN   (1 << 13)
 
+enum ucb1x00_reset {
+       UCB_RST_PROBE,
+       UCB_RST_RESUME,
+       UCB_RST_SUSPEND,
+       UCB_RST_REMOVE,
+       UCB_RST_PROBE_FAIL,
+};
 
-struct ucb1x00_irq {
-       void *devid;
-       void (*fn)(int, void *);
+struct ucb1x00_plat_data {
+       void                    (*reset)(enum ucb1x00_reset);
+       unsigned                irq_base;
+       int                     gpio_base;
+       unsigned                can_wakeup;
 };
 
 struct ucb1x00 {
-       spinlock_t              lock;
+       raw_spinlock_t          irq_lock;
        struct mcp              *mcp;
        unsigned int            irq;
-       struct semaphore        adc_sem;
+       int                     irq_base;
+       struct mutex            adc_mutex;
        spinlock_t              io_lock;
        u16                     id;
        u16                     io_dir;
@@ -122,7 +132,8 @@ struct ucb1x00 {
        u16                     adc_cr;
        u16                     irq_fal_enbl;
        u16                     irq_ris_enbl;
-       struct ucb1x00_irq      irq_handler[16];
+       u16                     irq_mask;
+       u16                     irq_wake;
        struct device           dev;
        struct list_head        node;
        struct list_head        devs;
@@ -144,7 +155,7 @@ struct ucb1x00_driver {
        struct list_head        devs;
        int     (*add)(struct ucb1x00_dev *dev);
        void    (*remove)(struct ucb1x00_dev *dev);
-       int     (*suspend)(struct ucb1x00_dev *dev, pm_message_t state);
+       int     (*suspend)(struct ucb1x00_dev *dev);
        int     (*resume)(struct ucb1x00_dev *dev);
 };
 
@@ -245,15 +256,4 @@ unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync);
 void ucb1x00_adc_enable(struct ucb1x00 *ucb);
 void ucb1x00_adc_disable(struct ucb1x00 *ucb);
 
-/*
- * Which edges of the IRQ do you want to control today?
- */
-#define UCB_RISING     (1 << 0)
-#define UCB_FALLING    (1 << 1)
-
-int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid);
-void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
-void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
-int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid);
-
 #endif
index 06f8899..d02cca6 100644 (file)
@@ -57,8 +57,6 @@ struct gcry_mpi {
 
 typedef struct gcry_mpi *MPI;
 
-#define MPI_NULL NULL
-
 #define mpi_get_nlimbs(a)     ((a)->nlimbs)
 #define mpi_is_neg(a)        ((a)->sign)
 
index 2212952..d43dc25 100644 (file)
@@ -427,9 +427,7 @@ static inline int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
 static inline int mtd_suspend(struct mtd_info *mtd)
 {
-       if (!mtd->suspend)
-               return -EOPNOTSUPP;
-       return mtd->suspend(mtd);
+       return mtd->suspend ? mtd->suspend(mtd) : 0;
 }
 
 static inline void mtd_resume(struct mtd_info *mtd)
@@ -489,7 +487,7 @@ static inline int mtd_has_oob(const struct mtd_info *mtd)
 
 static inline int mtd_can_have_bb(const struct mtd_info *mtd)
 {
-       return 0;
+       return !!mtd->block_isbad;
 }
 
        /* Kernel-side ioctl definitions */
index 0885561..abb2776 100644 (file)
@@ -587,6 +587,7 @@ struct hw_perf_event {
        u64                             sample_period;
        u64                             last_period;
        local64_t                       period_left;
+       u64                             interrupts_seq;
        u64                             interrupts;
 
        u64                             freq_time_stamp;
index e5bbcba..4d99e4e 100644 (file)
@@ -110,7 +110,19 @@ static inline void pm_qos_remove_request(struct pm_qos_request *req)
                        { return; }
 
 static inline int pm_qos_request(int pm_qos_class)
-                       { return 0; }
+{
+       switch (pm_qos_class) {
+       case PM_QOS_CPU_DMA_LATENCY:
+               return PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+       case PM_QOS_NETWORK_LATENCY:
+               return PM_QOS_NETWORK_LAT_DEFAULT_VALUE;
+       case PM_QOS_NETWORK_THROUGHPUT:
+               return PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE;
+       default:
+               return PM_QOS_DEFAULT_VALUE;
+       }
+}
+
 static inline int pm_qos_add_notifier(int pm_qos_class,
                                      struct notifier_block *notifier)
                        { return 0; }
diff --git a/include/linux/sa11x0-dma.h b/include/linux/sa11x0-dma.h
new file mode 100644 (file)
index 0000000..65839a5
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SA11x0 DMA Engine support
+ *
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LINUX_SA11X0_DMA_H
+#define __LINUX_SA11X0_DMA_H
+
+struct dma_chan;
+
+#if defined(CONFIG_DMA_SA11X0) || defined(CONFIG_DMA_SA11X0_MODULE)
+bool sa11x0_dma_filter_fn(struct dma_chan *, void *);
+#else
+static inline bool sa11x0_dma_filter_fn(struct dma_chan *c, void *d)
+{
+       return false;
+}
+#endif
+
+#endif
index 2234985..7d379a6 100644 (file)
@@ -2259,6 +2259,12 @@ static inline void mmdrop(struct mm_struct * mm)
 extern void mmput(struct mm_struct *);
 /* Grab a reference to a task's mm, if it is not already going away */
 extern struct mm_struct *get_task_mm(struct task_struct *task);
+/*
+ * Grab a reference to a task's mm, if it is not already going away
+ * and ptrace_may_access with the mode parameter passed to it
+ * succeeds.
+ */
+extern struct mm_struct *mm_access(struct task_struct *task, unsigned int mode);
 /* Remove the current tasks stale references to the old mm_struct */
 extern void mm_release(struct task_struct *, struct mm_struct *);
 /* Allocate a new mm structure and copy contents from tsk->mm */
index 8cd7fe5..425450b 100644 (file)
@@ -70,6 +70,7 @@ struct sh_dmae_pdata {
        unsigned int needs_tend_set:1;
        unsigned int no_dmars:1;
        unsigned int chclr_present:1;
+       unsigned int slave_only:1;
 };
 
 /* DMA register */
index 5ab255f..cea1b54 100644 (file)
@@ -417,6 +417,7 @@ static inline int __snd_bug_on(int cond)
 #define gameport_get_port_data(gp) (gp)->port_data
 #endif
 
+#ifdef CONFIG_PCI
 /* PCI quirk list helper */
 struct snd_pci_quirk {
        unsigned short subvendor;       /* PCI subvendor ID */
@@ -456,5 +457,6 @@ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list);
 const struct snd_pci_quirk *
 snd_pci_quirk_lookup_id(u16 vendor, u16 device,
                        const struct snd_pci_quirk *list);
+#endif
 
 #endif /* __SOUND_CORE_H */
index 4866499..e5e6ff9 100644 (file)
@@ -59,7 +59,7 @@ int   transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *);
 int    transport_set_vpd_ident(struct t10_vpd *, unsigned char *);
 
 /* core helpers also used by command snooping in pscsi */
-void   *transport_kmap_first_data_page(struct se_cmd *);
-void   transport_kunmap_first_data_page(struct se_cmd *);
+void   *transport_kmap_data_sg(struct se_cmd *);
+void   transport_kunmap_data_sg(struct se_cmd *);
 
 #endif /* TARGET_CORE_BACKEND_H */
index daf532b..dc4e345 100644 (file)
@@ -582,6 +582,7 @@ struct se_cmd {
 
        struct scatterlist      *t_data_sg;
        unsigned int            t_data_nents;
+       void                    *t_data_vmap;
        struct scatterlist      *t_bidi_data_sg;
        unsigned int            t_bidi_data_nents;
 
index 523e8bc..d36fad3 100644 (file)
@@ -114,7 +114,7 @@ void        transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
                struct se_session *, u32, int, int, unsigned char *);
 int    transport_lookup_cmd_lun(struct se_cmd *, u32);
 int    transport_generic_allocate_tasks(struct se_cmd *, unsigned char *);
-int    target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
+void   target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
                unsigned char *, u32, u32, int, int, int);
 int    transport_handle_cdb_direct(struct se_cmd *);
 int    transport_generic_handle_cdb_map(struct se_cmd *);
index 062b3b2..483f67c 100644 (file)
@@ -590,6 +590,11 @@ struct omap_dss_device {
        int (*get_backlight)(struct omap_dss_device *dssdev);
 };
 
+struct omap_dss_hdmi_data
+{
+       int hpd_gpio;
+};
+
 struct omap_dss_driver {
        struct device_driver driver;
 
diff --git a/include/video/sa1100fb.h b/include/video/sa1100fb.h
new file mode 100644 (file)
index 0000000..4ab4096
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * StrongARM 1100 LCD Controller Frame Buffer Device
+ *
+ * Copyright (C) 1999 Eric A. Thomas
+ *  Based on acornfb.c Copyright (C) Russell King.
+ *  
+ * 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 _VIDEO_SA1100FB_H
+#define _VIDEO_SA1100FB_H
+
+#include <linux/fb.h>
+#include <linux/types.h>
+
+#define RGB_4  0
+#define RGB_8  1
+#define RGB_16 2
+#define NR_RGB 3
+
+/* These are the bitfields for each display depth that we support. */
+struct sa1100fb_rgb {
+       struct fb_bitfield      red;
+       struct fb_bitfield      green;
+       struct fb_bitfield      blue;
+       struct fb_bitfield      transp;
+};
+
+/* This structure describes the machine which we are running on. */
+struct sa1100fb_mach_info {
+       u_long          pixclock;
+
+       u_short         xres;
+       u_short         yres;
+
+       u_char          bpp;
+       u_char          hsync_len;
+       u_char          left_margin;
+       u_char          right_margin;
+
+       u_char          vsync_len;
+       u_char          upper_margin;
+       u_char          lower_margin;
+       u_char          sync;
+
+       u_int           cmap_greyscale:1,
+                       cmap_inverse:1,
+                       cmap_static:1,
+                       unused:29;
+
+       u_int           lccr0;
+       u_int           lccr3;
+
+       /* Overrides for the default RGB maps */
+       const struct sa1100fb_rgb *rgb[NR_RGB];
+
+       void (*backlight_power)(int);
+       void (*lcd_power)(int);
+       void (*set_visual)(u32);
+};
+
+#endif
index 32b48c8..ba36013 100644 (file)
@@ -2300,6 +2300,9 @@ do {                                      \
        return div64_u64(dividend, divisor);
 }
 
+static DEFINE_PER_CPU(int, perf_throttled_count);
+static DEFINE_PER_CPU(u64, perf_throttled_seq);
+
 static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
 {
        struct hw_perf_event *hwc = &event->hw;
@@ -2325,16 +2328,29 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
        }
 }
 
-static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
+/*
+ * combine freq adjustment with unthrottling to avoid two passes over the
+ * events. At the same time, make sure, having freq events does not change
+ * the rate of unthrottling as that would introduce bias.
+ */
+static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
+                                          int needs_unthr)
 {
        struct perf_event *event;
        struct hw_perf_event *hwc;
-       u64 interrupts, now;
+       u64 now, period = TICK_NSEC;
        s64 delta;
 
-       if (!ctx->nr_freq)
+       /*
+        * only need to iterate over all events iff:
+        * - context have events in frequency mode (needs freq adjust)
+        * - there are events to unthrottle on this cpu
+        */
+       if (!(ctx->nr_freq || needs_unthr))
                return;
 
+       raw_spin_lock(&ctx->lock);
+
        list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
                if (event->state != PERF_EVENT_STATE_ACTIVE)
                        continue;
@@ -2344,13 +2360,8 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
 
                hwc = &event->hw;
 
-               interrupts = hwc->interrupts;
-               hwc->interrupts = 0;
-
-               /*
-                * unthrottle events on the tick
-                */
-               if (interrupts == MAX_INTERRUPTS) {
+               if (needs_unthr && hwc->interrupts == MAX_INTERRUPTS) {
+                       hwc->interrupts = 0;
                        perf_log_throttle(event, 1);
                        event->pmu->start(event, 0);
                }
@@ -2358,14 +2369,26 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
                if (!event->attr.freq || !event->attr.sample_freq)
                        continue;
 
-               event->pmu->read(event);
+               /*
+                * stop the event and update event->count
+                */
+               event->pmu->stop(event, PERF_EF_UPDATE);
+
                now = local64_read(&event->count);
                delta = now - hwc->freq_count_stamp;
                hwc->freq_count_stamp = now;
 
+               /*
+                * restart the event
+                * reload only if value has changed
+                */
                if (delta > 0)
                        perf_adjust_period(event, period, delta);
+
+               event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0);
        }
+
+       raw_spin_unlock(&ctx->lock);
 }
 
 /*
@@ -2388,16 +2411,13 @@ static void rotate_ctx(struct perf_event_context *ctx)
  */
 static void perf_rotate_context(struct perf_cpu_context *cpuctx)
 {
-       u64 interval = (u64)cpuctx->jiffies_interval * TICK_NSEC;
        struct perf_event_context *ctx = NULL;
-       int rotate = 0, remove = 1, freq = 0;
+       int rotate = 0, remove = 1;
 
        if (cpuctx->ctx.nr_events) {
                remove = 0;
                if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active)
                        rotate = 1;
-               if (cpuctx->ctx.nr_freq)
-                       freq = 1;
        }
 
        ctx = cpuctx->task_ctx;
@@ -2405,37 +2425,26 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx)
                remove = 0;
                if (ctx->nr_events != ctx->nr_active)
                        rotate = 1;
-               if (ctx->nr_freq)
-                       freq = 1;
        }
 
-       if (!rotate && !freq)
+       if (!rotate)
                goto done;
 
        perf_ctx_lock(cpuctx, cpuctx->task_ctx);
        perf_pmu_disable(cpuctx->ctx.pmu);
 
-       if (freq) {
-               perf_ctx_adjust_freq(&cpuctx->ctx, interval);
-               if (ctx)
-                       perf_ctx_adjust_freq(ctx, interval);
-       }
-
-       if (rotate) {
-               cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
-               if (ctx)
-                       ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE);
+       cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
+       if (ctx)
+               ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE);
 
-               rotate_ctx(&cpuctx->ctx);
-               if (ctx)
-                       rotate_ctx(ctx);
+       rotate_ctx(&cpuctx->ctx);
+       if (ctx)
+               rotate_ctx(ctx);
 
-               perf_event_sched_in(cpuctx, ctx, current);
-       }
+       perf_event_sched_in(cpuctx, ctx, current);
 
        perf_pmu_enable(cpuctx->ctx.pmu);
        perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
-
 done:
        if (remove)
                list_del_init(&cpuctx->rotation_list);
@@ -2445,10 +2454,22 @@ void perf_event_task_tick(void)
 {
        struct list_head *head = &__get_cpu_var(rotation_list);
        struct perf_cpu_context *cpuctx, *tmp;
+       struct perf_event_context *ctx;
+       int throttled;
 
        WARN_ON(!irqs_disabled());
 
+       __this_cpu_inc(perf_throttled_seq);
+       throttled = __this_cpu_xchg(perf_throttled_count, 0);
+
        list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) {
+               ctx = &cpuctx->ctx;
+               perf_adjust_freq_unthr_context(ctx, throttled);
+
+               ctx = cpuctx->task_ctx;
+               if (ctx)
+                       perf_adjust_freq_unthr_context(ctx, throttled);
+
                if (cpuctx->jiffies_interval == 1 ||
                                !(jiffies % cpuctx->jiffies_interval))
                        perf_rotate_context(cpuctx);
@@ -4509,6 +4530,7 @@ static int __perf_event_overflow(struct perf_event *event,
 {
        int events = atomic_read(&event->event_limit);
        struct hw_perf_event *hwc = &event->hw;
+       u64 seq;
        int ret = 0;
 
        /*
@@ -4518,14 +4540,20 @@ static int __perf_event_overflow(struct perf_event *event,
        if (unlikely(!is_sampling_event(event)))
                return 0;
 
-       if (unlikely(hwc->interrupts >= max_samples_per_tick)) {
-               if (throttle) {
+       seq = __this_cpu_read(perf_throttled_seq);
+       if (seq != hwc->interrupts_seq) {
+               hwc->interrupts_seq = seq;
+               hwc->interrupts = 1;
+       } else {
+               hwc->interrupts++;
+               if (unlikely(throttle
+                            && hwc->interrupts >= max_samples_per_tick)) {
+                       __this_cpu_inc(perf_throttled_count);
                        hwc->interrupts = MAX_INTERRUPTS;
                        perf_log_throttle(event, 0);
                        ret = 1;
                }
-       } else
-               hwc->interrupts++;
+       }
 
        if (event->attr.freq) {
                u64 now = perf_clock();
index 294b170..4b4042f 100644 (file)
@@ -1038,6 +1038,22 @@ void do_exit(long code)
        if (tsk->nr_dirtied)
                __this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied);
        exit_rcu();
+
+       /*
+        * The setting of TASK_RUNNING by try_to_wake_up() may be delayed
+        * when the following two conditions become true.
+        *   - There is race condition of mmap_sem (It is acquired by
+        *     exit_mm()), and
+        *   - SMI occurs before setting TASK_RUNINNG.
+        *     (or hypervisor of virtual machine switches to other guest)
+        *  As a result, we may become TASK_RUNNING after becoming TASK_DEAD
+        *
+        * To avoid it, we have to wait for releasing tsk->pi_lock which
+        * is held by try_to_wake_up()
+        */
+       smp_mb();
+       raw_spin_unlock_wait(&tsk->pi_lock);
+
        /* causes final put_task_struct in finish_task_switch(). */
        tsk->state = TASK_DEAD;
        tsk->flags |= PF_NOFREEZE;      /* tell freezer to ignore us */
index 051f090..1b2ef3c 100644 (file)
@@ -647,6 +647,26 @@ struct mm_struct *get_task_mm(struct task_struct *task)
 }
 EXPORT_SYMBOL_GPL(get_task_mm);
 
+struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
+{
+       struct mm_struct *mm;
+       int err;
+
+       err =  mutex_lock_killable(&task->signal->cred_guard_mutex);
+       if (err)
+               return ERR_PTR(err);
+
+       mm = get_task_mm(task);
+       if (mm && mm != current->mm &&
+                       !ptrace_may_access(task, mode)) {
+               mmput(mm);
+               mm = ERR_PTR(-EACCES);
+       }
+       mutex_unlock(&task->signal->cred_guard_mutex);
+
+       return mm;
+}
+
 /* Please note the differences between mmput and mm_release.
  * mmput is called whenever we stop holding onto a mm_struct,
  * error success whatever.
index 29f5b65..9788c0e 100644 (file)
@@ -1673,8 +1673,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,
                ri->rp = rp;
                ri->task = current;
 
-               if (rp->entry_handler && rp->entry_handler(ri, regs))
+               if (rp->entry_handler && rp->entry_handler(ri, regs)) {
+                       raw_spin_lock_irqsave(&rp->lock, flags);
+                       hlist_add_head(&ri->hlist, &rp->free_instances);
+                       raw_spin_unlock_irqrestore(&rp->lock, flags);
                        return 0;
+               }
 
                arch_prepare_kretprobe(ri, regs);
 
index 0c4defe..21724ee 100644 (file)
@@ -231,8 +231,28 @@ extern int pm_test_level;
 #ifdef CONFIG_SUSPEND_FREEZER
 static inline int suspend_freeze_processes(void)
 {
-       int error = freeze_processes();
-       return error ? : freeze_kernel_threads();
+       int error;
+
+       error = freeze_processes();
+
+       /*
+        * freeze_processes() automatically thaws every task if freezing
+        * fails. So we need not do anything extra upon error.
+        */
+       if (error)
+               goto Finish;
+
+       error = freeze_kernel_threads();
+
+       /*
+        * freeze_kernel_threads() thaws only kernel threads upon freezing
+        * failure. So we have to thaw the userspace tasks ourselves.
+        */
+       if (error)
+               thaw_processes();
+
+ Finish:
+       return error;
 }
 
 static inline void suspend_thaw_processes(void)
index eeca003..7e42645 100644 (file)
@@ -143,7 +143,10 @@ int freeze_processes(void)
 /**
  * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
  *
- * On success, returns 0.  On failure, -errno and system is fully thawed.
+ * On success, returns 0.  On failure, -errno and only the kernel threads are
+ * thawed, so as to give a chance to the caller to do additional cleanups
+ * (if any) before thawing the userspace tasks. So, it is the responsibility
+ * of the caller to thaw the userspace tasks, when the time is right.
  */
 int freeze_kernel_threads(void)
 {
@@ -159,7 +162,7 @@ int freeze_kernel_threads(void)
        BUG_ON(in_atomic());
 
        if (error)
-               thaw_processes();
+               thaw_kernel_threads();
        return error;
 }
 
index e5a21a8..3e10007 100644 (file)
@@ -249,13 +249,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                }
                pm_restore_gfp_mask();
                error = hibernation_snapshot(data->platform_support);
-               if (!error) {
+               if (error) {
+                       thaw_kernel_threads();
+               } else {
                        error = put_user(in_suspend, (int __user *)arg);
                        if (!error && !freezer_test_done)
                                data->ready = 1;
                        if (freezer_test_done) {
                                freezer_test_done = false;
-                               thaw_processes();
+                               thaw_kernel_threads();
                        }
                }
                break;
index df00cb0..5255c9d 100644 (file)
@@ -74,6 +74,7 @@
 
 #include <asm/tlb.h>
 #include <asm/irq_regs.h>
+#include <asm/mutex.h>
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #endif
@@ -723,9 +724,6 @@ static void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
        p->sched_class->dequeue_task(rq, p, flags);
 }
 
-/*
- * activate_task - move a task to the runqueue.
- */
 void activate_task(struct rq *rq, struct task_struct *p, int flags)
 {
        if (task_contributes_to_load(p))
@@ -734,9 +732,6 @@ void activate_task(struct rq *rq, struct task_struct *p, int flags)
        enqueue_task(rq, p, flags);
 }
 
-/*
- * deactivate_task - remove a task from the runqueue.
- */
 void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
 {
        if (task_contributes_to_load(p))
@@ -4134,7 +4129,7 @@ recheck:
        on_rq = p->on_rq;
        running = task_current(rq, p);
        if (on_rq)
-               deactivate_task(rq, p, 0);
+               dequeue_task(rq, p, 0);
        if (running)
                p->sched_class->put_prev_task(rq, p);
 
@@ -4147,7 +4142,7 @@ recheck:
        if (running)
                p->sched_class->set_curr_task(rq);
        if (on_rq)
-               activate_task(rq, p, 0);
+               enqueue_task(rq, p, 0);
 
        check_class_changed(rq, p, prev_class, oldprio);
        task_rq_unlock(rq, p, &flags);
@@ -4998,9 +4993,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
         * placed properly.
         */
        if (p->on_rq) {
-               deactivate_task(rq_src, p, 0);
+               dequeue_task(rq_src, p, 0);
                set_task_cpu(p, dest_cpu);
-               activate_task(rq_dest, p, 0);
+               enqueue_task(rq_dest, p, 0);
                check_preempt_curr(rq_dest, p, 0);
        }
 done:
@@ -7032,10 +7027,10 @@ static void normalize_task(struct rq *rq, struct task_struct *p)
 
        on_rq = p->on_rq;
        if (on_rq)
-               deactivate_task(rq, p, 0);
+               dequeue_task(rq, p, 0);
        __setscheduler(rq, p, SCHED_NORMAL, 0);
        if (on_rq) {
-               activate_task(rq, p, 0);
+               enqueue_task(rq, p, 0);
                resched_task(rq->curr);
        }
 
index 84adb2d..7c6414f 100644 (file)
@@ -4866,6 +4866,15 @@ static void nohz_balancer_kick(int cpu)
        return;
 }
 
+static inline void clear_nohz_tick_stopped(int cpu)
+{
+       if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
+               cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
+               atomic_dec(&nohz.nr_cpus);
+               clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
+       }
+}
+
 static inline void set_cpu_sd_state_busy(void)
 {
        struct sched_domain *sd;
@@ -4904,6 +4913,12 @@ void select_nohz_load_balancer(int stop_tick)
 {
        int cpu = smp_processor_id();
 
+       /*
+        * If this cpu is going down, then nothing needs to be done.
+        */
+       if (!cpu_active(cpu))
+               return;
+
        if (stop_tick) {
                if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))
                        return;
@@ -4914,6 +4929,18 @@ void select_nohz_load_balancer(int stop_tick)
        }
        return;
 }
+
+static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb,
+                                       unsigned long action, void *hcpu)
+{
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_DYING:
+               clear_nohz_tick_stopped(smp_processor_id());
+               return NOTIFY_OK;
+       default:
+               return NOTIFY_DONE;
+       }
+}
 #endif
 
 static DEFINE_SPINLOCK(balancing);
@@ -5070,11 +5097,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
        * busy tick after returning from idle, we will update the busy stats.
        */
        set_cpu_sd_state_busy();
-       if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
-               clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
-               cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
-               atomic_dec(&nohz.nr_cpus);
-       }
+       clear_nohz_tick_stopped(cpu);
 
        /*
         * None are in tickless mode and hence no need for NOHZ idle load
@@ -5590,6 +5613,7 @@ __init void init_sched_fair_class(void)
 
 #ifdef CONFIG_NO_HZ
        zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT);
+       cpu_notifier(sched_ilb_notifier, 0);
 #endif
 #endif /* SMP */
 
index 3640ebb..f42ae7f 100644 (file)
@@ -1587,6 +1587,11 @@ static int push_rt_task(struct rq *rq)
        if (!next_task)
                return 0;
 
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+       if (unlikely(task_running(rq, next_task)))
+               return 0;
+#endif
+
 retry:
        if (unlikely(next_task == rq->curr)) {
                WARN_ON(1);
index 1d7bca7..d117262 100644 (file)
@@ -296,7 +296,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
                if (__this_cpu_read(soft_watchdog_warn) == true)
                        return HRTIMER_RESTART;
 
-               printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
+               printk(KERN_EMERG "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
                        smp_processor_id(), duration,
                        current->comm, task_pid_nr(current));
                print_modules();
index 169eb7c..028aba9 100644 (file)
@@ -19,6 +19,9 @@ config RATIONAL
 config GENERIC_FIND_FIRST_BIT
        bool
 
+config NO_GENERIC_PCI_IOPORT_MAP
+       bool
+
 config GENERIC_PCI_IOMAP
        bool
 
@@ -279,6 +282,9 @@ config AVERAGE
 
          If unsure, say N.
 
+config CLZ_TAB
+       bool
+
 config CORDIC
        tristate "CORDIC algorithm"
        help
@@ -287,6 +293,7 @@ config CORDIC
 
 config MPILIB
        tristate
+       select CLZ_TAB
        help
          Multiprecision maths library from GnuPG.
          It is used to implement RSA digital signature verification,
index d71aae1..18515f0 100644 (file)
@@ -121,6 +121,8 @@ obj-$(CONFIG_DQL) += dynamic_queue_limits.o
 obj-$(CONFIG_MPILIB) += mpi/
 obj-$(CONFIG_SIGNATURE) += digsig.o
 
+obj-$(CONFIG_CLZ_TAB) += clz_tab.o
+
 hostprogs-y    := gen_crc32table
 clean-files    := crc32table.h
 
index 1955209..a28c141 100644 (file)
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -169,7 +169,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
                return BUG_TRAP_TYPE_WARN;
        }
 
-       printk(KERN_EMERG "------------[ cut here ]------------\n");
+       printk(KERN_DEFAULT "------------[ cut here ]------------\n");
 
        if (file)
                printk(KERN_CRIT "kernel BUG at %s:%u!\n",
diff --git a/lib/clz_tab.c b/lib/clz_tab.c
new file mode 100644 (file)
index 0000000..7287b4a
--- /dev/null
@@ -0,0 +1,18 @@
+const unsigned char __clz_tab[] = {
+       0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+           5, 5, 5, 5, 5, 5, 5, 5,
+       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+           6, 6, 6, 6, 6, 6, 6, 6,
+       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+           7, 7, 7, 7, 7, 7, 7, 7,
+       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+           7, 7, 7, 7, 7, 7, 7, 7,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+};
index fd2402f..286d558 100644 (file)
@@ -34,14 +34,9 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
                        unsigned long  msglen,
                        unsigned long  modulus_bitlen,
                        unsigned char *out,
-                       unsigned long *outlen,
-                       int *is_valid)
+                       unsigned long *outlen)
 {
        unsigned long modulus_len, ps_len, i;
-       int result;
-
-       /* default to invalid packet */
-       *is_valid = 0;
 
        modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
 
@@ -50,39 +45,30 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
                return -EINVAL;
 
        /* separate encoded message */
-       if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) {
-               result = -EINVAL;
-               goto bail;
-       }
+       if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1))
+               return -EINVAL;
 
        for (i = 2; i < modulus_len - 1; i++)
                if (msg[i] != 0xFF)
                        break;
 
        /* separator check */
-       if (msg[i] != 0) {
+       if (msg[i] != 0)
                /* There was no octet with hexadecimal value 0x00
                to separate ps from m. */
-               result = -EINVAL;
-               goto bail;
-       }
+               return -EINVAL;
 
        ps_len = i - 2;
 
        if (*outlen < (msglen - (2 + ps_len + 1))) {
                *outlen = msglen - (2 + ps_len + 1);
-               result = -EOVERFLOW;
-               goto bail;
+               return -EOVERFLOW;
        }
 
        *outlen = (msglen - (2 + ps_len + 1));
        memcpy(out, &msg[2 + ps_len + 1], *outlen);
 
-       /* valid packet */
-       *is_valid = 1;
-       result    = 0;
-bail:
-       return result;
+       return 0;
 }
 
 /*
@@ -96,7 +82,7 @@ static int digsig_verify_rsa(struct key *key,
        unsigned long len;
        unsigned long mlen, mblen;
        unsigned nret, l;
-       int valid, head, i;
+       int head, i;
        unsigned char *out1 = NULL, *out2 = NULL;
        MPI in = NULL, res = NULL, pkey[2];
        uint8_t *p, *datap, *endp;
@@ -105,6 +91,10 @@ static int digsig_verify_rsa(struct key *key,
 
        down_read(&key->sem);
        ukp = key->payload.data;
+
+       if (ukp->datalen < sizeof(*pkh))
+               goto err1;
+
        pkh = (struct pubkey_hdr *)ukp->data;
 
        if (pkh->version != 1)
@@ -117,18 +107,23 @@ static int digsig_verify_rsa(struct key *key,
                goto err1;
 
        datap = pkh->mpi;
-       endp = datap + ukp->datalen;
+       endp = ukp->data + ukp->datalen;
+
+       err = -ENOMEM;
 
        for (i = 0; i < pkh->nmpi; i++) {
                unsigned int remaining = endp - datap;
                pkey[i] = mpi_read_from_buffer(datap, &remaining);
+               if (!pkey[i])
+                       goto err;
                datap += remaining;
        }
 
        mblen = mpi_get_nbits(pkey[0]);
        mlen = (mblen + 7)/8;
 
-       err = -ENOMEM;
+       if (mlen == 0)
+               goto err;
 
        out1 = kzalloc(mlen, GFP_KERNEL);
        if (!out1)
@@ -167,10 +162,9 @@ static int digsig_verify_rsa(struct key *key,
        memset(out1, 0, head);
        memcpy(out1 + head, p, l);
 
-       err = -EINVAL;
-       pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len, &valid);
+       err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
 
-       if (valid && len == hlen)
+       if (!err && len == hlen)
                err = memcmp(out2, h, hlen);
 
 err:
@@ -178,8 +172,8 @@ err:
        mpi_free(res);
        kfree(out1);
        kfree(out2);
-       mpi_free(pkey[0]);
-       mpi_free(pkey[1]);
+       while (--i >= 0)
+               mpi_free(pkey[i]);
 err1:
        up_read(&key->sem);
 
index b87487b..29f9862 100644 (file)
@@ -1200,18 +1200,40 @@ do { \
        "r" ((USItype)(v)) \
        : "%g1", "%g2" __AND_CLOBBER_CC)
 #define UMUL_TIME 39           /* 39 instructions */
-#endif
-#ifndef udiv_qrnnd
-#ifndef LONGLONG_STANDALONE
+/* It's quite necessary to add this much assembler for the sparc.
+   The default udiv_qrnnd (in C) is more than 10 times slower!  */
 #define udiv_qrnnd(q, r, n1, n0, d) \
-do { USItype __r; \
-       (q) = __udiv_qrnnd(&__r, (n1), (n0), (d)); \
-       (r) = __r; \
-} while (0)
-       extern USItype __udiv_qrnnd();
-#define UDIV_TIME 140
-#endif /* LONGLONG_STANDALONE */
-#endif /* udiv_qrnnd */
+  __asm__ ("! Inlined udiv_qrnnd\n\t"                                  \
+          "mov 32,%%g1\n\t"                                            \
+          "subcc       %1,%2,%%g0\n\t"                                 \
+          "1:  bcs     5f\n\t"                                         \
+          "addxcc %0,%0,%0     ! shift n1n0 and a q-bit in lsb\n\t"    \
+          "sub %1,%2,%1        ! this kills msb of n\n\t"              \
+          "addx        %1,%1,%1        ! so this can't give carry\n\t" \
+          "subcc       %%g1,1,%%g1\n\t"                                \
+          "2:  bne     1b\n\t"                                         \
+          "subcc       %1,%2,%%g0\n\t"                                 \
+          "bcs 3f\n\t"                                                 \
+          "addxcc %0,%0,%0     ! shift n1n0 and a q-bit in lsb\n\t"    \
+          "b           3f\n\t"                                         \
+          "sub %1,%2,%1        ! this kills msb of n\n\t"              \
+          "4:  sub     %1,%2,%1\n\t"                                   \
+          "5:  addxcc  %1,%1,%1\n\t"                                   \
+          "bcc 2b\n\t"                                                 \
+          "subcc       %%g1,1,%%g1\n\t"                                \
+          "! Got carry from n.  Subtract next step to cancel this carry.\n\t" \
+          "bne 4b\n\t"                                                 \
+          "addcc       %0,%0,%0        ! shift n1n0 and a 0-bit in lsb\n\t" \
+          "sub %1,%2,%1\n\t"                                           \
+          "3:  xnor    %0,0,%0\n\t"                                    \
+          "! End of inline udiv_qrnnd\n"                               \
+          : "=&r" ((USItype)(q)),                                      \
+            "=&r" ((USItype)(r))                                       \
+          : "r" ((USItype)(d)),                                        \
+            "1" ((USItype)(n1)),                                       \
+            "0" ((USItype)(n0)) : "%g1", "cc")
+#define UDIV_TIME (3+7*32)      /* 7 instructions/iteration. 32 iterations.  */
+#endif
 #endif /* __sparc__ */
 
 /***************************************
index 854c9c6..2f52662 100644 (file)
 #include "mpi-internal.h"
 #include "longlong.h"
 
-const unsigned char __clz_tab[] = {
-       0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
-           5, 5, 5, 5, 5, 5, 5, 5,
-       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-           6, 6, 6, 6, 6, 6, 6, 6,
-       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-           7, 7, 7, 7, 7, 7, 7, 7,
-       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-           7, 7, 7, 7, 7, 7, 7, 7,
-       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-           8, 8, 8, 8, 8, 8, 8, 8,
-       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-           8, 8, 8, 8, 8, 8, 8, 8,
-       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-           8, 8, 8, 8, 8, 8, 8, 8,
-       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-           8, 8, 8, 8, 8, 8, 8, 8,
-};
-
 #define A_LIMB_1 ((mpi_limb_t) 1)
 
 /****************
index c3087d1..f68cbbb 100644 (file)
@@ -149,6 +149,9 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)
        mpi_ptr_t marker[5];
        int markidx = 0;
 
+       if (!dsize)
+               return -EINVAL;
+
        memset(marker, 0, sizeof(marker));
 
        /* Ensure space is enough for quotient and remainder.
@@ -207,6 +210,8 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)
                 * numerator would be gradually overwritten by the quotient limbs.  */
                if (qp == np) { /* Copy NP object to temporary space.  */
                        np = marker[markidx++] = mpi_alloc_limb_space(nsize);
+                       if (!np)
+                               goto nomem;
                        MPN_COPY(np, qp, nsize);
                }
        } else                  /* Put quotient at top of remainder. */
index b04a3cf..67f3e79 100644 (file)
@@ -59,7 +59,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
        ep = exp->d;
 
        if (!msize)
-               msize = 1 / msize;      /* provoke a signal */
+               return -EINVAL;
 
        if (!esize) {
                /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
index 716802b..f26b41f 100644 (file)
 
 #include "mpi-internal.h"
 
-#define DIM(v) (sizeof(v)/sizeof((v)[0]))
 #define MAX_EXTERN_MPI_BITS 16384
 
-static uint8_t asn[15] =       /* Object ID is 1.3.14.3.2.26 */
-{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
-       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
-};
-
-MPI do_encode_md(const void *sha_buffer, unsigned nbits)
-{
-       int nframe = (nbits + 7) / 8;
-       uint8_t *frame, *fr_pt;
-       int i = 0, n;
-       size_t asnlen = DIM(asn);
-       MPI a = MPI_NULL;
-
-       if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe)
-               pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n",
-                      (int)(SHA1_DIGEST_LENGTH * 8), (int)nbits);
-
-       /* We encode the MD in this way:
-        *
-        *       0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
-        *
-        * PAD consists of FF bytes.
-        */
-       frame = kmalloc(nframe, GFP_KERNEL);
-       if (!frame)
-               return MPI_NULL;
-       n = 0;
-       frame[n++] = 0;
-       frame[n++] = 1;         /* block type */
-       i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3;
-
-       if (i <= 1) {
-               pr_info("MPI: message digest encoding failed\n");
-               kfree(frame);
-               return a;
-       }
-
-       memset(frame + n, 0xff, i);
-       n += i;
-       frame[n++] = 0;
-       memcpy(frame + n, &asn, asnlen);
-       n += asnlen;
-       memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH);
-       n += SHA1_DIGEST_LENGTH;
-
-       i = nframe;
-       fr_pt = frame;
-
-       if (n != nframe) {
-               printk
-                   ("MPI: message digest encoding failed, frame length is wrong\n");
-               kfree(frame);
-               return a;
-       }
-
-       a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);
-       mpi_set_buffer(a, frame, nframe, 0);
-       kfree(frame);
-
-       return a;
-}
-
 MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
 {
        const uint8_t *buffer = xbuffer;
        int i, j;
        unsigned nbits, nbytes, nlimbs, nread = 0;
        mpi_limb_t a;
-       MPI val = MPI_NULL;
+       MPI val = NULL;
 
        if (*ret_nread < 2)
                goto leave;
@@ -108,7 +45,7 @@ MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
        nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
        val = mpi_alloc(nlimbs);
        if (!val)
-               return MPI_NULL;
+               return NULL;
        i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
        i %= BYTES_PER_MPI_LIMB;
        val->nbits = nbits;
@@ -211,30 +148,6 @@ int mpi_fromstr(MPI val, const char *str)
 }
 EXPORT_SYMBOL_GPL(mpi_fromstr);
 
-/****************
- * Special function to get the low 8 bytes from an mpi.
- * This can be used as a keyid; KEYID is an 2 element array.
- * Return the low 4 bytes.
- */
-u32 mpi_get_keyid(const MPI a, u32 *keyid)
-{
-#if BYTES_PER_MPI_LIMB == 4
-       if (keyid) {
-               keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0;
-               keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0;
-       }
-       return a->nlimbs >= 1 ? a->d[0] : 0;
-#elif BYTES_PER_MPI_LIMB == 8
-       if (keyid) {
-               keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0;
-               keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
-       }
-       return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
-#else
-#error Make this function work with other LIMB sizes
-#endif
-}
-
 /****************
  * Return an allocated buffer with the MPI (msb first).
  * NBYTES receives the length of this buffer. Caller must free the
index 87ede16..cde1aae 100644 (file)
@@ -217,6 +217,10 @@ mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs,
        case 0:
                /* We are asked to divide by zero, so go ahead and do it!  (To make
                   the compiler not remove this statement, return the value.)  */
+               /*
+                * existing clients of this function have been modified
+                * not to call it with dsize == 0, so this should not happen
+                */
                return 1 / dsize;
 
        case 1:
index eefc55d..26e4ed3 100644 (file)
@@ -58,6 +58,9 @@ mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs)
 {
        size_t len = nlimbs * sizeof(mpi_limb_t);
 
+       if (!len)
+               return NULL;
+
        return kmalloc(len, GFP_KERNEL);
 }
 
@@ -135,7 +138,7 @@ int mpi_copy(MPI *copied, const MPI a)
        size_t i;
        MPI b;
 
-       *copied = MPI_NULL;
+       *copied = NULL;
 
        if (a) {
                b = mpi_alloc(a->nlimbs);
index 4b0fdc2..0d83ea8 100644 (file)
@@ -34,7 +34,7 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
        if (maxlen && len > maxlen)
                len = maxlen;
        if (flags & IORESOURCE_IO)
-               return ioport_map(start, len);
+               return __pci_ioport_map(dev, start, len);
        if (flags & IORESOURCE_MEM) {
                if (flags & IORESOURCE_CACHEABLE)
                        return ioremap(start, len);
index 71a58f6..d9ebebe 100644 (file)
@@ -313,12 +313,34 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
                } else if (!locked)
                        spin_lock_irq(&zone->lru_lock);
 
+               /*
+                * migrate_pfn does not necessarily start aligned to a
+                * pageblock. Ensure that pfn_valid is called when moving
+                * into a new MAX_ORDER_NR_PAGES range in case of large
+                * memory holes within the zone
+                */
+               if ((low_pfn & (MAX_ORDER_NR_PAGES - 1)) == 0) {
+                       if (!pfn_valid(low_pfn)) {
+                               low_pfn += MAX_ORDER_NR_PAGES - 1;
+                               continue;
+                       }
+               }
+
                if (!pfn_valid_within(low_pfn))
                        continue;
                nr_scanned++;
 
-               /* Get the page and skip if free */
+               /*
+                * Get the page and ensure the page is within the same zone.
+                * See the comment in isolate_freepages about overlapping
+                * nodes. It is deliberate that the new zone lock is not taken
+                * as memory compaction should not move pages between nodes.
+                */
                page = pfn_to_page(low_pfn);
+               if (page_zone(page) != zone)
+                       continue;
+
+               /* Skip if free */
                if (PageBuddy(page))
                        continue;
 
index 97f49ed..b662757 100644 (file)
@@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
        unsigned long seg = 0;
        size_t count;
        loff_t *ppos = &iocb->ki_pos;
-       struct blk_plug plug;
 
        count = 0;
        retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
        if (retval)
                return retval;
 
-       blk_start_plug(&plug);
-
        /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
        if (filp->f_flags & O_DIRECT) {
                loff_t size;
@@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                        retval = filemap_write_and_wait_range(mapping, pos,
                                        pos + iov_length(iov, nr_segs) - 1);
                        if (!retval) {
+                               struct blk_plug plug;
+
+                               blk_start_plug(&plug);
                                retval = mapping->a_ops->direct_IO(READ, iocb,
                                                        iov, pos, nr_segs);
+                               blk_finish_plug(&plug);
                        }
                        if (retval > 0) {
                                *ppos = pos + retval;
@@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                        break;
        }
 out:
-       blk_finish_plug(&plug);
        return retval;
 }
 EXPORT_SYMBOL(generic_file_aio_read);
index f91b2f6..a4eb311 100644 (file)
@@ -263,7 +263,12 @@ found:
                                                        xip_pfn);
                if (err == -ENOMEM)
                        return VM_FAULT_OOM;
-               BUG_ON(err);
+               /*
+                * err == -EBUSY is fine, we've raced against another thread
+                * that faulted-in the same page
+                */
+               if (err != -EBUSY)
+                       BUG_ON(err);
                return VM_FAULT_NOPAGE;
        } else {
                int err, ret = VM_FAULT_OOM;
index b3ffc21..91d3efb 100644 (file)
@@ -2083,7 +2083,7 @@ static void collect_mm_slot(struct mm_slot *mm_slot)
 {
        struct mm_struct *mm = mm_slot->mm;
 
-       VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock));
+       VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock));
 
        if (khugepaged_test_exit(mm)) {
                /* free mm_slot */
@@ -2113,7 +2113,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,
        int progress = 0;
 
        VM_BUG_ON(!pages);
-       VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock));
+       VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock));
 
        if (khugepaged_scan.mm_slot)
                mm_slot = khugepaged_scan.mm_slot;
index c833add..45eb621 100644 (file)
@@ -1036,7 +1036,7 @@ void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
 {
        pr_debug("%s(0x%p)\n", __func__, ptr);
 
-       if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
+       if (atomic_read(&kmemleak_enabled) && ptr && size && !IS_ERR(ptr))
                add_scan_area((unsigned long)ptr, size, gfp);
        else if (atomic_read(&kmemleak_early_log))
                log_early(KMEMLEAK_SCAN_AREA, ptr, size, 0);
@@ -1757,6 +1757,7 @@ void __init kmemleak_init(void)
 
 #ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF
        if (!kmemleak_skip_disable) {
+               atomic_set(&kmemleak_early_log, 0);
                kmemleak_disable();
                return;
        }
index 556859f..6728a7a 100644 (file)
@@ -776,7 +776,8 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)
        /* threshold event is triggered in finer grain than soft limit */
        if (unlikely(mem_cgroup_event_ratelimit(memcg,
                                                MEM_CGROUP_TARGET_THRESH))) {
-               bool do_softlimit, do_numainfo;
+               bool do_softlimit;
+               bool do_numainfo __maybe_unused;
 
                do_softlimit = mem_cgroup_event_ratelimit(memcg,
                                                MEM_CGROUP_TARGET_SOFTLIMIT);
index 9871a56..df141f6 100644 (file)
@@ -445,7 +445,6 @@ void migrate_page_copy(struct page *newpage, struct page *page)
        ClearPageSwapCache(page);
        ClearPagePrivate(page);
        set_page_private(page, 0);
-       page->mapping = NULL;
 
        /*
         * If any waiters have accumulated on the new page then
@@ -667,6 +666,7 @@ static int move_to_new_page(struct page *newpage, struct page *page,
        } else {
                if (remap_swapcache)
                        remove_migration_ptes(page, newpage);
+               page->mapping = NULL;
        }
 
        unlock_page(newpage);
index e920aa3..c20ff48 100644 (file)
@@ -298,23 +298,18 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec,
                goto free_proc_pages;
        }
 
-       task_lock(task);
-       if (__ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
-               task_unlock(task);
-               rc = -EPERM;
-               goto put_task_struct;
-       }
-       mm = task->mm;
-
-       if (!mm || (task->flags & PF_KTHREAD)) {
-               task_unlock(task);
-               rc = -EINVAL;
+       mm = mm_access(task, PTRACE_MODE_ATTACH);
+       if (!mm || IS_ERR(mm)) {
+               rc = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH;
+               /*
+                * Explicitly map EACCES to EPERM as EPERM is a more a
+                * appropriate error code for process_vw_readv/writev
+                */
+               if (rc == -EACCES)
+                       rc = -EPERM;
                goto put_task_struct;
        }
 
-       atomic_inc(&mm->mm_users);
-       task_unlock(task);
-
        for (i = 0; i < riovcnt && iov_l_curr_idx < liovcnt; i++) {
                rc = process_vm_rw_single_vec(
                        (unsigned long)rvec[i].iov_base, rvec[i].iov_len,
index b0f529b..fff1ff7 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -659,7 +659,7 @@ void lru_add_page_tail(struct zone* zone,
        VM_BUG_ON(!PageHead(page));
        VM_BUG_ON(PageCompound(page_tail));
        VM_BUG_ON(PageLRU(page_tail));
-       VM_BUG_ON(!spin_is_locked(&zone->lru_lock));
+       VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&zone->lru_lock));
 
        SetPageLRU(page_tail);
 
index 97f70e5..761ad9d 100644 (file)
@@ -85,8 +85,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
        } else {
                pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);
                memcpy(&client->fsid, fsid, sizeof(*fsid));
-               ceph_debugfs_client_init(client);
-               client->have_fsid = true;
        }
        return 0;
 }
index 0b62dea..1845cde 100644 (file)
@@ -8,8 +8,8 @@
 
 #include <linux/ceph/mon_client.h>
 #include <linux/ceph/libceph.h>
+#include <linux/ceph/debugfs.h>
 #include <linux/ceph/decode.h>
-
 #include <linux/ceph/auth.h>
 
 /*
@@ -340,8 +340,19 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,
        client->monc.monmap = monmap;
        kfree(old);
 
+       if (!client->have_fsid) {
+               client->have_fsid = true;
+               mutex_unlock(&monc->mutex);
+               /*
+                * do debugfs initialization without mutex to avoid
+                * creating a locking dependency
+                */
+               ceph_debugfs_client_init(client);
+               goto out_unlocked;
+       }
 out:
        mutex_unlock(&monc->mutex);
+out_unlocked:
        wake_up_all(&client->auth_wq);
 }
 
index e3bfcbe..a3b9782 100755 (executable)
@@ -1924,6 +1924,12 @@ sub process {
                        my $pre_ctx = "$1$2";
 
                        my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
+
+                       if ($line =~ /^\+\t{6,}/) {
+                               WARN("DEEP_INDENTATION",
+                                    "Too many leading tabs - consider code refactoring\n" . $herecurr);
+                       }
+
                        my $ctx_cnt = $realcnt - $#ctx - 1;
                        my $ctx = join("\n", @ctx);
 
index e09f144..c99c607 100644 (file)
@@ -22,7 +22,6 @@
 #include "emu8000_local.h"
 #include <asm/uaccess.h>
 #include <linux/moduleparam.h>
-#include <linux/moduleparam.h>
 
 static int emu8000_reset_addr;
 module_param(emu8000_reset_addr, int, 0444);
index 4df72c0..c2c65f6 100644 (file)
@@ -1447,7 +1447,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
                for (i = 0; i < c->cvt_setups.used; i++) {
                        p = snd_array_elem(&c->cvt_setups, i);
                        if (!p->active && p->stream_tag == stream_tag &&
-                           get_wcaps_type(get_wcaps(codec, p->nid)) == type)
+                           get_wcaps_type(get_wcaps(c, p->nid)) == type)
                                p->dirty = 1;
                }
        }
index d8a35da..9d819c4 100644 (file)
@@ -282,7 +282,8 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
 
 static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
-                        const struct auto_pin_cfg *cfg)
+                        const struct auto_pin_cfg *cfg,
+                        char *lastname, int *lastidx)
 {
        unsigned int def_conf, conn;
        char name[44];
@@ -298,6 +299,10 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
                return 0;
 
        snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
+       if (!strcmp(name, lastname) && idx == *lastidx)
+               idx++;
+       strncpy(lastname, name, 44);
+       *lastidx = idx;
        err = snd_hda_jack_add_kctl(codec, nid, name, idx);
        if (err < 0)
                return err;
@@ -311,41 +316,42 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
                           const struct auto_pin_cfg *cfg)
 {
        const hda_nid_t *p;
-       int i, err;
+       int i, err, lastidx = 0;
+       char lastname[44] = "";
 
        for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
-               err = add_jack_kctl(codec, *p, cfg);
+               err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
                if (err < 0)
                        return err;
        }
        for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
                if (*p == *cfg->line_out_pins) /* might be duplicated */
                        break;
-               err = add_jack_kctl(codec, *p, cfg);
+               err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
                if (err < 0)
                        return err;
        }
        for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
                if (*p == *cfg->line_out_pins) /* might be duplicated */
                        break;
-               err = add_jack_kctl(codec, *p, cfg);
+               err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
                if (err < 0)
                        return err;
        }
        for (i = 0; i < cfg->num_inputs; i++) {
-               err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg);
+               err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx);
                if (err < 0)
                        return err;
        }
        for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
-               err = add_jack_kctl(codec, *p, cfg);
+               err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
                if (err < 0)
                        return err;
        }
-       err = add_jack_kctl(codec, cfg->dig_in_pin, cfg);
+       err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx);
        if (err < 0)
                return err;
-       err = add_jack_kctl(codec, cfg->mono_out_pin, cfg);
+       err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx);
        if (err < 0)
                return err;
        return 0;
index 35abe3c..21d91d5 100644 (file)
@@ -728,18 +728,19 @@ static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol,
 
        err = chipio_read(codec, REG_CODEC_MUTE, &data);
        if (err < 0)
-               return err;
+               goto exit;
 
        /* *valp 0 is mute, 1 is unmute */
        data = (data & 0x7f) | (*valp ? 0 : 0x80);
-       chipio_write(codec, REG_CODEC_MUTE, data);
+       err = chipio_write(codec, REG_CODEC_MUTE, data);
        if (err < 0)
-               return err;
+               goto exit;
 
        spec->curr_hp_switch = *valp;
 
+ exit:
        snd_hda_power_down(codec);
-       return 1;
+       return err < 0 ? err : 1;
 }
 
 static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol,
@@ -770,18 +771,19 @@ static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol,
 
        err = chipio_read(codec, REG_CODEC_MUTE, &data);
        if (err < 0)
-               return err;
+               goto exit;
 
        /* *valp 0 is mute, 1 is unmute */
        data = (data & 0xef) | (*valp ? 0 : 0x10);
-       chipio_write(codec, REG_CODEC_MUTE, data);
+       err = chipio_write(codec, REG_CODEC_MUTE, data);
        if (err < 0)
-               return err;
+               goto exit;
 
        spec->curr_speaker_switch = *valp;
 
+ exit:
        snd_hda_power_down(codec);
-       return 1;
+       return err < 0 ? err : 1;
 }
 
 static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol,
@@ -819,25 +821,26 @@ static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol,
 
        err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data);
        if (err < 0)
-               return err;
+               goto exit;
 
        val = 31 - left_vol;
        data = (data & 0xe0) | val;
-       chipio_write(codec, REG_CODEC_HP_VOL_L, data);
+       err = chipio_write(codec, REG_CODEC_HP_VOL_L, data);
        if (err < 0)
-               return err;
+               goto exit;
 
        val = 31 - right_vol;
        data = (data & 0xe0) | val;
-       chipio_write(codec, REG_CODEC_HP_VOL_R, data);
+       err = chipio_write(codec, REG_CODEC_HP_VOL_R, data);
        if (err < 0)
-               return err;
+               goto exit;
 
        spec->curr_hp_volume[0] = left_vol;
        spec->curr_hp_volume[1] = right_vol;
 
+ exit:
        snd_hda_power_down(codec);
-       return 1;
+       return err < 0 ? err : 1;
 }
 
 static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid)
@@ -936,6 +939,8 @@ static int ca0132_build_controls(struct hda_codec *codec)
                if (err < 0)
                        return err;
                err = add_in_volume(codec, spec->dig_in, "IEC958");
+               if (err < 0)
+                       return err;
        }
        return 0;
 }
index 0e99357..bc5a993 100644 (file)
@@ -988,8 +988,10 @@ static void cs_automic(struct hda_codec *codec)
                        change_cur_input(codec, !spec->automic_idx, 0);
        } else {
                if (present) {
-                       spec->last_input = spec->cur_input;
-                       spec->cur_input = spec->automic_idx;
+                       if (spec->cur_input != spec->automic_idx) {
+                               spec->last_input = spec->cur_input;
+                               spec->cur_input = spec->automic_idx;
+                       }
                } else  {
                        spec->cur_input = spec->last_input;
                }
index 0db1dc4..9350f3c 100644 (file)
@@ -177,6 +177,7 @@ struct alc_spec {
        unsigned int detect_lo:1;       /* Line-out detection enabled */
        unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
        unsigned int automute_lo_possible:1;      /* there are line outs and HP */
+       unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
 
        /* other flags */
        unsigned int no_analog :1; /* digital I/O only */
@@ -495,13 +496,24 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
 
        for (i = 0; i < num_pins; i++) {
                hda_nid_t nid = pins[i];
+               unsigned int val;
                if (!nid)
                        break;
                switch (spec->automute_mode) {
                case ALC_AUTOMUTE_PIN:
+                       /* don't reset VREF value in case it's controlling
+                        * the amp (see alc861_fixup_asus_amp_vref_0f())
+                        */
+                       if (spec->keep_vref_in_automute) {
+                               val = snd_hda_codec_read(codec, nid, 0,
+                                       AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+                               val &= ~PIN_HP;
+                       } else
+                               val = 0;
+                       val |= pin_bits;
                        snd_hda_codec_write(codec, nid, 0,
                                            AC_VERB_SET_PIN_WIDGET_CONTROL,
-                                           pin_bits);
+                                           val);
                        break;
                case ALC_AUTOMUTE_AMP:
                        snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
@@ -1843,6 +1855,8 @@ static const char * const alc_slave_vols[] = {
        "Speaker Playback Volume",
        "Mono Playback Volume",
        "Line-Out Playback Volume",
+       "CLFE Playback Volume",
+       "Bass Speaker Playback Volume",
        "PCM Playback Volume",
        NULL,
 };
@@ -1858,6 +1872,8 @@ static const char * const alc_slave_sws[] = {
        "Mono Playback Switch",
        "IEC958 Playback Switch",
        "Line-Out Playback Switch",
+       "CLFE Playback Switch",
+       "Bass Speaker Playback Switch",
        "PCM Playback Switch",
        NULL,
 };
@@ -2306,7 +2322,7 @@ static int alc_build_pcms(struct hda_codec *codec)
                 "%s Analog", codec->chip_name);
        info->name = spec->stream_name_analog;
 
-       if (spec->multiout.dac_nids > 0) {
+       if (spec->multiout.num_dacs > 0) {
                p = spec->stream_analog_playback;
                if (!p)
                        p = &alc_pcm_analog_playback;
@@ -4735,7 +4751,6 @@ enum {
        ALC262_FIXUP_FSC_H270,
        ALC262_FIXUP_HP_Z200,
        ALC262_FIXUP_TYAN,
-       ALC262_FIXUP_TOSHIBA_RX1,
        ALC262_FIXUP_LENOVO_3000,
        ALC262_FIXUP_BENQ,
        ALC262_FIXUP_BENQ_T31,
@@ -4765,16 +4780,6 @@ static const struct alc_fixup alc262_fixups[] = {
                        { }
                }
        },
-       [ALC262_FIXUP_TOSHIBA_RX1] = {
-               .type = ALC_FIXUP_PINS,
-               .v.pins = (const struct alc_pincfg[]) {
-                       { 0x14, 0x90170110 }, /* speaker */
-                       { 0x15, 0x0421101f }, /* HP */
-                       { 0x1a, 0x40f000f0 }, /* N/A */
-                       { 0x1b, 0x40f000f0 }, /* N/A */
-                       { 0x1e, 0x40f000f0 }, /* N/A */
-               }
-       },
        [ALC262_FIXUP_LENOVO_3000] = {
                .type = ALC_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -4807,8 +4812,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
        SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ),
        SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
        SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
-       SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
-                     ALC262_FIXUP_TOSHIBA_RX1),
        SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
        SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
        SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
@@ -5377,7 +5380,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
                      ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
-       SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
@@ -5589,6 +5591,25 @@ enum {
        PINFIX_ASUS_A6RP,
 };
 
+/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
+static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
+                       const struct alc_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+       unsigned int val;
+
+       if (action != ALC_FIXUP_ACT_INIT)
+               return;
+       val = snd_hda_codec_read(codec, 0x0f, 0,
+                                AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+       if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
+               val |= AC_PINCTL_IN_EN;
+       val |= AC_PINCTL_VREF_50;
+       snd_hda_codec_write(codec, 0x0f, 0,
+                           AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+       spec->keep_vref_in_automute = 1;
+}
+
 static const struct alc_fixup alc861_fixups[] = {
        [PINFIX_FSC_AMILO_PI1505] = {
                .type = ALC_FIXUP_PINS,
@@ -5599,17 +5620,14 @@ static const struct alc_fixup alc861_fixups[] = {
                }
        },
        [PINFIX_ASUS_A6RP] = {
-               .type = ALC_FIXUP_VERBS,
-               .v.verbs = (const struct hda_verb[]) {
-                       /* node 0x0f VREF seems controlling the master output */
-                       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
-                       { }
-               },
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc861_fixup_asus_amp_vref_0f,
        },
 };
 
 static const struct snd_pci_quirk alc861_fixup_tbl[] = {
-       SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", PINFIX_ASUS_A6RP),
+       SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP),
+       SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP),   
        SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
        SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
        {}
index 03e63fe..284e311 100644 (file)
@@ -199,6 +199,9 @@ struct via_spec {
        unsigned int no_pin_power_ctl;
        enum VIA_HDA_CODEC codec_type;
 
+       /* analog low-power control */
+       bool alc_mode;
+
        /* smart51 setup */
        unsigned int smart51_nums;
        hda_nid_t smart51_pins[2];
@@ -687,6 +690,15 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
        }
 }
 
+static void update_power_state(struct hda_codec *codec, hda_nid_t nid,
+                              unsigned int parm)
+{
+       if (snd_hda_codec_read(codec, nid, 0,
+                              AC_VERB_GET_POWER_STATE, 0) == parm)
+               return;
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+}
+
 static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
                                unsigned int *affected_parm)
 {
@@ -709,7 +721,7 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
        } else
                parm = AC_PWRST_D3;
 
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, nid, parm);
 }
 
 static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
@@ -749,6 +761,7 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
                return 0;
        spec->no_pin_power_ctl = val;
        set_widgets_power_state(codec);
+       analog_low_current_mode(codec);
        return 1;
 }
 
@@ -1036,13 +1049,19 @@ static bool is_aa_path_mute(struct hda_codec *codec)
 }
 
 /* enter/exit analog low-current mode */
-static void analog_low_current_mode(struct hda_codec *codec)
+static void __analog_low_current_mode(struct hda_codec *codec, bool force)
 {
        struct via_spec *spec = codec->spec;
        bool enable;
        unsigned int verb, parm;
 
-       enable = is_aa_path_mute(codec) && (spec->opened_streams != 0);
+       if (spec->no_pin_power_ctl)
+               enable = false;
+       else
+               enable = is_aa_path_mute(codec) && !spec->opened_streams;
+       if (enable == spec->alc_mode && !force)
+               return;
+       spec->alc_mode = enable;
 
        /* decide low current mode's verb & parameter */
        switch (spec->codec_type) {
@@ -1074,6 +1093,11 @@ static void analog_low_current_mode(struct hda_codec *codec)
        snd_hda_codec_write(codec, codec->afg, 0, verb, parm);
 }
 
+static void analog_low_current_mode(struct hda_codec *codec)
+{
+       return __analog_low_current_mode(codec, false);
+}
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -1446,6 +1470,7 @@ static int via_build_controls(struct hda_codec *codec)
        struct snd_kcontrol *kctl;
        int err, i;
 
+       spec->no_pin_power_ctl = 1;
        if (spec->set_widgets_power_state)
                if (!via_clone_control(spec, &via_pin_power_ctl_enum))
                        return -ENOMEM;
@@ -1499,10 +1524,6 @@ static int via_build_controls(struct hda_codec *codec)
                        return err;
        }
 
-       /* init power states */
-       set_widgets_power_state(codec);
-       analog_low_current_mode(codec);
-
        via_free_kctls(codec); /* no longer needed */
 
        err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
@@ -2295,10 +2316,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
 
        if (mux) {
                /* switch to D0 beofre change index */
-               if (snd_hda_codec_read(codec, mux, 0,
-                              AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0)
-                       snd_hda_codec_write(codec, mux, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, mux, AC_PWRST_D0);
                snd_hda_codec_write(codec, mux, 0,
                                    AC_VERB_SET_CONNECT_SEL,
                                    spec->inputs[cur].mux_idx);
@@ -2776,6 +2794,10 @@ static int via_init(struct hda_codec *codec)
        for (i = 0; i < spec->num_iverbs; i++)
                snd_hda_sequence_write(codec, spec->init_verbs[i]);
 
+       /* init power states */
+       set_widgets_power_state(codec);
+       __analog_low_current_mode(codec, true);
+
        via_auto_init_multi_out(codec);
        via_auto_init_hp_out(codec);
        via_auto_init_speaker_out(codec);
@@ -2922,9 +2944,9 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
        if (imux_is_smixer)
                parm = AC_PWRST_D0;
        /* SW0 (17h), AIW 0/1 (13h/14h) */
-       snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x17, parm);
+       update_power_state(codec, 0x13, parm);
+       update_power_state(codec, 0x14, parm);
 
        /* outputs */
        /* PW0 (19h), SW1 (18h), AOW1 (11h) */
@@ -2932,8 +2954,8 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
        set_pin_power_state(codec, 0x19, &parm);
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x1b, &parm);
-       snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x18, parm);
+       update_power_state(codec, 0x11, parm);
 
        /* PW6 (22h), SW2 (26h), AOW2 (24h) */
        if (is_8ch) {
@@ -2941,20 +2963,16 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
                set_pin_power_state(codec, 0x22, &parm);
                if (spec->smart51_enabled)
                        set_pin_power_state(codec, 0x1a, &parm);
-               snd_hda_codec_write(codec, 0x26, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x24, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x26, parm);
+               update_power_state(codec, 0x24, parm);
        } else if (codec->vendor_id == 0x11064397) {
                /* PW7(23h), SW2(27h), AOW2(25h) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x23, &parm);
                if (spec->smart51_enabled)
                        set_pin_power_state(codec, 0x1a, &parm);
-               snd_hda_codec_write(codec, 0x27, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x25, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x27, parm);
+               update_power_state(codec, 0x25, parm);
        }
 
        /* PW 3/4/7 (1ch/1dh/23h) */
@@ -2966,17 +2984,13 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
                set_pin_power_state(codec, 0x23, &parm);
 
        /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
-       snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
-                           imux_is_smixer ? AC_PWRST_D0 : parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
+       update_power_state(codec, 0x10, parm);
        if (is_8ch) {
-               snd_hda_codec_write(codec, 0x25, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x27, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x25, parm);
+               update_power_state(codec, 0x27, parm);
        } else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode)
-               snd_hda_codec_write(codec, 0x25, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x25, parm);
 }
 
 static int patch_vt1708S(struct hda_codec *codec);
@@ -3149,10 +3163,10 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec)
        if (imux_is_smixer)
                parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
        /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
-       snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x13, parm);
+       update_power_state(codec, 0x12, parm);
+       update_power_state(codec, 0x1f, parm);
+       update_power_state(codec, 0x20, parm);
 
        /* outputs */
        /* PW 3/4 (16h/17h) */
@@ -3160,10 +3174,9 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec)
        set_pin_power_state(codec, 0x17, &parm);
        set_pin_power_state(codec, 0x16, &parm);
        /* MW0 (1ah), AOW 0/1 (10h/1dh) */
-       snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
-                           imux_is_smixer ? AC_PWRST_D0 : parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm);
+       update_power_state(codec, 0x10, parm);
+       update_power_state(codec, 0x1d, parm);
 }
 
 static int patch_vt1702(struct hda_codec *codec)
@@ -3228,52 +3241,48 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
        if (imux_is_smixer)
                parm = AC_PWRST_D0;
        /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
-       snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1e, parm);
+       update_power_state(codec, 0x1f, parm);
+       update_power_state(codec, 0x10, parm);
+       update_power_state(codec, 0x11, parm);
 
        /* outputs */
        /* PW3 (27h), MW2 (1ah), AOW3 (bh) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x27, &parm);
-       snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1a, parm);
+       update_power_state(codec, 0xb, parm);
 
        /* PW2 (26h), AOW2 (ah) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x26, &parm);
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x2b, &parm);
-       snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0xa, parm);
 
        /* PW0 (24h), AOW0 (8h) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x24, &parm);
        if (!spec->hp_independent_mode) /* check for redirected HP */
                set_pin_power_state(codec, 0x28, &parm);
-       snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x8, parm);
        /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
-       snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
-                           imux_is_smixer ? AC_PWRST_D0 : parm);
+       update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm);
 
        /* PW1 (25h), AOW1 (9h) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x25, &parm);
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x2a, &parm);
-       snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x9, parm);
 
        if (spec->hp_independent_mode) {
                /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x28, &parm);
-               snd_hda_codec_write(codec, 0x1b, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x34, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0xc, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x1b, parm);
+               update_power_state(codec, 0x34, parm);
+               update_power_state(codec, 0xc, parm);
        }
 }
 
@@ -3433,8 +3442,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
        if (imux_is_smixer)
                parm = AC_PWRST_D0;
        /* SW0 (17h), AIW0(13h) */
-       snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x17, parm);
+       update_power_state(codec, 0x13, parm);
 
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x1e, &parm);
@@ -3442,12 +3451,11 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
        if (spec->dmic_enabled)
                set_pin_power_state(codec, 0x22, &parm);
        else
-               snd_hda_codec_write(codec, 0x22, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+               update_power_state(codec, 0x22, AC_PWRST_D3);
 
        /* SW2(26h), AIW1(14h) */
-       snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x26, parm);
+       update_power_state(codec, 0x14, parm);
 
        /* outputs */
        /* PW0 (19h), SW1 (18h), AOW1 (11h) */
@@ -3456,8 +3464,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
        /* Smart 5.1 PW2(1bh) */
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x1b, &parm);
-       snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x18, parm);
+       update_power_state(codec, 0x11, parm);
 
        /* PW7 (23h), SW3 (27h), AOW3 (25h) */
        parm = AC_PWRST_D3;
@@ -3465,12 +3473,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
        /* Smart 5.1 PW1(1ah) */
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x1a, &parm);
-       snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x27, parm);
 
        /* Smart 5.1 PW5(1eh) */
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x1e, &parm);
-       snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x25, parm);
 
        /* Mono out */
        /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
@@ -3486,9 +3494,9 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
                        mono_out = 1;
        }
        parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
-       snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x28, parm);
+       update_power_state(codec, 0x29, parm);
+       update_power_state(codec, 0x2a, parm);
 
        /* PW 3/4 (1ch/1dh) */
        parm = AC_PWRST_D3;
@@ -3496,15 +3504,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
        set_pin_power_state(codec, 0x1d, &parm);
        /* HP Independent Mode, power on AOW3 */
        if (spec->hp_independent_mode)
-               snd_hda_codec_write(codec, 0x25, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x25, parm);
 
        /* force to D0 for internal Speaker */
        /* MW0 (16h), AOW0 (10h) */
-       snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
-                           imux_is_smixer ? AC_PWRST_D0 : parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
-                           mono_out ? AC_PWRST_D0 : parm);
+       update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
+       update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm);
 }
 
 static int patch_vt1716S(struct hda_codec *codec)
@@ -3580,54 +3585,45 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
        set_pin_power_state(codec, 0x2b, &parm);
        parm = AC_PWRST_D0;
        /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
-       snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1e, parm);
+       update_power_state(codec, 0x1f, parm);
+       update_power_state(codec, 0x10, parm);
+       update_power_state(codec, 0x11, parm);
 
        /* outputs */
        /* AOW0 (8h)*/
-       snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x8, parm);
 
        if (spec->codec_type == VT1802) {
                /* PW4 (28h), MW4 (18h), MUX4(38h) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x28, &parm);
-               snd_hda_codec_write(codec, 0x18, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x38, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x18, parm);
+               update_power_state(codec, 0x38, parm);
        } else {
                /* PW4 (26h), MW4 (1ch), MUX4(37h) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x26, &parm);
-               snd_hda_codec_write(codec, 0x1c, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x37, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x1c, parm);
+               update_power_state(codec, 0x37, parm);
        }
 
        if (spec->codec_type == VT1802) {
                /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x25, &parm);
-               snd_hda_codec_write(codec, 0x15, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x35, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x15, parm);
+               update_power_state(codec, 0x35, parm);
        } else {
                /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x25, &parm);
-               snd_hda_codec_write(codec, 0x19, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x35, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x19, parm);
+               update_power_state(codec, 0x35, parm);
        }
 
        if (spec->hp_independent_mode)
-               snd_hda_codec_write(codec, 0x9, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, 0x9, AC_PWRST_D0);
 
        /* Class-D */
        /* PW0 (24h), MW0(18h/14h), MUX0(34h) */
@@ -3637,12 +3633,10 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
        set_pin_power_state(codec, 0x24, &parm);
        parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
        if (spec->codec_type == VT1802)
-               snd_hda_codec_write(codec, 0x14, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x14, parm);
        else
-               snd_hda_codec_write(codec, 0x18, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x18, parm);
+       update_power_state(codec, 0x34, parm);
 
        /* Mono Out */
        present = snd_hda_jack_detect(codec, 0x26);
@@ -3650,28 +3644,20 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
        parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
        if (spec->codec_type == VT1802) {
                /* PW15 (33h), MW8(1ch), MUX8(3ch) */
-               snd_hda_codec_write(codec, 0x33, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x1c, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x3c, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x33, parm);
+               update_power_state(codec, 0x1c, parm);
+               update_power_state(codec, 0x3c, parm);
        } else {
                /* PW15 (31h), MW8(17h), MUX8(3bh) */
-               snd_hda_codec_write(codec, 0x31, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x17, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x3b, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x31, parm);
+               update_power_state(codec, 0x17, parm);
+               update_power_state(codec, 0x3b, parm);
        }
        /* MW9 (21h) */
        if (imux_is_smixer || !is_aa_path_mute(codec))
-               snd_hda_codec_write(codec, 0x21, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, 0x21, AC_PWRST_D0);
        else
-               snd_hda_codec_write(codec, 0x21, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+               update_power_state(codec, 0x21, AC_PWRST_D3);
 }
 
 /* patch for vt2002P */
@@ -3731,30 +3717,28 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
        set_pin_power_state(codec, 0x2b, &parm);
        parm = AC_PWRST_D0;
        /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
-       snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1e, parm);
+       update_power_state(codec, 0x1f, parm);
+       update_power_state(codec, 0x10, parm);
+       update_power_state(codec, 0x11, parm);
 
        /* outputs */
        /* AOW0 (8h)*/
-       snd_hda_codec_write(codec, 0x8, 0,
-                           AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+       update_power_state(codec, 0x8, AC_PWRST_D0);
 
        /* PW4 (28h), MW4 (18h), MUX4(38h) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x28, &parm);
-       snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x18, parm);
+       update_power_state(codec, 0x38, parm);
 
        /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x25, &parm);
-       snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x15, parm);
+       update_power_state(codec, 0x35, parm);
        if (spec->hp_independent_mode)
-               snd_hda_codec_write(codec, 0x9, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, 0x9, AC_PWRST_D0);
 
        /* Internal Speaker */
        /* PW0 (24h), MW0(14h), MUX0(34h) */
@@ -3763,15 +3747,11 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x24, &parm);
        if (present) {
-               snd_hda_codec_write(codec, 0x14, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-               snd_hda_codec_write(codec, 0x34, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+               update_power_state(codec, 0x14, AC_PWRST_D3);
+               update_power_state(codec, 0x34, AC_PWRST_D3);
        } else {
-               snd_hda_codec_write(codec, 0x14, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-               snd_hda_codec_write(codec, 0x34, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, 0x14, AC_PWRST_D0);
+               update_power_state(codec, 0x34, AC_PWRST_D0);
        }
 
 
@@ -3782,26 +3762,20 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x31, &parm);
        if (present) {
-               snd_hda_codec_write(codec, 0x1c, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-               snd_hda_codec_write(codec, 0x3c, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-               snd_hda_codec_write(codec, 0x3e, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+               update_power_state(codec, 0x1c, AC_PWRST_D3);
+               update_power_state(codec, 0x3c, AC_PWRST_D3);
+               update_power_state(codec, 0x3e, AC_PWRST_D3);
        } else {
-               snd_hda_codec_write(codec, 0x1c, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-               snd_hda_codec_write(codec, 0x3c, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-               snd_hda_codec_write(codec, 0x3e, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, 0x1c, AC_PWRST_D0);
+               update_power_state(codec, 0x3c, AC_PWRST_D0);
+               update_power_state(codec, 0x3e, AC_PWRST_D0);
        }
 
        /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x33, &parm);
-       snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1d, parm);
+       update_power_state(codec, 0x3d, parm);
 
 }
 
index 26c7e8b..c0dbb52 100644 (file)
@@ -618,9 +618,12 @@ static int ac97_volume_get(struct snd_kcontrol *ctl,
        mutex_lock(&chip->mutex);
        reg = oxygen_read_ac97(chip, codec, index);
        mutex_unlock(&chip->mutex);
-       value->value.integer.value[0] = 31 - (reg & 0x1f);
-       if (stereo)
-               value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f);
+       if (!stereo) {
+               value->value.integer.value[0] = 31 - (reg & 0x1f);
+       } else {
+               value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f);
+               value->value.integer.value[1] = 31 - (reg & 0x1f);
+       }
        return 0;
 }
 
@@ -636,14 +639,14 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,
 
        mutex_lock(&chip->mutex);
        oldreg = oxygen_read_ac97(chip, codec, index);
-       newreg = oldreg;
-       newreg = (newreg & ~0x1f) |
-               (31 - (value->value.integer.value[0] & 0x1f));
-       if (stereo)
-               newreg = (newreg & ~0x1f00) |
-                       ((31 - (value->value.integer.value[1] & 0x1f)) << 8);
-       else
-               newreg = (newreg & ~0x1f00) | ((newreg & 0x1f) << 8);
+       if (!stereo) {
+               newreg = oldreg & ~0x1f;
+               newreg |= 31 - (value->value.integer.value[0] & 0x1f);
+       } else {
+               newreg = oldreg & ~0x1f1f;
+               newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8;
+               newreg |= 31 - (value->value.integer.value[1] & 0x1f);
+       }
        change = newreg != oldreg;
        if (change)
                oxygen_write_ac97(chip, codec, index, newreg);
index 9d38db8..78979b3 100644 (file)
@@ -1113,7 +1113,7 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
                priv->config[id].mmcc &= 0xC0;
                priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;
                priv->config[id].spc &= 0xFC;
-               priv->config[id].spc &= MCK_SCLK_64FS;
+               priv->config[id].spc |= MCK_SCLK_MCLK;
        } else {
                /* CS42L73 Slave */
                priv->config[id].spc &= 0xFC;
index 66f0611..89f2af7 100644 (file)
@@ -1405,6 +1405,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_OFF:
                regcache_cache_only(wm5100->regmap, true);
+               regcache_mark_dirty(wm5100->regmap);
                if (wm5100->pdata.ldo_ena)
                        gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
                regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
@@ -2183,6 +2184,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
                if (wm5100->jack_detecting) {
                        dev_dbg(codec->dev, "Microphone detected\n");
                        wm5100->jack_mic = true;
+                       wm5100->jack_detecting = false;
                        snd_soc_jack_report(wm5100->jack,
                                            SND_JACK_HEADSET,
                                            SND_JACK_HEADSET | SND_JACK_BTN_0);
@@ -2221,6 +2223,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
                                            SND_JACK_BTN_0);
                } else if (wm5100->jack_detecting) {
                        dev_dbg(codec->dev, "Headphone detected\n");
+                       wm5100->jack_detecting = false;
                        snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
                                            SND_JACK_HEADPHONE);
 
@@ -2610,6 +2613,13 @@ static const struct regmap_config wm5100_regmap = {
        .cache_type = REGCACHE_RBTREE,
 };
 
+static const unsigned int wm5100_mic_ctrl_reg[] = {
+       WM5100_IN1L_CONTROL,
+       WM5100_IN2L_CONTROL,
+       WM5100_IN3L_CONTROL,
+       WM5100_IN4L_CONTROL,
+};
+
 static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
@@ -2742,7 +2752,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
        }
 
        for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
-               regmap_update_bits(wm5100->regmap, WM5100_IN1L_CONTROL,
+               regmap_update_bits(wm5100->regmap, wm5100_mic_ctrl_reg[i],
                                   WM5100_IN1_MODE_MASK |
                                   WM5100_IN1_DMIC_SUP_MASK,
                                   (wm5100->pdata.in_mode[i] <<
index 296de4e..29c4b02 100644 (file)
@@ -96,7 +96,7 @@ static int wm8962_regulator_event_##n(struct notifier_block *nb, \
        struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
                                                  disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               regcache_cache_only(wm8962->regmap, true);      \
+               regcache_mark_dirty(wm8962->regmap);    \
        } \
        return 0; \
 }
@@ -3159,13 +3159,13 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
        case SNDRV_PCM_FORMAT_S16_LE:
                break;
        case SNDRV_PCM_FORMAT_S20_3LE:
-               aif0 |= 0x40;
+               aif0 |= 0x4;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
-               aif0 |= 0x80;
+               aif0 |= 0x8;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
-               aif0 |= 0xc0;
+               aif0 |= 0xc;
                break;
        default:
                return -EINVAL;
index 93d27b6..ec69a6c 100644 (file)
@@ -770,6 +770,8 @@ static void vmid_reference(struct snd_soc_codec *codec)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
+       pm_runtime_get_sync(codec->dev);
+
        wm8994->vmid_refcount++;
 
        dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n",
@@ -783,7 +785,12 @@ static void vmid_reference(struct snd_soc_codec *codec)
                                    WM8994_VMID_RAMP_MASK,
                                    WM8994_STARTUP_BIAS_ENA |
                                    WM8994_VMID_BUF_ENA |
-                                   (0x11 << WM8994_VMID_RAMP_SHIFT));
+                                   (0x3 << WM8994_VMID_RAMP_SHIFT));
+
+               /* Remove discharge for line out */
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+                                   WM8994_LINEOUT1_DISCH |
+                                   WM8994_LINEOUT2_DISCH, 0);
 
                /* Main bias enable, VMID=2x40k */
                snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
@@ -837,6 +844,8 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_VMID_BUF_ENA |
                                    WM8994_VMID_RAMP_MASK, 0);
        }
+
+       pm_runtime_put(codec->dev);
 }
 
 static int vmid_event(struct snd_soc_dapm_widget *w,
@@ -2753,11 +2762,6 @@ static int wm8994_resume(struct snd_soc_codec *codec)
                codec->cache_only = 0;
        }
 
-       /* Restore the registers */
-       ret = snd_soc_cache_sync(codec);
-       if (ret != 0)
-               dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
-
        wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
index 13aa2bd..61f7daa 100644 (file)
@@ -108,7 +108,7 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \
        struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \
                                                  disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               regcache_cache_only(wm8996->regmap, true);      \
+               regcache_mark_dirty(wm8996->regmap);    \
        } \
        return 0; \
 }
index 2a61094..8a68cea 100644 (file)
@@ -586,14 +586,14 @@ SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
 };
 
 static const struct snd_kcontrol_new line2_mix[] = {
-SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0),
-SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0),
 SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
 };
 
 static const struct snd_kcontrol_new line2n_mix[] = {
-SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
-SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
 };
 
 static const struct snd_kcontrol_new line2p_mix[] = {
@@ -613,6 +613,8 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
 SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
 
+SND_SOC_DAPM_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0),
+
 SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
                   in1l_pga, ARRAY_SIZE(in1l_pga)),
 SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
@@ -834,9 +836,11 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
 };
 
 static const struct snd_soc_dapm_route lineout1_se_routes[] = {
+       { "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" },
        { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
        { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
 
+       { "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" },
        { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
 
        { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
@@ -844,8 +848,8 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = {
 };
 
 static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
-       { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
-       { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
+       { "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" },
+       { "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" },
        { "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },
 
        { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
@@ -853,9 +857,11 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
 };
 
 static const struct snd_soc_dapm_route lineout2_se_routes[] = {
+       { "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" },
        { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
        { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
 
+       { "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" },
        { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
 
        { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
index 7ac0ba2..c6012ff 100644 (file)
@@ -230,8 +230,6 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
 
 /* GTA02 specific routes and controls */
 
-#ifdef CONFIG_MACH_NEO1973_GTA02
-
 static int gta02_speaker_enabled;
 
 static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
@@ -311,10 +309,6 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
        return 0;
 }
 
-#else
-static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; }
-#endif
-
 static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_codec *codec = rtd->codec;
@@ -322,10 +316,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
        int ret;
 
        /* set up NC codec pins */
-       if (machine_is_neo1973_gta01()) {
-               snd_soc_dapm_nc_pin(dapm, "LOUT2");
-               snd_soc_dapm_nc_pin(dapm, "ROUT2");
-       }
        snd_soc_dapm_nc_pin(dapm, "OUT3");
        snd_soc_dapm_nc_pin(dapm, "OUT4");
        snd_soc_dapm_nc_pin(dapm, "LINE1");
@@ -370,50 +360,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-/* GTA01 specific controls */
-
-#ifdef CONFIG_MACH_NEO1973_GTA01
-
-static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = {
-       {"Amp IN", NULL, "ROUT1"},
-       {"Amp IN", NULL, "LOUT1"},
-
-       {"Handset Spk", NULL, "Amp EP"},
-       {"Stereo Out", NULL, "Amp LS"},
-       {"Headphone", NULL, "Amp HP"},
-};
-
-static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = {
-       SND_SOC_DAPM_SPK("Handset Spk", NULL),
-       SND_SOC_DAPM_SPK("Stereo Out", NULL),
-       SND_SOC_DAPM_HP("Headphone", NULL),
-};
-
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
-{
-       int ret;
-
-       ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets,
-                       ARRAY_SIZE(neo1973_lm4857_dapm_widgets));
-       if (ret)
-               return ret;
-
-       ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes,
-                       ARRAY_SIZE(neo1973_lm4857_routes));
-       if (ret)
-               return ret;
-
-       snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
-       snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
-       snd_soc_dapm_ignore_suspend(dapm, "Headphone");
-
-       return 0;
-}
-
-#else
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; };
-#endif
-
 static struct snd_soc_dai_link neo1973_dai[] = {
 { /* Hifi Playback - for similatious use with voice below */
        .name = "WM8753",
@@ -440,11 +386,6 @@ static struct snd_soc_aux_dev neo1973_aux_devs[] = {
                .name = "dfbmcs320",
                .codec_name = "dfbmcs320.0",
        },
-       {
-               .name = "lm4857",
-               .codec_name = "lm4857.0-007c",
-               .init = neo1973_lm4857_init,
-       },
 };
 
 static struct snd_soc_codec_conf neo1973_codec_conf[] = {
@@ -454,14 +395,10 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = {
        },
 };
 
-#ifdef CONFIG_MACH_NEO1973_GTA02
 static const struct gpio neo1973_gta02_gpios[] = {
        { GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
        { GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
 };
-#else
-static const struct gpio neo1973_gta02_gpios[] = {};
-#endif
 
 static struct snd_soc_card neo1973 = {
        .name = "neo1973",
@@ -480,7 +417,7 @@ static int __init neo1973_init(void)
 {
        int ret;
 
-       if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
+       if (!machine_is_neo1973_gta02())
                return -ENODEV;
 
        if (machine_is_neo1973_gta02()) {
index b5ecf6d..92cee24 100644 (file)
@@ -567,6 +567,17 @@ int snd_soc_suspend(struct device *dev)
                if (!codec->suspended && codec->driver->suspend) {
                        switch (codec->dapm.bias_level) {
                        case SND_SOC_BIAS_STANDBY:
+                               /*
+                                * If the CODEC is capable of idle
+                                * bias off then being in STANDBY
+                                * means it's doing something,
+                                * otherwise fall through.
+                                */
+                               if (codec->dapm.idle_bias_off) {
+                                       dev_dbg(codec->dev,
+                                               "idle_bias_off CODEC on over suspend\n");
+                                       break;
+                               }
                        case SND_SOC_BIAS_OFF:
                                codec->driver->suspend(codec);
                                codec->suspended = 1;
index 8edc503..d89ab4c 100644 (file)
@@ -1617,6 +1617,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       /* Edirol UM-3G */
+       USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .ifnum = 0,
+               .type = QUIRK_MIDI_STANDARD_INTERFACE
+       }
+},
 {
        /* Boss JS-8 Jam Station  */
        USB_DEVICE(0x0582, 0x0109),
index ac86d67..7c12650 100644 (file)
@@ -104,7 +104,7 @@ endif
 
 CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
 EXTLIBS = -lpthread -lrt -lelf -lm
-ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 ALL_LDFLAGS = $(LDFLAGS)
 STRIP ?= strip
 
@@ -168,10 +168,7 @@ endif
 
 ### --- END CONFIGURATION SECTION ---
 
-# Those must not be GNU-specific; they are shared with perl/ which may
-# be built by a different compiler. (Note that this is an artifact now
-# but it still might be nice to keep that distinction.)
-BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include
+BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 BASIC_LDFLAGS =
 
 # Guard against environment variables
index 59d43ab..fb85661 100644 (file)
@@ -20,7 +20,6 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
  */
-#define _GNU_SOURCE
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -31,7 +30,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#undef _GNU_SOURCE
 #include "perf.h"
 #include "builtin.h"
 #include "util/util.h"
index 8f80df8..dd162aa 100644 (file)
@@ -89,8 +89,6 @@ void get_term_dimensions(struct winsize *ws)
 
 static void perf_top__update_print_entries(struct perf_top *top)
 {
-       top->print_entries = top->winsize.ws_row;
-
        if (top->print_entries > 9)
                top->print_entries -= 9;
 }
@@ -100,6 +98,13 @@ static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *ar
        struct perf_top *top = arg;
 
        get_term_dimensions(&top->winsize);
+       if (!top->print_entries
+           || (top->print_entries+4) > top->winsize.ws_row) {
+               top->print_entries = top->winsize.ws_row;
+       } else {
+               top->print_entries += 4;
+               top->winsize.ws_row = top->print_entries;
+       }
        perf_top__update_print_entries(top);
 }
 
@@ -453,8 +458,10 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
                                };
                                perf_top__sig_winch(SIGWINCH, NULL, top);
                                sigaction(SIGWINCH, &act, NULL);
-                       } else
+                       } else {
+                               perf_top__sig_winch(SIGWINCH, NULL, top);
                                signal(SIGWINCH, SIG_DFL);
+                       }
                        break;
                case 'E':
                        if (top->evlist->nr_entries > 1) {
index 3e7e0b0..ecd7f4d 100644 (file)
@@ -2105,7 +2105,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool,
        strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
 
        ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
-       size = strlen(name);
+       size = strlen(ev.event_type.event_type.name);
        size = ALIGN(size, sizeof(u64));
        ev.event_type.header.size = sizeof(ev.event_type) -
                (sizeof(ev.event_type.event_type.name) - size);
index eb25900..29cb654 100644 (file)
@@ -19,7 +19,6 @@
  *
  */
 
-#define _GNU_SOURCE
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -33,7 +32,6 @@
 #include <limits.h>
 #include <elf.h>
 
-#undef _GNU_SOURCE
 #include "util.h"
 #include "event.h"
 #include "string.h"
index 215d50f..0975438 100644 (file)
@@ -1,4 +1,3 @@
-#define _GNU_SOURCE
 #include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
index 6c164dc..1a8d4dc 100644 (file)
  *  The parts for function graph printing was taken and modified from the
  *  Linux Kernel that were written by Frederic Weisbecker.
  */
-#define _GNU_SOURCE
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
 
-#undef _GNU_SOURCE
 #include "../perf.h"
 #include "util.h"
 #include "trace-event.h"
index 1212a38..e81aef1 100644 (file)
@@ -1,6 +1,4 @@
-#define _GNU_SOURCE
 #include <stdio.h>
-#undef _GNU_SOURCE
 #include "../libslang.h"
 #include <stdlib.h>
 #include <string.h>
index 6ef3c56..4f48f59 100644 (file)
@@ -1,4 +1,3 @@
-#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index b9c530c..ecf9898 100644 (file)
@@ -40,7 +40,6 @@
 #define decimal_length(x)      ((int)(sizeof(x) * 2.56 + 0.5) + 1)
 
 #define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
 #define _BSD_SOURCE 1
 #define HAS_BOOL
 
index 7287bf5..a91f980 100644 (file)
@@ -1543,7 +1543,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot,
        if (memslot && memslot->dirty_bitmap) {
                unsigned long rel_gfn = gfn - memslot->base_gfn;
 
-               if (!__test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap))
+               if (!test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap))
                        memslot->nr_dirty_pages++;
        }
 }