Merge branch 'pm-opp' of ssh://master.kernel.org/pub/scm/linux/kernel/git/khilman...
authorTony Lindgren <tony@atomide.com>
Wed, 22 Dec 2010 01:05:57 +0000 (17:05 -0800)
committerTony Lindgren <tony@atomide.com>
Wed, 22 Dec 2010 01:05:57 +0000 (17:05 -0800)
206 files changed:
Documentation/kernel-parameters.txt
Documentation/power/runtime_pm.txt
Makefile
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/board-pcontrol-g20.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/clock.c
arch/arm/mach-at91/include/mach/stamp9g20.h [new file with mode: 0644]
arch/arm/mach-omap1/Makefile
arch/arm/mach-omap1/dma.c [new file with mode: 0644]
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/control.c
arch/arm/mach-omap2/control.h
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/dma.c [new file with mode: 0644]
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm44xx.c
arch/arm/mach-omap2/sdrc.h
arch/arm/mach-omap2/sleep34xx.S
arch/arm/mach-s3c2412/Kconfig
arch/arm/mach-s3c2412/Makefile
arch/arm/mach-s3c2416/Kconfig
arch/arm/mach-s5pv210/mach-aquila.c
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-shmobile/include/mach/entry-macro.S
arch/arm/mach-shmobile/include/mach/vmalloc.h
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/include/plat/dma.h
arch/arm/plat-omap/include/plat/sram.h
arch/arm/plat-omap/sram.c
arch/arm/plat-s3c24xx/Kconfig
arch/mips/Kconfig
arch/mips/alchemy/common/platform.c
arch/mips/alchemy/devboards/prom.c
arch/mips/ar7/clock.c
arch/mips/ar7/time.c
arch/mips/bcm47xx/setup.c
arch/mips/include/asm/cpu.h
arch/mips/include/asm/elf.h
arch/mips/include/asm/io.h
arch/mips/include/asm/mach-ar7/ar7.h
arch/mips/include/asm/mach-bcm47xx/nvram.h
arch/mips/jz4740/board-qi_lb60.c
arch/mips/jz4740/platform.c
arch/mips/jz4740/prom.c
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/linux32.c
arch/mips/kernel/process.c
arch/mips/kernel/prom.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/traps.c
arch/mips/kernel/vpe.c
arch/mips/lib/memset.S
arch/mips/loongson/common/env.c
arch/mips/math-emu/cp1emu.c
arch/mips/mm/dma-default.c
arch/mips/mm/sc-mips.c
arch/mips/pmc-sierra/yosemite/py-console.c
arch/mips/sibyte/swarm/setup.c
arch/mn10300/kernel/time.c
arch/tile/include/asm/signal.h
arch/tile/kernel/compat_signal.c
arch/tile/kernel/intvec_32.S
arch/tile/kernel/process.c
arch/tile/kernel/signal.c
arch/x86/boot/compressed/misc.c
arch/x86/include/asm/e820.h
arch/x86/include/asm/kvm_host.h
arch/x86/kernel/Makefile
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/probe_64.c
arch/x86/kernel/head_32.S
arch/x86/kernel/hpet.c
arch/x86/kernel/resource.c [new file with mode: 0644]
arch/x86/kernel/setup.c
arch/x86/kernel/xsave.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h
arch/x86/lguest/boot.c
arch/x86/lguest/i386_head.S
arch/x86/pci/i386.c
arch/x86/vdso/Makefile
block/blk-map.c
block/blk-merge.c
block/blk-settings.c
block/blk-sysfs.c
block/blk-throttle.c
drivers/block/cciss.c
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_req.h
drivers/block/drbd/drbd_worker.c
drivers/clocksource/sh_cmt.c
drivers/input/evdev.c
drivers/input/tablet/wacom_wac.c
drivers/md/dm-table.c
drivers/md/md.c
drivers/media/common/saa7146_hlp.c
drivers/media/common/saa7146_video.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-miropcm20.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-si4713.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-timb.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/arv.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic.c
drivers/media/video/cx18/cx18-alsa-pcm.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/meye.c
drivers/media/video/pms.c
drivers/media/video/sh_vou.c
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvc_video.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/v4l2-dev.c
drivers/media/video/v4l2-device.c
drivers/media/video/w9966.c
drivers/pci/bus.c
drivers/pci/dmar.c
drivers/pci/quirks.c
drivers/scsi/scsi_lib.c
drivers/staging/cx25821/cx25821-video.c
drivers/staging/cx25821/cx25821-video.h
drivers/tty/n_gsm.c
drivers/usb/core/Kconfig
drivers/usb/gadget/composite.c
drivers/usb/host/xhci-mem.c
drivers/usb/misc/uss720.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/storage/unusual_devs.h
drivers/video/omap/Kconfig
drivers/video/omap2/vram.c
fs/btrfs/export.c
fs/ceph/dir.c
fs/ceph/file.c
fs/namei.c
fs/nilfs2/gcinode.c
fs/nilfs2/ioctl.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/notify/inotify/inotify_user.c
include/linux/blkdev.h
include/linux/bootmem.h
include/linux/ceph/libceph.h
include/linux/cnt32_to_63.h
include/linux/fanotify.h
include/linux/fsnotify.h
include/linux/fsnotify_backend.h
include/linux/input.h
include/linux/ioport.h
include/linux/perf_event.h
include/linux/pm_runtime.h
include/linux/sched.h
include/linux/ssb/ssb_driver_gige.h
include/media/saa7146.h
include/media/v4l2-device.h
kernel/fork.c
kernel/perf_event.c
kernel/power/swap.c
kernel/power/user.c
kernel/resource.c
kernel/sched.c
kernel/timer.c
kernel/trace/trace.c
net/ceph/messenger.c
net/ceph/pagevec.c
scripts/recordmcount.h
scripts/tags.sh
sound/pci/hda/patch_realtek.c
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8960.c
sound/soc/soc-dapm.c

index cdd2a6e8a3b79ae9fabc67230a27a21927642c9b..8b61c93609994dd91e36c25e1b29647ad084eaff 100644 (file)
@@ -2175,11 +2175,6 @@ and is between 256 and 4096 characters. It is defined in the file
        reset_devices   [KNL] Force drivers to reset the underlying device
                        during initialization.
 
-       resource_alloc_from_bottom
-                       Allocate new resources from the beginning of available
-                       space, not the end.  If you need to use this, please
-                       report a bug.
-
        resume=         [SWSUSP]
                        Specify the partition device for software suspend
 
index 489e9bacd165ad4a354130edcf7e03d97471b52b..41cc7b30d7ddaff700a198b590eb91047d90d0d0 100644 (file)
@@ -379,8 +379,8 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       zero)
 
   bool pm_runtime_suspended(struct device *dev);
-    - return true if the device's runtime PM status is 'suspended', or false
-      otherwise
+    - return true if the device's runtime PM status is 'suspended' and its
+      'power.disable_depth' field is equal to zero, or false otherwise
 
   void pm_runtime_allow(struct device *dev);
     - set the power.runtime_auto flag for the device and decrease its usage
index 5aa44278d95686e9719f38592599b094a72a1366..77044b7918a5cbe8439d9000175ca0b7f0ea4717 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 37
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc7
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
index 62d686f0b42602e6b1f7beb096524944452b3b45..d13add71f72accab27ae6abade209d8fad2259f9 100644 (file)
@@ -65,7 +65,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
 obj-$(CONFIG_MACH_CPU9G20)     += board-cpu9krea.o
 obj-$(CONFIG_MACH_STAMP9G20)   += board-stamp9g20.o
 obj-$(CONFIG_MACH_PORTUXG20)   += board-stamp9g20.o
-obj-$(CONFIG_MACH_PCONTROL_G20)        += board-pcontrol-g20.o
+obj-$(CONFIG_MACH_PCONTROL_G20)        += board-pcontrol-g20.o board-stamp9g20.o
 
 # AT91SAM9260/AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_SNAPPER_9260)        += board-snapper9260.o
index bba5a560e02b8c829304ffdded29038760167cdd..feb65787c30be5502985a112e4b200d0f7de8ac0 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <mach/board.h>
 #include <mach/at91sam9_smc.h>
+#include <mach/stamp9g20.h>
 
 #include "sam9_smc.h"
 #include "generic.h"
 
 static void __init pcontrol_g20_map_io(void)
 {
-       /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
-
-       /* DGBU on ttyS0. (Rx, Tx) only TTL -> JTAG connector X7 17,19 ) */
-       at91_register_uart(0, 0, 0);
+       stamp9g20_map_io();
 
        /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback  A2 */
        at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
@@ -54,9 +51,6 @@ static void __init pcontrol_g20_map_io(void)
 
        /* USART2 on ttyS3. (Rx, Tx)  9bit-Bus  Multidrop-mode  X4 */
        at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
 }
 
 
@@ -66,38 +60,6 @@ static void __init init_irq(void)
 }
 
 
-/*
- * NAND flash 512MiB 1,8V 8-bit, sector size 128 KiB
- */
-static struct atmel_nand_data __initdata nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-};
-
-/*
- * Bus timings; unit = 7.57ns
- */
-static struct sam9_smc_config __initdata nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 4,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 4,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
-                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-       .tdf_cycles             = 3,
-};
-
 static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
        .ncs_read_setup         = 16,
        .nrd_setup              = 18,
@@ -138,14 +100,6 @@ static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
        .tdf_cycles             = 1,
 } };
 
-static void __init add_device_nand(void)
-{
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(3, &nand_smc_config);
-       at91_add_device_nand(&nand_data);
-}
-
-
 static void __init add_device_pcontrol(void)
 {
        /* configure chip-select 4 (IO compatible to 8051  X4 ) */
@@ -155,23 +109,6 @@ static void __init add_device_pcontrol(void)
 }
 
 
-/*
- * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
- */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static struct mci_platform_data __initdata mmc_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-       },
-};
-#else
-static struct at91_mmc_data __initdata mmc_data = {
-       .wire4          = 1,
-};
-#endif
-
-
 /*
  * USB Host port
  */
@@ -265,42 +202,13 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = {
 };
 
 
-/*
- * Dallas 1-Wire  DS2431
- */
-static struct w1_gpio_platform_data w1_gpio_pdata = {
-       .pin            = AT91_PIN_PA29,
-       .is_open_drain  = 1,
-};
-
-static struct platform_device w1_device = {
-       .name                   = "w1-gpio",
-       .id                     = -1,
-       .dev.platform_data      = &w1_gpio_pdata,
-};
-
-static void add_wire1(void)
-{
-       at91_set_GPIO_periph(w1_gpio_pdata.pin, 1);
-       at91_set_multi_drive(w1_gpio_pdata.pin, 1);
-       platform_device_register(&w1_device);
-}
-
-
 static void __init pcontrol_g20_board_init(void)
 {
-       at91_add_device_serial();
-       add_device_nand();
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-       at91_add_device_mci(0, &mmc_data);
-#else
-       at91_add_device_mmc(0, &mmc_data);
-#endif
+       stamp9g20_board_init();
        at91_add_device_usbh(&usbh_data);
        at91_add_device_eth(&macb_data);
        at91_add_device_i2c(pcontrol_g20_i2c_devices,
                ARRAY_SIZE(pcontrol_g20_i2c_devices));
-       add_wire1();
        add_device_pcontrol();
        at91_add_device_spi(pcontrol_g20_spi_devices,
                ARRAY_SIZE(pcontrol_g20_spi_devices));
index 5206eef4a67eba12e1b22bd7ae0faa48ce29271a..f8902b118960d84f4d9bf6c57d3a28e9c302df64 100644 (file)
@@ -32,7 +32,7 @@
 #include "generic.h"
 
 
-static void __init portuxg20_map_io(void)
+void __init stamp9g20_map_io(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
        at91sam9260_initialize(18432000);
@@ -40,6 +40,24 @@ static void __init portuxg20_map_io(void)
        /* DGBU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
 
+       /* set serial console to ttyS0 (ie, DBGU) */
+       at91_set_serial_console(0);
+}
+
+static void __init stamp9g20evb_map_io(void)
+{
+       stamp9g20_map_io();
+
+       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+                                               | ATMEL_UART_DTR | ATMEL_UART_DSR
+                                               | ATMEL_UART_DCD | ATMEL_UART_RI);
+}
+
+static void __init portuxg20_map_io(void)
+{
+       stamp9g20_map_io();
+
        /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
        at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
                                                | ATMEL_UART_DTR | ATMEL_UART_DSR
@@ -56,26 +74,6 @@ static void __init portuxg20_map_io(void)
 
        /* USART5 on ttyS6. (Rx, Tx only) */
        at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
-}
-
-static void __init stamp9g20_map_io(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
-
-       /* DGBU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                                               | ATMEL_UART_DTR | ATMEL_UART_DSR
-                                               | ATMEL_UART_DCD | ATMEL_UART_RI);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
 }
 
 static void __init init_irq(void)
@@ -156,7 +154,7 @@ static struct at91_udc_data __initdata portuxg20_udc_data = {
        .pullup_pin     = 0,            /* pull-up driven by UDC */
 };
 
-static struct at91_udc_data __initdata stamp9g20_udc_data = {
+static struct at91_udc_data __initdata stamp9g20evb_udc_data = {
        .vbus_pin       = AT91_PIN_PA22,
        .pullup_pin     = 0,            /* pull-up driven by UDC */
 };
@@ -190,7 +188,7 @@ static struct gpio_led portuxg20_leds[] = {
        }
 };
 
-static struct gpio_led stamp9g20_leds[] = {
+static struct gpio_led stamp9g20evb_leds[] = {
        {
                .name                   = "D8",
                .gpio                   = AT91_PIN_PB18,
@@ -250,7 +248,7 @@ void add_w1(void)
 }
 
 
-static void __init generic_board_init(void)
+void __init stamp9g20_board_init(void)
 {
        /* Serial */
        at91_add_device_serial();
@@ -262,34 +260,40 @@ static void __init generic_board_init(void)
 #else
        at91_add_device_mmc(0, &mmc_data);
 #endif
-       /* USB Host */
-       at91_add_device_usbh(&usbh_data);
-       /* Ethernet */
-       at91_add_device_eth(&macb_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
        /* W1 */
        add_w1();
 }
 
 static void __init portuxg20_board_init(void)
 {
-       generic_board_init();
-       /* SPI */
-       at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));
+       stamp9g20_board_init();
+       /* USB Host */
+       at91_add_device_usbh(&usbh_data);
        /* USB Device */
        at91_add_device_udc(&portuxg20_udc_data);
+       /* Ethernet */
+       at91_add_device_eth(&macb_data);
+       /* I2C */
+       at91_add_device_i2c(NULL, 0);
+       /* SPI */
+       at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));
        /* LEDs */
        at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds));
 }
 
-static void __init stamp9g20_board_init(void)
+static void __init stamp9g20evb_board_init(void)
 {
-       generic_board_init();
+       stamp9g20_board_init();
+       /* USB Host */
+       at91_add_device_usbh(&usbh_data);
        /* USB Device */
-       at91_add_device_udc(&stamp9g20_udc_data);
+       at91_add_device_udc(&stamp9g20evb_udc_data);
+       /* Ethernet */
+       at91_add_device_eth(&macb_data);
+       /* I2C */
+       at91_add_device_i2c(NULL, 0);
        /* LEDs */
-       at91_gpio_leds(stamp9g20_leds, ARRAY_SIZE(stamp9g20_leds));
+       at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds));
 }
 
 MACHINE_START(PORTUXG20, "taskit PortuxG20")
@@ -305,7 +309,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")
        /* Maintainer: taskit GmbH */
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
-       .map_io         = stamp9g20_map_io,
+       .map_io         = stamp9g20evb_map_io,
        .init_irq       = init_irq,
-       .init_machine   = stamp9g20_board_init,
+       .init_machine   = stamp9g20evb_board_init,
 MACHINE_END
index 7525cee3983f7252fac0542be5955a490ca6869b..9113da6845f17482437ed984bd978b9b28378dfe 100644 (file)
@@ -658,7 +658,7 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)
        /* Now set uhpck values */
        uhpck.parent = &utmi_clk;
        uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
-       uhpck.rate_hz = utmi_clk.parent->rate_hz;
+       uhpck.rate_hz = utmi_clk.rate_hz;
        uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);
 }
 
diff --git a/arch/arm/mach-at91/include/mach/stamp9g20.h b/arch/arm/mach-at91/include/mach/stamp9g20.h
new file mode 100644 (file)
index 0000000..6120f9c
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __MACH_STAMP9G20_H
+#define __MACH_STAMP9G20_H
+
+void stamp9g20_map_io(void);
+void stamp9g20_board_init(void);
+
+#endif
index 0b1c07ffa2f1271c9cd05feb7e10b26e006dec7d..6ee19504845f3b476980e9e79307fc3735331d03 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o
+obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o dma.o
 obj-y += clock.o clock_data.o opp_data.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
new file mode 100644 (file)
index 0000000..d855934
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ * OMAP1/OMAP7xx - specific DMA driver
+ *
+ * Copyright (C) 2003 - 2008 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
+ * Graphics DMA and LCD DMA graphics tranformations
+ * by Imre Deak <imre.deak@nokia.com>
+ * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
+ * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Converted DMA library into platform driver
+ *                   - G, Manjunath Kondaiah <manjugk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <plat/dma.h>
+#include <plat/tc.h>
+#include <plat/irqs.h>
+
+#define OMAP1_DMA_BASE                 (0xfffed800)
+#define OMAP1_LOGICAL_DMA_CH_COUNT     17
+#define OMAP1_DMA_STRIDE               0x40
+
+static u32 errata;
+static u32 enable_1510_mode;
+static u8 dma_stride;
+static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
+
+static u16 reg_map[] = {
+       [GCR]           = 0x400,
+       [GSCR]          = 0x404,
+       [GRST1]         = 0x408,
+       [HW_ID]         = 0x442,
+       [PCH2_ID]       = 0x444,
+       [PCH0_ID]       = 0x446,
+       [PCH1_ID]       = 0x448,
+       [PCHG_ID]       = 0x44a,
+       [PCHD_ID]       = 0x44c,
+       [CAPS_0]        = 0x44e,
+       [CAPS_1]        = 0x452,
+       [CAPS_2]        = 0x456,
+       [CAPS_3]        = 0x458,
+       [CAPS_4]        = 0x45a,
+       [PCH2_SR]       = 0x460,
+       [PCH0_SR]       = 0x480,
+       [PCH1_SR]       = 0x482,
+       [PCHD_SR]       = 0x4c0,
+
+       /* Common Registers */
+       [CSDP]          = 0x00,
+       [CCR]           = 0x02,
+       [CICR]          = 0x04,
+       [CSR]           = 0x06,
+       [CEN]           = 0x10,
+       [CFN]           = 0x12,
+       [CSFI]          = 0x14,
+       [CSEI]          = 0x16,
+       [CPC]           = 0x18, /* 15xx only */
+       [CSAC]          = 0x18,
+       [CDAC]          = 0x1a,
+       [CDEI]          = 0x1c,
+       [CDFI]          = 0x1e,
+       [CLNK_CTRL]     = 0x28,
+
+       /* Channel specific register offsets */
+       [CSSA]          = 0x08,
+       [CDSA]          = 0x0c,
+       [COLOR]         = 0x20,
+       [CCR2]          = 0x24,
+       [LCH_CTRL]      = 0x2a,
+};
+
+static struct resource res[] __initdata = {
+       [0] = {
+               .start  = OMAP1_DMA_BASE,
+               .end    = OMAP1_DMA_BASE + SZ_2K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .name   = "0",
+               .start  = INT_DMA_CH0_6,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               .name   = "1",
+               .start  = INT_DMA_CH1_7,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [3] = {
+               .name   = "2",
+               .start  = INT_DMA_CH2_8,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [4] = {
+               .name   = "3",
+               .start  = INT_DMA_CH3,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [5] = {
+               .name   = "4",
+               .start  = INT_DMA_CH4,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [6] = {
+               .name   = "5",
+               .start  = INT_DMA_CH5,
+               .flags  = IORESOURCE_IRQ,
+       },
+       /* Handled in lcd_dma.c */
+       [7] = {
+               .name   = "6",
+               .start  = INT_1610_DMA_CH6,
+               .flags  = IORESOURCE_IRQ,
+       },
+       /* irq's for omap16xx and omap7xx */
+       [8] = {
+               .name   = "7",
+               .start  = INT_1610_DMA_CH7,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [9] = {
+               .name   = "8",
+               .start  = INT_1610_DMA_CH8,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [10] = {
+               .name  = "9",
+               .start = INT_1610_DMA_CH9,
+               .flags = IORESOURCE_IRQ,
+       },
+       [11] = {
+               .name  = "10",
+               .start = INT_1610_DMA_CH10,
+               .flags = IORESOURCE_IRQ,
+       },
+       [12] = {
+               .name  = "11",
+               .start = INT_1610_DMA_CH11,
+               .flags = IORESOURCE_IRQ,
+       },
+       [13] = {
+               .name  = "12",
+               .start = INT_1610_DMA_CH12,
+               .flags = IORESOURCE_IRQ,
+       },
+       [14] = {
+               .name  = "13",
+               .start = INT_1610_DMA_CH13,
+               .flags = IORESOURCE_IRQ,
+       },
+       [15] = {
+               .name  = "14",
+               .start = INT_1610_DMA_CH14,
+               .flags = IORESOURCE_IRQ,
+       },
+       [16] = {
+               .name  = "15",
+               .start = INT_1610_DMA_CH15,
+               .flags = IORESOURCE_IRQ,
+       },
+       [17] = {
+               .name  = "16",
+               .start = INT_DMA_LCD,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static void __iomem *dma_base;
+static inline void dma_write(u32 val, int reg, int lch)
+{
+       u8  stride;
+       u32 offset;
+
+       stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+       offset = reg_map[reg] + (stride * lch);
+
+       __raw_writew(val, dma_base + offset);
+       if ((reg > CLNK_CTRL && reg < CCEN) ||
+                       (reg > PCHD_ID && reg < CAPS_2)) {
+               u32 offset2 = reg_map[reg] + 2 + (stride * lch);
+               __raw_writew(val >> 16, dma_base + offset2);
+       }
+}
+
+static inline u32 dma_read(int reg, int lch)
+{
+       u8 stride;
+       u32 offset, val;
+
+       stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+       offset = reg_map[reg] + (stride * lch);
+
+       val = __raw_readw(dma_base + offset);
+       if ((reg > CLNK_CTRL && reg < CCEN) ||
+                       (reg > PCHD_ID && reg < CAPS_2)) {
+               u16 upper;
+               u32 offset2 = reg_map[reg] + 2 + (stride * lch);
+               upper = __raw_readw(dma_base + offset2);
+               val |= (upper << 16);
+       }
+       return val;
+}
+
+static void omap1_clear_lch_regs(int lch)
+{
+       int i = dma_common_ch_start;
+
+       for (; i <= dma_common_ch_end; i += 1)
+               dma_write(0, i, lch);
+}
+
+static void omap1_clear_dma(int lch)
+{
+       u32 l;
+
+       l = dma_read(CCR, lch);
+       l &= ~OMAP_DMA_CCR_EN;
+       dma_write(l, CCR, lch);
+
+       /* Clear pending interrupts */
+       l = dma_read(CSR, lch);
+}
+
+static void omap1_show_dma_caps(void)
+{
+       if (enable_1510_mode) {
+               printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
+       } else {
+               u16 w;
+               printk(KERN_INFO "OMAP DMA hardware version %d\n",
+                                                       dma_read(HW_ID, 0));
+               printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
+                       dma_read(CAPS_0, 0), dma_read(CAPS_1, 0),
+                       dma_read(CAPS_2, 0), dma_read(CAPS_3, 0),
+                       dma_read(CAPS_4, 0));
+
+               /* Disable OMAP 3.0/3.1 compatibility mode. */
+               w = dma_read(GSCR, 0);
+               w |= 1 << 3;
+               dma_write(w, GSCR, 0);
+       }
+       return;
+}
+
+static u32 configure_dma_errata(void)
+{
+
+       /*
+        * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+        * read before the DMA controller finished disabling the channel.
+        */
+       if (!cpu_is_omap15xx())
+               SET_DMA_ERRATA(DMA_ERRATA_3_3);
+
+       return errata;
+}
+
+static int __init omap1_system_dma_init(void)
+{
+       struct omap_system_dma_plat_info        *p;
+       struct omap_dma_dev_attr                *d;
+       struct platform_device                  *pdev;
+       int ret;
+
+       pdev = platform_device_alloc("omap_dma_system", 0);
+       if (!pdev) {
+               pr_err("%s: Unable to device alloc for dma\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       dma_base = ioremap(res[0].start, resource_size(&res[0]));
+       if (!dma_base) {
+               pr_err("%s: Unable to ioremap\n", __func__);
+               return -ENODEV;
+       }
+
+       ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+       if (ret) {
+               dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+                       __func__, pdev->name, pdev->id);
+               goto exit_device_del;
+       }
+
+       p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+       if (!p) {
+               dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n",
+                       __func__, pdev->name);
+               ret = -ENOMEM;
+               goto exit_device_put;
+       }
+
+       d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
+       if (!d) {
+               dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n",
+                       __func__, pdev->name);
+               ret = -ENOMEM;
+               goto exit_release_p;
+       }
+
+       d->lch_count            = OMAP1_LOGICAL_DMA_CH_COUNT;
+
+       /* Valid attributes for omap1 plus processors */
+       if (cpu_is_omap15xx())
+               d->dev_caps = ENABLE_1510_MODE;
+       enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
+
+       d->dev_caps             |= SRC_PORT;
+       d->dev_caps             |= DST_PORT;
+       d->dev_caps             |= SRC_INDEX;
+       d->dev_caps             |= DST_INDEX;
+       d->dev_caps             |= IS_BURST_ONLY4;
+       d->dev_caps             |= CLEAR_CSR_ON_READ;
+       d->dev_caps             |= IS_WORD_16;
+
+
+       d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+                                       (d->lch_count), GFP_KERNEL);
+       if (!d->chan) {
+               dev_err(&pdev->dev, "%s: Memory allocation failed"
+                                       "for d->chan!!!\n", __func__);
+               goto exit_release_d;
+       }
+
+       if (cpu_is_omap15xx())
+               d->chan_count = 9;
+       else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
+               if (!(d->dev_caps & ENABLE_1510_MODE))
+                       d->chan_count = 16;
+               else
+                       d->chan_count = 9;
+       }
+
+       p->dma_attr = d;
+
+       p->show_dma_caps        = omap1_show_dma_caps;
+       p->clear_lch_regs       = omap1_clear_lch_regs;
+       p->clear_dma            = omap1_clear_dma;
+       p->dma_write            = dma_write;
+       p->dma_read             = dma_read;
+       p->disable_irq_lch      = NULL;
+
+       p->errata = configure_dma_errata();
+
+       ret = platform_device_add_data(pdev, p, sizeof(*p));
+       if (ret) {
+               dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+                       __func__, pdev->name, pdev->id);
+               goto exit_release_chan;
+       }
+
+       ret = platform_device_add(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+                       __func__, pdev->name, pdev->id);
+               goto exit_release_chan;
+       }
+
+       dma_stride              = OMAP1_DMA_STRIDE;
+       dma_common_ch_start     = CPC;
+       dma_common_ch_end       = COLOR;
+
+       return ret;
+
+exit_release_chan:
+       kfree(d->chan);
+exit_release_d:
+       kfree(d);
+exit_release_p:
+       kfree(p);
+exit_device_put:
+       platform_device_put(pdev);
+exit_device_del:
+       platform_device_del(pdev);
+
+       return ret;
+}
+arch_initcall(omap1_system_dma_init);
index e11943d77fe0e1814eacb99742e5c1f9153d33a3..1b699d3c6cb8bd74c0a3e5ce43dcfc35dadf3d6a 100644 (file)
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
-        common.o gpio.o
+        common.o gpio.o dma.o
 
 omap-2-3-common                                = irq.o sdrc.o prm2xxx_3xxx.o
 hwmod-common                           = omap_hwmod.o \
index 1fa3294b6048b443a3b279ec8b14f78984c38246..0269bb055b693f14b0c78e967047e3c2cbdb2594 100644 (file)
@@ -239,9 +239,19 @@ void omap3_save_scratchpad_contents(void)
        struct omap3_scratchpad_prcm_block prcm_block_contents;
        struct omap3_scratchpad_sdrc_block sdrc_block_contents;
 
-       /* Populate the Scratchpad contents */
+       /*
+        * Populate the Scratchpad contents
+        *
+        * The "get_*restore_pointer" functions are used to provide a
+        * physical restore address where the ROM code jumps while waking
+        * up from MPU OFF/OSWR state.
+        * The restore pointer is stored into the scratchpad.
+        */
        scratchpad_contents.boot_config_ptr = 0x0;
-       if (omap_rev() != OMAP3430_REV_ES3_0 &&
+       if (cpu_is_omap3630())
+               scratchpad_contents.public_restore_ptr =
+                       virt_to_phys(get_omap3630_restore_pointer());
+       else if (omap_rev() != OMAP3430_REV_ES3_0 &&
                                        omap_rev() != OMAP3430_REV_ES3_1)
                scratchpad_contents.public_restore_ptr =
                        virt_to_phys(get_restore_pointer());
@@ -474,4 +484,12 @@ void omap3_control_restore_context(void)
        omap_ctrl_writel(control_context.csi, OMAP343X_CONTROL_CSI);
        return;
 }
+
+void omap3630_ctrl_disable_rta(void)
+{
+       if (!cpu_is_omap3630())
+               return;
+       omap_ctrl_writel(OMAP36XX_RTA_DISABLE, OMAP36XX_CONTROL_MEM_RTA_CTRL);
+}
+
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
index b6c6b7c450b303d80f20247a37904da4ed6d2666..6e5f7e512ff7da063dbeb9448670f38cefd486e6 100644 (file)
 #define OMAP343X_CONTROL_WKUP_DEBOBS3 (OMAP343X_CONTROL_GENERAL_WKUP + 0x014)
 #define OMAP343X_CONTROL_WKUP_DEBOBS4 (OMAP343X_CONTROL_GENERAL_WKUP + 0x018)
 
+/* 36xx-only RTA - Retention till Accesss control registers and bits */
+#define OMAP36XX_CONTROL_MEM_RTA_CTRL  0x40C
+#define OMAP36XX_RTA_DISABLE           0x0
+
 /* 34xx D2D idle-related pins, handled by PM core */
 #define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250
 #define OMAP3_PADCONF_SAD2D_IDLEACK    0x254
 #define OMAP343X_SCRATCHPAD_ROM                (OMAP343X_CTRL_BASE + 0x860)
 #define OMAP343X_SCRATCHPAD            (OMAP343X_CTRL_BASE + 0x910)
 #define OMAP343X_SCRATCHPAD_ROM_OFFSET 0x19C
+#define OMAP343X_SCRATCHPAD_REGADDR(reg)       OMAP2_L4_IO_ADDRESS(\
+                                               OMAP343X_SCRATCHPAD + reg)
 
 /* AM35XX_CONTROL_IPSS_CLK_CTRL bits */
 #define AM35XX_USBOTG_VBUSP_CLK_SHIFT   0
@@ -347,10 +353,11 @@ extern void omap3_save_scratchpad_contents(void);
 extern void omap3_clear_scratchpad_contents(void);
 extern u32 *get_restore_pointer(void);
 extern u32 *get_es3_restore_pointer(void);
+extern u32 *get_omap3630_restore_pointer(void);
 extern u32 omap3_arm_context[128];
 extern void omap3_control_save_context(void);
 extern void omap3_control_restore_context(void);
-
+extern void omap3630_ctrl_disable_rta(void);
 #else
 #define omap_ctrl_base_get()           0
 #define omap_ctrl_readb(x)             0
index 0d50b45d041c1d30d1f2aa1b8c84ed8ad7b1d667..0fb619c52588fee0a668191c0ee16cc1a3e435d0 100644 (file)
@@ -293,25 +293,26 @@ select_state:
 DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
 
 /**
- * omap3_cpuidle_update_states - Update the cpuidle states.
+ * omap3_cpuidle_update_states() - Update the cpuidle states
+ * @mpu_deepest_state: Enable states upto and including this for mpu domain
+ * @core_deepest_state:        Enable states upto and including this for core domain
  *
- * Currently, this function toggles the validity of idle states based upon
- * the flag 'enable_off_mode'. When the flag is set all states are valid.
- * Else, states leading to OFF state set to be invalid.
+ * This goes through the list of states available and enables and disables the
+ * validity of C states based on deepest state that can be achieved for the
+ * variable domain
  */
-void omap3_cpuidle_update_states(void)
+void omap3_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state)
 {
        int i;
 
        for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) {
                struct omap3_processor_cx *cx = &omap3_power_states[i];
 
-               if (enable_off_mode) {
+               if ((cx->mpu_state >= mpu_deepest_state) &&
+                   (cx->core_state >= core_deepest_state)) {
                        cx->valid = 1;
                } else {
-                       if ((cx->mpu_state == PWRDM_POWER_OFF) ||
-                               (cx->core_state == PWRDM_POWER_OFF))
-                               cx->valid = 0;
+                       cx->valid = 0;
                }
        }
 }
@@ -452,6 +453,18 @@ void omap_init_power_states(void)
        omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF;
        omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID |
                                CPUIDLE_FLAG_CHECK_BM;
+
+       /*
+        * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
+        * enable OFF mode in a stable form for previous revisions.
+        * we disable C7 state as a result.
+        */
+       if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
+               omap3_power_states[OMAP3_STATE_C7].valid = 0;
+               cpuidle_params_table[OMAP3_STATE_C7].valid = 0;
+               WARN_ONCE(1, "%s: core off state C7 disabled due to i583\n",
+                               __func__);
+       }
 }
 
 struct cpuidle_driver omap3_idle_driver = {
@@ -504,7 +517,10 @@ int __init omap3_idle_init(void)
                return -EINVAL;
        dev->state_count = count;
 
-       omap3_cpuidle_update_states();
+       if (enable_off_mode)
+               omap3_cpuidle_update_states(PWRDM_POWER_OFF, PWRDM_POWER_OFF);
+       else
+               omap3_cpuidle_update_states(PWRDM_POWER_RET, PWRDM_POWER_RET);
 
        if (cpuidle_register_device(dev)) {
                printk(KERN_ERR "%s: CPUidle register device failed\n",
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
new file mode 100644 (file)
index 0000000..d2f15f5
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * OMAP2+ DMA driver
+ *
+ * Copyright (C) 2003 - 2008 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
+ * Graphics DMA and LCD DMA graphics tranformations
+ * by Imre Deak <imre.deak@nokia.com>
+ * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
+ * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Converted DMA library into platform driver
+ *     - G, Manjunath Kondaiah <manjugk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <plat/dma.h>
+
+#define OMAP2_DMA_STRIDE       0x60
+
+static u32 errata;
+static u8 dma_stride;
+
+static struct omap_dma_dev_attr *d;
+
+static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
+
+static u16 reg_map[] = {
+       [REVISION]              = 0x00,
+       [GCR]                   = 0x78,
+       [IRQSTATUS_L0]          = 0x08,
+       [IRQSTATUS_L1]          = 0x0c,
+       [IRQSTATUS_L2]          = 0x10,
+       [IRQSTATUS_L3]          = 0x14,
+       [IRQENABLE_L0]          = 0x18,
+       [IRQENABLE_L1]          = 0x1c,
+       [IRQENABLE_L2]          = 0x20,
+       [IRQENABLE_L3]          = 0x24,
+       [SYSSTATUS]             = 0x28,
+       [OCP_SYSCONFIG]         = 0x2c,
+       [CAPS_0]                = 0x64,
+       [CAPS_2]                = 0x6c,
+       [CAPS_3]                = 0x70,
+       [CAPS_4]                = 0x74,
+
+       /* Common register offsets */
+       [CCR]                   = 0x80,
+       [CLNK_CTRL]             = 0x84,
+       [CICR]                  = 0x88,
+       [CSR]                   = 0x8c,
+       [CSDP]                  = 0x90,
+       [CEN]                   = 0x94,
+       [CFN]                   = 0x98,
+       [CSEI]                  = 0xa4,
+       [CSFI]                  = 0xa8,
+       [CDEI]                  = 0xac,
+       [CDFI]                  = 0xb0,
+       [CSAC]                  = 0xb4,
+       [CDAC]                  = 0xb8,
+
+       /* Channel specific register offsets */
+       [CSSA]                  = 0x9c,
+       [CDSA]                  = 0xa0,
+       [CCEN]                  = 0xbc,
+       [CCFN]                  = 0xc0,
+       [COLOR]                 = 0xc4,
+
+       /* OMAP4 specific registers */
+       [CDP]                   = 0xd0,
+       [CNDP]                  = 0xd4,
+       [CCDN]                  = 0xd8,
+};
+
+static struct omap_device_pm_latency omap2_dma_latency[] = {
+       {
+               .deactivate_func = omap_device_idle_hwmods,
+               .activate_func   = omap_device_enable_hwmods,
+               .flags           = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+       },
+};
+
+static void __iomem *dma_base;
+static inline void dma_write(u32 val, int reg, int lch)
+{
+       u8  stride;
+       u32 offset;
+
+       stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+       offset = reg_map[reg] + (stride * lch);
+       __raw_writel(val, dma_base + offset);
+}
+
+static inline u32 dma_read(int reg, int lch)
+{
+       u8 stride;
+       u32 offset, val;
+
+       stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+       offset = reg_map[reg] + (stride * lch);
+       val = __raw_readl(dma_base + offset);
+       return val;
+}
+
+static inline void omap2_disable_irq_lch(int lch)
+{
+       u32 val;
+
+       val = dma_read(IRQENABLE_L0, lch);
+       val &= ~(1 << lch);
+       dma_write(val, IRQENABLE_L0, lch);
+}
+
+static void omap2_clear_dma(int lch)
+{
+       int i = dma_common_ch_start;
+
+       for (; i <= dma_common_ch_end; i += 1)
+               dma_write(0, i, lch);
+}
+
+static void omap2_show_dma_caps(void)
+{
+       u8 revision = dma_read(REVISION, 0) & 0xff;
+       printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
+                               revision >> 4, revision & 0xf);
+       return;
+}
+
+static u32 configure_dma_errata(void)
+{
+
+       /*
+        * Errata applicable for OMAP2430ES1.0 and all omap2420
+        *
+        * I.
+        * Erratum ID: Not Available
+        * Inter Frame DMA buffering issue DMA will wrongly
+        * buffer elements if packing and bursting is enabled. This might
+        * result in data gets stalled in FIFO at the end of the block.
+        * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
+        * guarantee no data will stay in the DMA FIFO in case inter frame
+        * buffering occurs
+        *
+        * II.
+        * Erratum ID: Not Available
+        * DMA may hang when several channels are used in parallel
+        * In the following configuration, DMA channel hanging can occur:
+        * a. Channel i, hardware synchronized, is enabled
+        * b. Another channel (Channel x), software synchronized, is enabled.
+        * c. Channel i is disabled before end of transfer
+        * d. Channel i is reenabled.
+        * e. Steps 1 to 4 are repeated a certain number of times.
+        * f. A third channel (Channel y), software synchronized, is enabled.
+        * Channel x and Channel y may hang immediately after step 'f'.
+        * Workaround:
+        * For any channel used - make sure NextLCH_ID is set to the value j.
+        */
+       if (cpu_is_omap2420() || (cpu_is_omap2430() &&
+                               (omap_type() == OMAP2430_REV_ES1_0))) {
+
+               SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING);
+               SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS);
+       }
+
+       /*
+        * Erratum ID: i378: OMAP2+: sDMA Channel is not disabled
+        * after a transaction error.
+        * Workaround: SW should explicitely disable the channel.
+        */
+       if (cpu_class_is_omap2())
+               SET_DMA_ERRATA(DMA_ERRATA_i378);
+
+       /*
+        * Erratum ID: i541: sDMA FIFO draining does not finish
+        * If sDMA channel is disabled on the fly, sDMA enters standby even
+        * through FIFO Drain is still in progress
+        * Workaround: Put sDMA in NoStandby more before a logical channel is
+        * disabled, then put it back to SmartStandby right after the channel
+        * finishes FIFO draining.
+        */
+       if (cpu_is_omap34xx())
+               SET_DMA_ERRATA(DMA_ERRATA_i541);
+
+       /*
+        * Erratum ID: i88 : Special programming model needed to disable DMA
+        * before end of block.
+        * Workaround: software must ensure that the DMA is configured in No
+        * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01")
+        */
+       if (omap_type() == OMAP3430_REV_ES1_0)
+               SET_DMA_ERRATA(DMA_ERRATA_i88);
+
+       /*
+        * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+        * read before the DMA controller finished disabling the channel.
+        */
+       SET_DMA_ERRATA(DMA_ERRATA_3_3);
+
+       /*
+        * Erratum ID: Not Available
+        * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
+        * after secure sram context save and restore.
+        * Work around: Hence we need to manually clear those IRQs to avoid
+        * spurious interrupts. This affects only secure devices.
+        */
+       if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
+               SET_DMA_ERRATA(DMA_ROMCODE_BUG);
+
+       return errata;
+}
+
+/* One time initializations */
+static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
+{
+       struct omap_device                      *od;
+       struct omap_system_dma_plat_info        *p;
+       struct resource                         *mem;
+       char                                    *name = "omap_dma_system";
+
+       dma_stride              = OMAP2_DMA_STRIDE;
+       dma_common_ch_start     = CSDP;
+       if (cpu_is_omap3630() || cpu_is_omap4430())
+               dma_common_ch_end = CCDN;
+       else
+               dma_common_ch_end = CCFN;
+
+       p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+       if (!p) {
+               pr_err("%s: Unable to allocate pdata for %s:%s\n",
+                       __func__, name, oh->name);
+               return -ENOMEM;
+       }
+
+       p->dma_attr             = (struct omap_dma_dev_attr *)oh->dev_attr;
+       p->disable_irq_lch      = omap2_disable_irq_lch;
+       p->show_dma_caps        = omap2_show_dma_caps;
+       p->clear_dma            = omap2_clear_dma;
+       p->dma_write            = dma_write;
+       p->dma_read             = dma_read;
+
+       p->clear_lch_regs       = NULL;
+
+       p->errata               = configure_dma_errata();
+
+       od = omap_device_build(name, 0, oh, p, sizeof(*p),
+                       omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
+       kfree(p);
+       if (IS_ERR(od)) {
+               pr_err("%s: Cant build omap_device for %s:%s.\n",
+                       __func__, name, oh->name);
+               return IS_ERR(od);
+       }
+
+       mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&od->pdev.dev, "%s: no mem resource\n", __func__);
+               return -EINVAL;
+       }
+       dma_base = ioremap(mem->start, resource_size(mem));
+       if (!dma_base) {
+               dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__);
+               return -ENOMEM;
+       }
+
+       d = oh->dev_attr;
+       d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+                                       (d->lch_count), GFP_KERNEL);
+
+       if (!d->chan) {
+               dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static int __init omap2_system_dma_init(void)
+{
+       return omap_hwmod_for_each_by_class("dma",
+                       omap2_system_dma_init_dev, NULL);
+}
+arch_initcall(omap2_system_dma_init);
index d95342599793458806bfc8fa805eced2a151511e..42606f6b0cdf9209eb6246d30327e872708da683 100644 (file)
@@ -42,6 +42,7 @@ static struct omap_hwmod omap2420_gpio1_hwmod;
 static struct omap_hwmod omap2420_gpio2_hwmod;
 static struct omap_hwmod omap2420_gpio3_hwmod;
 static struct omap_hwmod omap2420_gpio4_hwmod;
+static struct omap_hwmod omap2420_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -779,6 +780,88 @@ static struct omap_hwmod omap2420_gpio4_hwmod = {
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
+/* system dma */
+static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x002c,
+       .syss_offs      = 0x0028,
+       .sysc_flags     = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
+                          SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
+                          SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_dma_hwmod_class = {
+       .name = "dma",
+       .sysc = &omap2420_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+       .dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+                                               IS_CSSA_32 | IS_CDSA_32,
+       .lch_count = 32,
+};
+
+static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = {
+       { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+       { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+       { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+       { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = {
+       {
+               .pa_start       = 0x48056000,
+               .pa_end         = 0x4a0560ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap2420_dma_system__l3 = {
+       .master         = &omap2420_dma_system_hwmod,
+       .slave          = &omap2420_l3_main_hwmod,
+       .clk            = "core_l3_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap2420_dma_system_masters[] = {
+       &omap2420_dma_system__l3,
+};
+
+/* l4_core -> dma_system */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dma_system = {
+       .master         = &omap2420_l4_core_hwmod,
+       .slave          = &omap2420_dma_system_hwmod,
+       .clk            = "sdma_ick",
+       .addr           = omap2420_dma_system_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap2420_dma_system_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dma_system_slaves[] = {
+       &omap2420_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap2420_dma_system_hwmod = {
+       .name           = "dma",
+       .class          = &omap2420_dma_hwmod_class,
+       .mpu_irqs       = omap2420_dma_system_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap2420_dma_system_irqs),
+       .main_clk       = "core_l3_ck",
+       .slaves         = omap2420_dma_system_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2420_dma_system_slaves),
+       .masters        = omap2420_dma_system_masters,
+       .masters_cnt    = ARRAY_SIZE(omap2420_dma_system_masters),
+       .dev_attr       = &dma_dev_attr,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+       .flags          = HWMOD_NO_IDLEST,
+};
+
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
        &omap2420_l3_main_hwmod,
        &omap2420_l4_core_hwmod,
@@ -797,6 +880,9 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = {
        &omap2420_gpio2_hwmod,
        &omap2420_gpio3_hwmod,
        &omap2420_gpio4_hwmod,
+
+       /* dma_system class*/
+       &omap2420_dma_system_hwmod,
        NULL,
 };
 
index ab1d662cb072d53ef173780cf69938ac854461f0..3315d241feef635887eb98d0e85b1ad2a811c582 100644 (file)
@@ -43,6 +43,7 @@ static struct omap_hwmod omap2430_gpio2_hwmod;
 static struct omap_hwmod omap2430_gpio3_hwmod;
 static struct omap_hwmod omap2430_gpio4_hwmod;
 static struct omap_hwmod omap2430_gpio5_hwmod;
+static struct omap_hwmod omap2430_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -838,6 +839,88 @@ static struct omap_hwmod omap2430_gpio5_hwmod = {
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
+/* dma_system */
+static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x002c,
+       .syss_offs      = 0x0028,
+       .sysc_flags     = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
+                          SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
+                          SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_dma_hwmod_class = {
+       .name = "dma",
+       .sysc = &omap2430_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+       .dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+                               IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+       .lch_count = 32,
+};
+
+static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
+       { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+       { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+       { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+       { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = {
+       {
+               .pa_start       = 0x48056000,
+               .pa_end         = 0x4a0560ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = {
+       .master         = &omap2430_dma_system_hwmod,
+       .slave          = &omap2430_l3_main_hwmod,
+       .clk            = "core_l3_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap2430_dma_system_masters[] = {
+       &omap2430_dma_system__l3,
+};
+
+/* l4_core -> dma_system */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = {
+       .master         = &omap2430_l4_core_hwmod,
+       .slave          = &omap2430_dma_system_hwmod,
+       .clk            = "sdma_ick",
+       .addr           = omap2430_dma_system_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap2430_dma_system_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = {
+       &omap2430_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap2430_dma_system_hwmod = {
+       .name           = "dma",
+       .class          = &omap2430_dma_hwmod_class,
+       .mpu_irqs       = omap2430_dma_system_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap2430_dma_system_irqs),
+       .main_clk       = "core_l3_ck",
+       .slaves         = omap2430_dma_system_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2430_dma_system_slaves),
+       .masters        = omap2430_dma_system_masters,
+       .masters_cnt    = ARRAY_SIZE(omap2430_dma_system_masters),
+       .dev_attr       = &dma_dev_attr,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+       .flags          = HWMOD_NO_IDLEST,
+};
+
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
        &omap2430_l3_main_hwmod,
        &omap2430_l4_core_hwmod,
@@ -857,6 +940,9 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = {
        &omap2430_gpio3_hwmod,
        &omap2430_gpio4_hwmod,
        &omap2430_gpio5_hwmod,
+
+       /* dma_system class*/
+       &omap2430_dma_system_hwmod,
        NULL,
 };
 
index 2687be10d7aa9619ca3c6e5e7b6172b9cb6e51b3..d5acb63ba9e0f1cc5bd2a93af16849e470adae44 100644 (file)
@@ -52,6 +52,8 @@ static struct omap_hwmod omap3xxx_gpio4_hwmod;
 static struct omap_hwmod omap3xxx_gpio5_hwmod;
 static struct omap_hwmod omap3xxx_gpio6_hwmod;
 
+static struct omap_hwmod omap3xxx_dma_system_hwmod;
+
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
        .master = &omap3xxx_l3_main_hwmod,
@@ -1090,6 +1092,98 @@ static struct omap_hwmod omap3xxx_gpio6_hwmod = {
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = {
+       .master         = &omap3xxx_dma_system_hwmod,
+       .slave          = &omap3xxx_l3_main_hwmod,
+       .clk            = "core_l3_ick",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+       .dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+                               IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+       .lch_count = 32,
+};
+
+static struct omap_hwmod_class_sysconfig omap3xxx_dma_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x002c,
+       .syss_offs      = 0x0028,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+                          SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+                          MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_dma_hwmod_class = {
+       .name = "dma",
+       .sysc = &omap3xxx_dma_sysc,
+};
+
+/* dma_system */
+static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = {
+       { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+       { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+       { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+       { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
+       {
+               .pa_start       = 0x48056000,
+               .pa_end         = 0x4a0560ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dma_system_masters[] = {
+       &omap3xxx_dma_system__l3,
+};
+
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = {
+       .master         = &omap3xxx_l4_core_hwmod,
+       .slave          = &omap3xxx_dma_system_hwmod,
+       .clk            = "core_l4_ick",
+       .addr           = omap3xxx_dma_system_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_dma_system_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
+       &omap3xxx_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap3xxx_dma_system_hwmod = {
+       .name           = "dma",
+       .class          = &omap3xxx_dma_hwmod_class,
+       .mpu_irqs       = omap3xxx_dma_system_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_dma_system_irqs),
+       .main_clk       = "core_l3_ick",
+       .prcm = {
+               .omap2 = {
+                       .module_offs            = CORE_MOD,
+                       .prcm_reg_id            = 1,
+                       .module_bit             = OMAP3430_ST_SDMA_SHIFT,
+                       .idlest_reg_id          = 1,
+                       .idlest_idle_bit        = OMAP3430_ST_SDMA_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_dma_system_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_dma_system_slaves),
+       .masters        = omap3xxx_dma_system_masters,
+       .masters_cnt    = ARRAY_SIZE(omap3xxx_dma_system_masters),
+       .dev_attr       = &dma_dev_attr,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+       .flags          = HWMOD_NO_IDLEST,
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_l3_main_hwmod,
        &omap3xxx_l4_core_hwmod,
@@ -1113,6 +1207,9 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_gpio4_hwmod,
        &omap3xxx_gpio5_hwmod,
        &omap3xxx_gpio6_hwmod,
+
+       /* dma_system class*/
+       &omap3xxx_dma_system_hwmod,
        NULL,
 };
 
index d258936410fb2b0736daed549827f30c30774b0e..f9778fba8322fd61dba97cf65872a06b7667ed21 100644 (file)
@@ -23,6 +23,7 @@
 #include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
 #include <plat/gpio.h>
+#include <plat/dma.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -36,6 +37,7 @@
 #define OMAP44XX_DMA_REQ_START  1
 
 /* Backward references (IPs with Bus Master capability) */
+static struct omap_hwmod omap44xx_dma_system_hwmod;
 static struct omap_hwmod omap44xx_dmm_hwmod;
 static struct omap_hwmod omap44xx_emif_fw_hwmod;
 static struct omap_hwmod omap44xx_l3_instr_hwmod;
@@ -216,6 +218,14 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* dma_system -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = {
+       .master         = &omap44xx_dma_system_hwmod,
+       .slave          = &omap44xx_l3_main_2_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_cfg -> l3_main_2 */
 static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
        .master         = &omap44xx_l4_cfg_hwmod,
@@ -226,6 +236,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
 
 /* l3_main_2 slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
+       &omap44xx_dma_system__l3_main_2,
        &omap44xx_l3_main_1__l3_main_2,
        &omap44xx_l4_cfg__l3_main_2,
 };
@@ -1376,6 +1387,93 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = {
        .slaves_cnt     = ARRAY_SIZE(omap44xx_gpio6_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
+
+/*
+ * 'dma' class
+ * dma controller for data exchange between memory to memory (i.e. internal or
+ * external memory) and gp peripherals to memory or memory to gp peripherals
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_dma_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x002c,
+       .syss_offs      = 0x0028,
+       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+                          SYSC_HAS_EMUFREE | SYSC_HAS_MIDLEMODE |
+                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+                          SYSS_HAS_RESET_STATUS),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+                          MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+       .dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+                               IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+       .lch_count = 32,
+};
+
+static struct omap_hwmod_class omap44xx_dma_hwmod_class = {
+       .name   = "dma",
+       .sysc   = &omap44xx_dma_sysc,
+};
+
+/* dma_system */
+static struct omap_hwmod_irq_info omap44xx_dma_system_irqs[] = {
+       { .name = "0", .irq = 12 + OMAP44XX_IRQ_GIC_START },
+       { .name = "1", .irq = 13 + OMAP44XX_IRQ_GIC_START },
+       { .name = "2", .irq = 14 + OMAP44XX_IRQ_GIC_START },
+       { .name = "3", .irq = 15 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap44xx_dma_system_masters[] = {
+       &omap44xx_dma_system__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
+       {
+               .pa_start       = 0x4a056000,
+               .pa_end         = 0x4a0560ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dma_system = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_dma_system_hwmod,
+       .clk            = "l4_div_ck",
+       .addr           = omap44xx_dma_system_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_dma_system_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dma_system_slaves[] = {
+       &omap44xx_l4_cfg__dma_system,
+};
+
+static struct omap_hwmod omap44xx_dma_system_hwmod = {
+       .name           = "dma_system",
+       .class          = &omap44xx_dma_hwmod_class,
+       .mpu_irqs       = omap44xx_dma_system_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_dma_system_irqs),
+       .main_clk       = "l3_div_ck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_SDMA_SDMA_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_dma_system_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_dma_system_slaves),
+       .masters        = omap44xx_dma_system_masters,
+       .masters_cnt    = ARRAY_SIZE(omap44xx_dma_system_masters),
+       .dev_attr       = &dma_dev_attr,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
 static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
        /* dmm class */
        &omap44xx_dmm_hwmod,
@@ -1391,6 +1489,10 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
        &omap44xx_l4_cfg_hwmod,
        &omap44xx_l4_per_hwmod,
        &omap44xx_l4_wkup_hwmod,
+
+       /* dma class */
+       &omap44xx_dma_system_hwmod,
+
        /* i2c class */
        &omap44xx_i2c1_hwmod,
        &omap44xx_i2c2_hwmod,
index 59ca03b0e691c4dda171d68ffc30fce327352dbd..6ec2ee12272a31eb3774501e60ff78832b38111e 100644 (file)
@@ -143,5 +143,5 @@ static int __init omap2_common_pm_init(void)
 
        return 0;
 }
-device_initcall(omap2_common_pm_init);
+postcore_initcall(omap2_common_pm_init);
 
index a43e0697b6bc1aa520f9979a264e2111b17eec0b..8b4f45eba1b5d5843ceeb908ad232dee7d29be8e 100644 (file)
@@ -72,7 +72,7 @@ extern u32 sleep_while_idle;
 #endif
 
 #if defined(CONFIG_CPU_IDLE)
-extern void omap3_cpuidle_update_states(void);
+extern void omap3_cpuidle_update_states(u32, u32);
 #endif
 
 #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
@@ -94,9 +94,20 @@ extern void save_secure_ram_context(u32 *addr);
 extern void omap3_save_scratchpad_contents(void);
 
 extern unsigned int omap24xx_idle_loop_suspend_sz;
-extern unsigned int omap34xx_suspend_sz;
 extern unsigned int save_secure_ram_context_sz;
 extern unsigned int omap24xx_cpu_suspend_sz;
 extern unsigned int omap34xx_cpu_suspend_sz;
 
+#define PM_RTA_ERRATUM_i608            (1 << 0)
+#define PM_SDRC_WAKEUP_ERRATUM_i583    (1 << 1)
+
+#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
+extern u16 pm34xx_errata;
+#define IS_PM34XX_ERRATUM(id)          (pm34xx_errata & (id))
+extern void enable_omap3630_toggle_l2_on_restore(void);
+#else
+#define IS_PM34XX_ERRATUM(id)          0
+static inline void enable_omap3630_toggle_l2_on_restore(void) { }
+#endif         /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
+
 #endif
index aaeea49b9bdd80f6e51affaee9c3a38ff6e2368f..aea7ced9a2ff6578bd5597f615fd5937c1d17027 100644 (file)
@@ -301,14 +301,8 @@ out:
 
 static int omap2_pm_begin(suspend_state_t state)
 {
-       suspend_state = state;
-       return 0;
-}
-
-static int omap2_pm_prepare(void)
-{
-       /* We cannot sleep in idle until we have resumed */
        disable_hlt();
+       suspend_state = state;
        return 0;
 }
 
@@ -349,21 +343,15 @@ static int omap2_pm_enter(suspend_state_t state)
        return ret;
 }
 
-static void omap2_pm_finish(void)
-{
-       enable_hlt();
-}
-
 static void omap2_pm_end(void)
 {
        suspend_state = PM_SUSPEND_ON;
+       enable_hlt();
 }
 
 static struct platform_suspend_ops omap_pm_ops = {
        .begin          = omap2_pm_begin,
-       .prepare        = omap2_pm_prepare,
        .enter          = omap2_pm_enter,
-       .finish         = omap2_pm_finish,
        .end            = omap2_pm_end,
        .valid          = suspend_valid_only_mem,
 };
index 648b8c50d02422eeda2146cf3d3ebbe4b44d5a75..c45b4fa1deeb3ef0ee8dea63b656f3b522352cb6 100644 (file)
@@ -68,6 +68,9 @@ static inline bool is_suspending(void)
 #define OMAP343X_TABLE_VALUE_OFFSET       0xc0
 #define OMAP343X_CONTROL_REG_VALUE_OFFSET  0xc8
 
+/* pm34xx errata defined in pm.h */
+u16 pm34xx_errata;
+
 struct power_state {
        struct powerdomain *pwrdm;
        u32 next_state;
@@ -143,7 +146,7 @@ static void omap3_core_save_context(void)
 
        /*
         * Force write last pad into memory, as this can fail in some
-        * cases according to erratas 1.157, 1.185
+        * cases according to errata 1.157, 1.185
         */
        omap_ctrl_writel(omap_ctrl_readl(OMAP343X_PADCONF_ETK_D14),
                OMAP343X_CONTROL_MEM_WKUP + 0x2a0);
@@ -430,7 +433,7 @@ void omap_sram_idle(void)
        /*
        * On EMU/HS devices ROM code restores a SRDC value
        * from scratchpad which has automatic self refresh on timeout
-       * of AUTO_CNT = 1 enabled. This takes care of errata 1.142.
+       * of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.
        * Hence store/restore the SDRC_POWER register here.
        */
        if (omap_rev() >= OMAP3430_REV_ES3_0 &&
@@ -529,12 +532,6 @@ out:
 }
 
 #ifdef CONFIG_SUSPEND
-static int omap3_pm_prepare(void)
-{
-       disable_hlt();
-       return 0;
-}
-
 static int omap3_pm_suspend(void)
 {
        struct power_state *pwrst;
@@ -597,14 +594,10 @@ static int omap3_pm_enter(suspend_state_t unused)
        return ret;
 }
 
-static void omap3_pm_finish(void)
-{
-       enable_hlt();
-}
-
 /* Hooks to enable / disable UART interrupts during suspend */
 static int omap3_pm_begin(suspend_state_t state)
 {
+       disable_hlt();
        suspend_state = state;
        omap_uart_enable_irqs(0);
        return 0;
@@ -614,15 +607,14 @@ static void omap3_pm_end(void)
 {
        suspend_state = PM_SUSPEND_ON;
        omap_uart_enable_irqs(1);
+       enable_hlt();
        return;
 }
 
 static struct platform_suspend_ops omap_pm_ops = {
        .begin          = omap3_pm_begin,
        .end            = omap3_pm_end,
-       .prepare        = omap3_pm_prepare,
        .enter          = omap3_pm_enter,
-       .finish         = omap3_pm_finish,
        .valid          = suspend_valid_only_mem,
 };
 #endif /* CONFIG_SUSPEND */
@@ -925,12 +917,29 @@ void omap3_pm_off_mode_enable(int enable)
                state = PWRDM_POWER_RET;
 
 #ifdef CONFIG_CPU_IDLE
-       omap3_cpuidle_update_states();
+       /*
+        * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
+        * enable OFF mode in a stable form for previous revisions, restrict
+        * instead to RET
+        */
+       if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
+               omap3_cpuidle_update_states(state, PWRDM_POWER_RET);
+       else
+               omap3_cpuidle_update_states(state, state);
 #endif
 
        list_for_each_entry(pwrst, &pwrst_list, node) {
-               pwrst->next_state = state;
-               omap_set_pwrdm_state(pwrst->pwrdm, state);
+               if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) &&
+                               pwrst->pwrdm == core_pwrdm &&
+                               state == PWRDM_POWER_OFF) {
+                       pwrst->next_state = PWRDM_POWER_RET;
+                       WARN_ONCE(1,
+                               "%s: Core OFF disabled due to errata i583\n",
+                               __func__);
+               } else {
+                       pwrst->next_state = state;
+               }
+               omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
        }
 }
 
@@ -1002,6 +1011,17 @@ void omap_push_sram_idle(void)
                                save_secure_ram_context_sz);
 }
 
+static void __init pm_errata_configure(void)
+{
+       if (cpu_is_omap3630()) {
+               pm34xx_errata |= PM_RTA_ERRATUM_i608;
+               /* Enable the l2 cache toggling in sleep logic */
+               enable_omap3630_toggle_l2_on_restore();
+               if (omap_rev() < OMAP3630_REV_ES1_2)
+                       pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583;
+       }
+}
+
 static int __init omap3_pm_init(void)
 {
        struct power_state *pwrst, *tmp;
@@ -1011,6 +1031,8 @@ static int __init omap3_pm_init(void)
        if (!cpu_is_omap34xx())
                return -ENODEV;
 
+       pm_errata_configure();
+
        printk(KERN_ERR "Power Management for TI OMAP3.\n");
 
        /* XXX prcm_setup_regs needs to be before enabling hw
@@ -1058,6 +1080,14 @@ static int __init omap3_pm_init(void)
        pm_idle = omap3_pm_idle;
        omap3_idle_init();
 
+       /*
+        * RTA is disabled during initialization as per erratum i608
+        * it is safer to disable RTA by the bootloader, but we would like
+        * to be doubly sure here and prevent any mishaps.
+        */
+       if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608))
+               omap3630_ctrl_disable_rta();
+
        clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
        if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
                omap3_secure_ram_storage =
index 54544b4fc76b0dfdbfb7b4a0feca981f79596dea..6aff9961e35d51fce552362809c256e3c1e89ca8 100644 (file)
@@ -31,12 +31,6 @@ struct power_state {
 static LIST_HEAD(pwrst_list);
 
 #ifdef CONFIG_SUSPEND
-static int omap4_pm_prepare(void)
-{
-       disable_hlt();
-       return 0;
-}
-
 static int omap4_pm_suspend(void)
 {
        do_wfi();
@@ -59,28 +53,22 @@ static int omap4_pm_enter(suspend_state_t suspend_state)
        return ret;
 }
 
-static void omap4_pm_finish(void)
-{
-       enable_hlt();
-       return;
-}
-
 static int omap4_pm_begin(suspend_state_t state)
 {
+       disable_hlt();
        return 0;
 }
 
 static void omap4_pm_end(void)
 {
+       enable_hlt();
        return;
 }
 
 static struct platform_suspend_ops omap_pm_ops = {
        .begin          = omap4_pm_begin,
        .end            = omap4_pm_end,
-       .prepare        = omap4_pm_prepare,
        .enter          = omap4_pm_enter,
-       .finish         = omap4_pm_finish,
        .valid          = suspend_valid_only_mem,
 };
 #endif /* CONFIG_SUSPEND */
index 68f57bb67fc567ca3a4193f548203eb4eb54f5b0..b3f83799e6cf0701d4388aa7785049a6241fad8d 100644 (file)
@@ -74,5 +74,4 @@ static inline u32 sms_read_reg(u16 reg)
  */
 #define SDRC_MPURATE_LOOPS             96
 
-
 #endif
index 2fb205a7f285505b46cd4c75b113673fe352809b..e3b5cd76c54c6ac4f0a39344096bf5088867221f 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/arch/arm/mach-omap2/sleep.S
- *
  * (C) Copyright 2007
  * Texas Instruments
  * Karthik Dasu <karthik-dp@ti.com>
@@ -26,6 +24,7 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <plat/sram.h>
 #include <mach/io.h>
 
 #include "cm.h"
 #include "sdrc.h"
 #include "control.h"
 
-#define SDRC_SCRATCHPAD_SEM_V  0xfa00291c
-
-#define PM_PREPWSTST_CORE_V    OMAP34XX_PRM_REGADDR(CORE_MOD, \
-                               OMAP3430_PM_PREPWSTST)
-#define PM_PREPWSTST_CORE_P    0x48306AE8
-#define PM_PREPWSTST_MPU_V     OMAP34XX_PRM_REGADDR(MPU_MOD, \
-                               OMAP3430_PM_PREPWSTST)
+/*
+ * Registers access definitions
+ */
+#define SDRC_SCRATCHPAD_SEM_OFFS       0xc
+#define SDRC_SCRATCHPAD_SEM_V  OMAP343X_SCRATCHPAD_REGADDR\
+                                       (SDRC_SCRATCHPAD_SEM_OFFS)
+#define PM_PREPWSTST_CORE_P    OMAP3430_PRM_BASE + CORE_MOD +\
+                                       OMAP3430_PM_PREPWSTST
 #define PM_PWSTCTRL_MPU_P      OMAP3430_PRM_BASE + MPU_MOD + OMAP2_PM_PWSTCTRL
 #define CM_IDLEST1_CORE_V      OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST1)
-#define SRAM_BASE_P            0x40200000
-#define CONTROL_STAT           0x480022F0
-#define SCRATCHPAD_MEM_OFFS    0x310 /* Move this as correct place is
-                                      * available */
-#define SCRATCHPAD_BASE_P      (OMAP343X_CTRL_BASE + OMAP343X_CONTROL_MEM_WKUP\
-                                               + SCRATCHPAD_MEM_OFFS)
+#define CM_IDLEST_CKGEN_V      OMAP34XX_CM_REGADDR(PLL_MOD, CM_IDLEST)
+#define SRAM_BASE_P            OMAP3_SRAM_PA
+#define CONTROL_STAT           OMAP343X_CTRL_BASE + OMAP343X_CONTROL_STATUS
+#define CONTROL_MEM_RTA_CTRL   (OMAP343X_CTRL_BASE +\
+                                       OMAP36XX_CONTROL_MEM_RTA_CTRL)
+
+/* Move this as correct place is available */
+#define SCRATCHPAD_MEM_OFFS    0x310
+#define SCRATCHPAD_BASE_P      (OMAP343X_CTRL_BASE +\
+                                       OMAP343X_CONTROL_MEM_WKUP +\
+                                       SCRATCHPAD_MEM_OFFS)
 #define SDRC_POWER_V           OMAP34XX_SDRC_REGADDR(SDRC_POWER)
 #define SDRC_SYSCONFIG_P       (OMAP343X_SDRC_BASE + SDRC_SYSCONFIG)
 #define SDRC_MR_0_P            (OMAP343X_SDRC_BASE + SDRC_MR_0)
 #define SDRC_DLLA_STATUS_V     OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
 #define SDRC_DLLA_CTRL_V       OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
 
-        .text
-/* Function to acquire the semaphore in scratchpad */
-ENTRY(lock_scratchpad_sem)
-       stmfd   sp!, {lr}       @ save registers on stack
-wait_sem:
-       mov     r0,#1
-       ldr     r1, sdrc_scratchpad_sem
-wait_loop:
-       ldr     r2, [r1]        @ load the lock value
-       cmp     r2, r0          @ is the lock free ?
-       beq     wait_loop       @ not free...
-       swp     r2, r0, [r1]    @ semaphore free so lock it and proceed
-       cmp     r2, r0          @ did we succeed ?
-       beq     wait_sem        @ no - try again
-       ldmfd   sp!, {pc}       @ restore regs and return
-sdrc_scratchpad_sem:
-        .word SDRC_SCRATCHPAD_SEM_V
-ENTRY(lock_scratchpad_sem_sz)
-        .word   . - lock_scratchpad_sem
-
-        .text
-/* Function to release the scratchpad semaphore */
-ENTRY(unlock_scratchpad_sem)
-       stmfd   sp!, {lr}       @ save registers on stack
-       ldr     r3, sdrc_scratchpad_sem
-       mov     r2,#0
-       str     r2,[r3]
-       ldmfd   sp!, {pc}       @ restore regs and return
-ENTRY(unlock_scratchpad_sem_sz)
-        .word   . - unlock_scratchpad_sem
+
+/*
+ * API functions
+ */
+
+/*
+ * The "get_*restore_pointer" functions are used to provide a
+ * physical restore address where the ROM code jumps while waking
+ * up from MPU OFF/OSWR state.
+ * The restore pointer is stored into the scratchpad.
+ */
 
        .text
 /* Function call to get the restore pointer for resume from OFF */
 ENTRY(get_restore_pointer)
-        stmfd   sp!, {lr}     @ save registers on stack
+       stmfd   sp!, {lr}       @ save registers on stack
        adr     r0, restore
-        ldmfd   sp!, {pc}     @ restore regs and return
+       ldmfd   sp!, {pc}       @ restore regs and return
 ENTRY(get_restore_pointer_sz)
-        .word   . - get_restore_pointer
+       .word   . - get_restore_pointer
 
        .text
-/* Function call to get the restore pointer for for ES3 to resume from OFF */
+/* Function call to get the restore pointer for 3630 resume from OFF */
+ENTRY(get_omap3630_restore_pointer)
+       stmfd   sp!, {lr}       @ save registers on stack
+       adr     r0, restore_3630
+       ldmfd   sp!, {pc}       @ restore regs and return
+ENTRY(get_omap3630_restore_pointer_sz)
+       .word   . - get_omap3630_restore_pointer
+
+       .text
+/* Function call to get the restore pointer for ES3 to resume from OFF */
 ENTRY(get_es3_restore_pointer)
        stmfd   sp!, {lr}       @ save registers on stack
        adr     r0, restore_es3
@@ -108,54 +103,23 @@ ENTRY(get_es3_restore_pointer)
 ENTRY(get_es3_restore_pointer_sz)
        .word   . - get_es3_restore_pointer
 
-ENTRY(es3_sdrc_fix)
-       ldr     r4, sdrc_syscfg         @ get config addr
-       ldr     r5, [r4]                @ get value
-       tst     r5, #0x100              @ is part access blocked
-       it      eq
-       biceq   r5, r5, #0x100          @ clear bit if set
-       str     r5, [r4]                @ write back change
-       ldr     r4, sdrc_mr_0           @ get config addr
-       ldr     r5, [r4]                @ get value
-       str     r5, [r4]                @ write back change
-       ldr     r4, sdrc_emr2_0         @ get config addr
-       ldr     r5, [r4]                @ get value
-       str     r5, [r4]                @ write back change
-       ldr     r4, sdrc_manual_0       @ get config addr
-       mov     r5, #0x2                @ autorefresh command
-       str     r5, [r4]                @ kick off refreshes
-       ldr     r4, sdrc_mr_1           @ get config addr
-       ldr     r5, [r4]                @ get value
-       str     r5, [r4]                @ write back change
-       ldr     r4, sdrc_emr2_1         @ get config addr
-       ldr     r5, [r4]                @ get value
-       str     r5, [r4]                @ write back change
-       ldr     r4, sdrc_manual_1       @ get config addr
-       mov     r5, #0x2                @ autorefresh command
-       str     r5, [r4]                @ kick off refreshes
-       bx      lr
-sdrc_syscfg:
-       .word   SDRC_SYSCONFIG_P
-sdrc_mr_0:
-       .word   SDRC_MR_0_P
-sdrc_emr2_0:
-       .word   SDRC_EMR2_0_P
-sdrc_manual_0:
-       .word   SDRC_MANUAL_0_P
-sdrc_mr_1:
-       .word   SDRC_MR_1_P
-sdrc_emr2_1:
-       .word   SDRC_EMR2_1_P
-sdrc_manual_1:
-       .word   SDRC_MANUAL_1_P
-ENTRY(es3_sdrc_fix_sz)
-       .word   . - es3_sdrc_fix
+       .text
+/*
+ * L2 cache needs to be toggled for stable OFF mode functionality on 3630.
+ * This function sets up a flag that will allow for this toggling to take
+ * place on 3630. Hopefully some version in the future may not need this.
+ */
+ENTRY(enable_omap3630_toggle_l2_on_restore)
+       stmfd   sp!, {lr}       @ save registers on stack
+       /* Setup so that we will disable and enable l2 */
+       mov     r1, #0x1
+       str     r1, l2dis_3630
+       ldmfd   sp!, {pc}       @ restore regs and return
 
+       .text
 /* Function to call rom code to save secure ram context */
 ENTRY(save_secure_ram_context)
        stmfd   sp!, {r1-r12, lr}       @ save registers on stack
-save_secure_ram_debug:
-       /* b save_secure_ram_debug */   @ enable to debug save code
        adr     r3, api_params          @ r3 points to parameters
        str     r0, [r3,#0x4]           @ r0 has sdram address
        ldr     r12, high_mask
@@ -184,36 +148,163 @@ api_params:
 ENTRY(save_secure_ram_context_sz)
        .word   . - save_secure_ram_context
 
+/*
+ * ======================
+ * == Idle entry point ==
+ * ======================
+ */
+
 /*
  * Forces OMAP into idle state
  *
- * omap34xx_suspend() - This bit of code just executes the WFI
- * for normal idles.
+ * omap34xx_cpu_suspend() - This bit of code saves the CPU context if needed
+ * and executes the WFI instruction. Calling WFI effectively changes the
+ * power domains states to the desired target power states.
+ *
  *
- * Note: This code get's copied to internal SRAM at boot. When the OMAP
- *      wakes up it continues execution at the point it went to sleep.
+ * Notes:
+ * - this code gets copied to internal SRAM at boot and after wake-up
+ *   from OFF mode. The execution pointer in SRAM is _omap_sram_idle.
+ * - when the OMAP wakes up it continues at different execution points
+ *   depending on the low power mode (non-OFF vs OFF modes),
+ *   cf. 'Resume path for xxx mode' comments.
  */
 ENTRY(omap34xx_cpu_suspend)
-       stmfd   sp!, {r0-r12, lr}               @ save registers on stack
-loop:
-       /*b     loop*/  @Enable to debug by stepping through code
-       /* r0 contains restore pointer in sdram */
-       /* r1 contains information about saving context */
-       ldr     r4, sdrc_power          @ read the SDRC_POWER register
-       ldr     r5, [r4]                @ read the contents of SDRC_POWER
-       orr     r5, r5, #0x40           @ enable self refresh on idle req
-       str     r5, [r4]                @ write back to SDRC_POWER register
+       stmfd   sp!, {r0-r12, lr}       @ save registers on stack
 
+       /*
+        * r0 contains restore pointer in sdram
+        * r1 contains information about saving context:
+        *   0 - No context lost
+        *   1 - Only L1 and logic lost
+        *   2 - Only L2 lost
+        *   3 - Both L1 and L2 lost
+        */
+
+       /* Directly jump to WFI is the context save is not required */
        cmp     r1, #0x0
-       /* If context save is required, do that and execute wfi */
-       bne     save_context_wfi
+       beq     omap3_do_wfi
+
+       /* Otherwise fall through to the save context code */
+save_context_wfi:
+       mov     r8, r0                  @ Store SDRAM address in r8
+       mrc     p15, 0, r5, c1, c0, 1   @ Read Auxiliary Control Register
+       mov     r4, #0x1                @ Number of parameters for restore call
+       stmia   r8!, {r4-r5}            @ Push parameters for restore call
+       mrc     p15, 1, r5, c9, c0, 2   @ Read L2 AUX ctrl register
+       stmia   r8!, {r4-r5}            @ Push parameters for restore call
+
+        /* Check what that target sleep state is from r1 */
+       cmp     r1, #0x2                @ Only L2 lost, no need to save context
+       beq     clean_caches
+
+l1_logic_lost:
+       /* Store sp and spsr to SDRAM */
+       mov     r4, sp
+       mrs     r5, spsr
+       mov     r6, lr
+       stmia   r8!, {r4-r6}
+       /* Save all ARM registers */
+       /* Coprocessor access control register */
+       mrc     p15, 0, r6, c1, c0, 2
+       stmia   r8!, {r6}
+       /* TTBR0, TTBR1 and Translation table base control */
+       mrc     p15, 0, r4, c2, c0, 0
+       mrc     p15, 0, r5, c2, c0, 1
+       mrc     p15, 0, r6, c2, c0, 2
+       stmia   r8!, {r4-r6}
+       /*
+        * Domain access control register, data fault status register,
+        * and instruction fault status register
+        */
+       mrc     p15, 0, r4, c3, c0, 0
+       mrc     p15, 0, r5, c5, c0, 0
+       mrc     p15, 0, r6, c5, c0, 1
+       stmia   r8!, {r4-r6}
+       /*
+        * Data aux fault status register, instruction aux fault status,
+        * data fault address register and instruction fault address register
+        */
+       mrc     p15, 0, r4, c5, c1, 0
+       mrc     p15, 0, r5, c5, c1, 1
+       mrc     p15, 0, r6, c6, c0, 0
+       mrc     p15, 0, r7, c6, c0, 2
+       stmia   r8!, {r4-r7}
+       /*
+        * user r/w thread and process ID, user r/o thread and process ID,
+        * priv only thread and process ID, cache size selection
+        */
+       mrc     p15, 0, r4, c13, c0, 2
+       mrc     p15, 0, r5, c13, c0, 3
+       mrc     p15, 0, r6, c13, c0, 4
+       mrc     p15, 2, r7, c0, c0, 0
+       stmia   r8!, {r4-r7}
+       /* Data TLB lockdown, instruction TLB lockdown registers */
+       mrc     p15, 0, r5, c10, c0, 0
+       mrc     p15, 0, r6, c10, c0, 1
+       stmia   r8!, {r5-r6}
+       /* Secure or non secure vector base address, FCSE PID, Context PID*/
+       mrc     p15, 0, r4, c12, c0, 0
+       mrc     p15, 0, r5, c13, c0, 0
+       mrc     p15, 0, r6, c13, c0, 1
+       stmia   r8!, {r4-r6}
+       /* Primary remap, normal remap registers */
+       mrc     p15, 0, r4, c10, c2, 0
+       mrc     p15, 0, r5, c10, c2, 1
+       stmia   r8!,{r4-r5}
+
+       /* Store current cpsr*/
+       mrs     r2, cpsr
+       stmia   r8!, {r2}
+
+       mrc     p15, 0, r4, c1, c0, 0
+       /* save control register */
+       stmia   r8!, {r4}
+
+clean_caches:
+       /*
+        * Clean Data or unified cache to POU
+        * How to invalidate only L1 cache???? - #FIX_ME#
+        * mcr  p15, 0, r11, c7, c11, 1
+        */
+       cmp     r1, #0x1                @ Check whether L2 inval is required
+       beq     omap3_do_wfi
+
+clean_l2:
+       /*
+        * jump out to kernel flush routine
+        *  - reuse that code is better
+        *  - it executes in a cached space so is faster than refetch per-block
+        *  - should be faster and will change with kernel
+        *  - 'might' have to copy address, load and jump to it
+        */
+       ldr     r1, kernel_flush
+       mov     lr, pc
+       bx      r1
+
+omap3_do_wfi:
+       ldr     r4, sdrc_power          @ read the SDRC_POWER register
+       ldr     r5, [r4]                @ read the contents of SDRC_POWER
+       orr     r5, r5, #0x40           @ enable self refresh on idle req
+       str     r5, [r4]                @ write back to SDRC_POWER register
+
        /* Data memory barrier and Data sync barrier */
        mov     r1, #0
        mcr     p15, 0, r1, c7, c10, 4
        mcr     p15, 0, r1, c7, c10, 5
 
+/*
+ * ===================================
+ * == WFI instruction => Enter idle ==
+ * ===================================
+ */
        wfi                             @ wait for interrupt
 
+/*
+ * ===================================
+ * == Resume path for non-OFF modes ==
+ * ===================================
+ */
        nop
        nop
        nop
@@ -226,9 +317,30 @@ loop:
        nop
        bl wait_sdrc_ok
 
-       ldmfd   sp!, {r0-r12, pc}               @ restore regs and return
+/*
+ * ===================================
+ * == Exit point from non-OFF modes ==
+ * ===================================
+ */
+       ldmfd   sp!, {r0-r12, pc}       @ restore regs and return
+
+
+/*
+ * ==============================
+ * == Resume path for OFF mode ==
+ * ==============================
+ */
+
+/*
+ * The restore_* functions are called by the ROM code
+ *  when back from WFI in OFF mode.
+ * Cf. the get_*restore_pointer functions.
+ *
+ *  restore_es3: applies to 34xx >= ES3.0
+ *  restore_3630: applies to 36xx
+ *  restore: common code for 3xxx
+ */
 restore_es3:
-       /*b restore_es3*/               @ Enable to debug restore code
        ldr     r5, pm_prepwstst_core_p
        ldr     r4, [r5]
        and     r4, r4, #0x3
@@ -245,82 +357,117 @@ copy_to_sram:
        bne     copy_to_sram
        ldr     r1, sram_base
        blx     r1
+       b       restore
+
+restore_3630:
+       ldr     r1, pm_prepwstst_core_p
+       ldr     r2, [r1]
+       and     r2, r2, #0x3
+       cmp     r2, #0x0        @ Check if previous power state of CORE is OFF
+       bne     restore
+       /* Disable RTA before giving control */
+       ldr     r1, control_mem_rta
+       mov     r2, #OMAP36XX_RTA_DISABLE
+       str     r2, [r1]
+
+       /* Fall through to common code for the remaining logic */
+
 restore:
-       /* b restore*/  @ Enable to debug restore code
-        /* Check what was the reason for mpu reset and store the reason in r9*/
-        /* 1 - Only L1 and logic lost */
-        /* 2 - Only L2 lost - In this case, we wont be here */
-        /* 3 - Both L1 and L2 lost */
-       ldr     r1, pm_pwstctrl_mpu
+       /*
+        * Check what was the reason for mpu reset and store the reason in r9:
+        *  0 - No context lost
+        *  1 - Only L1 and logic lost
+        *  2 - Only L2 lost - In this case, we wont be here
+        *  3 - Both L1 and L2 lost
+        */
+       ldr     r1, pm_pwstctrl_mpu
        ldr     r2, [r1]
-       and     r2, r2, #0x3
-       cmp     r2, #0x0        @ Check if target power state was OFF or RET
-        moveq   r9, #0x3        @ MPU OFF => L1 and L2 lost
+       and     r2, r2, #0x3
+       cmp     r2, #0x0        @ Check if target power state was OFF or RET
+       moveq   r9, #0x3        @ MPU OFF => L1 and L2 lost
        movne   r9, #0x1        @ Only L1 and L2 lost => avoid L2 invalidation
        bne     logic_l1_restore
+
+       ldr     r0, l2dis_3630
+       cmp     r0, #0x1        @ should we disable L2 on 3630?
+       bne     skipl2dis
+       mrc     p15, 0, r0, c1, c0, 1
+       bic     r0, r0, #2      @ disable L2 cache
+       mcr     p15, 0, r0, c1, c0, 1
+skipl2dis:
        ldr     r0, control_stat
        ldr     r1, [r0]
        and     r1, #0x700
        cmp     r1, #0x300
        beq     l2_inv_gp
-       mov     r0, #40         @ set service ID for PPA
-       mov     r12, r0         @ copy secure Service ID in r12
-       mov     r1, #0          @ set task id for ROM code in r1
-       mov     r2, #4          @ set some flags in r2, r6
+       mov     r0, #40                 @ set service ID for PPA
+       mov     r12, r0                 @ copy secure Service ID in r12
+       mov     r1, #0                  @ set task id for ROM code in r1
+       mov     r2, #4                  @ set some flags in r2, r6
        mov     r6, #0xff
        adr     r3, l2_inv_api_params   @ r3 points to dummy parameters
        mcr     p15, 0, r0, c7, c10, 4  @ data write barrier
        mcr     p15, 0, r0, c7, c10, 5  @ data memory barrier
        .word   0xE1600071              @ call SMI monitor (smi #1)
        /* Write to Aux control register to set some bits */
-       mov     r0, #42         @ set service ID for PPA
-       mov     r12, r0         @ copy secure Service ID in r12
-       mov     r1, #0          @ set task id for ROM code in r1
-       mov     r2, #4          @ set some flags in r2, r6
+       mov     r0, #42                 @ set service ID for PPA
+       mov     r12, r0                 @ copy secure Service ID in r12
+       mov     r1, #0                  @ set task id for ROM code in r1
+       mov     r2, #4                  @ set some flags in r2, r6
        mov     r6, #0xff
        ldr     r4, scratchpad_base
-       ldr     r3, [r4, #0xBC] @ r3 points to parameters
+       ldr     r3, [r4, #0xBC]         @ r3 points to parameters
        mcr     p15, 0, r0, c7, c10, 4  @ data write barrier
        mcr     p15, 0, r0, c7, c10, 5  @ data memory barrier
        .word   0xE1600071              @ call SMI monitor (smi #1)
 
 #ifdef CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE
        /* Restore L2 aux control register */
-       @ set service ID for PPA
+                                       @ set service ID for PPA
        mov     r0, #CONFIG_OMAP3_L2_AUX_SECURE_SERVICE_SET_ID
-       mov     r12, r0         @ copy service ID in r12
-       mov     r1, #0          @ set task ID for ROM code in r1
-       mov     r2, #4          @ set some flags in r2, r6
+       mov     r12, r0                 @ copy service ID in r12
+       mov     r1, #0                  @ set task ID for ROM code in r1
+       mov     r2, #4                  @ set some flags in r2, r6
        mov     r6, #0xff
        ldr     r4, scratchpad_base
        ldr     r3, [r4, #0xBC]
-       adds    r3, r3, #8      @ r3 points to parameters
+       adds    r3, r3, #8              @ r3 points to parameters
        mcr     p15, 0, r0, c7, c10, 4  @ data write barrier
        mcr     p15, 0, r0, c7, c10, 5  @ data memory barrier
        .word   0xE1600071              @ call SMI monitor (smi #1)
 #endif
        b       logic_l1_restore
+
 l2_inv_api_params:
-       .word   0x1, 0x00
+       .word   0x1, 0x00
 l2_inv_gp:
        /* Execute smi to invalidate L2 cache */
-       mov r12, #0x1                         @ set up to invalide L2
-smi:    .word 0xE1600070               @ Call SMI monitor (smieq)
+       mov r12, #0x1                   @ set up to invalidate L2
+       .word 0xE1600070                @ Call SMI monitor (smieq)
        /* Write to Aux control register to set some bits */
        ldr     r4, scratchpad_base
        ldr     r3, [r4,#0xBC]
        ldr     r0, [r3,#4]
        mov     r12, #0x3
-       .word 0xE1600070        @ Call SMI monitor (smieq)
+       .word   0xE1600070              @ Call SMI monitor (smieq)
        ldr     r4, scratchpad_base
        ldr     r3, [r4,#0xBC]
        ldr     r0, [r3,#12]
        mov     r12, #0x2
-       .word 0xE1600070        @ Call SMI monitor (smieq)
+       .word   0xE1600070              @ Call SMI monitor (smieq)
 logic_l1_restore:
+       ldr     r1, l2dis_3630
+       cmp     r1, #0x1                @ Test if L2 re-enable needed on 3630
+       bne     skipl2reen
+       mrc     p15, 0, r1, c1, c0, 1
+       orr     r1, r1, #2              @ re-enable L2 cache
+       mcr     p15, 0, r1, c1, c0, 1
+skipl2reen:
        mov     r1, #0
-       /* Invalidate all instruction caches to PoU
-        * and flush branch target cache */
+       /*
+        * Invalidate all instruction caches to PoU
+        * and flush branch target cache
+        */
        mcr     p15, 0, r1, c7, c5, 0
 
        ldr     r4, scratchpad_base
@@ -341,33 +488,33 @@ logic_l1_restore:
        MCR p15, 0, r6, c2, c0, 1
        /* Translation table base control register */
        MCR p15, 0, r7, c2, c0, 2
-       /*domain access Control Register */
+       /* Domain access Control Register */
        MCR p15, 0, r8, c3, c0, 0
-       /* data fault status Register */
+       /* Data fault status Register */
        MCR p15, 0, r9, c5, c0, 0
 
-       ldmia  r3!,{r4-r8}
-       /* instruction fault status Register */
+       ldmia   r3!,{r4-r8}
+       /* Instruction fault status Register */
        MCR p15, 0, r4, c5, c0, 1
-       /*Data Auxiliary Fault Status Register */
+       /* Data Auxiliary Fault Status Register */
        MCR p15, 0, r5, c5, c1, 0
-       /*Instruction Auxiliary Fault Status Register*/
+       /* Instruction Auxiliary Fault Status Register*/
        MCR p15, 0, r6, c5, c1, 1
-       /*Data Fault Address Register */
+       /* Data Fault Address Register */
        MCR p15, 0, r7, c6, c0, 0
-       /*Instruction Fault Address Register*/
+       /* Instruction Fault Address Register*/
        MCR p15, 0, r8, c6, c0, 2
-       ldmia  r3!,{r4-r7}
+       ldmia   r3!,{r4-r7}
 
-       /* user r/w thread and process ID */
+       /* User r/w thread and process ID */
        MCR p15, 0, r4, c13, c0, 2
-       /* user ro thread and process ID */
+       /* User ro thread and process ID */
        MCR p15, 0, r5, c13, c0, 3
-       /*Privileged only thread and process ID */
+       /* Privileged only thread and process ID */
        MCR p15, 0, r6, c13, c0, 4
-       /* cache size selection */
+       /* Cache size selection */
        MCR p15, 2, r7, c0, c0, 0
-       ldmia  r3!,{r4-r8}
+       ldmia   r3!,{r4-r8}
        /* Data TLB lockdown registers */
        MCR p15, 0, r4, c10, c0, 0
        /* Instruction TLB lockdown registers */
@@ -379,26 +526,27 @@ logic_l1_restore:
        /* Context PID */
        MCR p15, 0, r8, c13, c0, 1
 
-       ldmia  r3!,{r4-r5}
-       /* primary memory remap register */
+       ldmia   r3!,{r4-r5}
+       /* Primary memory remap register */
        MCR p15, 0, r4, c10, c2, 0
-       /*normal memory remap register */
+       /* Normal memory remap register */
        MCR p15, 0, r5, c10, c2, 1
 
        /* Restore cpsr */
-       ldmia   r3!,{r4}        /*load CPSR from SDRAM*/
-       msr     cpsr, r4        /*store cpsr */
+       ldmia   r3!,{r4}                @ load CPSR from SDRAM
+       msr     cpsr, r4                @ store cpsr
 
        /* Enabling MMU here */
-       mrc     p15, 0, r7, c2, c0, 2 /* Read TTBRControl */
-       /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1*/
+       mrc     p15, 0, r7, c2, c0, 2   @ Read TTBRControl
+       /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */
        and     r7, #0x7
        cmp     r7, #0x0
        beq     usettbr0
 ttbr_error:
-       /* More work needs to be done to support N[0:2] value other than 0
-       * So looping here so that the error can be detected
-       */
+       /*
+        * More work needs to be done to support N[0:2] value other than 0
+        * So looping here so that the error can be detected
+        */
        b       ttbr_error
 usettbr0:
        mrc     p15, 0, r2, c2, c0, 0
@@ -406,21 +554,25 @@ usettbr0:
        and     r2, r5
        mov     r4, pc
        ldr     r5, table_index_mask
-       and     r4, r5 /* r4 = 31 to 20 bits of pc */
+       and     r4, r5                  @ r4 = 31 to 20 bits of pc
        /* Extract the value to be written to table entry */
        ldr     r1, table_entry
-       add     r1, r1, r4 /* r1 has value to be written to table entry*/
+       /* r1 has the value to be written to table entry*/
+       add     r1, r1, r4
        /* Getting the address of table entry to modify */
        lsr     r4, #18
-       add     r2, r4 /* r2 has the location which needs to be modified */
+       /* r2 has the location which needs to be modified */
+       add     r2, r4
        /* Storing previous entry of location being modified */
        ldr     r5, scratchpad_base
        ldr     r4, [r2]
        str     r4, [r5, #0xC0]
        /* Modify the table entry */
        str     r1, [r2]
-       /* Storing address of entry being modified
-        * - will be restored after enabling MMU */
+       /*
+        * Storing address of entry being modified
+        * - will be restored after enabling MMU
+        */
        ldr     r5, scratchpad_base
        str     r2, [r5, #0xC4]
 
@@ -429,8 +581,11 @@ usettbr0:
        mcr     p15, 0, r0, c7, c5, 6   @ Invalidate branch predictor array
        mcr     p15, 0, r0, c8, c5, 0   @ Invalidate instruction TLB
        mcr     p15, 0, r0, c8, c6, 0   @ Invalidate data TLB
-       /* Restore control register  but dont enable caches here*/
-       /* Caches will be enabled after restoring MMU table entry */
+       /*
+        * Restore control register. This enables the MMU.
+        * The caches and prediction are not enabled here, they
+        * will be enabled after restoring the MMU table entry.
+        */
        ldmia   r3!, {r4}
        /* Store previous value of control register in scratchpad */
        str     r4, [r5, #0xC8]
@@ -438,212 +593,144 @@ usettbr0:
        and     r4, r2
        mcr     p15, 0, r4, c1, c0, 0
 
-       ldmfd   sp!, {r0-r12, pc}               @ restore regs and return
-save_context_wfi:
-       /*b     save_context_wfi*/      @ enable to debug save code
-       mov     r8, r0 /* Store SDRAM address in r8 */
-       mrc     p15, 0, r5, c1, c0, 1   @ Read Auxiliary Control Register
-       mov     r4, #0x1                @ Number of parameters for restore call
-       stmia   r8!, {r4-r5}            @ Push parameters for restore call
-       mrc     p15, 1, r5, c9, c0, 2   @ Read L2 AUX ctrl register
-       stmia   r8!, {r4-r5}            @ Push parameters for restore call
-        /* Check what that target sleep state is:stored in r1*/
-        /* 1 - Only L1 and logic lost */
-        /* 2 - Only L2 lost */
-        /* 3 - Both L1 and L2 lost */
-       cmp     r1, #0x2 /* Only L2 lost */
-       beq     clean_l2
-       cmp     r1, #0x1 /* L2 retained */
-       /* r9 stores whether to clean L2 or not*/
-       moveq   r9, #0x0 /* Dont Clean L2 */
-       movne   r9, #0x1 /* Clean L2 */
-l1_logic_lost:
-       /* Store sp and spsr to SDRAM */
-       mov     r4, sp
-       mrs     r5, spsr
-       mov     r6, lr
-       stmia   r8!, {r4-r6}
-       /* Save all ARM registers */
-       /* Coprocessor access control register */
-       mrc     p15, 0, r6, c1, c0, 2
-       stmia   r8!, {r6}
-       /* TTBR0, TTBR1 and Translation table base control */
-       mrc     p15, 0, r4, c2, c0, 0
-       mrc     p15, 0, r5, c2, c0, 1
-       mrc     p15, 0, r6, c2, c0, 2
-       stmia   r8!, {r4-r6}
-       /* Domain access control register, data fault status register,
-       and instruction fault status register */
-       mrc     p15, 0, r4, c3, c0, 0
-       mrc     p15, 0, r5, c5, c0, 0
-       mrc     p15, 0, r6, c5, c0, 1
-       stmia   r8!, {r4-r6}
-       /* Data aux fault status register, instruction aux fault status,
-       datat fault address register and instruction fault address register*/
-       mrc     p15, 0, r4, c5, c1, 0
-       mrc     p15, 0, r5, c5, c1, 1
-       mrc     p15, 0, r6, c6, c0, 0
-       mrc     p15, 0, r7, c6, c0, 2
-       stmia   r8!, {r4-r7}
-       /* user r/w thread and process ID, user r/o thread and process ID,
-       priv only thread and process ID, cache size selection */
-       mrc     p15, 0, r4, c13, c0, 2
-       mrc     p15, 0, r5, c13, c0, 3
-       mrc     p15, 0, r6, c13, c0, 4
-       mrc     p15, 2, r7, c0, c0, 0
-       stmia   r8!, {r4-r7}
-       /* Data TLB lockdown, instruction TLB lockdown registers */
-       mrc     p15, 0, r5, c10, c0, 0
-       mrc     p15, 0, r6, c10, c0, 1
-       stmia   r8!, {r5-r6}
-       /* Secure or non secure vector base address, FCSE PID, Context PID*/
-       mrc     p15, 0, r4, c12, c0, 0
-       mrc     p15, 0, r5, c13, c0, 0
-       mrc     p15, 0, r6, c13, c0, 1
-       stmia   r8!, {r4-r6}
-       /* Primary remap, normal remap registers */
-       mrc     p15, 0, r4, c10, c2, 0
-       mrc     p15, 0, r5, c10, c2, 1
-       stmia   r8!,{r4-r5}
+/*
+ * ==============================
+ * == Exit point from OFF mode ==
+ * ==============================
+ */
+       ldmfd   sp!, {r0-r12, pc}       @ restore regs and return
 
-       /* Store current cpsr*/
-       mrs     r2, cpsr
-       stmia   r8!, {r2}
 
-       mrc     p15, 0, r4, c1, c0, 0
-       /* save control register */
-       stmia   r8!, {r4}
-clean_caches:
-       /* Clean Data or unified cache to POU*/
-       /* How to invalidate only L1 cache???? - #FIX_ME# */
-       /* mcr  p15, 0, r11, c7, c11, 1 */
-       cmp     r9, #1 /* Check whether L2 inval is required or not*/
-       bne     skip_l2_inval
-clean_l2:
-       /* read clidr */
-       mrc     p15, 1, r0, c0, c0, 1
-       /* extract loc from clidr */
-       ands    r3, r0, #0x7000000
-       /* left align loc bit field */
-       mov     r3, r3, lsr #23
-       /* if loc is 0, then no need to clean */
-       beq     finished
-       /* start clean at cache level 0 */
-       mov     r10, #0
-loop1:
-       /* work out 3x current cache level */
-       add     r2, r10, r10, lsr #1
-       /* extract cache type bits from clidr*/
-       mov     r1, r0, lsr r2
-       /* mask of the bits for current cache only */
-       and     r1, r1, #7
-       /* see what cache we have at this level */
-       cmp     r1, #2
-       /* skip if no cache, or just i-cache */
-       blt     skip
-       /* select current cache level in cssr */
-       mcr     p15, 2, r10, c0, c0, 0
-       /* isb to sych the new cssr&csidr */
-       isb
-       /* read the new csidr */
-       mrc     p15, 1, r1, c0, c0, 0
-       /* extract the length of the cache lines */
-       and     r2, r1, #7
-       /* add 4 (line length offset) */
-       add     r2, r2, #4
-       ldr     r4, assoc_mask
-       /* find maximum number on the way size */
-       ands    r4, r4, r1, lsr #3
-       /* find bit position of way size increment */
-       clz     r5, r4
-       ldr     r7, numset_mask
-       /* extract max number of the index size*/
-       ands    r7, r7, r1, lsr #13
-loop2:
-       mov     r9, r4
-       /* create working copy of max way size*/
-loop3:
-       /* factor way and cache number into r11 */
-       orr     r11, r10, r9, lsl r5
-       /* factor index number into r11 */
-       orr     r11, r11, r7, lsl r2
-       /*clean & invalidate by set/way */
-       mcr     p15, 0, r11, c7, c10, 2
-       /* decrement the way*/
-       subs    r9, r9, #1
-       bge     loop3
-       /*decrement the index */
-       subs    r7, r7, #1
-       bge     loop2
-skip:
-       add     r10, r10, #2
-       /* increment cache number */
-       cmp     r3, r10
-       bgt     loop1
-finished:
-       /*swith back to cache level 0 */
-       mov     r10, #0
-       /* select current cache level in cssr */
-       mcr     p15, 2, r10, c0, c0, 0
-       isb
-skip_l2_inval:
-       /* Data memory barrier and Data sync barrier */
-       mov     r1, #0
-       mcr     p15, 0, r1, c7, c10, 4
-       mcr     p15, 0, r1, c7, c10, 5
+/*
+ * Internal functions
+ */
 
-       wfi                             @ wait for interrupt
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       bl wait_sdrc_ok
-       /* restore regs and return */
-       ldmfd   sp!, {r0-r12, pc}
+/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */
+       .text
+ENTRY(es3_sdrc_fix)
+       ldr     r4, sdrc_syscfg         @ get config addr
+       ldr     r5, [r4]                @ get value
+       tst     r5, #0x100              @ is part access blocked
+       it      eq
+       biceq   r5, r5, #0x100          @ clear bit if set
+       str     r5, [r4]                @ write back change
+       ldr     r4, sdrc_mr_0           @ get config addr
+       ldr     r5, [r4]                @ get value
+       str     r5, [r4]                @ write back change
+       ldr     r4, sdrc_emr2_0         @ get config addr
+       ldr     r5, [r4]                @ get value
+       str     r5, [r4]                @ write back change
+       ldr     r4, sdrc_manual_0       @ get config addr
+       mov     r5, #0x2                @ autorefresh command
+       str     r5, [r4]                @ kick off refreshes
+       ldr     r4, sdrc_mr_1           @ get config addr
+       ldr     r5, [r4]                @ get value
+       str     r5, [r4]                @ write back change
+       ldr     r4, sdrc_emr2_1         @ get config addr
+       ldr     r5, [r4]                @ get value
+       str     r5, [r4]                @ write back change
+       ldr     r4, sdrc_manual_1       @ get config addr
+       mov     r5, #0x2                @ autorefresh command
+       str     r5, [r4]                @ kick off refreshes
+       bx      lr
+
+sdrc_syscfg:
+       .word   SDRC_SYSCONFIG_P
+sdrc_mr_0:
+       .word   SDRC_MR_0_P
+sdrc_emr2_0:
+       .word   SDRC_EMR2_0_P
+sdrc_manual_0:
+       .word   SDRC_MANUAL_0_P
+sdrc_mr_1:
+       .word   SDRC_MR_1_P
+sdrc_emr2_1:
+       .word   SDRC_EMR2_1_P
+sdrc_manual_1:
+       .word   SDRC_MANUAL_1_P
+ENTRY(es3_sdrc_fix_sz)
+       .word   . - es3_sdrc_fix
+
+/*
+ * This function implements the erratum ID i581 WA:
+ *  SDRC state restore before accessing the SDRAM
+ *
+ * Only used at return from non-OFF mode. For OFF
+ * mode the ROM code configures the SDRC and
+ * the DPLL before calling the restore code directly
+ * from DDR.
+ */
 
 /* Make sure SDRC accesses are ok */
 wait_sdrc_ok:
-        ldr     r4, cm_idlest1_core
-        ldr     r5, [r4]
-        and     r5, r5, #0x2
-        cmp     r5, #0
-        bne     wait_sdrc_ok
-        ldr     r4, sdrc_power
-        ldr     r5, [r4]
-        bic     r5, r5, #0x40
-        str     r5, [r4]
+
+/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
+       ldr     r4, cm_idlest_ckgen
+wait_dpll3_lock:
+       ldr     r5, [r4]
+       tst     r5, #1
+       beq     wait_dpll3_lock
+
+       ldr     r4, cm_idlest1_core
+wait_sdrc_ready:
+       ldr     r5, [r4]
+       tst     r5, #0x2
+       bne     wait_sdrc_ready
+       /* allow DLL powerdown upon hw idle req */
+       ldr     r4, sdrc_power
+       ldr     r5, [r4]
+       bic     r5, r5, #0x40
+       str     r5, [r4]
+
+is_dll_in_lock_mode:
+       /* Is dll in lock mode? */
+       ldr     r4, sdrc_dlla_ctrl
+       ldr     r5, [r4]
+       tst     r5, #0x4
+       bxne    lr                      @ Return if locked
+       /* wait till dll locks */
+wait_dll_lock_timed:
+       ldr     r4, wait_dll_lock_counter
+       add     r4, r4, #1
+       str     r4, wait_dll_lock_counter
+       ldr     r4, sdrc_dlla_status
+       /* Wait 20uS for lock */
+       mov     r6, #8
 wait_dll_lock:
-        /* Is dll in lock mode? */
-        ldr     r4, sdrc_dlla_ctrl
-        ldr     r5, [r4]
-        tst     r5, #0x4
-        bxne    lr
-        /* wait till dll locks */
-        ldr     r4, sdrc_dlla_status
-        ldr     r5, [r4]
-        and     r5, r5, #0x4
-        cmp     r5, #0x4
-        bne     wait_dll_lock
-        bx      lr
+       subs    r6, r6, #0x1
+       beq     kick_dll
+       ldr     r5, [r4]
+       and     r5, r5, #0x4
+       cmp     r5, #0x4
+       bne     wait_dll_lock
+       bx      lr                      @ Return when locked
+
+       /* disable/reenable DLL if not locked */
+kick_dll:
+       ldr     r4, sdrc_dlla_ctrl
+       ldr     r5, [r4]
+       mov     r6, r5
+       bic     r6, #(1<<3)             @ disable dll
+       str     r6, [r4]
+       dsb
+       orr     r6, r6, #(1<<3)         @ enable dll
+       str     r6, [r4]
+       dsb
+       ldr     r4, kick_counter
+       add     r4, r4, #1
+       str     r4, kick_counter
+       b       wait_dll_lock_timed
 
 cm_idlest1_core:
        .word   CM_IDLEST1_CORE_V
+cm_idlest_ckgen:
+       .word   CM_IDLEST_CKGEN_V
 sdrc_dlla_status:
        .word   SDRC_DLLA_STATUS_V
 sdrc_dlla_ctrl:
        .word   SDRC_DLLA_CTRL_V
-pm_prepwstst_core:
-       .word   PM_PREPWSTST_CORE_V
 pm_prepwstst_core_p:
        .word   PM_PREPWSTST_CORE_P
-pm_prepwstst_mpu:
-       .word   PM_PREPWSTST_MPU_V
 pm_pwstctrl_mpu:
        .word   PM_PWSTCTRL_MPU_P
 scratchpad_base:
@@ -651,13 +738,7 @@ scratchpad_base:
 sram_base:
        .word   SRAM_BASE_P + 0x8000
 sdrc_power:
-       .word SDRC_POWER_V
-clk_stabilize_delay:
-       .word 0x000001FF
-assoc_mask:
-       .word   0x3ff
-numset_mask:
-       .word   0x7fff
+       .word   SDRC_POWER_V
 ttbrbit_mask:
        .word   0xFFFFC000
 table_index_mask:
@@ -668,5 +749,20 @@ cache_pred_disable_mask:
        .word   0xFFFFE7FB
 control_stat:
        .word   CONTROL_STAT
+control_mem_rta:
+       .word   CONTROL_MEM_RTA_CTRL
+kernel_flush:
+       .word   v7_flush_dcache_all
+l2dis_3630:
+       .word   0
+       /*
+        * When exporting to userspace while the counters are in SRAM,
+        * these 2 words need to be at the end to facilitate retrival!
+        */
+kick_counter:
+       .word   0
+wait_dll_lock_counter:
+       .word   0
+
 ENTRY(omap34xx_cpu_suspend_sz)
        .word   . - omap34xx_cpu_suspend
index fa2e5bffbb8eaa37c6d4db06a2213fb476115c64..6983cb4d4cae81b4791e877e07018f4fe170a531 100644 (file)
@@ -28,9 +28,16 @@ config S3C2412_DMA
 
 config S3C2412_PM
        bool
+       select S3C2412_PM_SLEEP
        help
          Internal config node to apply S3C2412 power management
 
+config S3C2412_PM_SLEEP
+       bool
+       help
+         Internal config node to apply sleep for S3C2412 power management.
+         Can be selected by another SoCs with similar sleep procedure.
+
 # Note, the S3C2412 IOtiming support is in plat-s3c24xx
 
 config S3C2412_CPUFREQ
index 530ec46cbaea52d9a4ff16c6047450c4029195e4..6c48a91ea39e75a00e29b88a968553fc1e796fbb 100644 (file)
@@ -14,7 +14,8 @@ obj-$(CONFIG_CPU_S3C2412)     += irq.o
 obj-$(CONFIG_CPU_S3C2412)      += clock.o
 obj-$(CONFIG_CPU_S3C2412)      += gpio.o
 obj-$(CONFIG_S3C2412_DMA)      += dma.o
-obj-$(CONFIG_S3C2412_PM)       += pm.o sleep.o
+obj-$(CONFIG_S3C2412_PM)       += pm.o
+obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep.o
 obj-$(CONFIG_S3C2412_CPUFREQ)  += cpu-freq.o
 
 # Machine support
index 27b3e7c9d61366edcdc59f234e563cec3b5b6b2b..df8d14974c90876b31d16ab2a2d2367ef1f7af89 100644 (file)
@@ -27,6 +27,7 @@ config S3C2416_DMA
 
 config S3C2416_PM
        bool
+       select S3C2412_PM_SLEEP
        help
          Internal config node to apply S3C2416 power management
 
index 28677caf3613cca0ec00bf02862ba01c049fd6fd..461aa035afc05956a6262ea53921a941bf757b84 100644 (file)
@@ -378,6 +378,12 @@ static struct max8998_regulator_data aquila_regulators[] = {
 static struct max8998_platform_data aquila_max8998_pdata = {
        .num_regulators = ARRAY_SIZE(aquila_regulators),
        .regulators     = aquila_regulators,
+       .buck1_set1     = S5PV210_GPH0(3),
+       .buck1_set2     = S5PV210_GPH0(4),
+       .buck2_set3     = S5PV210_GPH0(5),
+       .buck1_max_voltage1 = 1200000,
+       .buck1_max_voltage2 = 1200000,
+       .buck2_max_voltage = 1200000,
 };
 #endif
 
index b1dcf964a768773772659b7a01b9e3b6cb8de545..e22d5112fd44aa3267c3bee3a23b023331b951cd 100644 (file)
@@ -518,6 +518,12 @@ static struct max8998_regulator_data goni_regulators[] = {
 static struct max8998_platform_data goni_max8998_pdata = {
        .num_regulators = ARRAY_SIZE(goni_regulators),
        .regulators     = goni_regulators,
+       .buck1_set1     = S5PV210_GPH0(3),
+       .buck1_set2     = S5PV210_GPH0(4),
+       .buck2_set3     = S5PV210_GPH0(5),
+       .buck1_max_voltage1 = 1200000,
+       .buck1_max_voltage2 = 1200000,
+       .buck2_max_voltage = 1200000,
 };
 #endif
 
index a285d13c74165a2e73a3941a7d1d47d03b91b8ac..f428c4db2b60e60f2c21761859aaec3e4401eea3 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2010 Magnus Damm
  * Copyright (C) 2008 Renesas Solutions Corp.
  *
  * This program is free software; you can redistribute it and/or modify
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-#include <mach/hardware.h>
 #include <mach/irqs.h>
 
+#define INTCA_BASE     0xe6980000
+#define INTFLGA_OFFS   0x00000018 /* accept pending interrupt */
+#define INTEVTA_OFFS   0x00000020 /* vector number of accepted interrupt */
+#define INTLVLA_OFFS   0x00000030 /* priority level of accepted interrupt */
+#define INTLVLB_OFFS   0x00000034 /* previous priority level */
+
        .macro  disable_fiq
        .endm
 
        .macro  get_irqnr_preamble, base, tmp
-       ldr     \base, =INTFLGA
+       ldr     \base, =INTCA_BASE
        .endm
 
        .macro  arch_ret_to_user, tmp1, tmp2
        .endm
 
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       ldr     \irqnr, [\base]
+       /* The single INTFLGA read access below results in the following:
+        *
+        * 1. INTLVLB is updated with old priority value from INTLVLA
+        * 2. Highest priority interrupt is accepted
+        * 3. INTLVLA is updated to contain priority of accepted interrupt
+        * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA
+        */
+       ldr     \irqnr, [\base, #INTFLGA_OFFS]
+
+       /* Restore INTLVLA with the value saved in INTLVLB.
+        * This is required to support interrupt priorities properly.
+        */
+       ldrb    \tmp, [\base, #INTLVLB_OFFS]
+       strb    \tmp, [\base, #INTLVLA_OFFS]
+
+       /* Handle invalid vector number case */
        cmp     \irqnr, #0
        beq     1000f
-       /* intevt to irq number */
+
+       /* Convert vector to irq number, same as the evt2irq() macro */
        lsr     \irqnr, \irqnr, #0x5
        subs    \irqnr, \irqnr, #16
 
index 4aecf6e3a859f801111fafa328a44b3d0de3b311..2b8fd8b942feca160e61fe513d8856ffcb0d83a7 100644 (file)
@@ -2,6 +2,6 @@
 #define __ASM_MACH_VMALLOC_H
 
 /* Vmalloc at ... - 0xe5ffffff */
-#define VMALLOC_END 0xe6000000
+#define VMALLOC_END 0xe6000000UL
 
 #endif /* __ASM_MACH_VMALLOC_H */
index a863f5546a6b1aa989a37e9c8d7914591ad63a0e..c4b2b478b1a544e6ef768c3f3e6a3543ca37119c 100644 (file)
  *
  * Support functions for the OMAP internal DMA channels.
  *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Converted DMA library into DMA platform driver.
+ *     - G, Manjunath Kondaiah <manjugk@ti.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -53,7 +57,11 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
 
 #define OMAP_FUNC_MUX_ARM_BASE         (0xfffe1000 + 0xec)
 
+static struct omap_system_dma_plat_info *p;
+static struct omap_dma_dev_attr *d;
+
 static int enable_1510_mode;
+static u32 errata;
 
 static struct omap_dma_global_context_registers {
        u32 dma_irqenable_l0;
@@ -61,27 +69,6 @@ static struct omap_dma_global_context_registers {
        u32 dma_gcr;
 } omap_dma_global_context;
 
-struct omap_dma_lch {
-       int next_lch;
-       int dev_id;
-       u16 saved_csr;
-       u16 enabled_irqs;
-       const char *dev_name;
-       void (*callback)(int lch, u16 ch_status, void *data);
-       void *data;
-
-#ifndef CONFIG_ARCH_OMAP1
-       /* required for Dynamic chaining */
-       int prev_linked_ch;
-       int next_linked_ch;
-       int state;
-       int chain_id;
-
-       int status;
-#endif
-       long flags;
-};
-
 struct dma_link_info {
        int *linked_dmach_q;
        int no_of_lchs_linked;
@@ -137,15 +124,6 @@ static int omap_dma_reserve_channels;
 
 static spinlock_t dma_chan_lock;
 static struct omap_dma_lch *dma_chan;
-static void __iomem *omap_dma_base;
-
-static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = {
-       INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3,
-       INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7,
-       INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10,
-       INT_1610_DMA_CH11, INT_1610_DMA_CH12, INT_1610_DMA_CH13,
-       INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD
-};
 
 static inline void disable_lnk(int lch);
 static void omap_disable_channel_irq(int lch);
@@ -154,27 +132,9 @@ static inline void omap_enable_channel_irq(int lch);
 #define REVISIT_24XX()         printk(KERN_ERR "FIXME: no %s on 24xx\n", \
                                                __func__);
 
-#define dma_read(reg)                                                  \
-({                                                                     \
-       u32 __val;                                                      \
-       if (cpu_class_is_omap1())                                       \
-               __val = __raw_readw(omap_dma_base + OMAP1_DMA_##reg);   \
-       else                                                            \
-               __val = __raw_readl(omap_dma_base + OMAP_DMA4_##reg);   \
-       __val;                                                          \
-})
-
-#define dma_write(val, reg)                                            \
-({                                                                     \
-       if (cpu_class_is_omap1())                                       \
-               __raw_writew((u16)(val), omap_dma_base + OMAP1_DMA_##reg); \
-       else                                                            \
-               __raw_writel((val), omap_dma_base + OMAP_DMA4_##reg);   \
-})
-
 #ifdef CONFIG_ARCH_OMAP15XX
 /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
-static int omap_dma_in_1510_mode(void)
+int omap_dma_in_1510_mode(void)
 {
        return enable_1510_mode;
 }
@@ -206,16 +166,6 @@ static inline void set_gdma_dev(int req, int dev)
 #define set_gdma_dev(req, dev) do {} while (0)
 #endif
 
-/* Omap1 only */
-static void clear_lch_regs(int lch)
-{
-       int i;
-       void __iomem *lch_base = omap_dma_base + OMAP1_DMA_CH_BASE(lch);
-
-       for (i = 0; i < 0x2c; i += 2)
-               __raw_writew(0, lch_base + i);
-}
-
 void omap_set_dma_priority(int lch, int dst_port, int priority)
 {
        unsigned long reg;
@@ -248,12 +198,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority)
        if (cpu_class_is_omap2()) {
                u32 ccr;
 
-               ccr = dma_read(CCR(lch));
+               ccr = p->dma_read(CCR, lch);
                if (priority)
                        ccr |= (1 << 6);
                else
                        ccr &= ~(1 << 6);
-               dma_write(ccr, CCR(lch));
+               p->dma_write(ccr, CCR, lch);
        }
 }
 EXPORT_SYMBOL(omap_set_dma_priority);
@@ -264,31 +214,31 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 {
        u32 l;
 
-       l = dma_read(CSDP(lch));
+       l = p->dma_read(CSDP, lch);
        l &= ~0x03;
        l |= data_type;
-       dma_write(l, CSDP(lch));
+       p->dma_write(l, CSDP, lch);
 
        if (cpu_class_is_omap1()) {
                u16 ccr;
 
-               ccr = dma_read(CCR(lch));
+               ccr = p->dma_read(CCR, lch);
                ccr &= ~(1 << 5);
                if (sync_mode == OMAP_DMA_SYNC_FRAME)
                        ccr |= 1 << 5;
-               dma_write(ccr, CCR(lch));
+               p->dma_write(ccr, CCR, lch);
 
-               ccr = dma_read(CCR2(lch));
+               ccr = p->dma_read(CCR2, lch);
                ccr &= ~(1 << 2);
                if (sync_mode == OMAP_DMA_SYNC_BLOCK)
                        ccr |= 1 << 2;
-               dma_write(ccr, CCR2(lch));
+               p->dma_write(ccr, CCR2, lch);
        }
 
        if (cpu_class_is_omap2() && dma_trigger) {
                u32 val;
 
-               val = dma_read(CCR(lch));
+               val = p->dma_read(CCR, lch);
 
                /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
                val &= ~((1 << 23) | (3 << 19) | 0x1f);
@@ -313,11 +263,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
                } else {
                        val &= ~(1 << 24);      /* dest synch */
                }
-               dma_write(val, CCR(lch));
+               p->dma_write(val, CCR, lch);
        }
 
-       dma_write(elem_count, CEN(lch));
-       dma_write(frame_count, CFN(lch));
+       p->dma_write(elem_count, CEN, lch);
+       p->dma_write(frame_count, CFN, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
 
@@ -328,7 +278,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
        if (cpu_class_is_omap1()) {
                u16 w;
 
-               w = dma_read(CCR2(lch));
+               w = p->dma_read(CCR2, lch);
                w &= ~0x03;
 
                switch (mode) {
@@ -343,23 +293,22 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
                default:
                        BUG();
                }
-               dma_write(w, CCR2(lch));
+               p->dma_write(w, CCR2, lch);
 
-               w = dma_read(LCH_CTRL(lch));
+               w = p->dma_read(LCH_CTRL, lch);
                w &= ~0x0f;
                /* Default is channel type 2D */
                if (mode) {
-                       dma_write((u16)color, COLOR_L(lch));
-                       dma_write((u16)(color >> 16), COLOR_U(lch));
+                       p->dma_write(color, COLOR, lch);
                        w |= 1;         /* Channel type G */
                }
-               dma_write(w, LCH_CTRL(lch));
+               p->dma_write(w, LCH_CTRL, lch);
        }
 
        if (cpu_class_is_omap2()) {
                u32 val;
 
-               val = dma_read(CCR(lch));
+               val = p->dma_read(CCR, lch);
                val &= ~((1 << 17) | (1 << 16));
 
                switch (mode) {
@@ -374,10 +323,10 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
                default:
                        BUG();
                }
-               dma_write(val, CCR(lch));
+               p->dma_write(val, CCR, lch);
 
                color &= 0xffffff;
-               dma_write(color, COLOR(lch));
+               p->dma_write(color, COLOR, lch);
        }
 }
 EXPORT_SYMBOL(omap_set_dma_color_mode);
@@ -387,10 +336,10 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
        if (cpu_class_is_omap2()) {
                u32 csdp;
 
-               csdp = dma_read(CSDP(lch));
+               csdp = p->dma_read(CSDP, lch);
                csdp &= ~(0x3 << 16);
                csdp |= (mode << 16);
-               dma_write(csdp, CSDP(lch));
+               p->dma_write(csdp, CSDP, lch);
        }
 }
 EXPORT_SYMBOL(omap_set_dma_write_mode);
@@ -400,10 +349,10 @@ void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)
        if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
                u32 l;
 
-               l = dma_read(LCH_CTRL(lch));
+               l = p->dma_read(LCH_CTRL, lch);
                l &= ~0x7;
                l |= mode;
-               dma_write(l, LCH_CTRL(lch));
+               p->dma_write(l, LCH_CTRL, lch);
        }
 }
 EXPORT_SYMBOL(omap_set_dma_channel_mode);
@@ -418,27 +367,21 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
        if (cpu_class_is_omap1()) {
                u16 w;
 
-               w = dma_read(CSDP(lch));
+               w = p->dma_read(CSDP, lch);
                w &= ~(0x1f << 2);
                w |= src_port << 2;
-               dma_write(w, CSDP(lch));
+               p->dma_write(w, CSDP, lch);
        }
 
-       l = dma_read(CCR(lch));
+       l = p->dma_read(CCR, lch);
        l &= ~(0x03 << 12);
        l |= src_amode << 12;
-       dma_write(l, CCR(lch));
-
-       if (cpu_class_is_omap1()) {
-               dma_write(src_start >> 16, CSSA_U(lch));
-               dma_write((u16)src_start, CSSA_L(lch));
-       }
+       p->dma_write(l, CCR, lch);
 
-       if (cpu_class_is_omap2())
-               dma_write(src_start, CSSA(lch));
+       p->dma_write(src_start, CSSA, lch);
 
-       dma_write(src_ei, CSEI(lch));
-       dma_write(src_fi, CSFI(lch));
+       p->dma_write(src_ei, CSEI, lch);
+       p->dma_write(src_fi, CSFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_params);
 
@@ -466,8 +409,8 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx)
        if (cpu_class_is_omap2())
                return;
 
-       dma_write(eidx, CSEI(lch));
-       dma_write(fidx, CSFI(lch));
+       p->dma_write(eidx, CSEI, lch);
+       p->dma_write(fidx, CSFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_index);
 
@@ -475,11 +418,11 @@ void omap_set_dma_src_data_pack(int lch, int enable)
 {
        u32 l;
 
-       l = dma_read(CSDP(lch));
+       l = p->dma_read(CSDP, lch);
        l &= ~(1 << 6);
        if (enable)
                l |= (1 << 6);
-       dma_write(l, CSDP(lch));
+       p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_data_pack);
 
@@ -488,7 +431,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
        unsigned int burst = 0;
        u32 l;
 
-       l = dma_read(CSDP(lch));
+       l = p->dma_read(CSDP, lch);
        l &= ~(0x03 << 7);
 
        switch (burst_mode) {
@@ -524,7 +467,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
        }
 
        l |= (burst << 7);
-       dma_write(l, CSDP(lch));
+       p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
 
@@ -536,27 +479,21 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
        u32 l;
 
        if (cpu_class_is_omap1()) {
-               l = dma_read(CSDP(lch));
+               l = p->dma_read(CSDP, lch);
                l &= ~(0x1f << 9);
                l |= dest_port << 9;
-               dma_write(l, CSDP(lch));
+               p->dma_write(l, CSDP, lch);
        }
 
-       l = dma_read(CCR(lch));
+       l = p->dma_read(CCR, lch);
        l &= ~(0x03 << 14);
        l |= dest_amode << 14;
-       dma_write(l, CCR(lch));
-
-       if (cpu_class_is_omap1()) {
-               dma_write(dest_start >> 16, CDSA_U(lch));
-               dma_write(dest_start, CDSA_L(lch));
-       }
+       p->dma_write(l, CCR, lch);
 
-       if (cpu_class_is_omap2())
-               dma_write(dest_start, CDSA(lch));
+       p->dma_write(dest_start, CDSA, lch);
 
-       dma_write(dst_ei, CDEI(lch));
-       dma_write(dst_fi, CDFI(lch));
+       p->dma_write(dst_ei, CDEI, lch);
+       p->dma_write(dst_fi, CDFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_params);
 
@@ -565,8 +502,8 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx)
        if (cpu_class_is_omap2())
                return;
 
-       dma_write(eidx, CDEI(lch));
-       dma_write(fidx, CDFI(lch));
+       p->dma_write(eidx, CDEI, lch);
+       p->dma_write(fidx, CDFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_index);
 
@@ -574,11 +511,11 @@ void omap_set_dma_dest_data_pack(int lch, int enable)
 {
        u32 l;
 
-       l = dma_read(CSDP(lch));
+       l = p->dma_read(CSDP, lch);
        l &= ~(1 << 13);
        if (enable)
                l |= 1 << 13;
-       dma_write(l, CSDP(lch));
+       p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
 
@@ -587,7 +524,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
        unsigned int burst = 0;
        u32 l;
 
-       l = dma_read(CSDP(lch));
+       l = p->dma_read(CSDP, lch);
        l &= ~(0x03 << 14);
 
        switch (burst_mode) {
@@ -620,7 +557,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
                return;
        }
        l |= (burst << 14);
-       dma_write(l, CSDP(lch));
+       p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
 
@@ -630,18 +567,18 @@ static inline void omap_enable_channel_irq(int lch)
 
        /* Clear CSR */
        if (cpu_class_is_omap1())
-               status = dma_read(CSR(lch));
+               status = p->dma_read(CSR, lch);
        else if (cpu_class_is_omap2())
-               dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch));
+               p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
 
        /* Enable some nice interrupts. */
-       dma_write(dma_chan[lch].enabled_irqs, CICR(lch));
+       p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
 }
 
 static void omap_disable_channel_irq(int lch)
 {
        if (cpu_class_is_omap2())
-               dma_write(0, CICR(lch));
+               p->dma_write(0, CICR, lch);
 }
 
 void omap_enable_dma_irq(int lch, u16 bits)
@@ -660,7 +597,7 @@ static inline void enable_lnk(int lch)
 {
        u32 l;
 
-       l = dma_read(CLNK_CTRL(lch));
+       l = p->dma_read(CLNK_CTRL, lch);
 
        if (cpu_class_is_omap1())
                l &= ~(1 << 14);
@@ -675,18 +612,18 @@ static inline void enable_lnk(int lch)
                        l = dma_chan[lch].next_linked_ch | (1 << 15);
 #endif
 
-       dma_write(l, CLNK_CTRL(lch));
+       p->dma_write(l, CLNK_CTRL, lch);
 }
 
 static inline void disable_lnk(int lch)
 {
        u32 l;
 
-       l = dma_read(CLNK_CTRL(lch));
+       l = p->dma_read(CLNK_CTRL, lch);
 
        /* Disable interrupts */
        if (cpu_class_is_omap1()) {
-               dma_write(0, CICR(lch));
+               p->dma_write(0, CICR, lch);
                /* Set the STOP_LNK bit */
                l |= 1 << 14;
        }
@@ -697,7 +634,7 @@ static inline void disable_lnk(int lch)
                l &= ~(1 << 15);
        }
 
-       dma_write(l, CLNK_CTRL(lch));
+       p->dma_write(l, CLNK_CTRL, lch);
        dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
@@ -710,9 +647,9 @@ static inline void omap2_enable_irq_lch(int lch)
                return;
 
        spin_lock_irqsave(&dma_chan_lock, flags);
-       val = dma_read(IRQENABLE_L0);
+       val = p->dma_read(IRQENABLE_L0, lch);
        val |= 1 << lch;
-       dma_write(val, IRQENABLE_L0);
+       p->dma_write(val, IRQENABLE_L0, lch);
        spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 
@@ -725,9 +662,9 @@ static inline void omap2_disable_irq_lch(int lch)
                return;
 
        spin_lock_irqsave(&dma_chan_lock, flags);
-       val = dma_read(IRQENABLE_L0);
+       val = p->dma_read(IRQENABLE_L0, lch);
        val &= ~(1 << lch);
-       dma_write(val, IRQENABLE_L0);
+       p->dma_write(val, IRQENABLE_L0, lch);
        spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 
@@ -754,8 +691,8 @@ int omap_request_dma(int dev_id, const char *dev_name,
        chan = dma_chan + free_ch;
        chan->dev_id = dev_id;
 
-       if (cpu_class_is_omap1())
-               clear_lch_regs(free_ch);
+       if (p->clear_lch_regs)
+               p->clear_lch_regs(free_ch);
 
        if (cpu_class_is_omap2())
                omap_clear_dma(free_ch);
@@ -792,17 +729,17 @@ int omap_request_dma(int dev_id, const char *dev_name,
                 * Disable the 1510 compatibility mode and set the sync device
                 * id.
                 */
-               dma_write(dev_id | (1 << 10), CCR(free_ch));
+               p->dma_write(dev_id | (1 << 10), CCR, free_ch);
        } else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
-               dma_write(dev_id, CCR(free_ch));
+               p->dma_write(dev_id, CCR, free_ch);
        }
 
        if (cpu_class_is_omap2()) {
                omap2_enable_irq_lch(free_ch);
                omap_enable_channel_irq(free_ch);
                /* Clear the CSR register and IRQ status register */
-               dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(free_ch));
-               dma_write(1 << free_ch, IRQSTATUS_L0);
+               p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch);
+               p->dma_write(1 << free_ch, IRQSTATUS_L0, 0);
        }
 
        *dma_ch_out = free_ch;
@@ -823,23 +760,23 @@ void omap_free_dma(int lch)
 
        if (cpu_class_is_omap1()) {
                /* Disable all DMA interrupts for the channel. */
-               dma_write(0, CICR(lch));
+               p->dma_write(0, CICR, lch);
                /* Make sure the DMA transfer is stopped. */
-               dma_write(0, CCR(lch));
+               p->dma_write(0, CCR, lch);
        }
 
        if (cpu_class_is_omap2()) {
                omap2_disable_irq_lch(lch);
 
                /* Clear the CSR register and IRQ status register */
-               dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch));
-               dma_write(1 << lch, IRQSTATUS_L0);
+               p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
+               p->dma_write(1 << lch, IRQSTATUS_L0, lch);
 
                /* Disable all DMA interrupts for the channel. */
-               dma_write(0, CICR(lch));
+               p->dma_write(0, CICR, lch);
 
                /* Make sure the DMA transfer is stopped. */
-               dma_write(0, CCR(lch));
+               p->dma_write(0, CCR, lch);
                omap_clear_dma(lch);
        }
 
@@ -880,7 +817,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
        reg |= (0x3 & tparams) << 12;
        reg |= (arb_rate & 0xff) << 16;
 
-       dma_write(reg, GCR);
+       p->dma_write(reg, GCR, 0);
 }
 EXPORT_SYMBOL(omap_dma_set_global_params);
 
@@ -903,14 +840,14 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio,
                printk(KERN_ERR "Invalid channel id\n");
                return -EINVAL;
        }
-       l = dma_read(CCR(lch));
+       l = p->dma_read(CCR, lch);
        l &= ~((1 << 6) | (1 << 26));
        if (cpu_is_omap2430() || cpu_is_omap34xx() ||  cpu_is_omap44xx())
                l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
        else
                l |= ((read_prio & 0x1) << 6);
 
-       dma_write(l, CCR(lch));
+       p->dma_write(l, CCR, lch);
 
        return 0;
 }
@@ -925,25 +862,7 @@ void omap_clear_dma(int lch)
        unsigned long flags;
 
        local_irq_save(flags);
-
-       if (cpu_class_is_omap1()) {
-               u32 l;
-
-               l = dma_read(CCR(lch));
-               l &= ~OMAP_DMA_CCR_EN;
-               dma_write(l, CCR(lch));
-
-               /* Clear pending interrupts */
-               l = dma_read(CSR(lch));
-       }
-
-       if (cpu_class_is_omap2()) {
-               int i;
-               void __iomem *lch_base = omap_dma_base + OMAP_DMA4_CH_BASE(lch);
-               for (i = 0; i < 0x44; i += 4)
-                       __raw_writel(0, lch_base + i);
-       }
-
+       p->clear_dma(lch);
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL(omap_clear_dma);
@@ -957,13 +876,13 @@ void omap_start_dma(int lch)
         * before starting dma transfer.
         */
        if (cpu_is_omap15xx())
-               dma_write(0, CPC(lch));
+               p->dma_write(0, CPC, lch);
        else
-               dma_write(0, CDAC(lch));
+               p->dma_write(0, CDAC, lch);
 
        if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
                int next_lch, cur_lch;
-               char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT];
+               char dma_chan_link_map[dma_lch_count];
 
                dma_chan_link_map[lch] = 1;
                /* Set the link register of the first channel */
@@ -985,32 +904,18 @@ void omap_start_dma(int lch)
 
                        cur_lch = next_lch;
                } while (next_lch != -1);
-       } else if (cpu_is_omap242x() ||
-               (cpu_is_omap243x() &&  omap_type() <= OMAP2430_REV_ES1_0)) {
-
-               /* Errata: Need to write lch even if not using chaining */
-               dma_write(lch, CLNK_CTRL(lch));
-       }
+       } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS))
+               p->dma_write(lch, CLNK_CTRL, lch);
 
        omap_enable_channel_irq(lch);
 
-       l = dma_read(CCR(lch));
-
-       /*
-        * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
-        * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and
-        * bursting is enabled. This might result in data gets stalled in
-        * FIFO at the end of the block.
-        * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
-        * guarantee no data will stay in the DMA FIFO in case inter frame
-        * buffering occurs.
-        */
-       if (cpu_is_omap2420() ||
-           (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0)))
-               l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
+       l = p->dma_read(CCR, lch);
 
+       if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
+                       l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
        l |= OMAP_DMA_CCR_EN;
-       dma_write(l, CCR(lch));
+
+       p->dma_write(l, CCR, lch);
 
        dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
 }
@@ -1022,46 +927,46 @@ void omap_stop_dma(int lch)
 
        /* Disable all interrupts on the channel */
        if (cpu_class_is_omap1())
-               dma_write(0, CICR(lch));
+               p->dma_write(0, CICR, lch);
 
-       l = dma_read(CCR(lch));
-       /* OMAP3 Errata i541: sDMA FIFO draining does not finish */
-       if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
+       l = p->dma_read(CCR, lch);
+       if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
+                       (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
                int i = 0;
                u32 sys_cf;
 
                /* Configure No-Standby */
-               l = dma_read(OCP_SYSCONFIG);
+               l = p->dma_read(OCP_SYSCONFIG, lch);
                sys_cf = l;
                l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
                l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
-               dma_write(l , OCP_SYSCONFIG);
+               p->dma_write(l , OCP_SYSCONFIG, 0);
 
-               l = dma_read(CCR(lch));
+               l = p->dma_read(CCR, lch);
                l &= ~OMAP_DMA_CCR_EN;
-               dma_write(l, CCR(lch));
+               p->dma_write(l, CCR, lch);
 
                /* Wait for sDMA FIFO drain */
-               l = dma_read(CCR(lch));
+               l = p->dma_read(CCR, lch);
                while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
                                        OMAP_DMA_CCR_WR_ACTIVE))) {
                        udelay(5);
                        i++;
-                       l = dma_read(CCR(lch));
+                       l = p->dma_read(CCR, lch);
                }
                if (i >= 100)
                        printk(KERN_ERR "DMA drain did not complete on "
                                        "lch %d\n", lch);
                /* Restore OCP_SYSCONFIG */
-               dma_write(sys_cf, OCP_SYSCONFIG);
+               p->dma_write(sys_cf, OCP_SYSCONFIG, lch);
        } else {
                l &= ~OMAP_DMA_CCR_EN;
-               dma_write(l, CCR(lch));
+               p->dma_write(l, CCR, lch);
        }
 
        if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
                int next_lch, cur_lch = lch;
-               char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT];
+               char dma_chan_link_map[dma_lch_count];
 
                memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
                do {
@@ -1122,19 +1027,15 @@ dma_addr_t omap_get_dma_src_pos(int lch)
        dma_addr_t offset = 0;
 
        if (cpu_is_omap15xx())
-               offset = dma_read(CPC(lch));
+               offset = p->dma_read(CPC, lch);
        else
-               offset = dma_read(CSAC(lch));
+               offset = p->dma_read(CSAC, lch);
 
-       /*
-        * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
-        * read before the DMA controller finished disabling the channel.
-        */
-       if (!cpu_is_omap15xx() && offset == 0)
-               offset = dma_read(CSAC(lch));
+       if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
+               offset = p->dma_read(CSAC, lch);
 
        if (cpu_class_is_omap1())
-               offset |= (dma_read(CSSA_U(lch)) << 16);
+               offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000);
 
        return offset;
 }
@@ -1153,19 +1054,19 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
        dma_addr_t offset = 0;
 
        if (cpu_is_omap15xx())
-               offset = dma_read(CPC(lch));
+               offset = p->dma_read(CPC, lch);
        else
-               offset = dma_read(CDAC(lch));
+               offset = p->dma_read(CDAC, lch);
 
        /*
         * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
         * read before the DMA controller finished disabling the channel.
         */
        if (!cpu_is_omap15xx() && offset == 0)
-               offset = dma_read(CDAC(lch));
+               offset = p->dma_read(CDAC, lch);
 
        if (cpu_class_is_omap1())
-               offset |= (dma_read(CDSA_U(lch)) << 16);
+               offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000);
 
        return offset;
 }
@@ -1173,7 +1074,7 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos);
 
 int omap_get_dma_active_status(int lch)
 {
-       return (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) != 0;
+       return (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0;
 }
 EXPORT_SYMBOL(omap_get_dma_active_status);
 
@@ -1186,7 +1087,7 @@ int omap_dma_running(void)
                        return 1;
 
        for (lch = 0; lch < dma_chan_count; lch++)
-               if (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN)
+               if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN)
                        return 1;
 
        return 0;
@@ -1201,8 +1102,8 @@ void omap_dma_link_lch(int lch_head, int lch_queue)
 {
        if (omap_dma_in_1510_mode()) {
                if (lch_head == lch_queue) {
-                       dma_write(dma_read(CCR(lch_head)) | (3 << 8),
-                                                               CCR(lch_head));
+                       p->dma_write(p->dma_read(CCR, lch_head) | (3 << 8),
+                                                               CCR, lch_head);
                        return;
                }
                printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
@@ -1228,8 +1129,8 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)
 {
        if (omap_dma_in_1510_mode()) {
                if (lch_head == lch_queue) {
-                       dma_write(dma_read(CCR(lch_head)) & ~(3 << 8),
-                                                               CCR(lch_head));
+                       p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8),
+                                                               CCR, lch_head);
                        return;
                }
                printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
@@ -1255,8 +1156,6 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)
 }
 EXPORT_SYMBOL(omap_dma_unlink_lch);
 
-/*----------------------------------------------------------------------------*/
-
 #ifndef CONFIG_ARCH_OMAP1
 /* Create chain of DMA channesls */
 static void create_dma_lch_chain(int lch_head, int lch_queue)
@@ -1281,15 +1180,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue)
                                        lch_queue;
        }
 
-       l = dma_read(CLNK_CTRL(lch_head));
+       l = p->dma_read(CLNK_CTRL, lch_head);
        l &= ~(0x1f);
        l |= lch_queue;
-       dma_write(l, CLNK_CTRL(lch_head));
+       p->dma_write(l, CLNK_CTRL, lch_head);
 
-       l = dma_read(CLNK_CTRL(lch_queue));
+       l = p->dma_read(CLNK_CTRL, lch_queue);
        l &= ~(0x1f);
        l |= (dma_chan[lch_queue].next_linked_ch);
-       dma_write(l, CLNK_CTRL(lch_queue));
+       p->dma_write(l, CLNK_CTRL, lch_queue);
 }
 
 /**
@@ -1565,13 +1464,13 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
 
        /* Set the params to the free channel */
        if (src_start != 0)
-               dma_write(src_start, CSSA(lch));
+               p->dma_write(src_start, CSSA, lch);
        if (dest_start != 0)
-               dma_write(dest_start, CDSA(lch));
+               p->dma_write(dest_start, CDSA, lch);
 
        /* Write the buffer size */
-       dma_write(elem_count, CEN(lch));
-       dma_write(frame_count, CFN(lch));
+       p->dma_write(elem_count, CEN, lch);
+       p->dma_write(frame_count, CFN, lch);
 
        /*
         * If the chain is dynamically linked,
@@ -1604,8 +1503,8 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
                                enable_lnk(dma_chan[lch].prev_linked_ch);
                                dma_chan[lch].state = DMA_CH_QUEUED;
                                start_dma = 0;
-                               if (0 == ((1 << 7) & dma_read(
-                                       CCR(dma_chan[lch].prev_linked_ch)))) {
+                               if (0 == ((1 << 7) & p->dma_read(
+                                       CCR, dma_chan[lch].prev_linked_ch))) {
                                        disable_lnk(dma_chan[lch].
                                                    prev_linked_ch);
                                        pr_debug("\n prev ch is stopped\n");
@@ -1621,7 +1520,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
                        }
                        omap_enable_channel_irq(lch);
 
-                       l = dma_read(CCR(lch));
+                       l = p->dma_read(CCR, lch);
 
                        if ((0 == (l & (1 << 24))))
                                l &= ~(1 << 25);
@@ -1632,12 +1531,12 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
                                        l |= (1 << 7);
                                        dma_chan[lch].state = DMA_CH_STARTED;
                                        pr_debug("starting %d\n", lch);
-                                       dma_write(l, CCR(lch));
+                                       p->dma_write(l, CCR, lch);
                                } else
                                        start_dma = 0;
                        } else {
                                if (0 == (l & (1 << 7)))
-                                       dma_write(l, CCR(lch));
+                                       p->dma_write(l, CCR, lch);
                        }
                        dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
                }
@@ -1682,7 +1581,7 @@ int omap_start_dma_chain_transfers(int chain_id)
                omap_enable_channel_irq(channels[0]);
        }
 
-       l = dma_read(CCR(channels[0]));
+       l = p->dma_read(CCR, channels[0]);
        l |= (1 << 7);
        dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
        dma_chan[channels[0]].state = DMA_CH_STARTED;
@@ -1691,7 +1590,7 @@ int omap_start_dma_chain_transfers(int chain_id)
                l &= ~(1 << 25);
        else
                l |= (1 << 25);
-       dma_write(l, CCR(channels[0]));
+       p->dma_write(l, CCR, channels[0]);
 
        dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
 
@@ -1711,7 +1610,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
 {
        int *channels;
        u32 l, i;
-       u32 sys_cf;
+       u32 sys_cf = 0;
 
        /* Check for input params */
        if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
@@ -1726,22 +1625,20 @@ int omap_stop_dma_chain_transfers(int chain_id)
        }
        channels = dma_linked_lch[chain_id].linked_dmach_q;
 
-       /*
-        * DMA Errata:
-        * Special programming model needed to disable DMA before end of block
-        */
-       sys_cf = dma_read(OCP_SYSCONFIG);
-       l = sys_cf;
-       /* Middle mode reg set no Standby */
-       l &= ~((1 << 12)|(1 << 13));
-       dma_write(l, OCP_SYSCONFIG);
+       if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
+               sys_cf = p->dma_read(OCP_SYSCONFIG, 0);
+               l = sys_cf;
+               /* Middle mode reg set no Standby */
+               l &= ~((1 << 12)|(1 << 13));
+               p->dma_write(l, OCP_SYSCONFIG, 0);
+       }
 
        for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
 
                /* Stop the Channel transmission */
-               l = dma_read(CCR(channels[i]));
+               l = p->dma_read(CCR, channels[i]);
                l &= ~(1 << 7);
-               dma_write(l, CCR(channels[i]));
+               p->dma_write(l, CCR, channels[i]);
 
                /* Disable the link in all the channels */
                disable_lnk(channels[i]);
@@ -1753,8 +1650,8 @@ int omap_stop_dma_chain_transfers(int chain_id)
        /* Reset the Queue pointers */
        OMAP_DMA_CHAIN_QINIT(chain_id);
 
-       /* Errata - put in the old value */
-       dma_write(sys_cf, OCP_SYSCONFIG);
+       if (IS_DMA_ERRATA(DMA_ERRATA_i88))
+               p->dma_write(sys_cf, OCP_SYSCONFIG, 0);
 
        return 0;
 }
@@ -1796,8 +1693,8 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
        /* Get the current channel */
        lch = channels[dma_linked_lch[chain_id].q_head];
 
-       *ei = dma_read(CCEN(lch));
-       *fi = dma_read(CCFN(lch));
+       *ei = p->dma_read(CCEN, lch);
+       *fi = p->dma_read(CCFN, lch);
 
        return 0;
 }
@@ -1834,7 +1731,7 @@ int omap_get_dma_chain_dst_pos(int chain_id)
        /* Get the current channel */
        lch = channels[dma_linked_lch[chain_id].q_head];
 
-       return dma_read(CDAC(lch));
+       return p->dma_read(CDAC, lch);
 }
 EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
 
@@ -1868,7 +1765,7 @@ int omap_get_dma_chain_src_pos(int chain_id)
        /* Get the current channel */
        lch = channels[dma_linked_lch[chain_id].q_head];
 
-       return dma_read(CSAC(lch));
+       return p->dma_read(CSAC, lch);
 }
 EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
 #endif /* ifndef CONFIG_ARCH_OMAP1 */
@@ -1885,7 +1782,7 @@ static int omap1_dma_handle_ch(int ch)
                csr = dma_chan[ch].saved_csr;
                dma_chan[ch].saved_csr = 0;
        } else
-               csr = dma_read(CSR(ch));
+               csr = p->dma_read(CSR, ch);
        if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
                dma_chan[ch + 6].saved_csr = csr >> 7;
                csr &= 0x7f;
@@ -1938,13 +1835,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
 
 static int omap2_dma_handle_ch(int ch)
 {
-       u32 status = dma_read(CSR(ch));
+       u32 status = p->dma_read(CSR, ch);
 
        if (!status) {
                if (printk_ratelimit())
                        printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",
                                ch);
-               dma_write(1 << ch, IRQSTATUS_L0);
+               p->dma_write(1 << ch, IRQSTATUS_L0, ch);
                return 0;
        }
        if (unlikely(dma_chan[ch].dev_id == -1)) {
@@ -1960,17 +1857,12 @@ static int omap2_dma_handle_ch(int ch)
        if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
                printk(KERN_INFO "DMA transaction error with device %d\n",
                       dma_chan[ch].dev_id);
-               if (cpu_class_is_omap2()) {
-                       /*
-                        * Errata: sDMA Channel is not disabled
-                        * after a transaction error. So we explicitely
-                        * disable the channel
-                        */
+               if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
                        u32 ccr;
 
-                       ccr = dma_read(CCR(ch));
+                       ccr = p->dma_read(CCR, ch);
                        ccr &= ~OMAP_DMA_CCR_EN;
-                       dma_write(ccr, CCR(ch));
+                       p->dma_write(ccr, CCR, ch);
                        dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
                }
        }
@@ -1981,16 +1873,16 @@ static int omap2_dma_handle_ch(int ch)
                printk(KERN_INFO "DMA misaligned error with device %d\n",
                       dma_chan[ch].dev_id);
 
-       dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch));
-       dma_write(1 << ch, IRQSTATUS_L0);
+       p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch);
+       p->dma_write(1 << ch, IRQSTATUS_L0, ch);
        /* read back the register to flush the write */
-       dma_read(IRQSTATUS_L0);
+       p->dma_read(IRQSTATUS_L0, ch);
 
        /* If the ch is not chained then chain_id will be -1 */
        if (dma_chan[ch].chain_id != -1) {
                int chain_id = dma_chan[ch].chain_id;
                dma_chan[ch].state = DMA_CH_NOTSTARTED;
-               if (dma_read(CLNK_CTRL(ch)) & (1 << 15))
+               if (p->dma_read(CLNK_CTRL, ch) & (1 << 15))
                        dma_chan[dma_chan[ch].next_linked_ch].state =
                                                        DMA_CH_STARTED;
                if (dma_linked_lch[chain_id].chain_mode ==
@@ -2000,10 +1892,10 @@ static int omap2_dma_handle_ch(int ch)
                if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
                        OMAP_DMA_CHAIN_INCQHEAD(chain_id);
 
-               status = dma_read(CSR(ch));
+               status = p->dma_read(CSR, ch);
        }
 
-       dma_write(status, CSR(ch));
+       p->dma_write(status, CSR, ch);
 
        if (likely(dma_chan[ch].callback != NULL))
                dma_chan[ch].callback(ch, status, dma_chan[ch].data);
@@ -2017,13 +1909,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
        u32 val, enable_reg;
        int i;
 
-       val = dma_read(IRQSTATUS_L0);
+       val = p->dma_read(IRQSTATUS_L0, 0);
        if (val == 0) {
                if (printk_ratelimit())
                        printk(KERN_WARNING "Spurious DMA IRQ\n");
                return IRQ_HANDLED;
        }
-       enable_reg = dma_read(IRQENABLE_L0);
+       enable_reg = p->dma_read(IRQENABLE_L0, 0);
        val &= enable_reg; /* Dispatch only relevant interrupts */
        for (i = 0; i < dma_lch_count && val != 0; i++) {
                if (val & 1)
@@ -2049,119 +1941,66 @@ static struct irqaction omap24xx_dma_irq;
 void omap_dma_global_context_save(void)
 {
        omap_dma_global_context.dma_irqenable_l0 =
-               dma_read(IRQENABLE_L0);
+               p->dma_read(IRQENABLE_L0, 0);
        omap_dma_global_context.dma_ocp_sysconfig =
-               dma_read(OCP_SYSCONFIG);
-       omap_dma_global_context.dma_gcr = dma_read(GCR);
+               p->dma_read(OCP_SYSCONFIG, 0);
+       omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0);
 }
 
 void omap_dma_global_context_restore(void)
 {
        int ch;
 
-       dma_write(omap_dma_global_context.dma_gcr, GCR);
-       dma_write(omap_dma_global_context.dma_ocp_sysconfig,
-               OCP_SYSCONFIG);
-       dma_write(omap_dma_global_context.dma_irqenable_l0,
-               IRQENABLE_L0);
+       p->dma_write(omap_dma_global_context.dma_gcr, GCR, 0);
+       p->dma_write(omap_dma_global_context.dma_ocp_sysconfig,
+               OCP_SYSCONFIG, 0);
+       p->dma_write(omap_dma_global_context.dma_irqenable_l0,
+               IRQENABLE_L0, 0);
 
-       /*
-        * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
-        * after secure sram context save and restore. Hence we need to
-        * manually clear those IRQs to avoid spurious interrupts. This
-        * affects only secure devices.
-        */
-       if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
-               dma_write(0x3 , IRQSTATUS_L0);
+       if (IS_DMA_ERRATA(DMA_ROMCODE_BUG))
+               p->dma_write(0x3 , IRQSTATUS_L0, 0);
 
        for (ch = 0; ch < dma_chan_count; ch++)
                if (dma_chan[ch].dev_id != -1)
                        omap_clear_dma(ch);
 }
 
-/*----------------------------------------------------------------------------*/
-
-static int __init omap_init_dma(void)
+static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 {
-       unsigned long base;
-       int ch, r;
-
-       if (cpu_class_is_omap1()) {
-               base = OMAP1_DMA_BASE;
-               dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT;
-       } else if (cpu_is_omap24xx()) {
-               base = OMAP24XX_DMA4_BASE;
-               dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
-       } else if (cpu_is_omap34xx()) {
-               base = OMAP34XX_DMA4_BASE;
-               dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
-       } else if (cpu_is_omap44xx()) {
-               base = OMAP44XX_DMA4_BASE;
-               dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
-       } else {
-               pr_err("DMA init failed for unsupported omap\n");
-               return -ENODEV;
+       int ch, ret = 0;
+       int dma_irq;
+       char irq_name[4];
+       int irq_rel;
+
+       p = pdev->dev.platform_data;
+       if (!p) {
+               dev_err(&pdev->dev, "%s: System DMA initialized without"
+                       "platform data\n", __func__);
+               return -EINVAL;
        }
 
-       omap_dma_base = ioremap(base, SZ_4K);
-       BUG_ON(!omap_dma_base);
+       d                       = p->dma_attr;
+       errata                  = p->errata;
 
-       if (cpu_class_is_omap2() && omap_dma_reserve_channels
+       if ((d->dev_caps & RESERVE_CHANNEL) && omap_dma_reserve_channels
                        && (omap_dma_reserve_channels <= dma_lch_count))
-               dma_lch_count = omap_dma_reserve_channels;
+               d->lch_count    = omap_dma_reserve_channels;
 
-       dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count,
-                               GFP_KERNEL);
-       if (!dma_chan) {
-               r = -ENOMEM;
-               goto out_unmap;
-       }
+       dma_lch_count           = d->lch_count;
+       dma_chan_count          = dma_lch_count;
+       dma_chan                = d->chan;
+       enable_1510_mode        = d->dev_caps & ENABLE_1510_MODE;
 
        if (cpu_class_is_omap2()) {
                dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
                                                dma_lch_count, GFP_KERNEL);
                if (!dma_linked_lch) {
-                       r = -ENOMEM;
-                       goto out_free;
+                       ret = -ENOMEM;
+                       goto exit_dma_lch_fail;
                }
        }
 
-       if (cpu_is_omap15xx()) {
-               printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
-               dma_chan_count = 9;
-               enable_1510_mode = 1;
-       } else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
-               printk(KERN_INFO "OMAP DMA hardware version %d\n",
-                      dma_read(HW_ID));
-               printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
-                      (dma_read(CAPS_0_U) << 16) |
-                      dma_read(CAPS_0_L),
-                      (dma_read(CAPS_1_U) << 16) |
-                      dma_read(CAPS_1_L),
-                      dma_read(CAPS_2), dma_read(CAPS_3),
-                      dma_read(CAPS_4));
-               if (!enable_1510_mode) {
-                       u16 w;
-
-                       /* Disable OMAP 3.0/3.1 compatibility mode. */
-                       w = dma_read(GSCR);
-                       w |= 1 << 3;
-                       dma_write(w, GSCR);
-                       dma_chan_count = 16;
-               } else
-                       dma_chan_count = 9;
-       } else if (cpu_class_is_omap2()) {
-               u8 revision = dma_read(REVISION) & 0xff;
-               printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
-                      revision >> 4, revision & 0xf);
-               dma_chan_count = dma_lch_count;
-       } else {
-               dma_chan_count = 0;
-               return 0;
-       }
-
        spin_lock_init(&dma_chan_lock);
-
        for (ch = 0; ch < dma_chan_count; ch++) {
                omap_clear_dma(ch);
                if (cpu_class_is_omap2())
@@ -2178,20 +2017,23 @@ static int __init omap_init_dma(void)
                         * request_irq() doesn't like dev_id (ie. ch) being
                         * zero, so we have to kludge around this.
                         */
-                       r = request_irq(omap1_dma_irq[ch],
+                       sprintf(&irq_name[0], "%d", ch);
+                       dma_irq = platform_get_irq_byname(pdev, irq_name);
+
+                       if (dma_irq < 0) {
+                               ret = dma_irq;
+                               goto exit_dma_irq_fail;
+                       }
+
+                       /* INT_DMA_LCD is handled in lcd_dma.c */
+                       if (dma_irq == INT_DMA_LCD)
+                               continue;
+
+                       ret = request_irq(dma_irq,
                                        omap1_dma_irq_handler, 0, "DMA",
                                        (void *) (ch + 1));
-                       if (r != 0) {
-                               int i;
-
-                               printk(KERN_ERR "unable to request IRQ %d "
-                                      "for DMA (error %d)\n",
-                                      omap1_dma_irq[ch], r);
-                               for (i = 0; i < ch; i++)
-                                       free_irq(omap1_dma_irq[i],
-                                                (void *) (i + 1));
-                               goto out_free;
-                       }
+                       if (ret != 0)
+                               goto exit_dma_irq_fail;
                }
        }
 
@@ -2200,46 +2042,91 @@ static int __init omap_init_dma(void)
                                DMA_DEFAULT_FIFO_DEPTH, 0);
 
        if (cpu_class_is_omap2()) {
-               int irq;
-               if (cpu_is_omap44xx())
-                       irq = OMAP44XX_IRQ_SDMA_0;
-               else
-                       irq = INT_24XX_SDMA_IRQ0;
-               setup_irq(irq, &omap24xx_dma_irq);
-       }
-
-       if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-               /* Enable smartidle idlemodes and autoidle */
-               u32 v = dma_read(OCP_SYSCONFIG);
-               v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK |
-                               DMA_SYSCONFIG_SIDLEMODE_MASK |
-                               DMA_SYSCONFIG_AUTOIDLE);
-               v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
-                       DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
-                       DMA_SYSCONFIG_AUTOIDLE);
-               dma_write(v , OCP_SYSCONFIG);
-               /* reserve dma channels 0 and 1 in high security devices */
-               if (cpu_is_omap34xx() &&
-                       (omap_type() != OMAP2_DEVICE_TYPE_GP)) {
-                       printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
-                                       "HS ROM code\n");
-                       dma_chan[0].dev_id = 0;
-                       dma_chan[1].dev_id = 1;
+               strcpy(irq_name, "0");
+               dma_irq = platform_get_irq_byname(pdev, irq_name);
+               if (dma_irq < 0) {
+                       dev_err(&pdev->dev, "failed: request IRQ %d", dma_irq);
+                       goto exit_dma_lch_fail;
+               }
+               ret = setup_irq(dma_irq, &omap24xx_dma_irq);
+               if (ret) {
+                       dev_err(&pdev->dev, "set_up failed for IRQ %d"
+                               "for DMA (error %d)\n", dma_irq, ret);
+                       goto exit_dma_lch_fail;
                }
        }
 
+       /* reserve dma channels 0 and 1 in high security devices */
+       if (cpu_is_omap34xx() &&
+               (omap_type() != OMAP2_DEVICE_TYPE_GP)) {
+               printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
+                               "HS ROM code\n");
+               dma_chan[0].dev_id = 0;
+               dma_chan[1].dev_id = 1;
+       }
+       p->show_dma_caps();
        return 0;
 
-out_free:
+exit_dma_irq_fail:
+       dev_err(&pdev->dev, "unable to request IRQ %d"
+                       "for DMA (error %d)\n", dma_irq, ret);
+       for (irq_rel = 0; irq_rel < ch; irq_rel++) {
+               dma_irq = platform_get_irq(pdev, irq_rel);
+               free_irq(dma_irq, (void *)(irq_rel + 1));
+       }
+
+exit_dma_lch_fail:
+       kfree(p);
+       kfree(d);
        kfree(dma_chan);
+       return ret;
+}
 
-out_unmap:
-       iounmap(omap_dma_base);
+static int __devexit omap_system_dma_remove(struct platform_device *pdev)
+{
+       int dma_irq;
 
-       return r;
+       if (cpu_class_is_omap2()) {
+               char irq_name[4];
+               strcpy(irq_name, "0");
+               dma_irq = platform_get_irq_byname(pdev, irq_name);
+               remove_irq(dma_irq, &omap24xx_dma_irq);
+       } else {
+               int irq_rel = 0;
+               for ( ; irq_rel < dma_chan_count; irq_rel++) {
+                       dma_irq = platform_get_irq(pdev, irq_rel);
+                       free_irq(dma_irq, (void *)(irq_rel + 1));
+               }
+       }
+       kfree(p);
+       kfree(d);
+       kfree(dma_chan);
+       return 0;
+}
+
+static struct platform_driver omap_system_dma_driver = {
+       .probe          = omap_system_dma_probe,
+       .remove         = omap_system_dma_remove,
+       .driver         = {
+               .name   = "omap_dma_system"
+       },
+};
+
+static int __init omap_system_dma_init(void)
+{
+       return platform_driver_register(&omap_system_dma_driver);
+}
+arch_initcall(omap_system_dma_init);
+
+static void __exit omap_system_dma_exit(void)
+{
+       platform_driver_unregister(&omap_system_dma_driver);
 }
 
-arch_initcall(omap_init_dma);
+MODULE_DESCRIPTION("OMAP SYSTEM DMA DRIVER");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
 
 /*
  * Reserve the omap SDMA channels using cmdline bootarg
index 0cce4ca83aa0c70217fadd03ea07856665436ef0..d1c916fcf7700440c80deb96759807622009ae56 100644 (file)
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-/* Move omap4 specific defines to dma-44xx.h */
-#include "dma-44xx.h"
+#include <linux/platform_device.h>
 
-/* Hardware registers for omap1 */
-#define OMAP1_DMA_BASE                 (0xfffed800)
-
-#define OMAP1_DMA_GCR                  0x400
-#define OMAP1_DMA_GSCR                 0x404
-#define OMAP1_DMA_GRST                 0x408
-#define OMAP1_DMA_HW_ID                        0x442
-#define OMAP1_DMA_PCH2_ID              0x444
-#define OMAP1_DMA_PCH0_ID              0x446
-#define OMAP1_DMA_PCH1_ID              0x448
-#define OMAP1_DMA_PCHG_ID              0x44a
-#define OMAP1_DMA_PCHD_ID              0x44c
-#define OMAP1_DMA_CAPS_0_U             0x44e
-#define OMAP1_DMA_CAPS_0_L             0x450
-#define OMAP1_DMA_CAPS_1_U             0x452
-#define OMAP1_DMA_CAPS_1_L             0x454
-#define OMAP1_DMA_CAPS_2               0x456
-#define OMAP1_DMA_CAPS_3               0x458
-#define OMAP1_DMA_CAPS_4               0x45a
-#define OMAP1_DMA_PCH2_SR              0x460
-#define OMAP1_DMA_PCH0_SR              0x480
-#define OMAP1_DMA_PCH1_SR              0x482
-#define OMAP1_DMA_PCHD_SR              0x4c0
-
-/* Hardware registers for omap2 and omap3 */
-#define OMAP24XX_DMA4_BASE             (L4_24XX_BASE + 0x56000)
-#define OMAP34XX_DMA4_BASE             (L4_34XX_BASE + 0x56000)
-#define OMAP44XX_DMA4_BASE             (L4_44XX_BASE + 0x56000)
-
-#define OMAP_DMA4_REVISION             0x00
-#define OMAP_DMA4_GCR                  0x78
-#define OMAP_DMA4_IRQSTATUS_L0         0x08
-#define OMAP_DMA4_IRQSTATUS_L1         0x0c
-#define OMAP_DMA4_IRQSTATUS_L2         0x10
-#define OMAP_DMA4_IRQSTATUS_L3         0x14
-#define OMAP_DMA4_IRQENABLE_L0         0x18
-#define OMAP_DMA4_IRQENABLE_L1         0x1c
-#define OMAP_DMA4_IRQENABLE_L2         0x20
-#define OMAP_DMA4_IRQENABLE_L3         0x24
-#define OMAP_DMA4_SYSSTATUS            0x28
-#define OMAP_DMA4_OCP_SYSCONFIG                0x2c
-#define OMAP_DMA4_CAPS_0               0x64
-#define OMAP_DMA4_CAPS_2               0x6c
-#define OMAP_DMA4_CAPS_3               0x70
-#define OMAP_DMA4_CAPS_4               0x74
-
-#define OMAP1_LOGICAL_DMA_CH_COUNT     17
-#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32      /* REVISIT: Is this 32 + 2? */
-
-/* Common channel specific registers for omap1 */
-#define OMAP1_DMA_CH_BASE(n)           (0x40 * (n) + 0x00)
-#define OMAP1_DMA_CSDP(n)              (0x40 * (n) + 0x00)
-#define OMAP1_DMA_CCR(n)               (0x40 * (n) + 0x02)
-#define OMAP1_DMA_CICR(n)              (0x40 * (n) + 0x04)
-#define OMAP1_DMA_CSR(n)               (0x40 * (n) + 0x06)
-#define OMAP1_DMA_CEN(n)               (0x40 * (n) + 0x10)
-#define OMAP1_DMA_CFN(n)               (0x40 * (n) + 0x12)
-#define OMAP1_DMA_CSFI(n)              (0x40 * (n) + 0x14)
-#define OMAP1_DMA_CSEI(n)              (0x40 * (n) + 0x16)
-#define OMAP1_DMA_CPC(n)               (0x40 * (n) + 0x18)     /* 15xx only */
-#define OMAP1_DMA_CSAC(n)              (0x40 * (n) + 0x18)
-#define OMAP1_DMA_CDAC(n)              (0x40 * (n) + 0x1a)
-#define OMAP1_DMA_CDEI(n)              (0x40 * (n) + 0x1c)
-#define OMAP1_DMA_CDFI(n)              (0x40 * (n) + 0x1e)
-#define OMAP1_DMA_CLNK_CTRL(n)         (0x40 * (n) + 0x28)
-
-/* Common channel specific registers for omap2 */
-#define OMAP_DMA4_CH_BASE(n)           (0x60 * (n) + 0x80)
-#define OMAP_DMA4_CCR(n)               (0x60 * (n) + 0x80)
-#define OMAP_DMA4_CLNK_CTRL(n)         (0x60 * (n) + 0x84)
-#define OMAP_DMA4_CICR(n)              (0x60 * (n) + 0x88)
-#define OMAP_DMA4_CSR(n)               (0x60 * (n) + 0x8c)
-#define OMAP_DMA4_CSDP(n)              (0x60 * (n) + 0x90)
-#define OMAP_DMA4_CEN(n)               (0x60 * (n) + 0x94)
-#define OMAP_DMA4_CFN(n)               (0x60 * (n) + 0x98)
-#define OMAP_DMA4_CSEI(n)              (0x60 * (n) + 0xa4)
-#define OMAP_DMA4_CSFI(n)              (0x60 * (n) + 0xa8)
-#define OMAP_DMA4_CDEI(n)              (0x60 * (n) + 0xac)
-#define OMAP_DMA4_CDFI(n)              (0x60 * (n) + 0xb0)
-#define OMAP_DMA4_CSAC(n)              (0x60 * (n) + 0xb4)
-#define OMAP_DMA4_CDAC(n)              (0x60 * (n) + 0xb8)
-
-/* Channel specific registers only on omap1 */
-#define OMAP1_DMA_CSSA_L(n)            (0x40 * (n) + 0x08)
-#define OMAP1_DMA_CSSA_U(n)            (0x40 * (n) + 0x0a)
-#define OMAP1_DMA_CDSA_L(n)            (0x40 * (n) + 0x0c)
-#define OMAP1_DMA_CDSA_U(n)            (0x40 * (n) + 0x0e)
-#define OMAP1_DMA_COLOR_L(n)           (0x40 * (n) + 0x20)
-#define OMAP1_DMA_COLOR_U(n)           (0x40 * (n) + 0x22)
-#define OMAP1_DMA_CCR2(n)              (0x40 * (n) + 0x24)
-#define OMAP1_DMA_LCH_CTRL(n)          (0x40 * (n) + 0x2a)     /* not on 15xx */
-#define OMAP1_DMA_CCEN(n)              0
-#define OMAP1_DMA_CCFN(n)              0
-
-/* Channel specific registers only on omap2 */
-#define OMAP_DMA4_CSSA(n)              (0x60 * (n) + 0x9c)
-#define OMAP_DMA4_CDSA(n)              (0x60 * (n) + 0xa0)
-#define OMAP_DMA4_CCEN(n)              (0x60 * (n) + 0xbc)
-#define OMAP_DMA4_CCFN(n)              (0x60 * (n) + 0xc0)
-#define OMAP_DMA4_COLOR(n)             (0x60 * (n) + 0xc4)
-
-/* Additional registers available on OMAP4 */
-#define OMAP_DMA4_CDP(n)               (0x60 * (n) + 0xd0)
-#define OMAP_DMA4_CNDP(n)              (0x60 * (n) + 0xd4)
-#define OMAP_DMA4_CCDN(n)              (0x60 * (n) + 0xd8)
-
-/* Dummy defines to keep multi-omap compiles happy */
-#define OMAP1_DMA_REVISION             0
-#define OMAP1_DMA_IRQSTATUS_L0         0
-#define OMAP1_DMA_IRQENABLE_L0         0
-#define OMAP1_DMA_OCP_SYSCONFIG                0
-#define OMAP_DMA4_HW_ID                        0
-#define OMAP_DMA4_CAPS_0_L             0
-#define OMAP_DMA4_CAPS_0_U             0
-#define OMAP_DMA4_CAPS_1_L             0
-#define OMAP_DMA4_CAPS_1_U             0
-#define OMAP_DMA4_GSCR                 0
-#define OMAP_DMA4_CPC(n)               0
-
-#define OMAP_DMA4_LCH_CTRL(n)          0
-#define OMAP_DMA4_COLOR_L(n)           0
-#define OMAP_DMA4_COLOR_U(n)           0
-#define OMAP_DMA4_CCR2(n)              0
-#define OMAP1_DMA_CSSA(n)              0
-#define OMAP1_DMA_CDSA(n)              0
-#define OMAP_DMA4_CSSA_L(n)            0
-#define OMAP_DMA4_CSSA_U(n)            0
-#define OMAP_DMA4_CDSA_L(n)            0
-#define OMAP_DMA4_CDSA_U(n)            0
-#define OMAP1_DMA_COLOR(n)             0
+/*
+ * TODO: These dma channel defines should go away once all
+ * the omap drivers hwmod adapted.
+ */
 
-/*----------------------------------------------------------------------------*/
+/* Move omap4 specific defines to dma-44xx.h */
+#include "dma-44xx.h"
 
 /* DMA channels for omap1 */
 #define OMAP_DMA_NO_DEVICE             0
 #define DMA_CH_PRIO_HIGH               0x1
 #define DMA_CH_PRIO_LOW                        0x0 /* Def */
 
+/* Errata handling */
+#define IS_DMA_ERRATA(id)              (errata & (id))
+#define SET_DMA_ERRATA(id)             (errata |= (id))
+
+#define DMA_ERRATA_IFRAME_BUFFERING    BIT(0x0)
+#define DMA_ERRATA_PARALLEL_CHANNELS   BIT(0x1)
+#define DMA_ERRATA_i378                        BIT(0x2)
+#define DMA_ERRATA_i541                        BIT(0x3)
+#define DMA_ERRATA_i88                 BIT(0x4)
+#define DMA_ERRATA_3_3                 BIT(0x5)
+#define DMA_ROMCODE_BUG                        BIT(0x6)
+
+/* Attributes for OMAP DMA Contrller */
+#define DMA_LINKED_LCH                 BIT(0x0)
+#define GLOBAL_PRIORITY                        BIT(0x1)
+#define RESERVE_CHANNEL                        BIT(0x2)
+#define IS_CSSA_32                     BIT(0x3)
+#define IS_CDSA_32                     BIT(0x4)
+#define IS_RW_PRIORITY                 BIT(0x5)
+#define ENABLE_1510_MODE               BIT(0x6)
+#define SRC_PORT                       BIT(0x7)
+#define DST_PORT                       BIT(0x8)
+#define SRC_INDEX                      BIT(0x9)
+#define DST_INDEX                      BIT(0xA)
+#define IS_BURST_ONLY4                 BIT(0xB)
+#define CLEAR_CSR_ON_READ              BIT(0xC)
+#define IS_WORD_16                     BIT(0xD)
+
+enum omap_reg_offsets {
+
+GCR,           GSCR,           GRST1,          HW_ID,
+PCH2_ID,       PCH0_ID,        PCH1_ID,        PCHG_ID,
+PCHD_ID,       CAPS_0,         CAPS_1,         CAPS_2,
+CAPS_3,                CAPS_4,         PCH2_SR,        PCH0_SR,
+PCH1_SR,       PCHD_SR,        REVISION,       IRQSTATUS_L0,
+IRQSTATUS_L1,  IRQSTATUS_L2,   IRQSTATUS_L3,   IRQENABLE_L0,
+IRQENABLE_L1,  IRQENABLE_L2,   IRQENABLE_L3,   SYSSTATUS,
+OCP_SYSCONFIG,
+
+/* omap1+ specific */
+CPC, CCR2, LCH_CTRL,
+
+/* Common registers for all omap's */
+CSDP,          CCR,            CICR,           CSR,
+CEN,           CFN,            CSFI,           CSEI,
+CSAC,          CDAC,           CDEI,
+CDFI,          CLNK_CTRL,
+
+/* Channel specific registers */
+CSSA,          CDSA,           COLOR,
+CCEN,          CCFN,
+
+/* omap3630 and omap4 specific */
+CDP,           CNDP,           CCDN,
+
+};
+
 enum omap_dma_burst_mode {
        OMAP_DMA_DATA_BURST_DIS = 0,
        OMAP_DMA_DATA_BURST_4,
@@ -470,6 +401,41 @@ struct omap_dma_channel_params {
 #endif
 };
 
+struct omap_dma_lch {
+       int next_lch;
+       int dev_id;
+       u16 saved_csr;
+       u16 enabled_irqs;
+       const char *dev_name;
+       void (*callback)(int lch, u16 ch_status, void *data);
+       void *data;
+       long flags;
+       /* required for Dynamic chaining */
+       int prev_linked_ch;
+       int next_linked_ch;
+       int state;
+       int chain_id;
+       int status;
+};
+
+struct omap_dma_dev_attr {
+       u32 dev_caps;
+       u16 lch_count;
+       u16 chan_count;
+       struct omap_dma_lch *chan;
+};
+
+/* System DMA platform data structure */
+struct omap_system_dma_plat_info {
+       struct omap_dma_dev_attr *dma_attr;
+       u32 errata;
+       void (*disable_irq_lch)(int lch);
+       void (*show_dma_caps)(void);
+       void (*clear_lch_regs)(int lch);
+       void (*clear_dma)(int lch);
+       void (*dma_write)(u32 val, int reg, int lch);
+       u32 (*dma_read)(int reg, int lch);
+};
 
 extern void omap_set_dma_priority(int lch, int dst_port, int priority);
 extern int omap_request_dma(int dev_id, const char *dev_name,
index 5905100b29a1391078a9239e01c6d28b22f5f5be..9967d5e855c76c810e3190fd93f81742993230d3 100644 (file)
@@ -11,6 +11,7 @@
 #ifndef __ARCH_ARM_OMAP_SRAM_H
 #define __ARCH_ARM_OMAP_SRAM_H
 
+#ifndef __ASSEMBLY__
 extern void * omap_sram_push(void * start, unsigned long size);
 extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
 
@@ -74,4 +75,14 @@ extern void omap_push_sram_idle(void);
 static inline void omap_push_sram_idle(void) {}
 #endif /* CONFIG_PM */
 
+#endif /* __ASSEMBLY__ */
+
+/*
+ * OMAP2+: define the SRAM PA addresses.
+ * Used by the SRAM management code and the idle sleep code.
+ */
+#define OMAP2_SRAM_PA          0x40200000
+#define OMAP3_SRAM_PA           0x40200000
+#define OMAP4_SRAM_PA          0x40300000
+
 #endif
index 819ea0cfb81ab8fdd1625f885ed07abc23c36910..1a686c89d8ddce3049474c5c0533244f97da2580 100644 (file)
 
 #define OMAP1_SRAM_PA          0x20000000
 #define OMAP1_SRAM_VA          VMALLOC_END
-#define OMAP2_SRAM_PA          0x40200000
-#define OMAP2_SRAM_PUB_PA      0x4020f800
+#define OMAP2_SRAM_PUB_PA      (OMAP2_SRAM_PA + 0xf800)
 #define OMAP2_SRAM_VA          0xfe400000
 #define OMAP2_SRAM_PUB_VA      (OMAP2_SRAM_VA + 0x800)
-#define OMAP3_SRAM_PA           0x40200000
 #define OMAP3_SRAM_VA           0xfe400000
-#define OMAP3_SRAM_PUB_PA       0x40208000
+#define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)
 #define OMAP3_SRAM_PUB_VA       (OMAP3_SRAM_VA + 0x8000)
-#define OMAP4_SRAM_PA          0x40300000
 #define OMAP4_SRAM_VA          0xfe400000
 #define OMAP4_SRAM_PUB_PA      (OMAP4_SRAM_PA + 0x4000)
 #define OMAP4_SRAM_PUB_VA      (OMAP4_SRAM_VA + 0x4000)
index 5a27b1b538f2885eab6cd6ccdfd670834607f665..eb105e61c746750f716cb0f8d392da560f8f1332 100644 (file)
@@ -8,7 +8,7 @@ config PLAT_S3C24XX
        default y
        select NO_IOPORT
        select ARCH_REQUIRE_GPIOLIB
-       select S3C_DEVICE_NAND
+       select S3C_DEV_NAND
        select S3C_GPIO_CFG_S3C24XX
        help
          Base platform code for any Samsung S3C24XX device
index 67a2fa2caa494ff06e2550aa8cea7cf61d69f39e..0a9b5b8b2a1935103ecf9d81a2367d0a0633f1e4 100644 (file)
@@ -19,6 +19,8 @@ config MIPS
        select GENERIC_ATOMIC64 if !64BIT
        select HAVE_DMA_ATTRS
        select HAVE_DMA_API_DEBUG
+       select HAVE_GENERIC_HARDIRQS
+       select GENERIC_IRQ_PROBE
 
 menu "Machine selection"
 
@@ -1664,6 +1666,28 @@ config PAGE_SIZE_64KB
 
 endchoice
 
+config FORCE_MAX_ZONEORDER
+       int "Maximum zone order"
+       range 13 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB
+       default "13" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB
+       range 12 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB
+       default "12" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB
+       range 11 64
+       default "11"
+       help
+         The kernel memory allocator divides physically contiguous memory
+         blocks into "zones", where each zone is a power of two number of
+         pages.  This option selects the largest power of two that the kernel
+         keeps in the memory allocator.  If you need to allocate very large
+         blocks of physically contiguous memory, then you may need to
+         increase this value.
+
+         This config option is actually maximum order plus one. For example,
+         a value of 11 means that the largest free memory block is 2^10 pages.
+
+         The page size is not necessarily 4KB.  Keep this in mind
+         when choosing a value for this option.
+
 config BOARD_SCACHE
        bool
 
@@ -1921,20 +1945,6 @@ config CPU_R4000_WORKAROUNDS
 config CPU_R4400_WORKAROUNDS
        bool
 
-#
-# Use the generic interrupt handling code in kernel/irq/:
-#
-config GENERIC_HARDIRQS
-       bool
-       default y
-
-config GENERIC_IRQ_PROBE
-       bool
-       default y
-
-config IRQ_PER_CPU
-       bool
-
 #
 # - Highmem only makes sense for the 32-bit kernel.
 # - The current highmem code will only work properly on physically indexed
index 3691630931d6100ae901d8adbddcc6ccb6cf960e..9e7814db3d03411d08bfe93868f84d646dd93d93 100644 (file)
@@ -27,6 +27,7 @@
 static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
                            unsigned int old_state)
 {
+#ifdef CONFIG_SERIAL_8250
        switch (state) {
        case 0:
                if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) {
@@ -49,6 +50,7 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
                serial8250_do_pm(port, state, old_state);
                break;
        }
+#endif
 }
 
 #define PORT(_base, _irq)                                      \
index b30df5c97ad35e46e534b047c144975c01db6b76..baeb21385058b8d5efe5e046620e66746b754d73 100644 (file)
@@ -54,10 +54,9 @@ void __init prom_init(void)
 
        prom_init_cmdline();
        memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
+       if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize))
                memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE;
-       else
-               strict_strtoul(memsize_str, 0, &memsize);
+
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
 
index fc0e7154e8d69835c56eb45891a9e98beca0e82f..2ca4ada1c291cf7cb13f0ac047d6b879e9e1b400 100644 (file)
@@ -239,12 +239,12 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
        calculate(base_clock, frequency, &prediv, &postdiv, &mul);
 
        writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
-       msleep(1);
+       mdelay(1);
        writel(4, &clock->pll);
        while (readl(&clock->pll) & PLL_STATUS)
                ;
        writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
-       msleep(75);
+       mdelay(75);
 }
 
 static void __init tnetd7300_init_clocks(void)
@@ -456,7 +456,7 @@ void clk_put(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_put);
 
-int __init ar7_init_clocks(void)
+void __init ar7_init_clocks(void)
 {
        switch (ar7_chip_id()) {
        case AR7_CHIP_7100:
@@ -472,7 +472,4 @@ int __init ar7_init_clocks(void)
        }
        /* adjust vbus clock rate */
        vbus_clk.rate = bus_clk.rate / 2;
-
-       return 0;
 }
-arch_initcall(ar7_init_clocks);
index 5fb8a01340855f402340914784c65924faaa163e..22c93213b233db0090a2c8175cee864f2cf62619 100644 (file)
@@ -30,6 +30,9 @@ void __init plat_time_init(void)
 {
        struct clk *cpu_clk;
 
+       /* Initialize ar7 clocks so the CPU clock frequency is correct */
+       ar7_init_clocks();
+
        cpu_clk = clk_get(NULL, "cpu");
        if (IS_ERR(cpu_clk)) {
                printk(KERN_ERR "unable to get cpu clock\n");
index b1aee33efd11454e7f47c7d8beb7d0d50ed9ca2a..c95f90bf734ca9c1765b14728f391a14af62917b 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <bcm47xx.h>
-#include <asm/fw/cfe/cfe_api.h>
 #include <asm/mach-bcm47xx/nvram.h>
 
 struct ssb_bus ssb_bcm47xx;
@@ -57,68 +56,112 @@ static void bcm47xx_machine_halt(void)
                cpu_relax();
 }
 
-static void str2eaddr(char *str, char *dest)
-{
-       int i = 0;
+#define READ_FROM_NVRAM(_outvar, name, buf) \
+       if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\
+               sprom->_outvar = simple_strtoul(buf, NULL, 0);
 
-       if (str == NULL) {
-               memset(dest, 0, 6);
-               return;
+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
+{
+       char buf[100];
+       u32 boardflags;
+
+       memset(sprom, 0, sizeof(struct ssb_sprom));
+
+       sprom->revision = 1; /* Fallback: Old hardware does not define this. */
+       READ_FROM_NVRAM(revision, "sromrev", buf);
+       if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->il0mac);
+       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et0mac);
+       if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et1mac);
+       READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
+       READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
+       READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf);
+       READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf);
+       READ_FROM_NVRAM(board_rev, "boardrev", buf);
+       READ_FROM_NVRAM(country_code, "ccode", buf);
+       READ_FROM_NVRAM(ant_available_a, "aa5g", buf);
+       READ_FROM_NVRAM(ant_available_bg, "aa2g", buf);
+       READ_FROM_NVRAM(pa0b0, "pa0b0", buf);
+       READ_FROM_NVRAM(pa0b1, "pa0b1", buf);
+       READ_FROM_NVRAM(pa0b2, "pa0b2", buf);
+       READ_FROM_NVRAM(pa1b0, "pa1b0", buf);
+       READ_FROM_NVRAM(pa1b1, "pa1b1", buf);
+       READ_FROM_NVRAM(pa1b2, "pa1b2", buf);
+       READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf);
+       READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf);
+       READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf);
+       READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
+       READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
+       READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
+       READ_FROM_NVRAM(gpio0, "wl0gpio0", buf);
+       READ_FROM_NVRAM(gpio1, "wl0gpio1", buf);
+       READ_FROM_NVRAM(gpio2, "wl0gpio2", buf);
+       READ_FROM_NVRAM(gpio3, "wl0gpio3", buf);
+       READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf);
+       READ_FROM_NVRAM(itssi_a, "pa1itssit", buf);
+       READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf);
+       READ_FROM_NVRAM(tri2g, "tri2g", buf);
+       READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
+       READ_FROM_NVRAM(tri5g, "tri5g", buf);
+       READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
+       READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
+       READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
+       READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
+       READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf);
+       READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf);
+       READ_FROM_NVRAM(bxa2g, "bxa2g", buf);
+       READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf);
+       READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf);
+       READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
+       READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
+       READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
+       READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf);
+       READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf);
+       READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf);
+       READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf);
+
+       if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
+                       sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
+               }
        }
-
-       for (;;) {
-               dest[i++] = (char) simple_strtoul(str, NULL, 16);
-               str += 2;
-               if (!*str++ || i == 6)
-                       break;
+       if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
+                       sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16;
+               }
        }
 }
 
 static int bcm47xx_get_invariants(struct ssb_bus *bus,
                                   struct ssb_init_invariants *iv)
 {
-       char buf[100];
+       char buf[20];
 
        /* Fill boardinfo structure */
        memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
 
-       if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
-               iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
-       if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
+       if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+               iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0);
+       else
+               iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+       if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
                iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
-       if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
+       if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
                iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
 
-       /* Fill sprom structure */
-       memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
-       iv->sprom.revision = 3;
-
-       if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
-               str2eaddr(buf, iv->sprom.et0mac);
+       bcm47xx_fill_sprom(&iv->sprom);
 
-       if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
-               str2eaddr(buf, iv->sprom.et1mac);
-
-       if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
-               iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
-
-       if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
-               iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
-
-       if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
-               iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
-
-       if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
-               iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
+       if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
+               iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
 
        return 0;
 }
@@ -126,12 +169,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
 void __init plat_mem_setup(void)
 {
        int err;
+       char buf[100];
+       struct ssb_mipscore *mcore;
 
        err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
                                      bcm47xx_get_invariants);
        if (err)
                panic("Failed to initialize SSB bus (err %d)\n", err);
 
+       mcore = &ssb_bcm47xx.mipscore;
+       if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
+               if (strstr(buf, "console=ttyS1")) {
+                       struct ssb_serial_port port;
+
+                       printk(KERN_DEBUG "Swapping serial ports!\n");
+                       /* swap serial ports */
+                       memcpy(&port, &mcore->serial_ports[0], sizeof(port));
+                       memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1],
+                              sizeof(port));
+                       memcpy(&mcore->serial_ports[1], &port, sizeof(port));
+               }
+       }
+
        _machine_restart = bcm47xx_machine_restart;
        _machine_halt = bcm47xx_machine_halt;
        pm_power_off = bcm47xx_machine_halt;
index 06d59dcbe24310a92669983231a51e3aad34d324..86877539c6e83679f248d7245324693a690105e6 100644 (file)
  * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM
  */
 
-#define PRID_IMP_BMIPS4KC      0x4000
-#define PRID_IMP_BMIPS32       0x8000
+#define PRID_IMP_BMIPS32_REV4  0x4000
+#define PRID_IMP_BMIPS32_REV8  0x8000
 #define PRID_IMP_BMIPS3300     0x9000
 #define PRID_IMP_BMIPS3300_ALT 0x9100
 #define PRID_IMP_BMIPS3300_BUG 0x0000
index fd1d39eb74319b60473daf46cb5e4ecf1bcacb2e..455c0ac7d4ea84632cc41c40ee48e7dd9e82ce86 100644 (file)
@@ -249,7 +249,8 @@ extern struct mips_abi mips_abi_n32;
 
 #define SET_PERSONALITY(ex)                                            \
 do {                                                                   \
-       set_personality(PER_LINUX);                                     \
+       if (personality(current->personality) != PER_LINUX)             \
+               set_personality(PER_LINUX);                             \
                                                                        \
        current->thread.abi = &mips_abi;                                \
 } while (0)
@@ -296,6 +297,8 @@ do {                                                                        \
 
 #define SET_PERSONALITY(ex)                                            \
 do {                                                                   \
+       unsigned int p;                                                 \
+                                                                       \
        clear_thread_flag(TIF_32BIT_REGS);                              \
        clear_thread_flag(TIF_32BIT_ADDR);                              \
                                                                        \
@@ -304,7 +307,8 @@ do {                                                                        \
        else                                                            \
                current->thread.abi = &mips_abi;                        \
                                                                        \
-       if (current->personality != PER_LINUX32)                        \
+       p = personality(current->personality);                          \
+       if (p != PER_LINUX32 && p != PER_LINUX)                         \
                set_personality(PER_LINUX);                             \
 } while (0)
 
index c98bf514ec7de9efe6596721cfa472d878da3f16..5b017f23e243d71b195cfea786c70ef389da7810 100644 (file)
@@ -329,10 +329,14 @@ static inline void pfx##write##bwlq(type val,                             \
                        "dsrl32 %L0, %L0, 0"                    "\n\t"  \
                        "dsll32 %M0, %M0, 0"                    "\n\t"  \
                        "or     %L0, %L0, %M0"                  "\n\t"  \
+                       ".set   push"                           "\n\t"  \
+                       ".set   noreorder"                      "\n\t"  \
+                       ".set   nomacro"                        "\n\t"  \
                        "sd     %L0, %2"                        "\n\t"  \
+                       ".set   pop"                            "\n\t"  \
                        ".set   mips0"                          "\n"    \
                        : "=r" (__tmp)                                  \
-                       : "0" (__val), "m" (*__mem));                   \
+                       : "0" (__val), "R" (*__mem));                   \
                if (irq)                                                \
                        local_irq_restore(__flags);                     \
        } else                                                          \
@@ -355,12 +359,16 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem)      \
                        local_irq_save(__flags);                        \
                __asm__ __volatile__(                                   \
                        ".set   mips3"          "\t\t# __readq" "\n\t"  \
+                       ".set   push"                           "\n\t"  \
+                       ".set   noreorder"                      "\n\t"  \
+                       ".set   nomacro"                        "\n\t"  \
                        "ld     %L0, %1"                        "\n\t"  \
+                       ".set   pop"                            "\n\t"  \
                        "dsra32 %M0, %L0, 0"                    "\n\t"  \
                        "sll    %L0, %L0, 0"                    "\n\t"  \
                        ".set   mips0"                          "\n"    \
                        : "=r" (__val)                                  \
-                       : "m" (*__mem));                                \
+                       : "R" (*__mem));                                \
                if (irq)                                                \
                        local_irq_restore(__flags);                     \
        } else {                                                        \
index 7919d76186bf1b78dca75c62e1fc41f731fc6ebb..07d3fadb24437e289bae5c8da747b2fdd647e8a5 100644 (file)
@@ -201,7 +201,6 @@ static inline void ar7_device_off(u32 bit)
 }
 
 int __init ar7_gpio_init(void);
-
-int __init ar7_gpio_init(void);
+void __init ar7_init_clocks(void);
 
 #endif /* __AR7_H__ */
index c58ebd8bc1551dd92e14111acc1ac92c4b17d1b7..9759588ba3cff0c81da6cd454148a6787e4babcf 100644 (file)
@@ -12,6 +12,7 @@
 #define __NVRAM_H
 
 #include <linux/types.h>
+#include <linux/kernel.h>
 
 struct nvram_header {
        u32 magic;
@@ -36,4 +37,10 @@ struct nvram_header {
 
 extern int nvram_getenv(char *name, char *val, size_t val_len);
 
+static inline void nvram_parse_macaddr(char *buf, u8 *macaddr)
+{
+       sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], &macaddr[1],
+              &macaddr[2], &macaddr[3], &macaddr[4], &macaddr[5]);
+}
+
 #endif
index 5742bb4d78f4db6aefa966b443dee7e095a2cfc5..5c0a3575877cce27c171d2d9a676dd8cf8073a7a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 2009 Qi Hardware inc.,
  * Author: Xiangfu Liu <xiangfu@qi-hardware.com>
- * Copyright 2010, Lars-Petrer Clausen <lars@metafoo.de>
+ * Copyright 2010, Lars-Peter Clausen <lars@metafoo.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 or later
@@ -235,7 +235,7 @@ static const unsigned int qi_lb60_keypad_rows[] = {
        QI_LB60_GPIO_KEYIN(3),
        QI_LB60_GPIO_KEYIN(4),
        QI_LB60_GPIO_KEYIN(5),
-       QI_LB60_GPIO_KEYIN(7),
+       QI_LB60_GPIO_KEYIN(6),
        QI_LB60_GPIO_KEYIN8,
 };
 
index 95bc2b5b14f1b2c56cd141f2c8a2b8ea6370dcde..1cc9e544d16bd16609aaef30bd5779ad26f5dc14 100644 (file)
@@ -208,7 +208,7 @@ struct platform_device jz4740_i2s_device = {
 
 /* PCM */
 struct platform_device jz4740_pcm_device = {
-       .name           = "jz4740-pcm",
+       .name           = "jz4740-pcm-audio",
        .id             = -1,
 };
 
index cfeac15eb2e4d5716530fd07c5b6db3a8d77cadb..4a70407f55bb7df9d68bc46256b8c007c08c6e59 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/bootinfo.h>
 #include <asm/mach-jz4740/base.h>
 
-void jz4740_init_cmdline(int argc, char *argv[])
+static __init void jz4740_init_cmdline(int argc, char *argv[])
 {
        unsigned int count = COMMAND_LINE_SIZE - 1;
        int i;
index 2f4d7a99bcc2fcc91b3838599b0b0c3d4fb1c432..98c5a9737c14d2c200a161640122f9a8af053e88 100644 (file)
@@ -32,7 +32,7 @@ static int mips_next_event(unsigned long delta,
        cnt = read_c0_count();
        cnt += delta;
        write_c0_compare(cnt);
-       res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
+       res = ((int)(read_c0_count() - cnt) >= 0) ? -ETIME : 0;
        return res;
 }
 
index 71620e19827ad681a7834f0e400104cec4968ef2..68dae7b6b5db62a0a48a17e6fe339a2d56bd8bd8 100644 (file)
@@ -905,7 +905,8 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
        switch (c->processor_id & 0xff00) {
-       case PRID_IMP_BMIPS32:
+       case PRID_IMP_BMIPS32_REV4:
+       case PRID_IMP_BMIPS32_REV8:
                c->cputype = CPU_BMIPS32;
                __cpu_name[cpu] = "Broadcom BMIPS32";
                break;
@@ -933,10 +934,6 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
                __cpu_name[cpu] = "Broadcom BMIPS5000";
                c->options |= MIPS_CPU_ULRI;
                break;
-       case PRID_IMP_BMIPS4KC:
-               c->cputype = CPU_4KC;
-               __cpu_name[cpu] = "MIPS 4Kc";
-               break;
        }
 }
 
index 6343b4a5b8350cb3a93edea5d75f3154cde48343..876a75cc376f7a8602d231c1c11440be8c88d7ae 100644 (file)
@@ -251,14 +251,15 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
 
 SYSCALL_DEFINE1(32_personality, unsigned long, personality)
 {
+       unsigned int p = personality & 0xffffffff;
        int ret;
-       personality &= 0xffffffff;
+
        if (personality(current->personality) == PER_LINUX32 &&
-           personality == PER_LINUX)
-               personality = PER_LINUX32;
-       ret = sys_personality(personality);
-       if (ret == PER_LINUX32)
-               ret = PER_LINUX;
+           personality(p) == PER_LINUX)
+               p = (p & ~PER_MASK) | PER_LINUX32;
+       ret = sys_personality(p);
+       if (ret != -1 && personality(ret) == PER_LINUX32)
+               ret = (ret & ~PER_MASK) | PER_LINUX;
        return ret;
 }
 
index 99960940d4a410bba1e9842a7049161e74d04d25..ae167df73dddf2df41a2158050c164cb4fb346d4 100644 (file)
@@ -142,7 +142,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        childregs->regs[7] = 0; /* Clear error flag */
 
        childregs->regs[2] = 0; /* Child gets zero as return value */
-       regs->regs[2] = p->pid;
 
        if (childregs->cp0_status & ST0_CU0) {
                childregs->regs[28] = (unsigned long) ti;
index e000b278f0243cfdfa1986be89b728c5b371a480..9dbe58368953809f721e845a004f98cb57809dba 100644 (file)
@@ -100,7 +100,7 @@ void __init device_tree_init(void)
                return;
 
        base = virt_to_phys((void *)initial_boot_params);
-       size = initial_boot_params->totalsize;
+       size = be32_to_cpu(initial_boot_params->totalsize);
 
        /* Before we do anything, lets reserve the dt blob */
        reserve_mem_mach(base, size);
index 43e7cdc5ded23a42fa1a8f24376ddf60eb96ccac..c0e81418ba21281ea4f3b5cedff5e564f947c1a1 100644 (file)
@@ -153,7 +153,7 @@ static void __cpuinit vsmp_init_secondary(void)
 {
        extern int gic_present;
 
-       /* This is Malta specific: IPI,performance and timer inetrrupts */
+       /* This is Malta specific: IPI,performance and timer interrupts */
        if (gic_present)
                change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
                                         STATUSF_IP6 | STATUSF_IP7);
index 8e9fbe75894e5f5199618264fcddde6410d42dc7..e97104302541fd4111ae9ceca477e04cf2b5add7 100644 (file)
@@ -83,7 +83,8 @@ extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
 
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-       struct mips_fpu_struct *ctx, int has_fpu);
+                                   struct mips_fpu_struct *ctx, int has_fpu,
+                                   void *__user *fault_addr);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -661,12 +662,36 @@ asmlinkage void do_ov(struct pt_regs *regs)
        force_sig_info(SIGFPE, &info, current);
 }
 
+static int process_fpemu_return(int sig, void __user *fault_addr)
+{
+       if (sig == SIGSEGV || sig == SIGBUS) {
+               struct siginfo si = {0};
+               si.si_addr = fault_addr;
+               si.si_signo = sig;
+               if (sig == SIGSEGV) {
+                       if (find_vma(current->mm, (unsigned long)fault_addr))
+                               si.si_code = SEGV_ACCERR;
+                       else
+                               si.si_code = SEGV_MAPERR;
+               } else {
+                       si.si_code = BUS_ADRERR;
+               }
+               force_sig_info(sig, &si, current);
+               return 1;
+       } else if (sig) {
+               force_sig(sig, current);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
 /*
  * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
  */
 asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
-       siginfo_t info;
+       siginfo_t info = {0};
 
        if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)
            == NOTIFY_STOP)
@@ -675,6 +700,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 
        if (fcr31 & FPU_CSR_UNI_X) {
                int sig;
+               void __user *fault_addr = NULL;
 
                /*
                 * Unimplemented operation exception.  If we've got the full
@@ -690,7 +716,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                lose_fpu(1);
 
                /* Run the emulator */
-               sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1);
+               sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
+                                              &fault_addr);
 
                /*
                 * We can't allow the emulated instruction to leave any of
@@ -702,8 +729,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                own_fpu(1);     /* Using the FPU again.  */
 
                /* If something went wrong, signal */
-               if (sig)
-                       force_sig(sig, current);
+               process_fpemu_return(sig, fault_addr);
 
                return;
        } else if (fcr31 & FPU_CSR_INV_X)
@@ -996,11 +1022,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 
                if (!raw_cpu_has_fpu) {
                        int sig;
+                       void __user *fault_addr = NULL;
                        sig = fpu_emulator_cop1Handler(regs,
-                                               &current->thread.fpu, 0);
-                       if (sig)
-                               force_sig(sig, current);
-                       else
+                                                      &current->thread.fpu,
+                                                      0, &fault_addr);
+                       if (!process_fpemu_return(sig, fault_addr))
                                mt_ase_fp_affinity();
                }
 
index 3eb3cde2f66160c0b4f5aeee889dc9adbfedf823..6a1fdfef8fded5763a457ec026467b356717fc78 100644 (file)
@@ -1092,6 +1092,10 @@ static int vpe_open(struct inode *inode, struct file *filp)
 
        /* this of-course trashes what was there before... */
        v->pbuffer = vmalloc(P_SIZE);
+       if (!v->pbuffer) {
+               pr_warning("VPE loader: unable to allocate memory\n");
+               return -ENOMEM;
+       }
        v->plen = P_SIZE;
        v->load_addr = NULL;
        v->len = 0;
@@ -1149,10 +1153,9 @@ static int vpe_release(struct inode *inode, struct file *filp)
        if (ret < 0)
                v->shared_ptr = NULL;
 
-       // cleanup any temp buffers
-       if (v->pbuffer)
-               vfree(v->pbuffer);
+       vfree(v->pbuffer);
        v->plen = 0;
+
        return ret;
 }
 
@@ -1169,11 +1172,6 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
        if (v == NULL)
                return -ENODEV;
 
-       if (v->pbuffer == NULL) {
-               printk(KERN_ERR "VPE loader: no buffer for program\n");
-               return -ENOMEM;
-       }
-
        if ((count + v->len) > v->plen) {
                printk(KERN_WARNING
                       "VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
index 77dc3b20110ab9d583e09a9cac94e865bc2deab1..606c8a9efe3bb146930aca3b7c438f0095cbe066 100644 (file)
@@ -161,16 +161,16 @@ FEXPORT(__bzero)
 
 .Lfwd_fixup:
        PTR_L           t0, TI_TASK($28)
-       LONG_L          t0, THREAD_BUADDR(t0)
        andi            a2, 0x3f
+       LONG_L          t0, THREAD_BUADDR(t0)
        LONG_ADDU       a2, t1
        jr              ra
         LONG_SUBU      a2, t0
 
 .Lpartial_fixup:
        PTR_L           t0, TI_TASK($28)
-       LONG_L          t0, THREAD_BUADDR(t0)
        andi            a2, LONGMASK
+       LONG_L          t0, THREAD_BUADDR(t0)
        LONG_ADDU       a2, t1
        jr              ra
         LONG_SUBU      a2, t0
index ae4cff97a56c5073d75925a7c89a94ee5a410513..11b193f848f88b7aa1c5ab5a842c2cf4e80ed7d7 100644 (file)
@@ -29,9 +29,9 @@ unsigned long memsize, highmemsize;
 
 #define parse_even_earlier(res, option, p)                             \
 do {                                                                   \
+       int ret;                                                        \
        if (strncmp(option, (char *)p, strlen(option)) == 0)            \
-                       strict_strtol((char *)p + strlen(option"="),    \
-                                       10, &res);                      \
+               ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \
 } while (0)
 
 void __init prom_init_env(void)
index b2ad1b0910ffb86d009dac8769310f30af3c3fcc..d32cb050311053a8e873ea470617b0ec17f13e26 100644 (file)
@@ -64,7 +64,7 @@ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
 
 #if __mips >= 4 && __mips != 32
 static int fpux_emu(struct pt_regs *,
-       struct mips_fpu_struct *, mips_instruction);
+       struct mips_fpu_struct *, mips_instruction, void *__user *);
 #endif
 
 /* Further private data for which no space exists in mips_fpu_struct */
@@ -208,16 +208,23 @@ static inline int cop1_64bit(struct pt_regs *xcp)
  * Two instructions if the instruction is in a branch delay slot.
  */
 
-static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
+static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+                      void *__user *fault_addr)
 {
        mips_instruction ir;
        unsigned long emulpc, contpc;
        unsigned int cond;
 
-       if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
+       if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {
                MIPS_FPU_EMU_INC_STATS(errors);
+               *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                return SIGBUS;
        }
+       if (__get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
+               MIPS_FPU_EMU_INC_STATS(errors);
+               *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+               return SIGSEGV;
+       }
 
        /* XXX NEC Vr54xx bug workaround */
        if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
@@ -245,10 +252,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 #endif
                        return SIGILL;
                }
-               if (get_user(ir, (mips_instruction __user *) emulpc)) {
+               if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)emulpc;
                        return SIGBUS;
                }
+               if (__get_user(ir, (mips_instruction __user *) emulpc)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)emulpc;
+                       return SIGSEGV;
+               }
                /* __compute_return_epc() will have updated cp0_epc */
                contpc = xcp->cp0_epc;
                /* In order not to confuse ptrace() et al, tweak context */
@@ -269,10 +282,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                u64 val;
 
                MIPS_FPU_EMU_INC_STATS(loads);
-               if (get_user(val, va)) {
+
+               if (!access_ok(VERIFY_READ, va, sizeof(u64))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__get_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                DITOREG(val, MIPSInst_RT(ir));
                break;
        }
@@ -284,10 +304,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
                MIPS_FPU_EMU_INC_STATS(stores);
                DIFROMREG(val, MIPSInst_RT(ir));
-               if (put_user(val, va)) {
+               if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__put_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                break;
        }
 
@@ -297,10 +323,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                u32 val;
 
                MIPS_FPU_EMU_INC_STATS(loads);
-               if (get_user(val, va)) {
+               if (!access_ok(VERIFY_READ, va, sizeof(u32))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__get_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                SITOREG(val, MIPSInst_RT(ir));
                break;
        }
@@ -312,10 +344,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
                MIPS_FPU_EMU_INC_STATS(stores);
                SIFROMREG(val, MIPSInst_RT(ir));
-               if (put_user(val, va)) {
+               if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__put_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                break;
        }
 
@@ -440,11 +478,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                                contpc = (xcp->cp0_epc +
                                        (MIPSInst_SIMM(ir) << 2));
 
-                               if (get_user(ir,
-                                   (mips_instruction __user *) xcp->cp0_epc)) {
+                               if (!access_ok(VERIFY_READ, xcp->cp0_epc,
+                                              sizeof(mips_instruction))) {
                                        MIPS_FPU_EMU_INC_STATS(errors);
+                                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                                        return SIGBUS;
                                }
+                               if (__get_user(ir,
+                                   (mips_instruction __user *) xcp->cp0_epc)) {
+                                       MIPS_FPU_EMU_INC_STATS(errors);
+                                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+                                       return SIGSEGV;
+                               }
 
                                switch (MIPSInst_OPCODE(ir)) {
                                case lwc1_op:
@@ -506,9 +551,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
 #if __mips >= 4 && __mips != 32
        case cop1x_op:{
-               int sig;
-
-               if ((sig = fpux_emu(xcp, ctx, ir)))
+               int sig = fpux_emu(xcp, ctx, ir, fault_addr);
+               if (sig)
                        return sig;
                break;
        }
@@ -604,7 +648,7 @@ DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
 DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
 
 static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
-       mips_instruction ir)
+       mips_instruction ir, void *__user *fault_addr)
 {
        unsigned rcsr = 0;      /* resulting csr */
 
@@ -624,10 +668,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                                xcp->regs[MIPSInst_FT(ir)]);
 
                        MIPS_FPU_EMU_INC_STATS(loads);
-                       if (get_user(val, va)) {
+                       if (!access_ok(VERIFY_READ, va, sizeof(u32))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__get_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        SITOREG(val, MIPSInst_FD(ir));
                        break;
 
@@ -638,10 +688,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        MIPS_FPU_EMU_INC_STATS(stores);
 
                        SIFROMREG(val, MIPSInst_FS(ir));
-                       if (put_user(val, va)) {
+                       if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (put_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        break;
 
                case madd_s_op:
@@ -701,10 +757,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                                xcp->regs[MIPSInst_FT(ir)]);
 
                        MIPS_FPU_EMU_INC_STATS(loads);
-                       if (get_user(val, va)) {
+                       if (!access_ok(VERIFY_READ, va, sizeof(u64))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__get_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        DITOREG(val, MIPSInst_FD(ir));
                        break;
 
@@ -714,10 +776,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
                        MIPS_FPU_EMU_INC_STATS(stores);
                        DIFROMREG(val, MIPSInst_FS(ir));
-                       if (put_user(val, va)) {
+                       if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__put_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        break;
 
                case madd_d_op:
@@ -1242,7 +1310,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 }
 
 int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
-       int has_fpu)
+       int has_fpu, void *__user *fault_addr)
 {
        unsigned long oldepc, prevepc;
        mips_instruction insn;
@@ -1252,10 +1320,16 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
        do {
                prevepc = xcp->cp0_epc;
 
-               if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
+               if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                        return SIGBUS;
                }
+               if (__get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+                       return SIGSEGV;
+               }
                if (insn == 0)
                        xcp->cp0_epc += 4;      /* skip nops */
                else {
@@ -1267,7 +1341,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                         */
                        /* convert to ieee library modes */
                        ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
-                       sig = cop1Emulate(xcp, ctx);
+                       sig = cop1Emulate(xcp, ctx, fault_addr);
                        /* revert to mips rounding mode */
                        ieee754_csr.rm = mips_rm[ieee754_csr.rm];
                }
index 4fc1a0fbe0074e154c64a89f8f40d90bd6e1bd91..21ea14efb83747c5275858c6b64a18b6ea040131 100644 (file)
@@ -288,7 +288,7 @@ int mips_dma_supported(struct device *dev, u64 mask)
        return plat_dma_supported(dev, mask);
 }
 
-void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                         enum dma_data_direction direction)
 {
        BUG_ON(direction == DMA_NONE);
@@ -298,6 +298,8 @@ void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                __dma_sync((unsigned long)vaddr, size, direction);
 }
 
+EXPORT_SYMBOL(dma_cache_sync);
+
 static struct dma_map_ops mips_default_dma_map_ops = {
        .alloc_coherent = mips_dma_alloc_coherent,
        .free_coherent = mips_dma_free_coherent,
index 505fecad4684f272b7a00d6dd8e3f3098875df4c..9cca8de0054507ca3869071d6bc72dab01e13170 100644 (file)
@@ -68,6 +68,9 @@ static struct bcache_ops mips_sc_ops = {
  */
 static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 {
+       unsigned int config2 = read_c0_config2();
+       unsigned int tmp;
+
        /* Check the bypass bit (L2B) */
        switch (c->cputype) {
        case CPU_34K:
@@ -83,6 +86,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
                c->scache.linesz = 2 << tmp;
        else
                return 0;
+       return 1;
 }
 
 static inline int __init mips_sc_probe(void)
index b7f1d9c4a8a3c7d588b270d6bd6e1bad0590f6b2..434d7b1a8c6a7abf4c492a14b975111a21b1a4ab 100644 (file)
@@ -65,11 +65,15 @@ static unsigned char readb_outer_space(unsigned long long phys)
 
        __asm__ __volatile__ (
        "       .set    mips3           \n"
+       "       .set    push            \n"
+       "       .set    noreorder       \n"
+       "       .set    nomacro         \n"
        "       ld      %0, %1          \n"
+       "       .set    pop             \n"
        "       lbu     %0, (%0)        \n"
        "       .set    mips0           \n"
        : "=r" (res)
-       : "m" (vaddr));
+       : "R" (vaddr));
 
        write_c0_status(sr);
        ssnop_4();
@@ -89,11 +93,15 @@ static void writeb_outer_space(unsigned long long phys, unsigned char c)
 
        __asm__ __volatile__ (
        "       .set    mips3           \n"
+       "       .set    push            \n"
+       "       .set    noreorder       \n"
+       "       .set    nomacro         \n"
        "       ld      %0, %1          \n"
+       "       .set    pop             \n"
        "       sb      %2, (%0)        \n"
        "       .set    mips0           \n"
        : "=&r" (tmp)
-       : "m" (vaddr), "r" (c));
+       : "R" (vaddr), "r" (c));
 
        write_c0_status(sr);
        ssnop_4();
index c308989fc464c3c76a1bc258d38713543c4004c8..41707a245dea61c1cabd467f2bc3d2ec2ca28cd8 100644 (file)
@@ -82,7 +82,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup)
 enum swarm_rtc_type {
        RTC_NONE,
        RTC_XICOR,
-       RTC_M4LT81
+       RTC_M41T81,
 };
 
 enum swarm_rtc_type swarm_rtc_type;
@@ -96,7 +96,7 @@ void read_persistent_clock(struct timespec *ts)
                sec = xicor_get_time();
                break;
 
-       case RTC_M4LT81:
+       case RTC_M41T81:
                sec = m41t81_get_time();
                break;
 
@@ -115,7 +115,7 @@ int rtc_mips_set_time(unsigned long sec)
        case RTC_XICOR:
                return xicor_set_time(sec);
 
-       case RTC_M4LT81:
+       case RTC_M41T81:
                return m41t81_set_time(sec);
 
        case RTC_NONE:
@@ -141,7 +141,7 @@ void __init plat_mem_setup(void)
        if (xicor_probe())
                swarm_rtc_type = RTC_XICOR;
        if (m41t81_probe())
-               swarm_rtc_type = RTC_M4LT81;
+               swarm_rtc_type = RTC_M41T81;
 
 #ifdef CONFIG_VT
        screen_info = (struct screen_info) {
index f860a340acc920e0565f4d341fa263b5c8ea49a5..75da468090b90342ef5ff2566389b6efa1b28487 100644 (file)
@@ -40,21 +40,17 @@ unsigned long long sched_clock(void)
                unsigned long long ll;
                unsigned l[2];
        } tsc64, result;
-       unsigned long tsc, tmp;
+       unsigned long tmp;
        unsigned product[3]; /* 96-bit intermediate value */
 
        /* cnt32_to_63() is not safe with preemption */
        preempt_disable();
 
-       /* read the TSC value
-        */
-       tsc = get_cycles();
-
-       /* expand to 64-bits.
+       /* expand the tsc to 64-bits.
         * - sched_clock() must be called once a minute or better or the
         *   following will go horribly wrong - see cnt32_to_63()
         */
-       tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL;
+       tsc64.ll = cnt32_to_63(get_cycles()) & 0x7fffffffffffffffULL;
 
        preempt_enable();
 
index c1ee1d61d44ca8a07c504b9af425df3a9c7185c7..81d92a45cd4b613e2c18add9afe153e43a5d703e 100644 (file)
@@ -25,7 +25,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 struct pt_regs;
-int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
+int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
 int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
 void do_signal(struct pt_regs *regs);
 #endif
index 543d6a33aa26f6c02f7f41f59fcdceea1729bcd8..dbb0dfc7beceb10eaa25fd4b73579cdc620334c5 100644 (file)
@@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
        return ret;
 }
 
+/* The assembly shim for this function arranges to ignore the return value. */
 long compat_sys_rt_sigreturn(struct pt_regs *regs)
 {
        struct compat_rt_sigframe __user *frame =
                (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
        sigset_t set;
-       long r0;
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
@@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
                goto badframe;
 
-       return r0;
+       return 0;
 
 badframe:
        force_sig(SIGSEGV, current);
index f5821626247fee9891d47eca123b26440f6c025c..5eed4a02bf62335e17a39f663cd4485869f44ea5 100644 (file)
@@ -1342,8 +1342,8 @@ handle_syscall:
        lw      r20, r20
 
        /* Jump to syscall handler. */
-       jalr    r20; .Lhandle_syscall_link:
-       FEEDBACK_REENTER(handle_syscall)
+       jalr    r20
+.Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */
 
        /*
         * Write our r0 onto the stack so it gets restored instead
@@ -1352,6 +1352,9 @@ handle_syscall:
        PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))
        sw      r29, r0
 
+.Lsyscall_sigreturn_skip:
+       FEEDBACK_REENTER(handle_syscall)
+
        /* Do syscall trace again, if requested. */
        lw      r30, r31
        andi    r30, r30, _TIF_SYSCALL_TRACE
@@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr)
        };                                              \
        STD_ENDPROC(_##x)
 
+/*
+ * Special-case sigreturn to not write r0 to the stack on return.
+ * This is technically more efficient, but it also avoids difficulties
+ * in the 64-bit OS when handling 32-bit compat code, since we must not
+ * sign-extend r0 for the sigreturn return-value case.
+ */
+#define PTREGS_SYSCALL_SIGRETURN(x, reg)                \
+       STD_ENTRY(_##x);                                \
+       addli   lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \
+       {                                               \
+        PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
+        j      x                                       \
+       };                                              \
+       STD_ENDPROC(_##x)
+
 PTREGS_SYSCALL(sys_execve, r3)
 PTREGS_SYSCALL(sys_sigaltstack, r2)
-PTREGS_SYSCALL(sys_rt_sigreturn, r0)
+PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
 PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
 
 /* Save additional callee-saves to pt_regs, put address in r4 and jump. */
index 8430f45daea6bce566cc0980db85f0d0b213af72..e90eb53173b0b5e1c2f7c3ba60ad4be38940a34d 100644 (file)
@@ -211,6 +211,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        childregs->regs[0] = 0;         /* return value is zero */
        childregs->sp = sp;  /* override with new user stack pointer */
 
+       /*
+        * If CLONE_SETTLS is set, set "tp" in the new task to "r4",
+        * which is passed in as arg #5 to sys_clone().
+        */
+       if (clone_flags & CLONE_SETTLS)
+               childregs->tp = regs->regs[4];
+
        /*
         * Copy the callee-saved registers from the passed pt_regs struct
         * into the context-switch callee-saved registers area.
@@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
        return __switch_to(prev, next, next_current_ksp0(next));
 }
 
+/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
                void __user *, parent_tidptr, void __user *, child_tidptr,
                struct pt_regs *, regs)
index 757407e36696688d59810453b1ffca8da8522a62..1260321155f1d591b85131f44d9c72ad31122626 100644 (file)
@@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
  */
 
 int restore_sigcontext(struct pt_regs *regs,
-                      struct sigcontext __user *sc, long *pr0)
+                      struct sigcontext __user *sc)
 {
        int err = 0;
        int i;
@@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs,
 
        regs->faultnum = INT_SWINT_1_SIGRETURN;
 
-       err |= __get_user(*pr0, &sc->gregs[0]);
        return err;
 }
 
-/* sigreturn() returns long since it restores r0 in the interrupted code. */
+/* The assembly shim for this function arranges to ignore the return value. */
 SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
 {
        struct rt_sigframe __user *frame =
                (struct rt_sigframe __user *)(regs->sp);
        sigset_t set;
-       long r0;
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
@@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
                goto badframe;
 
-       return r0;
+       return 0;
 
 badframe:
        force_sig(SIGSEGV, current);
index 23f315c9f21560a10f4202676e75e4181a9c7f4a..325c05294fc40dfc662a52187eba92516e568e94 100644 (file)
@@ -355,7 +355,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
        if (heap > 0x3fffffffffffUL)
                error("Destination address too large");
 #else
-       if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
+       if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))
                error("Destination address too large");
 #endif
 #ifndef CONFIG_RELOCATABLE
index 5be1542fbfaf73bfccd03a101e94a1cca47d36b0..e99d55d74df5023d72b763ca244c9d17bbd1dd53 100644 (file)
@@ -72,6 +72,9 @@ struct e820map {
 #define BIOS_BEGIN             0x000a0000
 #define BIOS_END               0x00100000
 
+#define BIOS_ROM_BASE          0xffe00000
+#define BIOS_ROM_END           0xffffffff
+
 #ifdef __KERNEL__
 /* see comment in arch/x86/kernel/e820.c */
 extern struct e820map e820;
index 9e6fe391094e545eb41b9fa295df93a827c1fa30..f702f82aa1ebf5df3905ca32ac9326be76c03b91 100644 (file)
@@ -79,7 +79,7 @@
 #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT)
 #define KVM_MIN_FREE_MMU_PAGES 5
 #define KVM_REFILL_PAGES 25
-#define KVM_MAX_CPUID_ENTRIES 40
+#define KVM_MAX_CPUID_ENTRIES 80
 #define KVM_NR_FIXED_MTRR_REGION 88
 #define KVM_NR_VAR_MTRR 8
 
index 9e13763b609242e0c5429a364be461a7e8fc2594..1e994754d323f400b85c5d1d7350c6e52a702ff9 100644 (file)
@@ -45,6 +45,7 @@ obj-y                 += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
 obj-y                  += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
 obj-y                  += tsc.o io_delay.o rtc.o
 obj-y                  += pci-iommu_table.o
+obj-y                  += resource.o
 
 obj-$(CONFIG_X86_TRAMPOLINE)   += trampoline.o
 obj-y                          += process.o
index 3f838d537392b4ddb6d061e82bbf1ce8a2a3b9d2..78218135b48e6169d155fb4a097e5b6c8e30e53a 100644 (file)
@@ -1389,6 +1389,14 @@ void __cpuinit end_local_APIC_setup(void)
 
        setup_apic_nmi_watchdog(NULL);
        apic_pm_activate();
+
+       /*
+        * Now that local APIC setup is completed for BP, configure the fault
+        * handling for interrupt remapping.
+        */
+       if (!smp_processor_id() && intr_remapping_enabled)
+               enable_drhd_fault_handling();
+
 }
 
 #ifdef CONFIG_X86_X2APIC
index 7cc0a721f628c302d0d420ba0bf3af1945d5a1c0..fadcd743a74f8bdcd5effbaf7e28b01ea3003532 100644 (file)
@@ -2430,13 +2430,12 @@ static void ack_apic_level(struct irq_data *data)
 {
        struct irq_cfg *cfg = data->chip_data;
        int i, do_unmask_irq = 0, irq = data->irq;
-       struct irq_desc *desc = irq_to_desc(irq);
        unsigned long v;
 
        irq_complete_move(cfg);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        /* If we are moving the irq we need to mask it */
-       if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
+       if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {
                do_unmask_irq = 1;
                mask_ioapic(cfg);
        }
@@ -3413,6 +3412,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
        msg.data |= MSI_DATA_VECTOR(cfg->vector);
        msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
        msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+       msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);
 
        dmar_msi_write(irq, &msg);
 
index f9e4e6a54073e3d901d0475da9c5deceb21d55d8..d8c4a6feb2862f3a967f7eb4dcc4f503f2dac2f8 100644 (file)
@@ -79,13 +79,6 @@ void __init default_setup_apic_routing(void)
                /* need to update phys_pkg_id */
                apic->phys_pkg_id = apicid_phys_pkg_id;
        }
-
-       /*
-        * Now that apic routing model is selected, configure the
-        * fault handling for intr remapping.
-        */
-       if (intr_remapping_enabled)
-               enable_drhd_fault_handling();
 }
 
 /* Same for both flat and physical. */
index bcece91dd3116a14fa58af5c5216dbce20daa3e5..c0dbd9ac24f0d5cf7e87f8f0439275656b877f73 100644 (file)
 #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
 #endif
 
+/* Number of possible pages in the lowmem region */
+LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT)
+       
 /* Enough space to fit pagetables for the low memory linear map */
-MAPPING_BEYOND_END = \
-       PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
+MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT
 
 /*
  * Worst-case size of the kernel mapping we need to make:
- * the worst-case size of the kernel itself, plus the extra we need
- * to map for the linear map.
+ * a relocatable kernel can live anywhere in lowmem, so we need to be able
+ * to map all of lowmem.
  */
-KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT
+KERNEL_PAGES = LOWMEM_PAGES
 
 INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
 RESERVE_BRK(pagetables, INIT_MAP_SIZE)
@@ -620,13 +622,13 @@ ENTRY(initial_code)
 __PAGE_ALIGNED_BSS
        .align PAGE_SIZE_asm
 #ifdef CONFIG_X86_PAE
-initial_pg_pmd:
+ENTRY(initial_pg_pmd)
        .fill 1024*KPMDS,4,0
 #else
 ENTRY(initial_page_table)
        .fill 1024,4,0
 #endif
-initial_pg_fixmap:
+ENTRY(initial_pg_fixmap)
        .fill 1024,4,0
 ENTRY(empty_zero_page)
        .fill 4096,1,0
index ae03cab4352e8535946a835787c83e5c8563079b..4ff5968f12d295ac00a55ecbbae06dd97675a6c9 100644 (file)
@@ -27,6 +27,9 @@
 #define HPET_DEV_FSB_CAP               0x1000
 #define HPET_DEV_PERI_CAP              0x2000
 
+#define HPET_MIN_CYCLES                        128
+#define HPET_MIN_PROG_DELTA            (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
+
 #define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt)
 
 /*
@@ -299,8 +302,9 @@ static void hpet_legacy_clockevent_register(void)
        /* Calculate the min / max delta */
        hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
                                                           &hpet_clockevent);
-       /* 5 usec minimum reprogramming delta. */
-       hpet_clockevent.min_delta_ns = 5000;
+       /* Setup minimum reprogramming delta. */
+       hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA,
+                                                          &hpet_clockevent);
 
        /*
         * Start hpet with the boot cpu mask and make it
@@ -393,22 +397,24 @@ static int hpet_next_event(unsigned long delta,
         * the wraparound into account) nor a simple count down event
         * mode. Further the write to the comparator register is
         * delayed internally up to two HPET clock cycles in certain
-        * chipsets (ATI, ICH9,10). We worked around that by reading
-        * back the compare register, but that required another
-        * workaround for ICH9,10 chips where the first readout after
-        * write can return the old stale value. We already have a
-        * minimum delta of 5us enforced, but a NMI or SMI hitting
+        * chipsets (ATI, ICH9,10). Some newer AMD chipsets have even
+        * longer delays. We worked around that by reading back the
+        * compare register, but that required another workaround for
+        * ICH9,10 chips where the first readout after write can
+        * return the old stale value. We already had a minimum
+        * programming delta of 5us enforced, but a NMI or SMI hitting
         * between the counter readout and the comparator write can
         * move us behind that point easily. Now instead of reading
         * the compare register back several times, we make the ETIME
         * decision based on the following: Return ETIME if the
-        * counter value after the write is less than 8 HPET cycles
+        * counter value after the write is less than HPET_MIN_CYCLES
         * away from the event or if the counter is already ahead of
-        * the event.
+        * the event. The minimum programming delta for the generic
+        * clockevents code is set to 1.5 * HPET_MIN_CYCLES.
         */
        res = (s32)(cnt - hpet_readl(HPET_COUNTER));
 
-       return res < 8 ? -ETIME : 0;
+       return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
 
 static void hpet_legacy_set_mode(enum clock_event_mode mode,
diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c
new file mode 100644 (file)
index 0000000..2a26819
--- /dev/null
@@ -0,0 +1,48 @@
+#include <linux/ioport.h>
+#include <asm/e820.h>
+
+static void resource_clip(struct resource *res, resource_size_t start,
+                         resource_size_t end)
+{
+       resource_size_t low = 0, high = 0;
+
+       if (res->end < start || res->start > end)
+               return;         /* no conflict */
+
+       if (res->start < start)
+               low = start - res->start;
+
+       if (res->end > end)
+               high = res->end - end;
+
+       /* Keep the area above or below the conflict, whichever is larger */
+       if (low > high)
+               res->end = start - 1;
+       else
+               res->start = end + 1;
+}
+
+static void remove_e820_regions(struct resource *avail)
+{
+       int i;
+       struct e820entry *entry;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               entry = &e820.map[i];
+
+               resource_clip(avail, entry->addr,
+                             entry->addr + entry->size - 1);
+       }
+}
+
+void arch_remove_reservations(struct resource *avail)
+{
+       /* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */
+       if (avail->flags & IORESOURCE_MEM) {
+               if (avail->start < BIOS_END)
+                       avail->start = BIOS_END;
+               resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
+
+               remove_e820_regions(avail);
+       }
+}
index 21c6746338afef0949e89f8b2c0442654401546e..85268f8eadf667c6034c06882ed661cb7d03e4a8 100644 (file)
@@ -769,7 +769,6 @@ void __init setup_arch(char **cmdline_p)
 
        x86_init.oem.arch_setup();
 
-       resource_alloc_from_bottom = 0;
        iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;
        setup_memory_map();
        parse_setup_data();
index 9c253bd65e24ba3e803b044fca3ad57224a41c52..547128546cc3bd4644a189955c1b804f5c150770 100644 (file)
@@ -394,7 +394,8 @@ static void __init setup_xstate_init(void)
         * Setup init_xstate_buf to represent the init state of
         * all the features managed by the xsave
         */
-       init_xstate_buf = alloc_bootmem(xstate_size);
+       init_xstate_buf = alloc_bootmem_align(xstate_size,
+                                             __alignof__(struct xsave_struct));
        init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;
 
        clts();
index 1ca12298ffc74f2d783effb35da0953163bbb314..b81a9b7c2ca486f3faa8d8c8314ef4e1115e69e3 100644 (file)
@@ -3494,6 +3494,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu)
 static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
 {
        switch (func) {
+       case 0x00000001:
+               /* Mask out xsave bit as long as it is not supported by SVM */
+               entry->ecx &= ~(bit(X86_FEATURE_XSAVE));
+               break;
        case 0x80000001:
                if (nested)
                        entry->ecx |= (1 << 2); /* Set SVM bit */
index ff21fdda0c53b6dbf2ca84b1e4e2300e2a659b90..81fcbe9515c59d7e68734d2d4c53fa23bb72624a 100644 (file)
@@ -4227,11 +4227,6 @@ static int vmx_get_lpage_level(void)
                return PT_PDPE_LEVEL;
 }
 
-static inline u32 bit(int bitno)
-{
-       return 1 << (bitno & 31);
-}
-
 static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
index cdac9e592aa53ee84b7e184900601ab4730354e5..b989e1f1e5d36b732d1d9c864f369b39a7459105 100644 (file)
@@ -155,11 +155,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 u64 __read_mostly host_xcr0;
 
-static inline u32 bit(int bitno)
-{
-       return 1 << (bitno & 31);
-}
-
 static void kvm_on_user_return(struct user_return_notifier *urn)
 {
        unsigned slot;
@@ -4569,9 +4564,11 @@ static void kvm_timer_init(void)
 #ifdef CONFIG_CPU_FREQ
                struct cpufreq_policy policy;
                memset(&policy, 0, sizeof(policy));
-               cpufreq_get_policy(&policy, get_cpu());
+               cpu = get_cpu();
+               cpufreq_get_policy(&policy, cpu);
                if (policy.cpuinfo.max_freq)
                        max_tsc_khz = policy.cpuinfo.max_freq;
+               put_cpu();
 #endif
                cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,
                                          CPUFREQ_TRANSITION_NOTIFIER);
@@ -5522,6 +5519,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 
        mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;
        kvm_x86_ops->set_cr4(vcpu, sregs->cr4);
+       if (sregs->cr4 & X86_CR4_OSXSAVE)
+               update_cpuid(vcpu);
        if (!is_long_mode(vcpu) && is_pae(vcpu)) {
                load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3);
                mmu_reset_needed = 1;
index 2cea414489f37caa75876e7a186e00ac93937ec1..c600da830ce0e412fa4b60365909792a9b916a4d 100644 (file)
@@ -70,6 +70,11 @@ static inline int is_paging(struct kvm_vcpu *vcpu)
        return kvm_read_cr0_bits(vcpu, X86_CR0_PG);
 }
 
+static inline u32 bit(int bitno)
+{
+       return 1 << (bitno & 31);
+}
+
 void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
 int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq);
index 73b1e1a1f4891708a8714570e36ce62b15ba6fc7..4996cf5f73a07db446c2fe3e1c9fe7070662b741 100644 (file)
@@ -531,7 +531,10 @@ static void lguest_write_cr3(unsigned long cr3)
 {
        lguest_data.pgdir = cr3;
        lazy_hcall1(LHCALL_NEW_PGTABLE, cr3);
-       cr3_changed = true;
+
+       /* These two page tables are simple, linear, and used during boot */
+       if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table))
+               cr3_changed = true;
 }
 
 static unsigned long lguest_read_cr3(void)
@@ -703,9 +706,9 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
  * to forget all of them.  Fortunately, this is very rare.
  *
  * ... except in early boot when the kernel sets up the initial pagetables,
- * which makes booting astonishingly slow: 1.83 seconds!  So we don't even tell
- * the Host anything changed until we've done the first page table switch,
- * which brings boot back to 0.25 seconds.
+ * which makes booting astonishingly slow: 48 seconds!  So we don't even tell
+ * the Host anything changed until we've done the first real page table switch,
+ * which brings boot back to 4.3 seconds.
  */
 static void lguest_set_pte(pte_t *ptep, pte_t pteval)
 {
@@ -1002,7 +1005,7 @@ static void lguest_time_init(void)
        clockevents_register_device(&lguest_clockevent);
 
        /* Finally, we unblock the timer interrupt. */
-       enable_lguest_irq(0);
+       clear_bit(0, lguest_data.blocked_interrupts);
 }
 
 /*
@@ -1349,9 +1352,6 @@ __init void lguest_init(void)
         */
        switch_to_new_gdt(0);
 
-       /* We actually boot with all memory mapped, but let's say 128MB. */
-       max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT;
-
        /*
         * The Host<->Guest Switcher lives at the top of our address space, and
         * the Host told us how big it is when we made LGUEST_INIT hypercall:
index 4f420c2f2d5534ea4ac5af20292e25c4346c3cda..e7d5382ef26344534b0883a11d02b19a82d4a9cd 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/processor-flags.h>
+#include <asm/pgtable.h>
 
 /*G:020
  * Our story starts with the kernel booting into startup_32 in
@@ -37,9 +38,113 @@ ENTRY(lguest_entry)
        /* Set up the initial stack so we can run C code. */
        movl $(init_thread_union+THREAD_SIZE),%esp
 
+       call init_pagetables
+
        /* Jumps are relative: we're running __PAGE_OFFSET too low. */
        jmp lguest_init+__PAGE_OFFSET
 
+/*
+ * Initialize page tables.  This creates a PDE and a set of page
+ * tables, which are located immediately beyond __brk_base.  The variable
+ * _brk_end is set up to point to the first "safe" location.
+ * Mappings are created both at virtual address 0 (identity mapping)
+ * and PAGE_OFFSET for up to _end.
+ *
+ * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they
+ * don't have a stack at this point, so we can't just use call and ret.
+ */
+init_pagetables:
+#if PTRS_PER_PMD > 1
+#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
+#else
+#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
+#endif
+#define pa(X) ((X) - __PAGE_OFFSET)
+
+/* Enough space to fit pagetables for the low memory linear map */
+MAPPING_BEYOND_END = \
+       PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
+#ifdef CONFIG_X86_PAE
+
+       /*
+        * In PAE mode initial_page_table is statically defined to contain
+        * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
+        * entries). The identity mapping is handled by pointing two PGD entries
+        * to the first kernel PMD.
+        *
+        * Note the upper half of each PMD or PTE are always zero at this stage.
+        */
+
+#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
+
+       xorl %ebx,%ebx                          /* %ebx is kept at zero */
+
+       movl $pa(__brk_base), %edi
+       movl $pa(initial_pg_pmd), %edx
+       movl $PTE_IDENT_ATTR, %eax
+10:
+       leal PDE_IDENT_ATTR(%edi),%ecx          /* Create PMD entry */
+       movl %ecx,(%edx)                        /* Store PMD entry */
+                                               /* Upper half already zero */
+       addl $8,%edx
+       movl $512,%ecx
+11:
+       stosl
+       xchgl %eax,%ebx
+       stosl
+       xchgl %eax,%ebx
+       addl $0x1000,%eax
+       loop 11b
+
+       /*
+        * End condition: we must map up to the end + MAPPING_BEYOND_END.
+        */
+       movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
+       cmpl %ebp,%eax
+       jb 10b
+1:
+       addl $__PAGE_OFFSET, %edi
+       movl %edi, pa(_brk_end)
+       shrl $12, %eax
+       movl %eax, pa(max_pfn_mapped)
+
+       /* Do early initialization of the fixmap area */
+       movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+       movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
+#else  /* Not PAE */
+
+page_pde_offset = (__PAGE_OFFSET >> 20);
+
+       movl $pa(__brk_base), %edi
+       movl $pa(initial_page_table), %edx
+       movl $PTE_IDENT_ATTR, %eax
+10:
+       leal PDE_IDENT_ATTR(%edi),%ecx          /* Create PDE entry */
+       movl %ecx,(%edx)                        /* Store identity PDE entry */
+       movl %ecx,page_pde_offset(%edx)         /* Store kernel PDE entry */
+       addl $4,%edx
+       movl $1024, %ecx
+11:
+       stosl
+       addl $0x1000,%eax
+       loop 11b
+       /*
+        * End condition: we must map up to the end + MAPPING_BEYOND_END.
+        */
+       movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
+       cmpl %ebp,%eax
+       jb 10b
+       addl $__PAGE_OFFSET, %edi
+       movl %edi, pa(_brk_end)
+       shrl $12, %eax
+       movl %eax, pa(max_pfn_mapped)
+
+       /* Do early initialization of the fixmap area */
+       movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+       movl %eax,pa(initial_page_table+0xffc)
+#endif
+       ret
+
 /*G:055
  * We create a macro which puts the assembler code between lgstart_ and lgend_
  * markers.  These templates are put in the .text section: they can't be
index c4bb261c106e16eaeab09092a9942418dba61133..b1805b78842fec1efd9da3a1cebfca74c4b25371 100644 (file)
@@ -65,21 +65,13 @@ pcibios_align_resource(void *data, const struct resource *res,
                        resource_size_t size, resource_size_t align)
 {
        struct pci_dev *dev = data;
-       resource_size_t start = round_down(res->end - size + 1, align);
+       resource_size_t start = res->start;
 
        if (res->flags & IORESOURCE_IO) {
-
-               /*
-                * If we're avoiding ISA aliases, the largest contiguous I/O
-                * port space is 256 bytes.  Clearing bits 9 and 10 preserves
-                * all 256-byte and smaller alignments, so the result will
-                * still be correctly aligned.
-                */
-               if (!skip_isa_ioresource_align(dev))
-                       start &= ~0x300;
-       } else if (res->flags & IORESOURCE_MEM) {
-               if (start < BIOS_END)
-                       start = res->end;       /* fail; no space */
+               if (skip_isa_ioresource_align(dev))
+                       return start;
+               if (start & 0x300)
+                       start = (start + 0x3ff) & ~0x3ff;
        }
        return start;
 }
index 4a2afa1bac51f58d35e27ff6ffd18c4efc064f4b..b6552b189bcdbb43b1f3627616f1f69d488f9efa 100644 (file)
@@ -25,7 +25,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
 
 export CPPFLAGS_vdso.lds += -P -C
 
-VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \
+VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
                        -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
 
 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
@@ -69,7 +69,7 @@ vdso32.so-$(VDSO32-y)         += sysenter
 vdso32-images                  = $(vdso32.so-y:%=vdso32-%.so)
 
 CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
-VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1
+VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1
 
 # This makes sure the $(obj) subdirectory exists even though vdso32/
 # is not a kbuild sub-make subdirectory.
index 5d5dbe47c2285ee7ccb5f3ca784f9cdb8cb6df3e..e663ac2d8e68f70ff17ce274f3cebec16c1dd18c 100644 (file)
@@ -201,12 +201,13 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
        for (i = 0; i < iov_count; i++) {
                unsigned long uaddr = (unsigned long)iov[i].iov_base;
 
+               if (!iov[i].iov_len)
+                       return -EINVAL;
+
                if (uaddr & queue_dma_alignment(q)) {
                        unaligned = 1;
                        break;
                }
-               if (!iov[i].iov_len)
-                       return -EINVAL;
        }
 
        if (unaligned || (q->dma_pad_mask & len) || map_data)
index 77b7c26df6b50fea7a38ba0825d91583f1c4031c..74bc4a768f32e0f01e5c43f100f8663eea34c3a4 100644 (file)
@@ -21,7 +21,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
                return 0;
 
        fbio = bio;
-       cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+       cluster = blk_queue_cluster(q);
        seg_size = 0;
        nr_phys_segs = 0;
        for_each_bio(bio) {
@@ -87,7 +87,7 @@ EXPORT_SYMBOL(blk_recount_segments);
 static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
                                   struct bio *nxt)
 {
-       if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
+       if (!blk_queue_cluster(q))
                return 0;
 
        if (bio->bi_seg_back_size + nxt->bi_seg_front_size >
@@ -123,7 +123,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
        int nsegs, cluster;
 
        nsegs = 0;
-       cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+       cluster = blk_queue_cluster(q);
 
        /*
         * for each bio in rq
index 701859fb9647c31a505f0218800744e3e6d0a775..36c8c1f2af18088fb5fa34f4889d2fead2556600 100644 (file)
@@ -126,7 +126,7 @@ void blk_set_default_limits(struct queue_limits *lim)
        lim->alignment_offset = 0;
        lim->io_opt = 0;
        lim->misaligned = 0;
-       lim->no_cluster = 0;
+       lim->cluster = 1;
 }
 EXPORT_SYMBOL(blk_set_default_limits);
 
@@ -229,8 +229,8 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)
 EXPORT_SYMBOL(blk_queue_bounce_limit);
 
 /**
- * blk_queue_max_hw_sectors - set max sectors for a request for this queue
- * @q:  the request queue for the device
+ * blk_limits_max_hw_sectors - set hard and soft limit of max sectors for request
+ * @limits: the queue limits
  * @max_hw_sectors:  max hardware sectors in the usual 512b unit
  *
  * Description:
@@ -244,7 +244,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
  *    per-device basis in /sys/block/<device>/queue/max_sectors_kb.
  *    The soft limit can not exceed max_hw_sectors.
  **/
-void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
+void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_sectors)
 {
        if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) {
                max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
@@ -252,9 +252,23 @@ void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_secto
                       __func__, max_hw_sectors);
        }
 
-       q->limits.max_hw_sectors = max_hw_sectors;
-       q->limits.max_sectors = min_t(unsigned int, max_hw_sectors,
-                                     BLK_DEF_MAX_SECTORS);
+       limits->max_hw_sectors = max_hw_sectors;
+       limits->max_sectors = min_t(unsigned int, max_hw_sectors,
+                                   BLK_DEF_MAX_SECTORS);
+}
+EXPORT_SYMBOL(blk_limits_max_hw_sectors);
+
+/**
+ * blk_queue_max_hw_sectors - set max sectors for a request for this queue
+ * @q:  the request queue for the device
+ * @max_hw_sectors:  max hardware sectors in the usual 512b unit
+ *
+ * Description:
+ *    See description for blk_limits_max_hw_sectors().
+ **/
+void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
+{
+       blk_limits_max_hw_sectors(&q->limits, max_hw_sectors);
 }
 EXPORT_SYMBOL(blk_queue_max_hw_sectors);
 
@@ -464,15 +478,6 @@ EXPORT_SYMBOL(blk_queue_io_opt);
 void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
 {
        blk_stack_limits(&t->limits, &b->limits, 0);
-
-       if (!t->queue_lock)
-               WARN_ON_ONCE(1);
-       else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
-               unsigned long flags;
-               spin_lock_irqsave(t->queue_lock, flags);
-               queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
-               spin_unlock_irqrestore(t->queue_lock, flags);
-       }
 }
 EXPORT_SYMBOL(blk_queue_stack_limits);
 
@@ -545,7 +550,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
        t->io_min = max(t->io_min, b->io_min);
        t->io_opt = lcm(t->io_opt, b->io_opt);
 
-       t->no_cluster |= b->no_cluster;
+       t->cluster &= b->cluster;
        t->discard_zeroes_data &= b->discard_zeroes_data;
 
        /* Physical block size a multiple of the logical block size? */
@@ -641,7 +646,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
                       sector_t offset)
 {
        struct request_queue *t = disk->queue;
-       struct request_queue *b = bdev_get_queue(bdev);
 
        if (bdev_stack_limits(&t->limits, bdev, offset >> 9) < 0) {
                char top[BDEVNAME_SIZE], bottom[BDEVNAME_SIZE];
@@ -652,17 +656,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
                printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",
                       top, bottom);
        }
-
-       if (!t->queue_lock)
-               WARN_ON_ONCE(1);
-       else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
-               unsigned long flags;
-
-               spin_lock_irqsave(t->queue_lock, flags);
-               if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
-                       queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
-               spin_unlock_irqrestore(t->queue_lock, flags);
-       }
 }
 EXPORT_SYMBOL(disk_stack_limits);
 
index 013457f47fdc8b12eded858c852f588884b962c5..41fb69150b4d3c6758b0f5da6ff2005d4d7a0a3f 100644 (file)
@@ -119,7 +119,7 @@ static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *
 
 static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
 {
-       if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
+       if (blk_queue_cluster(q))
                return queue_var_show(queue_max_segment_size(q), (page));
 
        return queue_var_show(PAGE_CACHE_SIZE, (page));
index 004be80fd89402efbdc3f4a89a894570b7f27e59..381b09bb562b277620479fa92313cc6631995630 100644 (file)
@@ -355,6 +355,12 @@ throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
                        tg->slice_end[rw], jiffies);
 }
 
+static inline void throtl_set_slice_end(struct throtl_data *td,
+               struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
+{
+       tg->slice_end[rw] = roundup(jiffy_end, throtl_slice);
+}
+
 static inline void throtl_extend_slice(struct throtl_data *td,
                struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
 {
@@ -391,6 +397,16 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
        if (throtl_slice_used(td, tg, rw))
                return;
 
+       /*
+        * A bio has been dispatched. Also adjust slice_end. It might happen
+        * that initially cgroup limit was very low resulting in high
+        * slice_end, but later limit was bumped up and bio was dispached
+        * sooner, then we need to reduce slice_end. A high bogus slice_end
+        * is bad because it does not allow new slice to start.
+        */
+
+       throtl_set_slice_end(td, tg, rw, jiffies + throtl_slice);
+
        time_elapsed = jiffies - tg->slice_start[rw];
 
        nr_slices = time_elapsed / throtl_slice;
@@ -709,26 +725,21 @@ static void throtl_process_limit_change(struct throtl_data *td)
        struct throtl_grp *tg;
        struct hlist_node *pos, *n;
 
-       /*
-        * Make sure atomic_inc() effects from
-        * throtl_update_blkio_group_read_bps(), group of functions are
-        * visible.
-        * Is this required or smp_mb__after_atomic_inc() was suffcient
-        * after the atomic_inc().
-        */
-       smp_rmb();
        if (!atomic_read(&td->limits_changed))
                return;
 
        throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));
 
-       hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
-               /*
-                * Do I need an smp_rmb() here to make sure tg->limits_changed
-                * update is visible. I am relying on smp_rmb() at the
-                * beginning of function and not putting a new one here.
-                */
+       /*
+        * Make sure updates from throtl_update_blkio_group_read_bps() group
+        * of functions to tg->limits_changed are visible. We do not
+        * want update td->limits_changed to be visible but update to
+        * tg->limits_changed not being visible yet on this cpu. Hence
+        * the read barrier.
+        */
+       smp_rmb();
 
+       hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
                if (throtl_tg_on_rr(tg) && tg->limits_changed) {
                        throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
                                " riops=%u wiops=%u", tg->bps[READ],
index f291587d753e1b49ceb6138af1b925801b47a4db..8e0f9256eb5829102b47977ea489e6e03b205fde 100644 (file)
@@ -2834,6 +2834,8 @@ static int cciss_revalidate(struct gendisk *disk)
        InquiryData_struct *inq_buff = NULL;
 
        for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
+               if (!h->drv[logvol])
+                       continue;
                if (memcmp(h->drv[logvol]->LunID, drv->LunID,
                        sizeof(drv->LunID)) == 0) {
                        FOUND = 1;
index 89d8a7cc4054ba627b670a8786e05b1824f5a8b3..24487d4fb20297e6676a91e60c9525f26092e315 100644 (file)
@@ -3627,17 +3627,19 @@ static void drbdd(struct drbd_conf *mdev)
                }
 
                shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header);
-               rv = drbd_recv(mdev, &header->h80.payload, shs);
-               if (unlikely(rv != shs)) {
-                       dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
-                       goto err_out;
-               }
-
                if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {
                        dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);
                        goto err_out;
                }
 
+               if (shs) {
+                       rv = drbd_recv(mdev, &header->h80.payload, shs);
+                       if (unlikely(rv != shs)) {
+                               dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
+                               goto err_out;
+                       }
+               }
+
                rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);
 
                if (unlikely(!rv)) {
index 181ea0364822d4f6d559ff1101d95d7d675eff7f..ab2bd09d54b4bfc9fbf7bf74c2e46dbbeb389db5 100644 (file)
@@ -339,7 +339,8 @@ static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
 }
 
 /* completion of master bio is outside of spinlock.
- * If you need it irqsave, do it your self! */
+ * If you need it irqsave, do it your self!
+ * Which means: don't use from bio endio callback. */
 static inline int req_mod(struct drbd_request *req,
                enum drbd_req_event what)
 {
index 47d223c2409c8cebbd233103d8ff1790dfae833c..34f224b018b37b1e1781134fedf67179799ab20e 100644 (file)
@@ -193,8 +193,10 @@ void drbd_endio_sec(struct bio *bio, int error)
  */
 void drbd_endio_pri(struct bio *bio, int error)
 {
+       unsigned long flags;
        struct drbd_request *req = bio->bi_private;
        struct drbd_conf *mdev = req->mdev;
+       struct bio_and_error m;
        enum drbd_req_event what;
        int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
@@ -220,7 +222,13 @@ void drbd_endio_pri(struct bio *bio, int error)
        bio_put(req->private_bio);
        req->private_bio = ERR_PTR(error);
 
-       req_mod(req, what);
+       /* not req_mod(), we need irqsave here! */
+       spin_lock_irqsave(&mdev->req_lock, flags);
+       __req_mod(req, what, &m);
+       spin_unlock_irqrestore(&mdev->req_lock, flags);
+
+       if (m.bio)
+               complete_master_bio(mdev, &m);
 }
 
 int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
index d68d3aa1814b4ac635017e98cebd9625b0e7b40a..f975d24890fada4fd5db9c920fbc0a5c393d6511 100644 (file)
@@ -283,16 +283,21 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
        } while (delay);
 }
 
-static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+static void __sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
 {
-       unsigned long flags;
-
        if (delta > p->max_match_value)
                dev_warn(&p->pdev->dev, "delta out of range\n");
 
-       spin_lock_irqsave(&p->lock, flags);
        p->next_match_value = delta;
        sh_cmt_clock_event_program_verify(p, 0);
+}
+
+static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&p->lock, flags);
+       __sh_cmt_set_next(p, delta);
        spin_unlock_irqrestore(&p->lock, flags);
 }
 
@@ -359,7 +364,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
 
        /* setup timeout if no clockevent */
        if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
-               sh_cmt_set_next(p, p->max_match_value);
+               __sh_cmt_set_next(p, p->max_match_value);
  out:
        spin_unlock_irqrestore(&p->lock, flags);
 
@@ -381,7 +386,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
 
        /* adjust the timeout to maximum if only clocksource left */
        if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
-               sh_cmt_set_next(p, p->max_match_value);
+               __sh_cmt_set_next(p, p->max_match_value);
 
        spin_unlock_irqrestore(&p->lock, flags);
 }
index e3f7fc6f95657e2f4846cebc0efae905d309c31d..68f09a868434b52a6522c147dce8125f42f6505f 100644 (file)
@@ -534,76 +534,73 @@ static int handle_eviocgbit(struct input_dev *dev,
 }
 #undef OLD_KEY_MAX
 
-static int evdev_handle_get_keycode(struct input_dev *dev,
-                                   void __user *p, size_t size)
+static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p)
 {
-       struct input_keymap_entry ke;
+       struct input_keymap_entry ke = {
+               .len    = sizeof(unsigned int),
+               .flags  = 0,
+       };
+       int __user *ip = (int __user *)p;
        int error;
 
-       memset(&ke, 0, sizeof(ke));
-
-       if (size == sizeof(unsigned int[2])) {
-               /* legacy case */
-               int __user *ip = (int __user *)p;
+       /* legacy case */
+       if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+               return -EFAULT;
 
-               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
-                       return -EFAULT;
+       error = input_get_keycode(dev, &ke);
+       if (error)
+               return error;
 
-               ke.len = sizeof(unsigned int);
-               ke.flags = 0;
+       if (put_user(ke.keycode, ip + 1))
+               return -EFAULT;
 
-               error = input_get_keycode(dev, &ke);
-               if (error)
-                       return error;
+       return 0;
+}
 
-               if (put_user(ke.keycode, ip + 1))
-                       return -EFAULT;
+static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p)
+{
+       struct input_keymap_entry ke;
+       int error;
 
-       } else {
-               size = min(size, sizeof(ke));
+       if (copy_from_user(&ke, p, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_from_user(&ke, p, size))
-                       return -EFAULT;
+       error = input_get_keycode(dev, &ke);
+       if (error)
+               return error;
 
-               error = input_get_keycode(dev, &ke);
-               if (error)
-                       return error;
+       if (copy_to_user(p, &ke, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_to_user(p, &ke, size))
-                       return -EFAULT;
-       }
        return 0;
 }
 
-static int evdev_handle_set_keycode(struct input_dev *dev,
-                                   void __user *p, size_t size)
+static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p)
 {
-       struct input_keymap_entry ke;
-
-       memset(&ke, 0, sizeof(ke));
+       struct input_keymap_entry ke = {
+               .len    = sizeof(unsigned int),
+               .flags  = 0,
+       };
+       int __user *ip = (int __user *)p;
 
-       if (size == sizeof(unsigned int[2])) {
-               /* legacy case */
-               int __user *ip = (int __user *)p;
+       if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+               return -EFAULT;
 
-               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
-                       return -EFAULT;
+       if (get_user(ke.keycode, ip + 1))
+               return -EFAULT;
 
-               if (get_user(ke.keycode, ip + 1))
-                       return -EFAULT;
+       return input_set_keycode(dev, &ke);
+}
 
-               ke.len = sizeof(unsigned int);
-               ke.flags = 0;
+static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p)
+{
+       struct input_keymap_entry ke;
 
-       } else {
-               size = min(size, sizeof(ke));
+       if (copy_from_user(&ke, p, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_from_user(&ke, p, size))
-                       return -EFAULT;
-
-               if (ke.len > sizeof(ke.scancode))
-                       return -EINVAL;
-       }
+       if (ke.len > sizeof(ke.scancode))
+               return -EINVAL;
 
        return input_set_keycode(dev, &ke);
 }
@@ -669,6 +666,18 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return evdev_grab(evdev, client);
                else
                        return evdev_ungrab(evdev, client);
+
+       case EVIOCGKEYCODE:
+               return evdev_handle_get_keycode(dev, p);
+
+       case EVIOCSKEYCODE:
+               return evdev_handle_set_keycode(dev, p);
+
+       case EVIOCGKEYCODE_V2:
+               return evdev_handle_get_keycode_v2(dev, p);
+
+       case EVIOCSKEYCODE_V2:
+               return evdev_handle_set_keycode_v2(dev, p);
        }
 
        size = _IOC_SIZE(cmd);
@@ -708,12 +717,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                return error;
-
-       case EVIOC_MASK_SIZE(EVIOCGKEYCODE):
-               return evdev_handle_get_keycode(dev, p, size);
-
-       case EVIOC_MASK_SIZE(EVIOCSKEYCODE):
-               return evdev_handle_set_keycode(dev, p, size);
        }
 
        /* Multi-number variable-length handlers */
index 4852b440960abadea47ab158dc8e6e6140970b06..435b0af401e46e38b23fd6ffba9e862f90c9729b 100644 (file)
@@ -1436,6 +1436,8 @@ static struct wacom_features wacom_features_0xD2 =
        { "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xD3 =
        { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT };
+static const struct wacom_features wacom_features_0xD4 =
+       { "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xD8 =
        { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xDA =
@@ -1510,6 +1512,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xD1) },
        { USB_DEVICE_WACOM(0xD2) },
        { USB_DEVICE_WACOM(0xD3) },
+       { USB_DEVICE_WACOM(0xD4) },
        { USB_DEVICE_WACOM(0xD8) },
        { USB_DEVICE_WACOM(0xDA) },
        { USB_DEVICE_WACOM(0xDB) },
index 90267f8d64eeadf5d9e72afae174f6d4b22e6bf5..4d705cea0f8c74c4010e7fe6fbf8d77288f49c36 100644 (file)
@@ -517,9 +517,8 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
         */
 
        if (q->merge_bvec_fn && !ti->type->merge)
-               limits->max_sectors =
-                       min_not_zero(limits->max_sectors,
-                                    (unsigned int) (PAGE_SIZE >> 9));
+               blk_limits_max_hw_sectors(limits,
+                                         (unsigned int) (PAGE_SIZE >> 9));
        return 0;
 }
 EXPORT_SYMBOL_GPL(dm_set_device_limits);
@@ -1131,11 +1130,6 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
         */
        q->limits = *limits;
 
-       if (limits->no_cluster)
-               queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
-       else
-               queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
-
        if (!dm_table_supports_discards(t))
                queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
        else
index e71c5fa527f59ec3e6ea5fd6ce7d09746bfc437e..175c424f201f33caa0c50525a41b7f8fc3569387 100644 (file)
@@ -4295,9 +4295,6 @@ static int md_alloc(dev_t dev, char *name)
                goto abort;
        mddev->queue->queuedata = mddev;
 
-       /* Can be unlocked because the queue is new: no concurrency */
-       queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, mddev->queue);
-
        blk_queue_make_request(mddev->queue, md_make_request);
 
        disk = alloc_disk(1 << shift);
index 05bde9ccb770b377eb327409a707ef38b5e25a17..1d1d8d200755a2c9af0ca241b983dd55f1a672a4 100644 (file)
@@ -558,7 +558,7 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e
 static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
 {
        struct saa7146_vv *vv = dev->vv_data;
-       struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat);
 
        int b_depth = vv->ov_fmt->depth;
        int b_bpl = vv->ov_fb.fmt.bytesperline;
@@ -702,7 +702,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
        struct saa7146_vv *vv = dev->vv_data;
        struct saa7146_video_dma vdma1;
 
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
        int width = buf->fmt->width;
        int height = buf->fmt->height;
@@ -827,7 +827,7 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71
        struct saa7146_video_dma vdma2;
        struct saa7146_video_dma vdma3;
 
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
        int width = buf->fmt->width;
        int height = buf->fmt->height;
@@ -994,7 +994,7 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)
 
 void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
 {
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
        struct saa7146_vv *vv = dev->vv_data;
        u32 vdma1_prot_addr;
 
index 741c5732b430613ff816da949ba3116a4f23c1c9..d246910129e80c74065eeae233da090396614f45 100644 (file)
@@ -84,7 +84,7 @@ static struct saa7146_format formats[] = {
 
 static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format);
 
-struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc)
+struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)
 {
        int i, j = NUM_FORMATS;
 
@@ -266,7 +266,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
        struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
        struct scatterlist *list = dma->sglist;
        int length = dma->sglen;
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
        DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
 
@@ -408,7 +408,7 @@ static int video_begin(struct saa7146_fh *fh)
                }
        }
 
-       fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
        /* we need to have a valid format set here */
        BUG_ON(NULL == fmt);
 
@@ -460,7 +460,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
                return -EBUSY;
        }
 
-       fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
        /* we need to have a valid format set here */
        BUG_ON(NULL == fmt);
 
@@ -536,7 +536,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
                return -EPERM;
 
        /* check args */
-       fmt = format_by_fourcc(dev, fb->fmt.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat);
        if (NULL == fmt)
                return -EINVAL;
 
@@ -760,7 +760,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
 
        DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
 
-       fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
        if (NULL == fmt)
                return -EINVAL;
 
@@ -1264,7 +1264,7 @@ static int buffer_prepare(struct videobuf_queue *q,
                buf->fmt       = &fh->video_fmt;
                buf->vb.field  = fh->video_fmt.field;
 
-               sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+               sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
                release_all_pagetables(dev, buf);
                if( 0 != IS_PLANAR(sfmt->trans)) {
@@ -1378,7 +1378,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
        fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;
        fh->video_fmt.bytesperline = 0;
        fh->video_fmt.field = V4L2_FIELD_ANY;
-       sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+       sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
        fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
 
        videobuf_queue_sg_init(&fh->video_q, &video_qops,
index 5bf4985daede6a49e9b35adcb3b3256b51a14924..05e832f61c3e88772e1ae8b3b1059a0825a5b86c 100644 (file)
@@ -361,7 +361,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations rtrack_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops rtrack_ioctl_ops = {
@@ -412,13 +412,6 @@ static int __init rtrack_init(void)
        rt->vdev.release = video_device_release_empty;
        video_set_drvdata(&rt->vdev, rt);
 
-       if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(&rt->v4l2_dev);
-               release_region(rt->io, 2);
-               return -EINVAL;
-       }
-       v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n");
-
        /* Set up the I/O locking */
 
        mutex_init(&rt->lock);
@@ -430,6 +423,13 @@ static int __init rtrack_init(void)
        sleep_delay(2000000);   /* make sure it's totally down  */
        outb(0xc0, rt->io);             /* steady volume, mute card     */
 
+       if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(&rt->v4l2_dev);
+               release_region(rt->io, 2);
+               return -EINVAL;
+       }
+       v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n");
+
        return 0;
 }
 
index c22311393624d26ebfbe0d4db8776a7c536b3a70..dd8a6ab0d437ab10022d1b65f1d802cc8d2b006c 100644 (file)
@@ -324,7 +324,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 
 static const struct v4l2_file_operations aztech_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
@@ -375,6 +375,8 @@ static int __init aztech_init(void)
        az->vdev.ioctl_ops = &aztech_ioctl_ops;
        az->vdev.release = video_device_release_empty;
        video_set_drvdata(&az->vdev, az);
+       /* mute card - prevents noisy bootups */
+       outb(0, az->io);
 
        if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
@@ -383,8 +385,6 @@ static int __init aztech_init(void)
        }
 
        v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
-       /* mute card - prevents noisy bootups */
-       outb(0, az->io);
        return 0;
 }
 
index b701ea6e7c7379fc0593fae6c22c4678152cd4e7..bc9ad0897c559b9142aea9ba7cbf486caaf1d5c4 100644 (file)
@@ -328,11 +328,10 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
        unsigned char readbuf[RDS_BUFFER];
        int i = 0;
 
+       mutex_lock(&dev->lock);
        if (dev->rdsstat == 0) {
-               mutex_lock(&dev->lock);
                dev->rdsstat = 1;
                outb(0x80, dev->io);        /* Select RDS fifo */
-               mutex_unlock(&dev->lock);
                init_timer(&dev->readtimer);
                dev->readtimer.function = cadet_handler;
                dev->readtimer.data = (unsigned long)dev;
@@ -340,12 +339,15 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
                add_timer(&dev->readtimer);
        }
        if (dev->rdsin == dev->rdsout) {
+               mutex_unlock(&dev->lock);
                if (file->f_flags & O_NONBLOCK)
                        return -EWOULDBLOCK;
                interruptible_sleep_on(&dev->read_queue);
+               mutex_lock(&dev->lock);
        }
        while (i < count && dev->rdsin != dev->rdsout)
                readbuf[i++] = dev->rdsbuf[dev->rdsout++];
+       mutex_unlock(&dev->lock);
 
        if (copy_to_user(data, readbuf, i))
                return -EFAULT;
@@ -525,9 +527,11 @@ static int cadet_open(struct file *file)
 {
        struct cadet *dev = video_drvdata(file);
 
+       mutex_lock(&dev->lock);
        dev->users++;
        if (1 == dev->users)
                init_waitqueue_head(&dev->read_queue);
+       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -535,11 +539,13 @@ static int cadet_release(struct file *file)
 {
        struct cadet *dev = video_drvdata(file);
 
+       mutex_lock(&dev->lock);
        dev->users--;
        if (0 == dev->users) {
                del_timer_sync(&dev->readtimer);
                dev->rdsstat = 0;
        }
+       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -559,7 +565,7 @@ static const struct v4l2_file_operations cadet_fops = {
        .open           = cadet_open,
        .release        = cadet_release,
        .read           = cadet_read,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll           = cadet_poll,
 };
 
index 79039674a0e0bddff9976de584437a60b948e789..28fa85ba2087cfd56c067ac51a9669945eb44757 100644 (file)
@@ -361,7 +361,7 @@ MODULE_DEVICE_TABLE(pci, gemtek_pci_id);
 
 static const struct v4l2_file_operations gemtek_pci_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
@@ -422,11 +422,11 @@ static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_dev
        card->vdev.release = video_device_release_empty;
        video_set_drvdata(&card->vdev, card);
 
+       gemtek_pci_mute(card);
+
        if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0)
                goto err_video;
 
-       gemtek_pci_mute(card);
-
        v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
                pdev->revision, card->iobase, card->iobase + card->length - 1);
 
index 73985f641f072d361d128f769530281b150ffbfb..259936422e493b4dcf6dd6742d17bc5acd5b2995 100644 (file)
@@ -378,7 +378,7 @@ static int gemtek_probe(struct gemtek *gt)
 
 static const struct v4l2_file_operations gemtek_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int vidioc_querycap(struct file *file, void *priv,
@@ -577,12 +577,6 @@ static int __init gemtek_init(void)
        gt->vdev.release = video_device_release_empty;
        video_set_drvdata(&gt->vdev, gt);
 
-       if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(gt->io, 1);
-               return -EBUSY;
-       }
-
        /* Set defaults */
        gt->lastfreq = GEMTEK_LOWFREQ;
        gt->bu2614data = 0;
@@ -590,6 +584,12 @@ static int __init gemtek_init(void)
        if (initmute)
                gemtek_mute(gt);
 
+       if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(gt->io, 1);
+               return -EBUSY;
+       }
+
        return 0;
 }
 
index 08f1051979cae6f7508026dc0e957a23de775795..6af61bfeb1780089718f96884f6dc0dfc8550943 100644 (file)
@@ -299,7 +299,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations maestro_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops maestro_ioctl_ops = {
@@ -383,22 +383,20 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
 
+       if (!radio_power_on(dev)) {
+               retval = -EIO;
+               goto errfr1;
+       }
+
        retval = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);
        if (retval) {
                v4l2_err(v4l2_dev, "can't register video device!\n");
                goto errfr1;
        }
 
-       if (!radio_power_on(dev)) {
-               retval = -EIO;
-               goto errunr;
-       }
-
        v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n");
 
        return 0;
-errunr:
-       video_unregister_device(&dev->vdev);
 errfr1:
        v4l2_device_unregister(v4l2_dev);
 errfr:
index 255d40df4b461e9e5287462c08901a78758a565f..6459a220b0dd46ddb22326e0595f8964ae4915d2 100644 (file)
@@ -346,7 +346,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 
 static const struct v4l2_file_operations maxiradio_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
index 4ff885445fd455371823ad55a00f82e4c2afdcfe..3fb76e3834c99da96e8621ab4ecd89458913d259 100644 (file)
@@ -33,6 +33,7 @@ struct pcm20 {
        unsigned long freq;
        int muted;
        struct snd_miro_aci *aci;
+       struct mutex lock;
 };
 
 static struct pcm20 pcm20_card = {
@@ -72,7 +73,7 @@ static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)
 
 static const struct v4l2_file_operations pcm20_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int vidioc_querycap(struct file *file, void *priv,
@@ -229,7 +230,7 @@ static int __init pcm20_init(void)
                return -ENODEV;
        }
        strlcpy(v4l2_dev->name, "miropcm20", sizeof(v4l2_dev->name));
-
+       mutex_init(&dev->lock);
 
        res = v4l2_device_register(NULL, v4l2_dev);
        if (res < 0) {
@@ -242,6 +243,7 @@ static int __init pcm20_init(void)
        dev->vdev.fops = &pcm20_fops;
        dev->vdev.ioctl_ops = &pcm20_ioctl_ops;
        dev->vdev.release = video_device_release_empty;
+       dev->vdev.lock = &dev->lock;
        video_set_drvdata(&dev->vdev, dev);
 
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0)
index a79296aac9a9636e408a27a7da9a42cf9c4e21e3..8d6ea591bd188815c374ddf5c5e603a5aa3d6e8e 100644 (file)
@@ -266,7 +266,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations rtrack2_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = {
@@ -315,6 +315,10 @@ static int __init rtrack2_init(void)
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
 
+       /* mute card - prevents noisy bootups */
+       outb(1, dev->io);
+       dev->muted = 1;
+
        mutex_init(&dev->lock);
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
@@ -324,10 +328,6 @@ static int __init rtrack2_init(void)
 
        v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n");
 
-       /* mute card - prevents noisy bootups */
-       outb(1, dev->io);
-       dev->muted = 1;
-
        return 0;
 }
 
index 985359d18aa58fd8e350d0e06b05b66020534bc5..b5a5f89e238a91fe432326d0da9487cf32ad9943 100644 (file)
@@ -260,7 +260,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations fmi_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
@@ -382,6 +382,9 @@ static int __init fmi_init(void)
 
        mutex_init(&fmi->lock);
 
+       /* mute card - prevents noisy bootups */
+       fmi_mute(fmi);
+
        if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
                release_region(fmi->io, 2);
@@ -391,8 +394,6 @@ static int __init fmi_init(void)
        }
 
        v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io);
-       /* mute card - prevents noisy bootups */
-       fmi_mute(fmi);
        return 0;
 }
 
index 52c7bbb32b8b7ea10312ff58716c47f1ed472bd2..dc3f04c52d5e11e923829e74a548d78d1b3e6cad 100644 (file)
@@ -376,7 +376,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations fmr2_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops fmr2_ioctl_ops = {
@@ -424,6 +424,10 @@ static int __init fmr2_init(void)
        fmr2->vdev.release = video_device_release_empty;
        video_set_drvdata(&fmr2->vdev, fmr2);
 
+       /* mute card - prevents noisy bootups */
+       fmr2_mute(fmr2->io);
+       fmr2_product_info(fmr2);
+
        if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
                release_region(fmr2->io, 2);
@@ -431,11 +435,6 @@ static int __init fmr2_init(void)
        }
 
        v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io);
-       /* mute card - prevents noisy bootups */
-       mutex_lock(&fmr2->lock);
-       fmr2_mute(fmr2->io);
-       fmr2_product_info(fmr2);
-       mutex_unlock(&fmr2->lock);
        debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type));
        return 0;
 }
index 03829e6818bd4bc156d922c7c19ee8daaabc0fc8..726d367ad8d0f2119b5e832d8ccca593d2a6d3fa 100644 (file)
@@ -53,7 +53,8 @@ struct radio_si4713_device {
 /* radio_si4713_fops - file operations interface */
 static const struct v4l2_file_operations radio_si4713_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       /* Note: locking is done at the subdev level in the i2c driver. */
+       .unlocked_ioctl = video_ioctl2,
 };
 
 /* Video4Linux Interface */
index 789d2ec66e1948d2d071c3424f92dc820b0bcc0b..0e71d816c725885535cc4d1da4f992809d0d6257 100644 (file)
@@ -142,7 +142,6 @@ struct tea5764_device {
        struct video_device             *videodev;
        struct tea5764_regs             regs;
        struct mutex                    mutex;
-       int                             users;
 };
 
 /* I2C code related */
@@ -458,41 +457,10 @@ static int vidioc_s_audio(struct file *file, void *priv,
        return 0;
 }
 
-static int tea5764_open(struct file *file)
-{
-       /* Currently we support only one device */
-       struct tea5764_device *radio = video_drvdata(file);
-
-       mutex_lock(&radio->mutex);
-       /* Only exclusive access */
-       if (radio->users) {
-               mutex_unlock(&radio->mutex);
-               return -EBUSY;
-       }
-       radio->users++;
-       mutex_unlock(&radio->mutex);
-       file->private_data = radio;
-       return 0;
-}
-
-static int tea5764_close(struct file *file)
-{
-       struct tea5764_device *radio = video_drvdata(file);
-
-       if (!radio)
-               return -ENODEV;
-       mutex_lock(&radio->mutex);
-       radio->users--;
-       mutex_unlock(&radio->mutex);
-       return 0;
-}
-
 /* File system interface */
 static const struct v4l2_file_operations tea5764_fops = {
        .owner          = THIS_MODULE,
-       .open           = tea5764_open,
-       .release        = tea5764_close,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
@@ -527,7 +495,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
        int ret;
 
        PDEBUG("probe");
-       radio = kmalloc(sizeof(struct tea5764_device), GFP_KERNEL);
+       radio = kzalloc(sizeof(struct tea5764_device), GFP_KERNEL);
        if (!radio)
                return -ENOMEM;
 
@@ -555,12 +523,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, radio);
        video_set_drvdata(radio->videodev, radio);
-
-       ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
-       if (ret < 0) {
-               PWARN("Could not register video device!");
-               goto errrel;
-       }
+       radio->videodev->lock = &radio->mutex;
 
        /* initialize and power off the chip */
        tea5764_i2c_read(radio);
@@ -568,6 +531,12 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
        tea5764_mute(radio, 1);
        tea5764_power_down(radio);
 
+       ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+       if (ret < 0) {
+               PWARN("Could not register video device!");
+               goto errrel;
+       }
+
        PINFO("registered.");
        return 0;
 errrel:
index fc1c860fd43844c188d4e42cc845a5f40b4ae957..a32663917059c1cd4734247452c33444c02ad5d2 100644 (file)
@@ -338,7 +338,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations terratec_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops terratec_ioctl_ops = {
@@ -389,6 +389,9 @@ static int __init terratec_init(void)
 
        mutex_init(&tt->lock);
 
+       /* mute card - prevents noisy bootups */
+       tt_write_vol(tt, 0);
+
        if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(&tt->v4l2_dev);
                release_region(tt->io, 2);
@@ -396,9 +399,6 @@ static int __init terratec_init(void)
        }
 
        v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n");
-
-       /* mute card - prevents noisy bootups */
-       tt_write_vol(tt, 0);
        return 0;
 }
 
index b8bb3ef47df5c72153e7e1964ddbc679b3c1b8ed..a185610b376be1a14e79b52751c7f95aab777dd0 100644 (file)
@@ -34,6 +34,7 @@ struct timbradio {
        struct v4l2_subdev      *sd_dsp;
        struct video_device     video_dev;
        struct v4l2_device      v4l2_dev;
+       struct mutex            lock;
 };
 
 
@@ -142,7 +143,7 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {
 
 static const struct v4l2_file_operations timbradio_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int __devinit timbradio_probe(struct platform_device *pdev)
@@ -164,6 +165,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
        }
 
        tr->pdata = *pdata;
+       mutex_init(&tr->lock);
 
        strlcpy(tr->video_dev.name, "Timberdale Radio",
                sizeof(tr->video_dev.name));
@@ -171,6 +173,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
        tr->video_dev.ioctl_ops = &timbradio_ioctl_ops;
        tr->video_dev.release = video_device_release_empty;
        tr->video_dev.minor = -1;
+       tr->video_dev.lock = &tr->lock;
 
        strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
        err = v4l2_device_register(NULL, &tr->v4l2_dev);
index 9d6dcf8af5b01de328436a0955ae190fe651aa72..22fa9cc28abed060cff57e1e3a78227575c9ee36 100644 (file)
@@ -344,7 +344,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations trust_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops trust_ioctl_ops = {
@@ -396,14 +396,6 @@ static int __init trust_init(void)
        tr->vdev.release = video_device_release_empty;
        video_set_drvdata(&tr->vdev, tr);
 
-       if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(tr->io, 2);
-               return -EINVAL;
-       }
-
-       v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n");
-
        write_i2c(tr, 2, TDA7318_ADDR, 0x80);   /* speaker att. LF = 0 dB */
        write_i2c(tr, 2, TDA7318_ADDR, 0xa0);   /* speaker att. RF = 0 dB */
        write_i2c(tr, 2, TDA7318_ADDR, 0xc0);   /* speaker att. LR = 0 dB */
@@ -418,6 +410,14 @@ static int __init trust_init(void)
        /* mute card - prevents noisy bootups */
        tr_setmute(tr, 1);
 
+       if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(tr->io, 2);
+               return -EINVAL;
+       }
+
+       v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n");
+
        return 0;
 }
 
index b1f630527dc12df962d9eeef051413e800e6a785..8dbbf08f22077ad2b7c84e8e3992d3b33eab88e7 100644 (file)
@@ -317,7 +317,7 @@ static int vidioc_log_status(struct file *file, void *priv)
 
 static const struct v4l2_file_operations typhoon_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops typhoon_ioctl_ops = {
@@ -344,18 +344,18 @@ static int __init typhoon_init(void)
 
        strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name));
        dev->io = io;
-       dev->curfreq = dev->mutefreq = mutefreq;
 
        if (dev->io == -1) {
                v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n");
                return -EINVAL;
        }
 
-       if (dev->mutefreq < 87000 || dev->mutefreq > 108500) {
+       if (mutefreq < 87000 || mutefreq > 108500) {
                v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n");
                v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n");
                return -EINVAL;
        }
+       dev->curfreq = dev->mutefreq = mutefreq << 4;
 
        mutex_init(&dev->lock);
        if (!request_region(dev->io, 8, "typhoon")) {
@@ -378,17 +378,17 @@ static int __init typhoon_init(void)
        dev->vdev.ioctl_ops = &typhoon_ioctl_ops;
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
+
+       /* mute card - prevents noisy bootups */
+       typhoon_mute(dev);
+
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(&dev->v4l2_dev);
                release_region(dev->io, 8);
                return -EINVAL;
        }
        v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io);
-       v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq);
-       dev->mutefreq <<= 4;
-
-       /* mute card - prevents noisy bootups */
-       typhoon_mute(dev);
+       v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", mutefreq);
 
        return 0;
 }
index f31eab99c943ba9cdc722e7b3163ed91f079d8a1..af99c5bd88c1f0ce15311ec63c137aeee2ce42ab 100644 (file)
@@ -377,7 +377,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 static const struct v4l2_file_operations zoltrix_fops =
 {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = {
@@ -424,20 +424,6 @@ static int __init zoltrix_init(void)
                return res;
        }
 
-       strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name));
-       zol->vdev.v4l2_dev = v4l2_dev;
-       zol->vdev.fops = &zoltrix_fops;
-       zol->vdev.ioctl_ops = &zoltrix_ioctl_ops;
-       zol->vdev.release = video_device_release_empty;
-       video_set_drvdata(&zol->vdev, zol);
-
-       if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(zol->io, 2);
-               return -EINVAL;
-       }
-       v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n");
-
        mutex_init(&zol->lock);
 
        /* mute card - prevents noisy bootups */
@@ -452,6 +438,20 @@ static int __init zoltrix_init(void)
        zol->curvol = 0;
        zol->stereo = 1;
 
+       strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name));
+       zol->vdev.v4l2_dev = v4l2_dev;
+       zol->vdev.fops = &zoltrix_fops;
+       zol->vdev.ioctl_ops = &zoltrix_ioctl_ops;
+       zol->vdev.release = video_device_release_empty;
+       video_set_drvdata(&zol->vdev, zol);
+
+       if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(zol->io, 2);
+               return -EINVAL;
+       }
+       v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n");
+
        return 0;
 }
 
index 31e7a123d19a954f86808ec80ae8978fd044d3d8..f989f2820d88e90f49f5b4fc6081002126c0c3c2 100644 (file)
@@ -712,7 +712,7 @@ static int ar_initialize(struct ar *ar)
 static const struct v4l2_file_operations ar_fops = {
        .owner          = THIS_MODULE,
        .read           = ar_read,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops ar_ioctl_ops = {
index a529619e51f687d1386c6c673a0feaa9ba8d517a..0902ec041c7a71fd11842b3128de23dbb4ec5daf 100644 (file)
@@ -854,7 +854,6 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
                xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
 
        /* is it free? */
-       mutex_lock(&btv->lock);
        if (btv->resources & xbits) {
                /* no, someone else uses it */
                goto fail;
@@ -884,11 +883,9 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
        /* it's free, grab it */
        fh->resources  |= bit;
        btv->resources |= bit;
-       mutex_unlock(&btv->lock);
        return 1;
 
  fail:
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -940,7 +937,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
                /* trying to free ressources not allocated by us ... */
                printk("bttv: BUG! (btres)\n");
        }
-       mutex_lock(&btv->lock);
        fh->resources  &= ~bits;
        btv->resources &= ~bits;
 
@@ -951,8 +947,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
 
        if (0 == (bits & VBI_RESOURCES))
                disclaim_vbi_lines(btv);
-
-       mutex_unlock(&btv->lock);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1713,28 +1707,20 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
 
                /* Make sure tvnorm and vbi_end remain consistent
                   until we're done. */
-               mutex_lock(&btv->lock);
 
                norm = btv->tvnorm;
 
                /* In this mode capturing always starts at defrect.top
                   (default VDELAY), ignoring cropping parameters. */
                if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
-                       mutex_unlock(&btv->lock);
                        return -EINVAL;
                }
 
-               mutex_unlock(&btv->lock);
-
                c.rect = bttv_tvnorms[norm].cropcap.defrect;
        } else {
-               mutex_lock(&btv->lock);
-
                norm = btv->tvnorm;
                c = btv->crop[!!fh->do_crop];
 
-               mutex_unlock(&btv->lock);
-
                if (width < c.min_scaled_width ||
                    width > c.max_scaled_width ||
                    height < c.min_scaled_height)
@@ -1858,7 +1844,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
        unsigned int i;
        int err;
 
-       mutex_lock(&btv->lock);
        err = v4l2_prio_check(&btv->prio, fh->prio);
        if (err)
                goto err;
@@ -1874,7 +1859,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
        set_tvnorm(btv, i);
 
 err:
-       mutex_unlock(&btv->lock);
 
        return err;
 }
@@ -1898,7 +1882,6 @@ static int bttv_enum_input(struct file *file, void *priv,
        struct bttv *btv = fh->btv;
        int rc = 0;
 
-       mutex_lock(&btv->lock);
        if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
                rc = -EINVAL;
                goto err;
@@ -1928,7 +1911,6 @@ static int bttv_enum_input(struct file *file, void *priv,
        i->std = BTTV_NORMS;
 
 err:
-       mutex_unlock(&btv->lock);
 
        return rc;
 }
@@ -1938,9 +1920,7 @@ static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
        struct bttv_fh *fh = priv;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        *i = btv->input;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -1952,7 +1932,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
 
        int err;
 
-       mutex_lock(&btv->lock);
        err = v4l2_prio_check(&btv->prio, fh->prio);
        if (unlikely(err))
                goto err;
@@ -1965,7 +1944,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
        set_input(btv, i, btv->tvnorm);
 
 err:
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -1979,7 +1957,6 @@ static int bttv_s_tuner(struct file *file, void *priv,
        if (unlikely(0 != t->index))
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
                err = -EINVAL;
                goto err;
@@ -1995,7 +1972,6 @@ static int bttv_s_tuner(struct file *file, void *priv,
                btv->audio_mode_gpio(btv, t, 1);
 
 err:
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2006,10 +1982,8 @@ static int bttv_g_frequency(struct file *file, void *priv,
        struct bttv_fh *fh  = priv;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
        f->frequency = btv->freq;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2024,7 +1998,6 @@ static int bttv_s_frequency(struct file *file, void *priv,
        if (unlikely(f->tuner != 0))
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        err = v4l2_prio_check(&btv->prio, fh->prio);
        if (unlikely(err))
                goto err;
@@ -2039,7 +2012,6 @@ static int bttv_s_frequency(struct file *file, void *priv,
        if (btv->has_matchbox && btv->radio_user)
                tea5757_set_freq(btv, btv->freq);
 err:
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2172,7 +2144,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
 
        /* Make sure tvnorm, vbi_end and the current cropping parameters
           remain consistent until we're done. */
-       mutex_lock(&btv->lock);
 
        b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
 
@@ -2250,7 +2221,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
        rc = 0; /* success */
 
  fail:
-       mutex_unlock(&btv->lock);
 
        return rc;
 }
@@ -2282,9 +2252,7 @@ verify_window_lock                (struct bttv_fh *               fh,
        if (V4L2_FIELD_ANY == field) {
                __s32 height2;
 
-               mutex_lock(&fh->btv->lock);
                height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
-               mutex_unlock(&fh->btv->lock);
                field = (win->w.height > height2)
                        ? V4L2_FIELD_INTERLACED
                        : V4L2_FIELD_TOP;
@@ -2360,7 +2328,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
                }
        }
 
-       mutex_lock(&fh->cap.vb_lock);
        /* clip against screen */
        if (NULL != btv->fbuf.base)
                n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
@@ -2391,13 +2358,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
        fh->ov.field    = win->field;
        fh->ov.setup_ok = 1;
 
-       /*
-        * FIXME: btv is protected by btv->lock mutex, while btv->init
-        *        is protected by fh->cap.vb_lock. This seems to open the
-        *        possibility for some race situations. Maybe the better would
-        *        be to unify those locks or to use another way to store the
-        *        init values that will be consumed by videobuf callbacks
-        */
        btv->init.ov.w.width   = win->w.width;
        btv->init.ov.w.height  = win->w.height;
        btv->init.ov.field     = win->field;
@@ -2412,7 +2372,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
                bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
                retval = bttv_switch_overlay(btv,fh,new);
        }
-       mutex_unlock(&fh->cap.vb_lock);
        return retval;
 }
 
@@ -2526,9 +2485,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
        if (V4L2_FIELD_ANY == field) {
                __s32 height2;
 
-               mutex_lock(&btv->lock);
                height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
-               mutex_unlock(&btv->lock);
                field = (f->fmt.pix.height > height2)
                        ? V4L2_FIELD_INTERLACED
                        : V4L2_FIELD_BOTTOM;
@@ -2614,7 +2571,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
        fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 
        /* update our state informations */
-       mutex_lock(&fh->cap.vb_lock);
        fh->fmt              = fmt;
        fh->cap.field        = f->fmt.pix.field;
        fh->cap.last         = V4L2_FIELD_NONE;
@@ -2623,7 +2579,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
        btv->init.fmt        = fmt;
        btv->init.width      = f->fmt.pix.width;
        btv->init.height     = f->fmt.pix.height;
-       mutex_unlock(&fh->cap.vb_lock);
 
        return 0;
 }
@@ -2649,11 +2604,9 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
        unsigned int i;
        struct bttv_fh *fh = priv;
 
-       mutex_lock(&fh->cap.vb_lock);
        retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
                                     V4L2_MEMORY_MMAP);
        if (retval < 0) {
-               mutex_unlock(&fh->cap.vb_lock);
                return retval;
        }
 
@@ -2665,7 +2618,6 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
        for (i = 0; i < gbuffers; i++)
                mbuf->offsets[i] = i * gbufsize;
 
-       mutex_unlock(&fh->cap.vb_lock);
        return 0;
 }
 #endif
@@ -2775,10 +2727,8 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
        int retval = 0;
 
        if (on) {
-               mutex_lock(&fh->cap.vb_lock);
                /* verify args */
                if (unlikely(!btv->fbuf.base)) {
-                       mutex_unlock(&fh->cap.vb_lock);
                        return -EINVAL;
                }
                if (unlikely(!fh->ov.setup_ok)) {
@@ -2787,13 +2737,11 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
                }
                if (retval)
                        return retval;
-               mutex_unlock(&fh->cap.vb_lock);
        }
 
        if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
                return -EBUSY;
 
-       mutex_lock(&fh->cap.vb_lock);
        if (on) {
                fh->ov.tvnorm = btv->tvnorm;
                new = videobuf_sg_alloc(sizeof(*new));
@@ -2805,7 +2753,6 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
 
        /* switch over */
        retval = bttv_switch_overlay(btv, fh, new);
-       mutex_unlock(&fh->cap.vb_lock);
        return retval;
 }
 
@@ -2844,7 +2791,6 @@ static int bttv_s_fbuf(struct file *file, void *f,
        }
 
        /* ok, accept it */
-       mutex_lock(&fh->cap.vb_lock);
        btv->fbuf.base       = fb->base;
        btv->fbuf.fmt.width  = fb->fmt.width;
        btv->fbuf.fmt.height = fb->fmt.height;
@@ -2876,7 +2822,6 @@ static int bttv_s_fbuf(struct file *file, void *f,
                        retval = bttv_switch_overlay(btv, fh, new);
                }
        }
-       mutex_unlock(&fh->cap.vb_lock);
        return retval;
 }
 
@@ -2955,7 +2900,6 @@ static int bttv_queryctrl(struct file *file, void *priv,
             c->id >= V4L2_CID_PRIVATE_LASTP1))
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
                *c = no_ctl;
        else {
@@ -2963,7 +2907,6 @@ static int bttv_queryctrl(struct file *file, void *priv,
 
                *c = (NULL != ctrl) ? *ctrl : no_ctl;
        }
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2974,10 +2917,8 @@ static int bttv_g_parm(struct file *file, void *f,
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
                                    &parm->parm.capture.timeperframe);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2993,7 +2934,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
        if (0 != t->index)
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        t->rxsubchans = V4L2_TUNER_SUB_MONO;
        bttv_call_all(btv, tuner, g_tuner, t);
        strcpy(t->name, "Television");
@@ -3005,7 +2945,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
        if (btv->audio_mode_gpio)
                btv->audio_mode_gpio(btv, t, 0);
 
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -3014,9 +2953,7 @@ static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        *p = v4l2_prio_max(&btv->prio);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3028,9 +2965,7 @@ static int bttv_s_priority(struct file *file, void *f,
        struct bttv *btv = fh->btv;
        int     rc;
 
-       mutex_lock(&btv->lock);
        rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
-       mutex_unlock(&btv->lock);
 
        return rc;
 }
@@ -3045,9 +2980,7 @@ static int bttv_cropcap(struct file *file, void *priv,
            cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        *cap = bttv_tvnorms[btv->tvnorm].cropcap;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3065,9 +2998,7 @@ static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
           inconsistent with fh->width or fh->height and apps
           do not expect a change here. */
 
-       mutex_lock(&btv->lock);
        crop->c = btv->crop[!!fh->do_crop].rect;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3091,17 +3022,14 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
        /* Make sure tvnorm, vbi_end and the current cropping
           parameters remain consistent until we're done. Note
           read() may change vbi_end in check_alloc_btres_lock(). */
-       mutex_lock(&btv->lock);
        retval = v4l2_prio_check(&btv->prio, fh->prio);
        if (0 != retval) {
-               mutex_unlock(&btv->lock);
                return retval;
        }
 
        retval = -EBUSY;
 
        if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
-               mutex_unlock(&btv->lock);
                return retval;
        }
 
@@ -3113,7 +3041,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
        b_top = max(b->top, btv->vbi_end);
        if (b_top + 32 >= b_bottom) {
-               mutex_unlock(&btv->lock);
                return retval;
        }
 
@@ -3136,12 +3063,8 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
        btv->crop[1] = c;
 
-       mutex_unlock(&btv->lock);
-
        fh->do_crop = 1;
 
-       mutex_lock(&fh->cap.vb_lock);
-
        if (fh->width < c.min_scaled_width) {
                fh->width = c.min_scaled_width;
                btv->init.width = c.min_scaled_width;
@@ -3158,8 +3081,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
                btv->init.height = c.max_scaled_height;
        }
 
-       mutex_unlock(&fh->cap.vb_lock);
-
        return 0;
 }
 
@@ -3227,7 +3148,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
                return videobuf_poll_stream(file, &fh->vbi, wait);
        }
 
-       mutex_lock(&fh->cap.vb_lock);
        if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
                /* streaming capture */
                if (list_empty(&fh->cap.stream))
@@ -3262,7 +3182,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
        else
                rc = 0;
 err:
-       mutex_unlock(&fh->cap.vb_lock);
        return rc;
 }
 
@@ -3293,23 +3212,11 @@ static int bttv_open(struct file *file)
                return -ENOMEM;
        file->private_data = fh;
 
-       /*
-        * btv is protected by btv->lock mutex, while btv->init and other
-        * streaming vars are protected by fh->cap.vb_lock. We need to take
-        * care of both locks to avoid troubles. However, vb_lock is used also
-        * inside videobuf, without calling buf->lock. So, it is a very bad
-        * idea to hold both locks at the same time.
-        * Let's first copy btv->init at fh, holding cap.vb_lock, and then work
-        * with the rest of init, holding btv->lock.
-        */
-       mutex_lock(&fh->cap.vb_lock);
        *fh = btv->init;
-       mutex_unlock(&fh->cap.vb_lock);
 
        fh->type = type;
        fh->ov.setup_ok = 0;
 
-       mutex_lock(&btv->lock);
        v4l2_prio_open(&btv->prio, &fh->prio);
 
        videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
@@ -3317,13 +3224,13 @@ static int bttv_open(struct file *file)
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct bttv_buffer),
-                           fh, NULL);
+                           fh, &btv->lock);
        videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
                            &btv->c.pci->dev, &btv->s_lock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB,
                            sizeof(struct bttv_buffer),
-                           fh, NULL);
+                           fh, &btv->lock);
        set_tvnorm(btv,btv->tvnorm);
        set_input(btv, btv->input, btv->tvnorm);
 
@@ -3346,7 +3253,6 @@ static int bttv_open(struct file *file)
        bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
 
        bttv_field_count(btv);
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -3355,7 +3261,6 @@ static int bttv_release(struct file *file)
        struct bttv_fh *fh = file->private_data;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        /* turn off overlay */
        if (check_btres(fh, RESOURCE_OVERLAY))
                bttv_switch_overlay(btv,fh,NULL);
@@ -3381,14 +3286,8 @@ static int bttv_release(struct file *file)
 
        /* free stuff */
 
-       /*
-        * videobuf uses cap.vb_lock - we should avoid holding btv->lock,
-        * otherwise we may have dead lock conditions
-        */
-       mutex_unlock(&btv->lock);
        videobuf_mmap_free(&fh->cap);
        videobuf_mmap_free(&fh->vbi);
-       mutex_lock(&btv->lock);
        v4l2_prio_close(&btv->prio, fh->prio);
        file->private_data = NULL;
        kfree(fh);
@@ -3398,7 +3297,6 @@ static int bttv_release(struct file *file)
 
        if (!btv->users)
                audio_mute(btv, 1);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3502,11 +3400,8 @@ static int radio_open(struct file *file)
        if (unlikely(!fh))
                return -ENOMEM;
        file->private_data = fh;
-       mutex_lock(&fh->cap.vb_lock);
        *fh = btv->init;
-       mutex_unlock(&fh->cap.vb_lock);
 
-       mutex_lock(&btv->lock);
        v4l2_prio_open(&btv->prio, &fh->prio);
 
        btv->radio_user++;
@@ -3514,7 +3409,6 @@ static int radio_open(struct file *file)
        bttv_call_all(btv, tuner, s_radio);
        audio_input(btv,TVAUDIO_INPUT_RADIO);
 
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -3524,7 +3418,6 @@ static int radio_release(struct file *file)
        struct bttv *btv = fh->btv;
        struct rds_command cmd;
 
-       mutex_lock(&btv->lock);
        v4l2_prio_close(&btv->prio, fh->prio);
        file->private_data = NULL;
        kfree(fh);
@@ -3532,7 +3425,6 @@ static int radio_release(struct file *file)
        btv->radio_user--;
 
        bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3561,7 +3453,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
                return -EINVAL;
        if (0 != t->index)
                return -EINVAL;
-       mutex_lock(&btv->lock);
        strcpy(t->name, "Radio");
        t->type = V4L2_TUNER_RADIO;
 
@@ -3570,8 +3461,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
        if (btv->audio_mode_gpio)
                btv->audio_mode_gpio(btv, t, 0);
 
-       mutex_unlock(&btv->lock);
-
        return 0;
 }
 
@@ -3692,7 +3581,7 @@ static const struct v4l2_file_operations radio_fops =
        .open     = radio_open,
        .read     = radio_read,
        .release  = radio_release,
-       .ioctl    = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll     = radio_poll,
 };
 
index 935e0c9a96744aa1e4f0cd3d443c8ee4c8b407d2..c1193506131c3a37e3c347a8703771a98f3938af 100644 (file)
@@ -860,7 +860,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = qcam_read,
 };
 
index 6e4b19698c13fe6212ee08cfd0d9bee7be3cf964..24fc00965a12d048be055498230b734b794283fa 100644 (file)
@@ -718,7 +718,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = qcam_read,
 };
 
index 260c666ce9317266fb271ffead70ea1605e99db1..0dfff50891e404056059eaf18316bd81fed0824f 100644 (file)
@@ -1775,7 +1775,7 @@ static const struct v4l2_file_operations cafe_v4l_fops = {
        .read = cafe_v4l_read,
        .poll = cafe_v4l_poll,
        .mmap = cafe_v4l_mmap,
-       .ioctl = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = {
index 8f55692db36d278e01191bd3fd2ea9e380c90965..82d195be91976ad18ae3cb9059e64efcf2c44788 100644 (file)
@@ -218,7 +218,13 @@ static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream)
 static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream,
                     unsigned int cmd, void *arg)
 {
-       return snd_pcm_lib_ioctl(substream, cmd, arg);
+       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+       int ret;
+
+       snd_cx18_lock(cxsc);
+       ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+       snd_cx18_unlock(cxsc);
+       return ret;
 }
 
 
index 9045f1ece0ebb35cdb1b85eec68b96cc2344fcfc..ab461e27d9dd1ad6206e9054f391605556563a74 100644 (file)
@@ -41,7 +41,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = {
        .read = cx18_v4l2_read,
        .open = cx18_v4l2_open,
        /* FIXME change to video_ioctl2 if serialization lock can be removed */
-       .ioctl = cx18_v4l2_ioctl,
+       .unlocked_ioctl = cx18_v4l2_ioctl,
        .release = cx18_v4l2_close,
        .poll = cx18_v4l2_enc_poll,
 };
index a5cfc76b40b71e26dcc68e41f1f0b8acdf128e51..bb164099ea2c866a4a250664dbd7f06ddf48767c 100644 (file)
@@ -2530,7 +2530,7 @@ static const struct v4l2_file_operations et61x251_fops = {
        .owner = THIS_MODULE,
        .open =    et61x251_open,
        .release = et61x251_release,
-       .ioctl =   et61x251_ioctl,
+       .unlocked_ioctl =   et61x251_ioctl,
        .read =    et61x251_read,
        .poll =    et61x251_poll,
        .mmap =    et61x251_mmap,
index 330dadc001064e1a477e16acd65723ad72adcc76..e23de57e2c73de5d3c575eb4f52ae2a96be3259c 100644 (file)
@@ -63,7 +63,10 @@ struct sd {
 #define QUALITY_DEF 80
        u8 jpegqual;                    /* webcam quality */
 
+       u8 reg01;
+       u8 reg17;
        u8 reg18;
+       u8 flags;
 
        s8 ag_cnt;
 #define AG_CNT_START 13
@@ -96,6 +99,22 @@ enum sensors {
        SENSOR_SP80708,
 };
 
+/* device flags */
+#define PDN_INV        1               /* inverse pin S_PWR_DN / sn_xxx tables */
+
+/* sn9c1xx definitions */
+/* register 0x01 */
+#define S_PWR_DN       0x01    /* sensor power down */
+#define S_PDN_INV      0x02    /* inverse pin S_PWR_DN */
+#define V_TX_EN                0x04    /* video transfer enable */
+#define LED            0x08    /* output to pin LED */
+#define SCL_SEL_OD     0x20    /* open-drain mode */
+#define SYS_SEL_48M    0x40    /* system clock 0: 24MHz, 1: 48MHz */
+/* register 0x17 */
+#define MCK_SIZE_MASK  0x1f    /* sensor master clock */
+#define SEN_CLK_EN     0x20    /* enable sensor clock */
+#define DEF_EN         0x80    /* defect pixel by 0: soft, 1: hard */
+
 /* V4L2 controls supported by the driver */
 static void setbrightness(struct gspca_dev *gspca_dev);
 static void setcontrast(struct gspca_dev *gspca_dev);
@@ -1755,141 +1774,6 @@ static void po2030n_probe(struct gspca_dev *gspca_dev)
        }
 }
 
-static void bridge_init(struct gspca_dev *gspca_dev,
-                         const u8 *sn9c1xx)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 reg0102[2];
-       const u8 *reg9a;
-       static const u8 reg9a_def[] =
-               {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
-       static const u8 reg9a_spec[] =
-               {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
-       static const u8 regd4[] = {0x60, 0x00, 0x00};
-
-       /* sensor clock already enabled in sd_init */
-       /* reg_w1(gspca_dev, 0xf1, 0x00); */
-       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-
-       /* configure gpio */
-       reg0102[0] = sn9c1xx[1];
-       reg0102[1] = sn9c1xx[2];
-       if (gspca_dev->audio)
-               reg0102[1] |= 0x04;     /* keep the audio connection */
-       reg_w(gspca_dev, 0x01, reg0102, 2);
-       reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
-       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
-       switch (sd->sensor) {
-       case SENSOR_GC0307:
-       case SENSOR_OV7660:
-       case SENSOR_PO1030:
-       case SENSOR_PO2030N:
-       case SENSOR_SOI768:
-       case SENSOR_SP80708:
-               reg9a = reg9a_spec;
-               break;
-       default:
-               reg9a = reg9a_def;
-               break;
-       }
-       reg_w(gspca_dev, 0x9a, reg9a, 6);
-
-       reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
-
-       reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
-
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-               reg_w1(gspca_dev, 0x01, 0x43);
-               reg_w1(gspca_dev, 0x17, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               break;
-       case SENSOR_GC0307:
-               msleep(50);
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x22);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               msleep(50);
-               break;
-       case SENSOR_MI0360B:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_MT9V111:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x61);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_OM6802:
-               msleep(10);
-               reg_w1(gspca_dev, 0x02, 0x73);
-               reg_w1(gspca_dev, 0x17, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x22);
-               msleep(100);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x17, 0x64);
-               reg_w1(gspca_dev, 0x17, 0x64);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               msleep(10);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               i2c_w8(gspca_dev, om6802_init0[0]);
-               i2c_w8(gspca_dev, om6802_init0[1]);
-               msleep(15);
-               reg_w1(gspca_dev, 0x02, 0x71);
-               msleep(150);
-               break;
-       case SENSOR_OV7630:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0xe2);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_OV7648:
-               reg_w1(gspca_dev, 0x01, 0x63);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               break;
-       case SENSOR_PO1030:
-       case SENSOR_SOI768:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_PO2030N:
-       case SENSOR_OV7660:
-               reg_w1(gspca_dev, 0x01, 0x63);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               break;
-       case SENSOR_SP80708:
-               reg_w1(gspca_dev, 0x01, 0x63);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               msleep(100);
-               reg_w1(gspca_dev, 0x02, 0x62);
-               break;
-       default:
-/*     case SENSOR_HV7131R: */
-/*     case SENSOR_MI0360: */
-/*     case SENSOR_MO4000: */
-               reg_w1(gspca_dev, 0x01, 0x43);
-               reg_w1(gspca_dev, 0x17, 0x61);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               if (sd->sensor == SENSOR_HV7131R)
-                       hv7131r_probe(gspca_dev);
-               break;
-       }
-}
-
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
                        const struct usb_device_id *id)
@@ -1898,7 +1782,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        sd->bridge = id->driver_info >> 16;
-       sd->sensor = id->driver_info;
+       sd->sensor = id->driver_info >> 8;
+       sd->flags = id->driver_info;
 
        cam = &gspca_dev->cam;
        if (sd->sensor == SENSOR_ADCM1700) {
@@ -1929,7 +1814,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        /* setup a selector by bridge */
        reg_w1(gspca_dev, 0xf1, 0x01);
        reg_r(gspca_dev, 0x00, 1);
-       reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
+       reg_w1(gspca_dev, 0xf1, 0x00);
        reg_r(gspca_dev, 0x00, 1);              /* get sonix chip id */
        regF1 = gspca_dev->usb_buf[0];
        if (gspca_dev->usb_err < 0)
@@ -2423,10 +2308,17 @@ static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int i;
-       u8 reg1, reg17;
+       u8 reg01, reg17;
+       u8 reg0102[2];
        const u8 *sn9c1xx;
        const u8 (*init)[8];
+       const u8 *reg9a;
        int mode;
+       static const u8 reg9a_def[] =
+               {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
+       static const u8 reg9a_spec[] =
+               {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
+       static const u8 regd4[] = {0x60, 0x00, 0x00};
        static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
        static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
        static const u8 CA_adcm1700[] =
@@ -2448,7 +2340,85 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        /* initialize the bridge */
        sn9c1xx = sn_tb[sd->sensor];
-       bridge_init(gspca_dev, sn9c1xx);
+
+       /* sensor clock already enabled in sd_init */
+       /* reg_w1(gspca_dev, 0xf1, 0x00); */
+       reg01 = sn9c1xx[1];
+       if (sd->flags & PDN_INV)
+               reg01 ^= S_PDN_INV;             /* power down inverted */
+       reg_w1(gspca_dev, 0x01, reg01);
+
+       /* configure gpio */
+       reg0102[0] = reg01;
+       reg0102[1] = sn9c1xx[2];
+       if (gspca_dev->audio)
+               reg0102[1] |= 0x04;     /* keep the audio connection */
+       reg_w(gspca_dev, 0x01, reg0102, 2);
+       reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
+       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
+       switch (sd->sensor) {
+       case SENSOR_GC0307:
+       case SENSOR_OV7660:
+       case SENSOR_PO1030:
+       case SENSOR_PO2030N:
+       case SENSOR_SOI768:
+       case SENSOR_SP80708:
+               reg9a = reg9a_spec;
+               break;
+       default:
+               reg9a = reg9a_def;
+               break;
+       }
+       reg_w(gspca_dev, 0x9a, reg9a, 6);
+
+       reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
+
+       reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
+
+       reg17 = sn9c1xx[0x17];
+       switch (sd->sensor) {
+       case SENSOR_GC0307:
+               msleep(50);             /*fixme: is it useful? */
+               break;
+       case SENSOR_OM6802:
+               msleep(10);
+               reg_w1(gspca_dev, 0x02, 0x73);
+               reg17 |= SEN_CLK_EN;
+               reg_w1(gspca_dev, 0x17, reg17);
+               reg_w1(gspca_dev, 0x01, 0x22);
+               msleep(100);
+               reg01 = SCL_SEL_OD | S_PDN_INV;
+               reg17 &= MCK_SIZE_MASK;
+               reg17 |= 0x04;          /* clock / 4 */
+               break;
+       }
+       reg01 |= SYS_SEL_48M;
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg17 |= SEN_CLK_EN;
+       reg_w1(gspca_dev, 0x17, reg17);
+       reg01 &= ~S_PWR_DN;             /* sensor power on */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 &= ~SYS_SEL_48M;
+       reg_w1(gspca_dev, 0x01, reg01);
+
+       switch (sd->sensor) {
+       case SENSOR_HV7131R:
+               hv7131r_probe(gspca_dev);       /*fixme: is it useful? */
+               break;
+       case SENSOR_OM6802:
+               msleep(10);
+               reg_w1(gspca_dev, 0x01, reg01);
+               i2c_w8(gspca_dev, om6802_init0[0]);
+               i2c_w8(gspca_dev, om6802_init0[1]);
+               msleep(15);
+               reg_w1(gspca_dev, 0x02, 0x71);
+               msleep(150);
+               break;
+       case SENSOR_SP80708:
+               msleep(100);
+               reg_w1(gspca_dev, 0x02, 0x62);
+               break;
+       }
 
        /* initialize the sensor */
        i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
@@ -2476,30 +2446,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
        }
        reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
        switch (sd->sensor) {
-       case SENSOR_GC0307:
-               reg17 = 0xa2;
-               break;
-       case SENSOR_MT9V111:
-       case SENSOR_MI0360B:
-               reg17 = 0xe0;
-               break;
-       case SENSOR_ADCM1700:
-       case SENSOR_OV7630:
-               reg17 = 0xe2;
-               break;
-       case SENSOR_OV7648:
-               reg17 = 0x20;
-               break;
-       case SENSOR_OV7660:
-       case SENSOR_SOI768:
-               reg17 = 0xa0;
-               break;
-       case SENSOR_PO1030:
-       case SENSOR_PO2030N:
-               reg17 = 0xa0;
+       case SENSOR_OM6802:
+/*     case SENSOR_OV7648:             * fixme: sometimes */
                break;
        default:
-               reg17 = 0x60;
+               reg17 |= DEF_EN;
                break;
        }
        reg_w1(gspca_dev, 0x17, reg17);
@@ -2546,95 +2497,67 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        init = NULL;
        mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       if (mode)
-               reg1 = 0x46;    /* 320x240: clk 48Mhz, video trf enable */
-       else
-               reg1 = 0x06;    /* 640x480: clk 24Mhz, video trf enable */
-       reg17 = 0x61;           /* 0x:20: enable sensor clock */
+       reg01 |= SYS_SEL_48M | V_TX_EN;
+       reg17 &= ~MCK_SIZE_MASK;
+       reg17 |= 0x02;                  /* clock / 2 */
        switch (sd->sensor) {
        case SENSOR_ADCM1700:
                init = adcm1700_sensor_param1;
-               reg1 = 0x46;
-               reg17 = 0xe2;
                break;
        case SENSOR_GC0307:
                init = gc0307_sensor_param1;
-               reg17 = 0xa2;
-               reg1 = 0x44;
+               break;
+       case SENSOR_HV7131R:
+       case SENSOR_MI0360:
+               if (mode)
+                       reg01 |= SYS_SEL_48M;   /* 320x240: clk 48Mhz */
+               else
+                       reg01 &= ~SYS_SEL_48M;  /* 640x480: clk 24Mhz */
+               reg17 &= ~MCK_SIZE_MASK;
+               reg17 |= 0x01;                  /* clock / 1 */
                break;
        case SENSOR_MI0360B:
                init = mi0360b_sensor_param1;
-               reg1 &= ~0x02;          /* don't inverse pin S_PWR_DN */
-               reg17 = 0xe2;
                break;
        case SENSOR_MO4000:
-               if (mode) {
-/*                     reg1 = 0x46;     * 320 clk 48Mhz 60fp/s */
-                       reg1 = 0x06;    /* clk 24Mz */
-               } else {
-                       reg17 = 0x22;   /* 640 MCKSIZE */
-/*                     reg1 = 0x06;     * 640 clk 24Mz (done) */
+               if (mode) {                     /* if 320x240 */
+                       reg01 &= ~SYS_SEL_48M;  /* clk 24Mz */
+                       reg17 &= ~MCK_SIZE_MASK;
+                       reg17 |= 0x01;          /* clock / 1 */
                }
                break;
        case SENSOR_MT9V111:
                init = mt9v111_sensor_param1;
-               if (mode) {
-                       reg1 = 0x04;    /* 320 clk 48Mhz */
-               } else {
-/*                     reg1 = 0x06;     * 640 clk 24Mz (done) */
-                       reg17 = 0xc2;
-               }
                break;
        case SENSOR_OM6802:
                init = om6802_sensor_param1;
-               reg17 = 0x64;           /* 640 MCKSIZE */
+               if (!mode) {                    /* if 640x480 */
+                       reg17 &= ~MCK_SIZE_MASK;
+                       reg17 |= 0x01;          /* clock / 4 */
+               }
                break;
        case SENSOR_OV7630:
                init = ov7630_sensor_param1;
-               reg17 = 0xe2;
-               reg1 = 0x44;
                break;
        case SENSOR_OV7648:
                init = ov7648_sensor_param1;
-               reg17 = 0x21;
-/*             reg1 = 0x42;             * 42 - 46? */
+               reg17 &= ~MCK_SIZE_MASK;
+               reg17 |= 0x01;                  /* clock / 1 */
                break;
        case SENSOR_OV7660:
                init = ov7660_sensor_param1;
-               if (sd->bridge == BRIDGE_SN9C120) {
-                       if (mode) {             /* 320x240 - 160x120 */
-                               reg17 = 0xa2;
-                               reg1 = 0x44;    /* 48 Mhz, video trf eneble */
-                       }
-               } else {
-                       reg17 = 0x22;
-                       reg1 = 0x06;    /* 24 Mhz, video trf eneble
-                                        * inverse power down */
-               }
                break;
        case SENSOR_PO1030:
                init = po1030_sensor_param1;
-               reg17 = 0xa2;
-               reg1 = 0x44;
                break;
        case SENSOR_PO2030N:
                init = po2030n_sensor_param1;
-               reg1 = 0x46;
-               reg17 = 0xa2;
                break;
        case SENSOR_SOI768:
                init = soi768_sensor_param1;
-               reg1 = 0x44;
-               reg17 = 0xa2;
                break;
        case SENSOR_SP80708:
                init = sp80708_sensor_param1;
-               if (mode) {
-/*??                   reg1 = 0x04;     * 320 clk 48Mhz */
-               } else {
-                       reg1 = 0x46;     /* 640 clk 48Mz */
-                       reg17 = 0xa2;
-               }
                break;
        }
 
@@ -2684,7 +2607,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
        setjpegqual(gspca_dev);
 
        reg_w1(gspca_dev, 0x17, reg17);
-       reg_w1(gspca_dev, 0x01, reg1);
+       reg_w1(gspca_dev, 0x01, reg01);
+       sd->reg01 = reg01;
+       sd->reg17 = reg17;
 
        sethvflip(gspca_dev);
        setbrightness(gspca_dev);
@@ -2706,41 +2631,64 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
                { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
        static const u8 stopsoi768[] =
                { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
-       u8 data;
-       const u8 *sn9c1xx;
+       u8 reg01;
+       u8 reg17;
 
-       data = 0x0b;
+       reg01 = sd->reg01;
+       reg17 = sd->reg17 & ~SEN_CLK_EN;
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
        case SENSOR_GC0307:
-               data = 0x29;
+       case SENSOR_PO2030N:
+       case SENSOR_SP80708:
+               reg01 |= LED;
+               reg_w1(gspca_dev, 0x01, reg01);
+               reg01 &= ~(LED | V_TX_EN);
+               reg_w1(gspca_dev, 0x01, reg01);
+/*             reg_w1(gspca_dev, 0x02, 0x??);   * LED off ? */
                break;
        case SENSOR_HV7131R:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
                i2c_w8(gspca_dev, stophv7131);
-               data = 0x2b;
                break;
        case SENSOR_MI0360:
        case SENSOR_MI0360B:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+/*             reg_w1(gspca_dev, 0x02, 0x40);    * LED off ? */
                i2c_w8(gspca_dev, stopmi0360);
-               data = 0x29;
                break;
-       case SENSOR_OV7648:
-               i2c_w8(gspca_dev, stopov7648);
-               /* fall thru */
        case SENSOR_MT9V111:
-       case SENSOR_OV7630:
+       case SENSOR_OM6802:
        case SENSOR_PO1030:
-               data = 0x29;
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+               break;
+       case SENSOR_OV7630:
+       case SENSOR_OV7648:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+               i2c_w8(gspca_dev, stopov7648);
+               break;
+       case SENSOR_OV7660:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
                break;
        case SENSOR_SOI768:
                i2c_w8(gspca_dev, stopsoi768);
-               data = 0x29;
                break;
        }
-       sn9c1xx = sn_tb[sd->sensor];
-       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-       reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
-       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-       reg_w1(gspca_dev, 0x01, data);
+
+       reg01 |= SCL_SEL_OD;
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 |= S_PWR_DN;              /* sensor power down */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg_w1(gspca_dev, 0x17, reg17);
+       reg01 &= ~SYS_SEL_48M;          /* clock 24MHz */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 |= LED;
+       reg_w1(gspca_dev, 0x01, reg01);
        /* Don't disable sensor clock as that disables the button on the cam */
        /* reg_w1(gspca_dev, 0xf1, 0x01); */
 }
@@ -2954,14 +2902,18 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 #define BS(bridge, sensor) \
        .driver_info = (BRIDGE_ ## bridge << 16) \
-                       | SENSOR_ ## sensor
+                       | (SENSOR_ ## sensor << 8)
+#define BSF(bridge, sensor, flags) \
+       .driver_info = (BRIDGE_ ## bridge << 16) \
+                       | (SENSOR_ ## sensor << 8) \
+                       | (flags)
 static const __devinitdata struct usb_device_id device_table[] = {
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
        {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},
        {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
 #endif
-       {USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)},
-       {USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)},
+       {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)},
+       {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)},
        {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
        {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
        {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
index 2be23bccd3c89e9a72b1131cb6bf1804df1434d0..48d2c2419c13134abf0c55cdf347bdfd97c897bd 100644 (file)
@@ -1659,7 +1659,7 @@ static const struct v4l2_file_operations meye_fops = {
        .open           = meye_open,
        .release        = meye_release,
        .mmap           = meye_mmap,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll           = meye_poll,
 };
 
@@ -1831,12 +1831,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        msleep(1);
        mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
 
-       if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
-                                 video_nr) < 0) {
-               v4l2_err(v4l2_dev, "video_register_device failed\n");
-               goto outvideoreg;
-       }
-
        mutex_init(&meye.lock);
        init_waitqueue_head(&meye.proc_list);
        meye.brightness = 32 << 10;
@@ -1858,6 +1852,12 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);
        sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48);
 
+       if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
+                                 video_nr) < 0) {
+               v4l2_err(v4l2_dev, "video_register_device failed\n");
+               goto outvideoreg;
+       }
+
        v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n",
               MEYE_DRIVER_VERSION);
        v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n",
index 7129b50757dbd7605fa13449bd7793511019f52f..7551907f8c280f4b9f896094ea9fe0cc079bfd19 100644 (file)
@@ -932,7 +932,7 @@ static ssize_t pms_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations pms_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = pms_read,
 };
 
index 4e5a8cf76dedf7807b5a11ef5369f3f86c3c537c..07cf0c6c7c1f7a210c3a078fc580ee68845535c6 100644 (file)
@@ -75,6 +75,7 @@ struct sh_vou_device {
        int pix_idx;
        struct videobuf_buffer *active;
        enum sh_vou_status status;
+       struct mutex fop_lock;
 };
 
 struct sh_vou_file {
@@ -235,7 +236,7 @@ static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb)
        vb->state = VIDEOBUF_NEEDS_INIT;
 }
 
-/* Locking: caller holds vq->vb_lock mutex */
+/* Locking: caller holds fop_lock mutex */
 static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,
                            unsigned int *size)
 {
@@ -257,7 +258,7 @@ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,
        return 0;
 }
 
-/* Locking: caller holds vq->vb_lock mutex */
+/* Locking: caller holds fop_lock mutex */
 static int sh_vou_buf_prepare(struct videobuf_queue *vq,
                              struct videobuf_buffer *vb,
                              enum v4l2_field field)
@@ -306,7 +307,7 @@ static int sh_vou_buf_prepare(struct videobuf_queue *vq,
        return 0;
 }
 
-/* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */
+/* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */
 static void sh_vou_buf_queue(struct videobuf_queue *vq,
                             struct videobuf_buffer *vb)
 {
@@ -1190,7 +1191,7 @@ static int sh_vou_open(struct file *file)
                                       V4L2_BUF_TYPE_VIDEO_OUTPUT,
                                       V4L2_FIELD_NONE,
                                       sizeof(struct videobuf_buffer), vdev,
-                                      NULL);
+                                      &vou_dev->fop_lock);
 
        return 0;
 }
@@ -1292,7 +1293,7 @@ static const struct v4l2_file_operations sh_vou_fops = {
        .owner          = THIS_MODULE,
        .open           = sh_vou_open,
        .release        = sh_vou_release,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .mmap           = sh_vou_mmap,
        .poll           = sh_vou_poll,
 };
@@ -1331,6 +1332,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
 
        INIT_LIST_HEAD(&vou_dev->queue);
        spin_lock_init(&vou_dev->lock);
+       mutex_init(&vou_dev->fop_lock);
        atomic_set(&vou_dev->use_count, 0);
        vou_dev->pdata = vou_pdata;
        vou_dev->status = SH_VOU_IDLE;
@@ -1388,6 +1390,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
                vdev->tvnorms |= V4L2_STD_PAL;
        vdev->v4l2_dev = &vou_dev->v4l2_dev;
        vdev->release = video_device_release;
+       vdev->lock = &vou_dev->fop_lock;
 
        vou_dev->vdev = vdev;
        video_set_drvdata(vdev, vou_dev);
index 28e19daadec953b879084ec539a17eed2da147a6..f49fbfb7dc1377800da49d0c723caa13a5d14e27 100644 (file)
@@ -3238,7 +3238,7 @@ static const struct v4l2_file_operations sn9c102_fops = {
        .owner = THIS_MODULE,
        .open = sn9c102_open,
        .release = sn9c102_release,
-       .ioctl = sn9c102_ioctl,
+       .unlocked_ioctl = sn9c102_ioctl,
        .read = sn9c102_read,
        .poll = sn9c102_poll,
        .mmap = sn9c102_mmap,
index f169f77366771a925978e65a9eeae7c18d49b812..59f8a9ad3796c3ef5960b4e77f12a7269ea7b7b9 100644 (file)
@@ -785,7 +785,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,
        }
 }
 
-struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
+static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
        __u32 v4l2_id, struct uvc_control_mapping **mapping)
 {
        struct uvc_control *ctrl = NULL;
@@ -944,6 +944,52 @@ done:
        return ret;
 }
 
+/*
+ * Mapping V4L2 controls to UVC controls can be straighforward if done well.
+ * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
+ * must be grouped (for instance the Red Balance, Blue Balance and Do White
+ * Balance V4L2 controls use the White Balance Component UVC control) or
+ * otherwise translated. The approach we take here is to use a translation
+ * table for the controls that can be mapped directly, and handle the others
+ * manually.
+ */
+int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
+       struct v4l2_querymenu *query_menu)
+{
+       struct uvc_menu_info *menu_info;
+       struct uvc_control_mapping *mapping;
+       struct uvc_control *ctrl;
+       u32 index = query_menu->index;
+       u32 id = query_menu->id;
+       int ret;
+
+       memset(query_menu, 0, sizeof(*query_menu));
+       query_menu->id = id;
+       query_menu->index = index;
+
+       ret = mutex_lock_interruptible(&chain->ctrl_mutex);
+       if (ret < 0)
+               return -ERESTARTSYS;
+
+       ctrl = uvc_find_control(chain, query_menu->id, &mapping);
+       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if (query_menu->index >= mapping->menu_count) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       menu_info = &mapping->menu_info[query_menu->index];
+       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
+
+done:
+       mutex_unlock(&chain->ctrl_mutex);
+       return ret;
+}
+
 
 /* --------------------------------------------------------------------------
  * Control transactions
index ed6d5449741c58cb7b546b8a09a0b21f82759794..f14581bd707f0155248f788382fe6452cad7198c 100644 (file)
@@ -89,6 +89,39 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
        queue->type = type;
 }
 
+/*
+ * Free the video buffers.
+ *
+ * This function must be called with the queue lock held.
+ */
+static int __uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       unsigned int i;
+
+       for (i = 0; i < queue->count; ++i) {
+               if (queue->buffer[i].vma_use_count != 0)
+                       return -EBUSY;
+       }
+
+       if (queue->count) {
+               vfree(queue->mem);
+               queue->count = 0;
+       }
+
+       return 0;
+}
+
+int uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       int ret;
+
+       mutex_lock(&queue->mutex);
+       ret = __uvc_free_buffers(queue);
+       mutex_unlock(&queue->mutex);
+
+       return ret;
+}
+
 /*
  * Allocate the video buffers.
  *
@@ -110,7 +143,7 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
 
        mutex_lock(&queue->mutex);
 
-       if ((ret = uvc_free_buffers(queue)) < 0)
+       if ((ret = __uvc_free_buffers(queue)) < 0)
                goto done;
 
        /* Bail out if no buffers should be allocated. */
@@ -151,28 +184,6 @@ done:
        return ret;
 }
 
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
- */
-int uvc_free_buffers(struct uvc_video_queue *queue)
-{
-       unsigned int i;
-
-       for (i = 0; i < queue->count; ++i) {
-               if (queue->buffer[i].vma_use_count != 0)
-                       return -EBUSY;
-       }
-
-       if (queue->count) {
-               vfree(queue->mem);
-               queue->count = 0;
-       }
-
-       return 0;
-}
-
 /*
  * Check if buffers have been allocated.
  */
@@ -368,6 +379,82 @@ done:
        return ret;
 }
 
+/*
+ * VMA operations.
+ */
+static void uvc_vm_open(struct vm_area_struct *vma)
+{
+       struct uvc_buffer *buffer = vma->vm_private_data;
+       buffer->vma_use_count++;
+}
+
+static void uvc_vm_close(struct vm_area_struct *vma)
+{
+       struct uvc_buffer *buffer = vma->vm_private_data;
+       buffer->vma_use_count--;
+}
+
+static const struct vm_operations_struct uvc_vm_ops = {
+       .open           = uvc_vm_open,
+       .close          = uvc_vm_close,
+};
+
+/*
+ * Memory-map a video buffer.
+ *
+ * This function implements video buffers memory mapping and is intended to be
+ * used by the device mmap handler.
+ */
+int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
+{
+       struct uvc_buffer *uninitialized_var(buffer);
+       struct page *page;
+       unsigned long addr, start, size;
+       unsigned int i;
+       int ret = 0;
+
+       start = vma->vm_start;
+       size = vma->vm_end - vma->vm_start;
+
+       mutex_lock(&queue->mutex);
+
+       for (i = 0; i < queue->count; ++i) {
+               buffer = &queue->buffer[i];
+               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
+                       break;
+       }
+
+       if (i == queue->count || size != queue->buf_size) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       /*
+        * VM_IO marks the area as being an mmaped region for I/O to a
+        * device. It also prevents the region from being core dumped.
+        */
+       vma->vm_flags |= VM_IO;
+
+       addr = (unsigned long)queue->mem + buffer->buf.m.offset;
+       while (size > 0) {
+               page = vmalloc_to_page((void *)addr);
+               if ((ret = vm_insert_page(vma, start, page)) < 0)
+                       goto done;
+
+               start += PAGE_SIZE;
+               addr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       vma->vm_ops = &uvc_vm_ops;
+       vma->vm_private_data = buffer;
+       uvc_vm_open(vma);
+
+done:
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+
 /*
  * Poll the video queue.
  *
index 6d15de9b520437a4440dc8da2071efd0b91fe306..8cf61e8a634ffeb7cb23bfe004efc2c60053f1e8 100644 (file)
@@ -100,40 +100,6 @@ done:
  * V4L2 interface
  */
 
-/*
- * Mapping V4L2 controls to UVC controls can be straighforward if done well.
- * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
- * must be grouped (for instance the Red Balance, Blue Balance and Do White
- * Balance V4L2 controls use the White Balance Component UVC control) or
- * otherwise translated. The approach we take here is to use a translation
- * table for the controls that can be mapped directly, and handle the others
- * manually.
- */
-static int uvc_v4l2_query_menu(struct uvc_video_chain *chain,
-       struct v4l2_querymenu *query_menu)
-{
-       struct uvc_menu_info *menu_info;
-       struct uvc_control_mapping *mapping;
-       struct uvc_control *ctrl;
-       u32 index = query_menu->index;
-       u32 id = query_menu->id;
-
-       ctrl = uvc_find_control(chain, query_menu->id, &mapping);
-       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
-               return -EINVAL;
-
-       if (query_menu->index >= mapping->menu_count)
-               return -EINVAL;
-
-       memset(query_menu, 0, sizeof(*query_menu));
-       query_menu->id = id;
-       query_menu->index = index;
-
-       menu_info = &mapping->menu_info[query_menu->index];
-       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
-       return 0;
-}
-
 /*
  * Find the frame interval closest to the requested frame interval for the
  * given frame format and size. This should be done by the device as part of
@@ -260,12 +226,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
         * developers test their webcams with the Linux driver as well as with
         * the Windows driver).
         */
+       mutex_lock(&stream->mutex);
        if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
                probe->dwMaxVideoFrameSize =
                        stream->ctrl.dwMaxVideoFrameSize;
 
        /* Probe the device. */
        ret = uvc_probe_video(stream, probe);
+       mutex_unlock(&stream->mutex);
        if (ret < 0)
                goto done;
 
@@ -289,14 +257,21 @@ done:
 static int uvc_v4l2_get_format(struct uvc_streaming *stream,
        struct v4l2_format *fmt)
 {
-       struct uvc_format *format = stream->cur_format;
-       struct uvc_frame *frame = stream->cur_frame;
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+       int ret = 0;
 
        if (fmt->type != stream->type)
                return -EINVAL;
 
-       if (format == NULL || frame == NULL)
-               return -EINVAL;
+       mutex_lock(&stream->mutex);
+       format = stream->cur_format;
+       frame = stream->cur_frame;
+
+       if (format == NULL || frame == NULL) {
+               ret = -EINVAL;
+               goto done;
+       }
 
        fmt->fmt.pix.pixelformat = format->fcc;
        fmt->fmt.pix.width = frame->wWidth;
@@ -307,7 +282,9 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream,
        fmt->fmt.pix.colorspace = format->colorspace;
        fmt->fmt.pix.priv = 0;
 
-       return 0;
+done:
+       mutex_unlock(&stream->mutex);
+       return ret;
 }
 
 static int uvc_v4l2_set_format(struct uvc_streaming *stream,
@@ -321,18 +298,24 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
        if (fmt->type != stream->type)
                return -EINVAL;
 
-       if (uvc_queue_allocated(&stream->queue))
-               return -EBUSY;
-
        ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
        if (ret < 0)
                return ret;
 
+       mutex_lock(&stream->mutex);
+
+       if (uvc_queue_allocated(&stream->queue)) {
+               ret = -EBUSY;
+               goto done;
+       }
+
        memcpy(&stream->ctrl, &probe, sizeof probe);
        stream->cur_format = format;
        stream->cur_frame = frame;
 
-       return 0;
+done:
+       mutex_unlock(&stream->mutex);
+       return ret;
 }
 
 static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
@@ -343,7 +326,10 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
        if (parm->type != stream->type)
                return -EINVAL;
 
+       mutex_lock(&stream->mutex);
        numerator = stream->ctrl.dwFrameInterval;
+       mutex_unlock(&stream->mutex);
+
        denominator = 10000000;
        uvc_simplify_fraction(&numerator, &denominator, 8, 333);
 
@@ -370,7 +356,6 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
 static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
                struct v4l2_streamparm *parm)
 {
-       struct uvc_frame *frame = stream->cur_frame;
        struct uvc_streaming_control probe;
        struct v4l2_fract timeperframe;
        uint32_t interval;
@@ -379,28 +364,36 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
        if (parm->type != stream->type)
                return -EINVAL;
 
-       if (uvc_queue_streaming(&stream->queue))
-               return -EBUSY;
-
        if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
                timeperframe = parm->parm.capture.timeperframe;
        else
                timeperframe = parm->parm.output.timeperframe;
 
-       memcpy(&probe, &stream->ctrl, sizeof probe);
        interval = uvc_fraction_to_interval(timeperframe.numerator,
                timeperframe.denominator);
-
        uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
                timeperframe.numerator, timeperframe.denominator, interval);
-       probe.dwFrameInterval = uvc_try_frame_interval(frame, interval);
+
+       mutex_lock(&stream->mutex);
+
+       if (uvc_queue_streaming(&stream->queue)) {
+               mutex_unlock(&stream->mutex);
+               return -EBUSY;
+       }
+
+       memcpy(&probe, &stream->ctrl, sizeof probe);
+       probe.dwFrameInterval =
+               uvc_try_frame_interval(stream->cur_frame, interval);
 
        /* Probe the device with the new settings. */
        ret = uvc_probe_video(stream, &probe);
-       if (ret < 0)
+       if (ret < 0) {
+               mutex_unlock(&stream->mutex);
                return ret;
+       }
 
        memcpy(&stream->ctrl, &probe, sizeof probe);
+       mutex_unlock(&stream->mutex);
 
        /* Return the actual frame period. */
        timeperframe.numerator = probe.dwFrameInterval;
@@ -528,11 +521,9 @@ static int uvc_v4l2_release(struct file *file)
        if (uvc_has_privileges(handle)) {
                uvc_video_enable(stream, 0);
 
-               mutex_lock(&stream->queue.mutex);
                if (uvc_free_buffers(&stream->queue) < 0)
                        uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to "
                                        "free buffers.\n");
-               mutex_unlock(&stream->queue.mutex);
        }
 
        /* Release the file handle. */
@@ -624,7 +615,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        }
 
        case VIDIOC_QUERYMENU:
-               return uvc_v4l2_query_menu(chain, arg);
+               return uvc_query_v4l2_menu(chain, arg);
 
        case VIDIOC_G_EXT_CTRLS:
        {
@@ -905,15 +896,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_CROPCAP:
        {
                struct v4l2_cropcap *ccap = arg;
-               struct uvc_frame *frame = stream->cur_frame;
 
                if (ccap->type != stream->type)
                        return -EINVAL;
 
                ccap->bounds.left = 0;
                ccap->bounds.top = 0;
-               ccap->bounds.width = frame->wWidth;
-               ccap->bounds.height = frame->wHeight;
+
+               mutex_lock(&stream->mutex);
+               ccap->bounds.width = stream->cur_frame->wWidth;
+               ccap->bounds.height = stream->cur_frame->wHeight;
+               mutex_unlock(&stream->mutex);
 
                ccap->defrect = ccap->bounds;
 
@@ -930,8 +923,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_REQBUFS:
        {
                struct v4l2_requestbuffers *rb = arg;
-               unsigned int bufsize =
-                       stream->ctrl.dwMaxVideoFrameSize;
 
                if (rb->type != stream->type ||
                    rb->memory != V4L2_MEMORY_MMAP)
@@ -940,7 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if ((ret = uvc_acquire_privileges(handle)) < 0)
                        return ret;
 
-               ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize);
+               mutex_lock(&stream->mutex);
+               ret = uvc_alloc_buffers(&stream->queue, rb->count,
+                                       stream->ctrl.dwMaxVideoFrameSize);
+               mutex_unlock(&stream->mutex);
                if (ret < 0)
                        return ret;
 
@@ -988,7 +982,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if (!uvc_has_privileges(handle))
                        return -EBUSY;
 
+               mutex_lock(&stream->mutex);
                ret = uvc_video_enable(stream, 1);
+               mutex_unlock(&stream->mutex);
                if (ret < 0)
                        return ret;
                break;
@@ -1068,79 +1064,14 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
        return -EINVAL;
 }
 
-/*
- * VMA operations.
- */
-static void uvc_vm_open(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count++;
-}
-
-static void uvc_vm_close(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count--;
-}
-
-static const struct vm_operations_struct uvc_vm_ops = {
-       .open           = uvc_vm_open,
-       .close          = uvc_vm_close,
-};
-
 static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct uvc_fh *handle = file->private_data;
        struct uvc_streaming *stream = handle->stream;
-       struct uvc_video_queue *queue = &stream->queue;
-       struct uvc_buffer *uninitialized_var(buffer);
-       struct page *page;
-       unsigned long addr, start, size;
-       unsigned int i;
-       int ret = 0;
 
        uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
 
-       start = vma->vm_start;
-       size = vma->vm_end - vma->vm_start;
-
-       mutex_lock(&queue->mutex);
-
-       for (i = 0; i < queue->count; ++i) {
-               buffer = &queue->buffer[i];
-               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-                       break;
-       }
-
-       if (i == queue->count || size != queue->buf_size) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       /*
-        * VM_IO marks the area as being an mmaped region for I/O to a
-        * device. It also prevents the region from being core dumped.
-        */
-       vma->vm_flags |= VM_IO;
-
-       addr = (unsigned long)queue->mem + buffer->buf.m.offset;
-       while (size > 0) {
-               page = vmalloc_to_page((void *)addr);
-               if ((ret = vm_insert_page(vma, start, page)) < 0)
-                       goto done;
-
-               start += PAGE_SIZE;
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       vma->vm_ops = &uvc_vm_ops;
-       vma->vm_private_data = buffer;
-       uvc_vm_open(vma);
-
-done:
-       mutex_unlock(&queue->mutex);
-       return ret;
+       return uvc_queue_mmap(&stream->queue, vma);
 }
 
 static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
@@ -1157,7 +1088,7 @@ const struct v4l2_file_operations uvc_fops = {
        .owner          = THIS_MODULE,
        .open           = uvc_v4l2_open,
        .release        = uvc_v4l2_release,
-       .ioctl          = uvc_v4l2_ioctl,
+       .unlocked_ioctl = uvc_v4l2_ioctl,
        .read           = uvc_v4l2_read,
        .mmap           = uvc_v4l2_mmap,
        .poll           = uvc_v4l2_poll,
index 5555f01028385b3287952a53d45b2477db021582..5673d673504b838f510966c31c46c078da032bdd 100644 (file)
@@ -293,8 +293,6 @@ int uvc_probe_video(struct uvc_streaming *stream,
        unsigned int i;
        int ret;
 
-       mutex_lock(&stream->mutex);
-
        /* Perform probing. The device should adjust the requested values
         * according to its capabilities. However, some devices, namely the
         * first generation UVC Logitech webcams, don't implement the Video
@@ -346,7 +344,6 @@ int uvc_probe_video(struct uvc_streaming *stream,
        }
 
 done:
-       mutex_unlock(&stream->mutex);
        return ret;
 }
 
index d97cf6d6a4f96c5ef6da3c3b48de0c83652ace70..45f01e7e13d2f90abd30466c8390c8fcecc4fb5a 100644 (file)
@@ -436,7 +436,9 @@ struct uvc_streaming {
        struct uvc_streaming_control ctrl;
        struct uvc_format *cur_format;
        struct uvc_frame *cur_frame;
-
+       /* Protect access to ctrl, cur_format, cur_frame and hardware video
+        * probe control.
+        */
        struct mutex mutex;
 
        unsigned int frozen : 1;
@@ -574,6 +576,8 @@ extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
 extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
 extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
                struct uvc_buffer *buf);
+extern int uvc_queue_mmap(struct uvc_video_queue *queue,
+               struct vm_area_struct *vma);
 extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
                struct file *file, poll_table *wait);
 extern int uvc_queue_allocated(struct uvc_video_queue *queue);
@@ -606,10 +610,10 @@ extern int uvc_status_suspend(struct uvc_device *dev);
 extern int uvc_status_resume(struct uvc_device *dev);
 
 /* Controls */
-extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
-               __u32 v4l2_id, struct uvc_control_mapping **mapping);
 extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
                struct v4l2_queryctrl *v4l2_ctrl);
+extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
+               struct v4l2_querymenu *query_menu);
 
 extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
                const struct uvc_control_mapping *mapping);
index 03f7f4670e9badd4491f8cddb8e748a848c14119..359e23290a7e99ae0301a6d6844a445343cb900e 100644 (file)
@@ -186,12 +186,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
                size_t sz, loff_t *off)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = -EIO;
+       int ret = -ENODEV;
 
        if (!vdev->fops->read)
                return -EINVAL;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->read(filp, buf, sz, off);
        if (vdev->lock)
@@ -203,12 +203,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
                size_t sz, loff_t *off)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = -EIO;
+       int ret = -ENODEV;
 
        if (!vdev->fops->write)
                return -EINVAL;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->write(filp, buf, sz, off);
        if (vdev->lock)
@@ -219,10 +219,10 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
 static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = DEFAULT_POLLMASK;
+       int ret = POLLERR | POLLHUP;
 
        if (!vdev->fops->poll)
-               return ret;
+               return DEFAULT_POLLMASK;
        if (vdev->lock)
                mutex_lock(vdev->lock);
        if (video_is_registered(vdev))
@@ -238,20 +238,45 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        int ret = -ENODEV;
 
        if (vdev->fops->unlocked_ioctl) {
-               if (vdev->lock)
-                       mutex_lock(vdev->lock);
+               if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+                       return -ERESTARTSYS;
                if (video_is_registered(vdev))
                        ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
                if (vdev->lock)
                        mutex_unlock(vdev->lock);
        } else if (vdev->fops->ioctl) {
-               /* TODO: convert all drivers to unlocked_ioctl */
+               /* This code path is a replacement for the BKL. It is a major
+                * hack but it will have to do for those drivers that are not
+                * yet converted to use unlocked_ioctl.
+                *
+                * There are two options: if the driver implements struct
+                * v4l2_device, then the lock defined there is used to
+                * serialize the ioctls. Otherwise the v4l2 core lock defined
+                * below is used. This lock is really bad since it serializes
+                * completely independent devices.
+                *
+                * Both variants suffer from the same problem: if the driver
+                * sleeps, then it blocks all ioctls since the lock is still
+                * held. This is very common for VIDIOC_DQBUF since that
+                * normally waits for a frame to arrive. As a result any other
+                * ioctl calls will proceed very, very slowly since each call
+                * will have to wait for the VIDIOC_QBUF to finish. Things that
+                * should take 0.01s may now take 10-20 seconds.
+                *
+                * The workaround is to *not* take the lock for VIDIOC_DQBUF.
+                * This actually works OK for videobuf-based drivers, since
+                * videobuf will take its own internal lock.
+                */
                static DEFINE_MUTEX(v4l2_ioctl_mutex);
+               struct mutex *m = vdev->v4l2_dev ?
+                       &vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex;
 
-               mutex_lock(&v4l2_ioctl_mutex);
+               if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m))
+                       return -ERESTARTSYS;
                if (video_is_registered(vdev))
                        ret = vdev->fops->ioctl(filp, cmd, arg);
-               mutex_unlock(&v4l2_ioctl_mutex);
+               if (cmd != VIDIOC_DQBUF)
+                       mutex_unlock(m);
        } else
                ret = -ENOTTY;
 
@@ -265,8 +290,8 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
 
        if (!vdev->fops->mmap)
                return ret;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->mmap(filp, vm);
        if (vdev->lock)
@@ -284,7 +309,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        mutex_lock(&videodev_lock);
        vdev = video_devdata(filp);
        /* return ENODEV if the video device has already been removed. */
-       if (vdev == NULL) {
+       if (vdev == NULL || !video_is_registered(vdev)) {
                mutex_unlock(&videodev_lock);
                return -ENODEV;
        }
@@ -292,8 +317,10 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        video_get(vdev);
        mutex_unlock(&videodev_lock);
        if (vdev->fops->open) {
-               if (vdev->lock)
-                       mutex_lock(vdev->lock);
+               if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
+                       ret = -ERESTARTSYS;
+                       goto err;
+               }
                if (video_is_registered(vdev))
                        ret = vdev->fops->open(filp);
                else
@@ -302,6 +329,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
                        mutex_unlock(vdev->lock);
        }
 
+err:
        /* decrease the refcount in case of an error */
        if (ret)
                video_put(vdev);
@@ -596,7 +624,12 @@ void video_unregister_device(struct video_device *vdev)
        if (!vdev || !video_is_registered(vdev))
                return;
 
+       mutex_lock(&videodev_lock);
+       /* This must be in a critical section to prevent a race with v4l2_open.
+        * Once this bit has been cleared video_get may never be called again.
+        */
        clear_bit(V4L2_FL_REGISTERED, &vdev->flags);
+       mutex_unlock(&videodev_lock);
        device_unregister(&vdev->dev);
 }
 EXPORT_SYMBOL(video_unregister_device);
index 0b08f96b74a5ed5c750fdcc7541d2e38f069d79f..7fe6f92af480bc46288b3eff1d0358a30bd501e4 100644 (file)
@@ -35,6 +35,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
 
        INIT_LIST_HEAD(&v4l2_dev->subdevs);
        spin_lock_init(&v4l2_dev->lock);
+       mutex_init(&v4l2_dev->ioctl_lock);
        v4l2_dev->dev = dev;
        if (dev == NULL) {
                /* If dev == NULL, then name must be filled in by the caller */
index 635420d8d84a0536557582bbf507b4ae14f86f01..019ee206cbee0224fb71c9a86678c05ecf3da7d2 100644 (file)
@@ -815,7 +815,7 @@ out:
 
 static const struct v4l2_file_operations w9966_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = w9966_v4l_read,
 };
 
index 003170ea2e394193bdcb7af4033a98bca9d46127..69546e9213dd7727d7b0db8f9cd56d1772ea7431 100644 (file)
@@ -64,77 +64,6 @@ void pci_bus_remove_resources(struct pci_bus *bus)
        }
 }
 
-static bool pci_bus_resource_better(struct resource *res1, bool pos1,
-                                   struct resource *res2, bool pos2)
-{
-       /* If exactly one is positive decode, always prefer that one */
-       if (pos1 != pos2)
-               return pos1 ? true : false;
-
-       /* Prefer the one that contains the highest address */
-       if (res1->end != res2->end)
-               return (res1->end > res2->end) ? true : false;
-
-       /* Otherwise, prefer the one with highest "center of gravity" */
-       if (res1->start != res2->start)
-               return (res1->start > res2->start) ? true : false;
-
-       /* Otherwise, choose one arbitrarily (but consistently) */
-       return (res1 > res2) ? true : false;
-}
-
-static bool pci_bus_resource_positive(struct pci_bus *bus, struct resource *res)
-{
-       struct pci_bus_resource *bus_res;
-
-       /*
-        * This relies on the fact that pci_bus.resource[] refers to P2P or
-        * CardBus bridge base/limit registers, which are always positively
-        * decoded.  The pci_bus.resources list contains host bridge or
-        * subtractively decoded resources.
-        */
-       list_for_each_entry(bus_res, &bus->resources, list) {
-               if (bus_res->res == res)
-                       return (bus_res->flags & PCI_SUBTRACTIVE_DECODE) ?
-                               false : true;
-       }
-       return true;
-}
-
-/*
- * Find the next-best bus resource after the cursor "res".  If the cursor is
- * NULL, return the best resource.  "Best" means that we prefer positive
- * decode regions over subtractive decode, then those at higher addresses.
- */
-static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
-                                                  unsigned int type,
-                                                  struct resource *res)
-{
-       bool res_pos, r_pos, prev_pos = false;
-       struct resource *r, *prev = NULL;
-       int i;
-
-       res_pos = pci_bus_resource_positive(bus, res);
-       pci_bus_for_each_resource(bus, r, i) {
-               if (!r)
-                       continue;
-
-               if ((r->flags & IORESOURCE_TYPE_BITS) != type)
-                       continue;
-
-               r_pos = pci_bus_resource_positive(bus, r);
-               if (!res || pci_bus_resource_better(res, res_pos, r, r_pos)) {
-                       if (!prev || pci_bus_resource_better(r, r_pos,
-                                                            prev, prev_pos)) {
-                               prev = r;
-                               prev_pos = r_pos;
-                       }
-               }
-       }
-
-       return prev;
-}
-
 /**
  * pci_bus_alloc_resource - allocate a resource from a parent bus
  * @bus: PCI bus
@@ -160,10 +89,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
                                          resource_size_t),
                void *alignf_data)
 {
-       int ret = -ENOMEM;
+       int i, ret = -ENOMEM;
        struct resource *r;
        resource_size_t max = -1;
-       unsigned int type = res->flags & IORESOURCE_TYPE_BITS;
 
        type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
 
@@ -171,9 +99,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
        if (!(res->flags & IORESOURCE_MEM_64))
                max = PCIBIOS_MAX_MEM_32;
 
-       /* Look for space at highest addresses first */
-       r = pci_bus_find_resource_prev(bus, type, NULL);
-       for ( ; r; r = pci_bus_find_resource_prev(bus, type, r)) {
+       pci_bus_for_each_resource(bus, r, i) {
+               if (!r)
+                       continue;
+
                /* type_mask must match */
                if ((res->flags ^ r->flags) & type_mask)
                        continue;
index 0157708d474da57ad0532a3bb8bbbd90f0204aeb..09933eb9126be48f154e809bdcfdc57292a4858a 100644 (file)
@@ -1417,6 +1417,11 @@ int __init enable_drhd_fault_handling(void)
                               (unsigned long long)drhd->reg_base_addr, ret);
                        return -1;
                }
+
+               /*
+                * Clear any previous faults.
+                */
+               dmar_fault(iommu->irq, iommu);
        }
 
        return 0;
index 6f9350cabbd51d1574ec52bcf287d4065f8b3c36..53a786fd0d40c88d978bd4a656971be7b09cdb4a 100644 (file)
@@ -2329,6 +2329,9 @@ static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
 {
        u32 cfg;
 
+       if (!pci_find_capability(dev, PCI_CAP_ID_HT))
+               return;
+
        pci_read_config_dword(dev, 0x74, &cfg);
 
        if (cfg & ((1 << 2) | (1 << 15))) {
@@ -2764,6 +2767,29 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_m
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
 #endif /*CONFIG_MMC_RICOH_MMC*/
 
+#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
+#define VTUNCERRMSK_REG        0x1ac
+#define VTD_MSK_SPEC_ERRORS    (1 << 31)
+/*
+ * This is a quirk for masking vt-d spec defined errors to platform error
+ * handling logic. With out this, platforms using Intel 7500, 5500 chipsets
+ * (and the derivative chipsets like X58 etc) seem to generate NMI/SMI (based
+ * on the RAS config settings of the platform) when a vt-d fault happens.
+ * The resulting SMI caused the system to hang.
+ *
+ * VT-d spec related errors are already handled by the VT-d OS code, so no
+ * need to report the same error through other channels.
+ */
+static void vtd_mask_spec_errors(struct pci_dev *dev)
+{
+       u32 word;
+
+       pci_read_config_dword(dev, VTUNCERRMSK_REG, &word);
+       pci_write_config_dword(dev, VTUNCERRMSK_REG, word | VTD_MSK_SPEC_ERRORS);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
+#endif
 
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
                          struct pci_fixup *end)
index 5b6bbaea59fec92565d2af4d708cedce034295ae..4a3842212c5062811c7973413e4d7aec62679951 100644 (file)
@@ -1637,9 +1637,8 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
 
        blk_queue_max_segment_size(q, dma_get_max_seg_size(dev));
 
-       /* New queue, no concurrency on queue_flags */
        if (!shost->use_clustering)
-               queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
+               q->limits.cluster = 0;
 
        /*
         * set a reasonable default alignment on word boundaries: the
index e7f1d5778cec3f7b4044d5675caddfb0ecd10f54..52389308f3337ebb84daa31490f496b8057548ba 100644 (file)
@@ -92,7 +92,7 @@ int cx25821_get_format_size(void)
        return ARRAY_SIZE(formats);
 }
 
-struct cx25821_fmt *format_by_fourcc(unsigned int fourcc)
+struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
 {
        unsigned int i;
 
@@ -848,7 +848,7 @@ static int video_open(struct file *file)
        pix_format =
           (dev->channels[ch_id].pixel_formats ==
            PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
-       fh->fmt = format_by_fourcc(pix_format);
+       fh->fmt = cx25821_format_by_fourcc(pix_format);
 
        v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio);
 
@@ -1010,7 +1010,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        if (0 != err)
               return err;
 
-       fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
        fh->vidq.field = f->fmt.pix.field;
 
        /* check if width and height is valid based on set standard */
@@ -1119,7 +1119,7 @@ int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fo
        enum v4l2_field field;
        unsigned int maxw, maxh;
 
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
        if (NULL == fmt)
                return -EINVAL;
 
index cc6034b1a95d717ca632c1e95a70d49307449c45..a2415d33235b2b41a62a5230822a62250589e6b1 100644 (file)
@@ -87,7 +87,7 @@ extern unsigned int vid_limit;
 
 #define FORMAT_FLAGS_PACKED       0x01
 extern struct cx25821_fmt formats[];
-extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc);
+extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc);
 extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
 
 extern void cx25821_dump_video_queue(struct cx25821_dev *dev,
index 81b46585edf797561828f2adfac2e598543690f3..c5f8e5bda2b29c4606f3245ba9388f943d3f2147 100644 (file)
@@ -716,8 +716,8 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
                if (msg->len < 128)
                        *--dp = (msg->len << 1) | EA;
                else {
-                       *--dp = ((msg->len & 127) << 1) | EA;
-                       *--dp = (msg->len >> 6) & 0xfe;
+                       *--dp = (msg->len >> 7);        /* bits 7 - 15 */
+                       *--dp = (msg->len & 127) << 1;  /* bits 0 - 6 */
                }
        }
 
@@ -968,6 +968,8 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data,
 {
        struct gsm_msg *msg;
        msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->ftype);
+       if (msg == NULL)
+               return;
        msg->data[0] = (cmd & 0xFE) << 1 | EA;  /* Clear C/R */
        msg->data[1] = (dlen << 1) | EA;
        memcpy(msg->data + 2, data, dlen);
index 9eed5b52d9de22647f6ca7e94791cd97f6e60122..bcc24779ba0e3145f713dd7bf6c0f73368763de3 100644 (file)
@@ -107,11 +107,19 @@ config USB_SUSPEND
          If you are unsure about this, say N here.
 
 config USB_OTG
-       bool
+       bool "OTG support"
        depends on USB && EXPERIMENTAL
        depends on USB_SUSPEND
        default n
-
+       help
+         The most notable feature of USB OTG is support for a
+         "Dual-Role" device, which can act as either a device
+         or a host. The initial role is decided by the type of
+         plug inserted and can be changed later when two dual
+         role devices talk to each other.
+
+         Select this only if your board has Mini-AB/Micro-AB
+         connector.
 
 config USB_OTG_WHITELIST
        bool "Rely on OTG Targeted Peripherals List"
index 7b5cc16e4a0bbc4b61e0627df7bee1479fbda2f4..8572dad5ecbbffd0e0eb71ece46559b30ca6f796 100644 (file)
@@ -1047,9 +1047,9 @@ composite_unbind(struct usb_gadget *gadget)
                kfree(cdev->req->buf);
                usb_ep_free_request(gadget->ep0, cdev->req);
        }
+       device_remove_file(&gadget->dev, &dev_attr_suspended);
        kfree(cdev);
        set_gadget_data(gadget, NULL);
-       device_remove_file(&gadget->dev, &dev_attr_suspended);
        composite = NULL;
 }
 
@@ -1107,14 +1107,6 @@ static int composite_bind(struct usb_gadget *gadget)
         */
        usb_ep_autoconfig_reset(cdev->gadget);
 
-       /* standardized runtime overrides for device ID data */
-       if (idVendor)
-               cdev->desc.idVendor = cpu_to_le16(idVendor);
-       if (idProduct)
-               cdev->desc.idProduct = cpu_to_le16(idProduct);
-       if (bcdDevice)
-               cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
-
        /* composite gadget needs to assign strings for whole device (like
         * serial number), register function drivers, potentially update
         * power state and consumption, etc
@@ -1126,6 +1118,14 @@ static int composite_bind(struct usb_gadget *gadget)
        cdev->desc = *composite->dev;
        cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
+       /* standardized runtime overrides for device ID data */
+       if (idVendor)
+               cdev->desc.idVendor = cpu_to_le16(idVendor);
+       if (idProduct)
+               cdev->desc.idProduct = cpu_to_le16(idProduct);
+       if (bcdDevice)
+               cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
+
        /* stirng overrides */
        if (iManufacturer || !cdev->desc.iManufacturer) {
                if (!iManufacturer && !composite->iManufacturer &&
index 0fae58ef8afe7c43b145074fd8cbb1fe7b30e248..1d0f45f0e7a62fd191d4c856d0de87715456bfbf 100644 (file)
@@ -1680,6 +1680,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                                xhci->port_array[i] = (u8) -1;
                        }
                        /* FIXME: Should we disable the port? */
+                       continue;
                }
                xhci->port_array[i] = major_revision;
                if (major_revision == 0x03)
@@ -1758,16 +1759,20 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
                        return -ENOMEM;
 
                port_index = 0;
-               for (i = 0; i < num_ports; i++)
-                       if (xhci->port_array[i] != 0x03) {
-                               xhci->usb2_ports[port_index] =
-                                       &xhci->op_regs->port_status_base +
-                                       NUM_PORT_REGS*i;
-                               xhci_dbg(xhci, "USB 2.0 port at index %u, "
-                                               "addr = %p\n", i,
-                                               xhci->usb2_ports[port_index]);
-                               port_index++;
-                       }
+               for (i = 0; i < num_ports; i++) {
+                       if (xhci->port_array[i] == 0x03 ||
+                                       xhci->port_array[i] == 0 ||
+                                       xhci->port_array[i] == -1)
+                               continue;
+
+                       xhci->usb2_ports[port_index] =
+                               &xhci->op_regs->port_status_base +
+                               NUM_PORT_REGS*i;
+                       xhci_dbg(xhci, "USB 2.0 port at index %u, "
+                                       "addr = %p\n", i,
+                                       xhci->usb2_ports[port_index]);
+                       port_index++;
+               }
        }
        if (xhci->num_usb3_ports) {
                xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)*
index 796e2f68f7494fad857349e9ffc82ac4f9303984..4ff21587ab03214373364681a664df5d56a66a16 100644 (file)
@@ -3,7 +3,7 @@
 /*
  *     uss720.c  --  USS720 USB Parport Cable.
  *
- *     Copyright (C) 1999, 2005
+ *     Copyright (C) 1999, 2005, 2010
  *         Thomas Sailer (t.sailer@alumni.ethz.ch)
  *
  *     This program is free software; you can redistribute it and/or modify
@@ -776,6 +776,8 @@ static const struct usb_device_id uss720_table[] = {
        { USB_DEVICE(0x0557, 0x2001) },
        { USB_DEVICE(0x0729, 0x1284) },
        { USB_DEVICE(0x1293, 0x0002) },
+       { USB_DEVICE(0x1293, 0x0002) },
+       { USB_DEVICE(0x050d, 0x0002) },
        { }                                             /* Terminating entry */
 };
 
index 6a50965e23f29498b2055f4ecbf1912eb3628759..2dec500135282af0c668d58974c7d190519cf1b7 100644 (file)
@@ -796,6 +796,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
        { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { },                                    /* Optional parameter entry */
index 1286f1e23d8c1505de15be5e1c223128d854055c..bf0867285481bef7f839c5e2c2e7e5fa124f52bd 100644 (file)
 #define MJSG_XM_RADIO_PID      0x937A
 #define MJSG_HD_RADIO_PID      0x937C
 
+/*
+ * D.O.Tec products (http://www.directout.eu)
+ */
+#define FTDI_DOTEC_PID 0x9868
+
 /*
  * Xverve Signalyzer tools (http://www.signalyzer.com/)
  */
index 6ccdd3dd5259b6887fb4b93b5a165feb83b54f51..fcc1e32ce2566332a3bc6ad41b35fdaf5a23e8ff 100644 (file)
@@ -481,6 +481,13 @@ UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_MAX_SECTORS_64),
 
+/* Reported by Vitaly Kuznetsov <vitty@altlinux.ru> */
+UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x9999,
+               "Samsung",
+               "YP-CP3",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG),
+
 /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
  * Device uses standards-violating 32-byte Bulk Command Block Wrappers and
  * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
index 455c6055325dcae647858eb6cede512388f033dc..083c8fe53e24147962a1f821657cf1bfcff8608c 100644 (file)
@@ -1,7 +1,7 @@
 config FB_OMAP
        tristate "OMAP frame buffer support (EXPERIMENTAL)"
-       depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
-
+       depends on FB && (OMAP2_DSS = "n")
+       depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index 2fd7e5271be91ea1c9cd5b202ef40f985266dd46..9441e2eb3dee1a1d66259a406d0653da323570e6 100644 (file)
@@ -551,7 +551,7 @@ void __init omap_vram_reserve_sdram_memblock(void)
        if (!size)
                return;
 
-       size = PAGE_ALIGN(size);
+       size = ALIGN(size, SZ_2M);
 
        if (paddr) {
                if (paddr & ~PAGE_MASK) {
@@ -576,7 +576,7 @@ void __init omap_vram_reserve_sdram_memblock(void)
                        return;
                }
        } else {
-               paddr = memblock_alloc(size, PAGE_SIZE);
+               paddr = memblock_alloc(size, SZ_2M);
        }
 
        memblock_free(paddr, size);
index 6f0444473594a05df9b08b532c0d9e40f62bdca7..659f532d26a01f6b3b1da403a3834ba116d20bdd 100644 (file)
@@ -166,7 +166,7 @@ static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh,
 static struct dentry *btrfs_get_parent(struct dentry *child)
 {
        struct inode *dir = child->d_inode;
-       static struct dentry *dentry;
+       struct dentry *dentry;
        struct btrfs_root *root = BTRFS_I(dir)->root;
        struct btrfs_path *path;
        struct extent_buffer *leaf;
index 158c700fdca5e4f62763377a8374217d6371b68b..d902948a90d88622e9af8bbfc505a779fe735d99 100644 (file)
@@ -40,7 +40,8 @@ int ceph_init_dentry(struct dentry *dentry)
        if (dentry->d_fsdata)
                return 0;
 
-       if (ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
+       if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */
+           ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
                dentry->d_op = &ceph_dentry_ops;
        else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
                dentry->d_op = &ceph_snapdir_dentry_ops;
index 8d79b8912e31e4cb8fcb4961ec1f81d63c3d5070..7d0e4a82d898a83f2695eead6ffc767689ffe140 100644 (file)
@@ -282,7 +282,8 @@ int ceph_release(struct inode *inode, struct file *file)
 static int striped_read(struct inode *inode,
                        u64 off, u64 len,
                        struct page **pages, int num_pages,
-                       int *checkeof, bool align_to_pages)
+                       int *checkeof, bool align_to_pages,
+                       unsigned long buf_align)
 {
        struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_inode_info *ci = ceph_inode(inode);
@@ -307,7 +308,7 @@ static int striped_read(struct inode *inode,
 
 more:
        if (align_to_pages)
-               page_align = (pos - io_align) & ~PAGE_MASK;
+               page_align = (pos - io_align + buf_align) & ~PAGE_MASK;
        else
                page_align = pos & ~PAGE_MASK;
        this_len = left;
@@ -376,16 +377,18 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
        struct inode *inode = file->f_dentry->d_inode;
        struct page **pages;
        u64 off = *poff;
-       int num_pages = calc_pages_for(off, len);
-       int ret;
+       int num_pages, ret;
 
        dout("sync_read on file %p %llu~%u %s\n", file, off, len,
             (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
 
-       if (file->f_flags & O_DIRECT)
-               pages = ceph_get_direct_page_vector(data, num_pages);
-       else
+       if (file->f_flags & O_DIRECT) {
+               num_pages = calc_pages_for((unsigned long)data, len);
+               pages = ceph_get_direct_page_vector(data, num_pages, true);
+       } else {
+               num_pages = calc_pages_for(off, len);
                pages = ceph_alloc_page_vector(num_pages, GFP_NOFS);
+       }
        if (IS_ERR(pages))
                return PTR_ERR(pages);
 
@@ -400,7 +403,8 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
                goto done;
 
        ret = striped_read(inode, off, len, pages, num_pages, checkeof,
-                          file->f_flags & O_DIRECT);
+                          file->f_flags & O_DIRECT,
+                          (unsigned long)data & ~PAGE_MASK);
 
        if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)
                ret = ceph_copy_page_vector_to_user(pages, data, off, ret);
@@ -409,7 +413,7 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
 
 done:
        if (file->f_flags & O_DIRECT)
-               ceph_put_page_vector(pages, num_pages);
+               ceph_put_page_vector(pages, num_pages, true);
        else
                ceph_release_page_vector(pages, num_pages);
        dout("sync_read result %d\n", ret);
@@ -456,6 +460,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
        int do_sync = 0;
        int check_caps = 0;
        int page_align, io_align;
+       unsigned long buf_align;
        int ret;
        struct timespec mtime = CURRENT_TIME;
 
@@ -471,6 +476,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
                pos = *offset;
 
        io_align = pos & ~PAGE_MASK;
+       buf_align = (unsigned long)data & ~PAGE_MASK;
 
        ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left);
        if (ret < 0)
@@ -496,12 +502,15 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
         */
 more:
        len = left;
-       if (file->f_flags & O_DIRECT)
+       if (file->f_flags & O_DIRECT) {
                /* write from beginning of first page, regardless of
                   io alignment */
-               page_align = (pos - io_align) & ~PAGE_MASK;
-       else
+               page_align = (pos - io_align + buf_align) & ~PAGE_MASK;
+               num_pages = calc_pages_for((unsigned long)data, len);
+       } else {
                page_align = pos & ~PAGE_MASK;
+               num_pages = calc_pages_for(pos, len);
+       }
        req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
                                    ceph_vino(inode), pos, &len,
                                    CEPH_OSD_OP_WRITE, flags,
@@ -512,10 +521,8 @@ more:
        if (!req)
                return -ENOMEM;
 
-       num_pages = calc_pages_for(pos, len);
-
        if (file->f_flags & O_DIRECT) {
-               pages = ceph_get_direct_page_vector(data, num_pages);
+               pages = ceph_get_direct_page_vector(data, num_pages, false);
                if (IS_ERR(pages)) {
                        ret = PTR_ERR(pages);
                        goto out;
@@ -565,7 +572,7 @@ more:
        }
 
        if (file->f_flags & O_DIRECT)
-               ceph_put_page_vector(pages, num_pages);
+               ceph_put_page_vector(pages, num_pages, false);
        else if (file->f_flags & O_SYNC)
                ceph_release_page_vector(pages, num_pages);
 
index 5362af9b73729905817a76b5c24a5b33c48d5ce7..4ff7ca530533b121763dbe3b415ad79b162a85fb 100644 (file)
@@ -1748,6 +1748,9 @@ struct file *do_filp_open(int dfd, const char *pathname,
        if (!(open_flag & O_CREAT))
                mode = 0;
 
+       /* Must never be set by userspace */
+       open_flag &= ~FMODE_NONOTIFY;
+
        /*
         * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
         * check for O_DSYNC if the need any syncing at all we enforce it's
index 33ad25ddd5c442a7875e8eca9b078b363e10d9ce..caf9a6a3fb54f0e0dd4cd63ccf103fd6aef20a70 100644 (file)
@@ -176,7 +176,6 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh)
 int nilfs_init_gcinode(struct inode *inode)
 {
        struct nilfs_inode_info *ii = NILFS_I(inode);
-       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
 
        inode->i_mode = S_IFREG;
        mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
@@ -186,14 +185,6 @@ int nilfs_init_gcinode(struct inode *inode)
        ii->i_flags = 0;
        nilfs_bmap_init_gc(ii->i_bmap);
 
-       /*
-        * Add the inode to GC inode list. Garbage Collection
-        * is serialized and no two processes manipulate the
-        * list simultaneously.
-        */
-       igrab(inode);
-       list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes);
-
        return 0;
 }
 
index e00d9457c256179279b141868d6ed86494dec24e..b185e937a335471ec224314909a959684f56d174 100644 (file)
@@ -337,6 +337,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
                                   struct nilfs_argv *argv, void *buf)
 {
        size_t nmembs = argv->v_nmembs;
+       struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
        struct inode *inode;
        struct nilfs_vdesc *vdesc;
        struct buffer_head *bh, *n;
@@ -353,6 +354,17 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
                        ret = PTR_ERR(inode);
                        goto failed;
                }
+               if (list_empty(&NILFS_I(inode)->i_dirty)) {
+                       /*
+                        * Add the inode to GC inode list. Garbage Collection
+                        * is serialized and no two processes manipulate the
+                        * list simultaneously.
+                        */
+                       igrab(inode);
+                       list_add(&NILFS_I(inode)->i_dirty,
+                                &nilfs->ns_gc_inodes);
+               }
+
                do {
                        ret = nilfs_ioctl_move_inode_block(inode, vdesc,
                                                           &buffers);
index b04f88eed09e98b6134f275cb7ba530a06e7f998..f35794b97e8e5cb5cc396af28206d69ca1202935 100644 (file)
@@ -92,7 +92,11 @@ static int fanotify_get_response_from_access(struct fsnotify_group *group,
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-       wait_event(group->fanotify_data.access_waitq, event->response);
+       wait_event(group->fanotify_data.access_waitq, event->response ||
+                               atomic_read(&group->fanotify_data.bypass_perm));
+
+       if (!event->response) /* bypass_perm set */
+               return 0;
 
        /* userspace responded, convert to something usable */
        spin_lock(&event->lock);
index 063224812b7e607879bffeedd5b90f9c4967346f..8b61220cffc597873bc0292bbf2fcd86300f3d5c 100644 (file)
@@ -106,20 +106,29 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
        return client_fd;
 }
 
-static ssize_t fill_event_metadata(struct fsnotify_group *group,
+static int fill_event_metadata(struct fsnotify_group *group,
                                   struct fanotify_event_metadata *metadata,
                                   struct fsnotify_event *event)
 {
+       int ret = 0;
+
        pr_debug("%s: group=%p metadata=%p event=%p\n", __func__,
                 group, metadata, event);
 
        metadata->event_len = FAN_EVENT_METADATA_LEN;
+       metadata->metadata_len = FAN_EVENT_METADATA_LEN;
        metadata->vers = FANOTIFY_METADATA_VERSION;
        metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS;
        metadata->pid = pid_vnr(event->tgid);
-       metadata->fd = create_fd(group, event);
+       if (unlikely(event->mask & FAN_Q_OVERFLOW))
+               metadata->fd = FAN_NOFD;
+       else {
+               metadata->fd = create_fd(group, event);
+               if (metadata->fd < 0)
+                       ret = metadata->fd;
+       }
 
-       return metadata->fd;
+       return ret;
 }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
@@ -200,7 +209,7 @@ static int prepare_for_access_response(struct fsnotify_group *group,
 
        mutex_lock(&group->fanotify_data.access_mutex);
 
-       if (group->fanotify_data.bypass_perm) {
+       if (atomic_read(&group->fanotify_data.bypass_perm)) {
                mutex_unlock(&group->fanotify_data.access_mutex);
                kmem_cache_free(fanotify_response_event_cache, re);
                event->response = FAN_ALLOW;
@@ -257,24 +266,34 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-       fd = fill_event_metadata(group, &fanotify_event_metadata, event);
-       if (fd < 0)
-               return fd;
+       ret = fill_event_metadata(group, &fanotify_event_metadata, event);
+       if (ret < 0)
+               goto out;
 
+       fd = fanotify_event_metadata.fd;
        ret = prepare_for_access_response(group, event, fd);
        if (ret)
                goto out_close_fd;
 
        ret = -EFAULT;
-       if (copy_to_user(buf, &fanotify_event_metadata, FAN_EVENT_METADATA_LEN))
+       if (copy_to_user(buf, &fanotify_event_metadata,
+                        fanotify_event_metadata.event_len))
                goto out_kill_access_response;
 
-       return FAN_EVENT_METADATA_LEN;
+       return fanotify_event_metadata.event_len;
 
 out_kill_access_response:
        remove_access_response(group, event, fd);
 out_close_fd:
-       sys_close(fd);
+       if (fd != FAN_NOFD)
+               sys_close(fd);
+out:
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       if (event->mask & FAN_ALL_PERM_EVENTS) {
+               event->response = FAN_DENY;
+               wake_up(&group->fanotify_data.access_waitq);
+       }
+#endif
        return ret;
 }
 
@@ -382,7 +401,7 @@ static int fanotify_release(struct inode *ignored, struct file *file)
 
        mutex_lock(&group->fanotify_data.access_mutex);
 
-       group->fanotify_data.bypass_perm = true;
+       atomic_inc(&group->fanotify_data.bypass_perm);
 
        list_for_each_entry_safe(re, lre, &group->fanotify_data.access_list, list) {
                pr_debug("%s: found group=%p re=%p event=%p\n", __func__, group,
@@ -586,11 +605,10 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark;
        __u32 added;
+       int ret = 0;
 
        fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);
        if (!fsn_mark) {
-               int ret;
-
                if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
                        return -ENOSPC;
 
@@ -600,17 +618,16 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 
                fsnotify_init_mark(fsn_mark, fanotify_free_mark);
                ret = fsnotify_add_mark(fsn_mark, group, NULL, mnt, 0);
-               if (ret) {
-                       fanotify_free_mark(fsn_mark);
-                       return ret;
-               }
+               if (ret)
+                       goto err;
        }
        added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
-       fsnotify_put_mark(fsn_mark);
+
        if (added & ~mnt->mnt_fsnotify_mask)
                fsnotify_recalc_vfsmount_mask(mnt);
-
-       return 0;
+err:
+       fsnotify_put_mark(fsn_mark);
+       return ret;
 }
 
 static int fanotify_add_inode_mark(struct fsnotify_group *group,
@@ -619,6 +636,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark;
        __u32 added;
+       int ret = 0;
 
        pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
 
@@ -634,8 +652,6 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 
        fsn_mark = fsnotify_find_inode_mark(group, inode);
        if (!fsn_mark) {
-               int ret;
-
                if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
                        return -ENOSPC;
 
@@ -645,16 +661,16 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 
                fsnotify_init_mark(fsn_mark, fanotify_free_mark);
                ret = fsnotify_add_mark(fsn_mark, group, inode, NULL, 0);
-               if (ret) {
-                       fanotify_free_mark(fsn_mark);
-                       return ret;
-               }
+               if (ret)
+                       goto err;
        }
        added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
-       fsnotify_put_mark(fsn_mark);
+
        if (added & ~inode->i_fsnotify_mask)
                fsnotify_recalc_inode_mask(inode);
-       return 0;
+err:
+       fsnotify_put_mark(fsn_mark);
+       return ret;
 }
 
 /* fanotify syscalls */
@@ -687,8 +703,10 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 
        /* fsnotify_alloc_group takes a ref.  Dropped in fanotify_release */
        group = fsnotify_alloc_group(&fanotify_fsnotify_ops);
-       if (IS_ERR(group))
+       if (IS_ERR(group)) {
+               free_uid(user);
                return PTR_ERR(group);
+       }
 
        group->fanotify_data.user = user;
        atomic_inc(&user->fanotify_listeners);
@@ -698,6 +716,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        mutex_init(&group->fanotify_data.access_mutex);
        init_waitqueue_head(&group->fanotify_data.access_waitq);
        INIT_LIST_HEAD(&group->fanotify_data.access_list);
+       atomic_set(&group->fanotify_data.bypass_perm, 0);
 #endif
        switch (flags & FAN_ALL_CLASS_BITS) {
        case FAN_CLASS_NOTIF:
@@ -764,8 +783,10 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
        if (flags & ~FAN_ALL_MARK_FLAGS)
                return -EINVAL;
        switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
-       case FAN_MARK_ADD:
+       case FAN_MARK_ADD:              /* fallthrough */
        case FAN_MARK_REMOVE:
+               if (!mask)
+                       return -EINVAL;
        case FAN_MARK_FLUSH:
                break;
        default:
index 444c305a468c531b7e9e8dda803a2d650a257c58..4cd5d5d78f9fa2b85f38bd9422efc3d387780295 100644 (file)
@@ -752,6 +752,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
        if (ret >= 0)
                return ret;
 
+       fsnotify_put_group(group);
        atomic_dec(&user->inotify_devs);
 out_free_uid:
        free_uid(user);
index aae86fd10c4f5dcea0eaf43cf6c39667a805dae4..36ab42c9bb991566dc5004fad9ca3c0c958bfeb0 100644 (file)
@@ -250,7 +250,7 @@ struct queue_limits {
 
        unsigned char           misaligned;
        unsigned char           discard_misaligned;
-       unsigned char           no_cluster;
+       unsigned char           cluster;
        signed char             discard_zeroes_data;
 };
 
@@ -380,7 +380,6 @@ struct request_queue
 #endif
 };
 
-#define QUEUE_FLAG_CLUSTER     0       /* cluster several segments into 1 */
 #define QUEUE_FLAG_QUEUED      1       /* uses generic tag queueing */
 #define QUEUE_FLAG_STOPPED     2       /* queue is stopped */
 #define        QUEUE_FLAG_SYNCFULL     3       /* read queue has been filled */
@@ -403,7 +402,6 @@ struct request_queue
 #define QUEUE_FLAG_SECDISCARD  19      /* supports SECDISCARD */
 
 #define QUEUE_FLAG_DEFAULT     ((1 << QUEUE_FLAG_IO_STAT) |            \
-                                (1 << QUEUE_FLAG_CLUSTER) |            \
                                 (1 << QUEUE_FLAG_STACKABLE)    |       \
                                 (1 << QUEUE_FLAG_SAME_COMP)    |       \
                                 (1 << QUEUE_FLAG_ADD_RANDOM))
@@ -510,6 +508,11 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
 
 #define rq_data_dir(rq)                ((rq)->cmd_flags & 1)
 
+static inline unsigned int blk_queue_cluster(struct request_queue *q)
+{
+       return q->limits.cluster;
+}
+
 /*
  * We regard a request as sync, if either a read or a sync write
  */
@@ -805,6 +808,7 @@ extern struct request_queue *blk_init_allocated_queue(struct request_queue *,
 extern void blk_cleanup_queue(struct request_queue *);
 extern void blk_queue_make_request(struct request_queue *, make_request_fn *);
 extern void blk_queue_bounce_limit(struct request_queue *, u64);
+extern void blk_limits_max_hw_sectors(struct queue_limits *, unsigned int);
 extern void blk_queue_max_hw_sectors(struct request_queue *, unsigned int);
 extern void blk_queue_max_segments(struct request_queue *, unsigned short);
 extern void blk_queue_max_segment_size(struct request_queue *, unsigned int);
index 266ab92912327bb7bfe9bf1d87ff008260cc424f..499dfe982a0e8a21066e815daa400ac8b57ec5b4 100644 (file)
@@ -105,6 +105,8 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,
 
 #define alloc_bootmem(x) \
        __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_align(x, align) \
+       __alloc_bootmem(x, align, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_nopanic(x) \
        __alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_pages(x) \
index 9e76d35670d204d6425b20d17595737fde4453ff..72c72bfccb88181b8b7c480e445849bfc0c8ab28 100644 (file)
@@ -227,8 +227,10 @@ extern int ceph_open_session(struct ceph_client *client);
 extern void ceph_release_page_vector(struct page **pages, int num_pages);
 
 extern struct page **ceph_get_direct_page_vector(const char __user *data,
-                                                int num_pages);
-extern void ceph_put_page_vector(struct page **pages, int num_pages);
+                                                int num_pages,
+                                                bool write_page);
+extern void ceph_put_page_vector(struct page **pages, int num_pages,
+                                bool dirty);
 extern void ceph_release_page_vector(struct page **pages, int num_pages);
 extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
 extern int ceph_copy_user_to_page_vector(struct page **pages,
index 7605fdd1eb65de1fffd5f1bf5b47428e16475133..e3d8bf26e5eb229a9ca2959fc5ea2b1638238988 100644 (file)
@@ -61,13 +61,31 @@ union cnt32_to_63 {
  *
  * 2) this code must not be preempted for a duration longer than the
  *    32-bit counter half period minus the longest period between two
- *    calls to this code.
+ *    calls to this code;
  *
  * Those requirements ensure proper update to the state bit in memory.
  * This is usually not a problem in practice, but if it is then a kernel
  * timer should be scheduled to manage for this code to be executed often
  * enough.
  *
+ * And finally:
+ *
+ * 3) the cnt_lo argument must be seen as a globally incrementing value,
+ *    meaning that it should be a direct reference to the counter data which
+ *    can be evaluated according to a specific ordering within the macro,
+ *    and not the result of a previous evaluation stored in a variable.
+ *
+ * For example, this is wrong:
+ *
+ *     u32 partial = get_hw_count();
+ *     u64 full = cnt32_to_63(partial);
+ *     return full;
+ *
+ * This is fine:
+ *
+ *     u64 full = cnt32_to_63(get_hw_count());
+ *     return full;
+ *
  * Note that the top bit (bit 63) in the returned value should be considered
  * as garbage.  It is not cleared here because callers are likely to use a
  * multiplier on the returned value which can get rid of the top bit
index 0f0121467fc4b8cf261cbb06a9ff6347b3596474..6c6133f76e163c88041c4a13a4b091ef6ccf13ac 100644 (file)
                                 FAN_ALL_PERM_EVENTS |\
                                 FAN_Q_OVERFLOW)
 
-#define FANOTIFY_METADATA_VERSION      2
+#define FANOTIFY_METADATA_VERSION      3
 
 struct fanotify_event_metadata {
        __u32 event_len;
-       __u32 vers;
+       __u8 vers;
+       __u8 reserved;
+       __u16 metadata_len;
        __aligned_u64 mask;
        __s32 fd;
        __s32 pid;
@@ -96,11 +98,13 @@ struct fanotify_event_metadata {
 struct fanotify_response {
        __s32 fd;
        __u32 response;
-} __attribute__ ((packed));
+};
 
 /* Legit userspace responses to a _PERM event */
 #define FAN_ALLOW      0x01
 #define FAN_DENY       0x02
+/* No fd set in event */
+#define FAN_NOFD       -1
 
 /* Helper functions to deal with fanotify_event_metadata buffers */
 #define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata))
index 5c185fa27089f03b4e9194445ee7bfd842f125c6..b10bcdeaef768b2b0b123c4a6c862b3f5f6c0694 100644 (file)
@@ -235,9 +235,6 @@ static inline void fsnotify_open(struct file *file)
        if (S_ISDIR(inode->i_mode))
                mask |= FS_ISDIR;
 
-       /* FMODE_NONOTIFY must never be set from user */
-       file->f_mode &= ~FMODE_NONOTIFY;
-
        fsnotify_parent(path, NULL, mask);
        fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
 }
index 0a68f924f06fcf3f6f75727f382971bc16e5608f..7380763595d30accb255728f45682550cc540d63 100644 (file)
@@ -166,7 +166,7 @@ struct fsnotify_group {
                        struct mutex access_mutex;
                        struct list_head access_list;
                        wait_queue_head_t access_waitq;
-                       bool bypass_perm; /* protected by access_mutex */
+                       atomic_t bypass_perm;
 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
                        int f_flags;
                        unsigned int max_marks;
index a8af21d42bc146cc6f6ee186894e623b01a884ff..9777668883be6aa18a309b6388616fe08ee900ea 100644 (file)
@@ -104,8 +104,10 @@ struct input_keymap_entry {
 #define EVIOCGREP              _IOR('E', 0x03, unsigned int[2])        /* get repeat settings */
 #define EVIOCSREP              _IOW('E', 0x03, unsigned int[2])        /* set repeat settings */
 
-#define EVIOCGKEYCODE          _IOR('E', 0x04, struct input_keymap_entry)      /* get keycode */
-#define EVIOCSKEYCODE          _IOW('E', 0x04, struct input_keymap_entry)      /* set keycode */
+#define EVIOCGKEYCODE          _IOR('E', 0x04, unsigned int[2])        /* get keycode */
+#define EVIOCGKEYCODE_V2       _IOR('E', 0x04, struct input_keymap_entry)
+#define EVIOCSKEYCODE          _IOW('E', 0x04, unsigned int[2])        /* set keycode */
+#define EVIOCSKEYCODE_V2       _IOW('E', 0x04, struct input_keymap_entry)
 
 #define EVIOCGNAME(len)                _IOC(_IOC_READ, 'E', 0x06, len)         /* get device name */
 #define EVIOCGPHYS(len)                _IOC(_IOC_READ, 'E', 0x07, len)         /* get physical location */
index d377ea815d453b9ec232f22efc5503f5d456b0cf..e9bb22cba764139cc69f3faa1e16f11cc0e05eb2 100644 (file)
@@ -112,7 +112,6 @@ struct resource_list {
 /* PC/ISA/whatever - the normal PC address spaces: IO and memory */
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
-extern int resource_alloc_from_bottom;
 
 extern struct resource *request_resource_conflict(struct resource *root, struct resource *new);
 extern int request_resource(struct resource *root, struct resource *new);
@@ -124,6 +123,7 @@ extern void reserve_region_with_split(struct resource *root,
 extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new);
 extern int insert_resource(struct resource *parent, struct resource *new);
 extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new);
+extern void arch_remove_reservations(struct resource *avail);
 extern int allocate_resource(struct resource *root, struct resource *new,
                             resource_size_t size, resource_size_t min,
                             resource_size_t max, resource_size_t align,
index de2c41758e29e20d6a709303f21a6d8242696fa0..4f1279e105ee143e4317219b3cb093bc8bbdd954 100644 (file)
@@ -887,6 +887,7 @@ struct perf_cpu_context {
        int                             exclusive;
        struct list_head                rotation_list;
        int                             jiffies_interval;
+       struct pmu                      *active_pmu;
 };
 
 struct perf_output_handle {
index 3ec2358f8692d11027e6af927402fcbc0f039da2..d19f1cca7f740a9150f516c98e5c9deecfd271ae 100644 (file)
@@ -77,7 +77,8 @@ static inline void device_set_run_wake(struct device *dev, bool enable)
 
 static inline bool pm_runtime_suspended(struct device *dev)
 {
-       return dev->power.runtime_status == RPM_SUSPENDED;
+       return dev->power.runtime_status == RPM_SUSPENDED
+               && !dev->power.disable_depth;
 }
 
 static inline void pm_runtime_mark_last_busy(struct device *dev)
index 2c79e921a68baeb9d5afa9b0deaa731232685ed5..223874538b33208e3c5ff11710f3161d58b4aef2 100644 (file)
@@ -143,7 +143,7 @@ extern unsigned long nr_iowait_cpu(int cpu);
 extern unsigned long this_cpu_load(void);
 
 
-extern void calc_global_load(void);
+extern void calc_global_load(unsigned long ticks);
 
 extern unsigned long get_parent_ip(unsigned long addr);
 
index 942e3873690190addb45bdde24a069a812f3b8b8..eba52a100533349461c1965f996074c187eaab08 100644 (file)
@@ -96,16 +96,21 @@ static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
        return 0;
 }
 
-extern char * nvram_get(const char *name);
+#ifdef CONFIG_BCM47XX
+#include <asm/mach-bcm47xx/nvram.h>
 /* Get the device MAC address */
 static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
 {
-#ifdef CONFIG_BCM47XX
-       char *res = nvram_get("et0macaddr");
-       if (res)
-               memcpy(macaddr, res, 6);
-#endif
+       char buf[20];
+       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
+               return;
+       nvram_parse_macaddr(buf, macaddr);
 }
+#else
+static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
+{
+}
+#endif
 
 extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
                                          struct pci_dev *pdev);
index 7a9f76ecbbbd8298339c5f88a92238af144e0a68..ac7ce00f39cff70a1fdd70e9b32dfb4c4a62c46f 100644 (file)
@@ -161,7 +161,7 @@ extern struct list_head saa7146_devices;
 extern struct mutex saa7146_devices_lock;
 int saa7146_register_extension(struct saa7146_extension*);
 int saa7146_unregister_extension(struct saa7146_extension*);
-struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc);
+struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc);
 int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);
 void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);
 int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
index 6648036b728d7e32beb09fb91757931265780823..b16f307d471a2df59fd622cba1b338e42503ec16 100644 (file)
@@ -51,6 +51,8 @@ struct v4l2_device {
                        unsigned int notification, void *arg);
        /* The control handler. May be NULL. */
        struct v4l2_ctrl_handler *ctrl_handler;
+       /* BKL replacement mutex. Temporary solution only. */
+       struct mutex ioctl_lock;
 };
 
 /* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev.
index 3b159c5991b7561bdba253eeb479f91622a35fb9..5447dc7defa95b8f0e13acb80b45487df7dc2e73 100644 (file)
@@ -273,6 +273,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 
        setup_thread_stack(tsk, orig);
        clear_user_return_notifier(tsk);
+       clear_tsk_need_resched(tsk);
        stackend = end_of_stack(tsk);
        *stackend = STACK_END_MAGIC;    /* for overflow detection */
 
index eac7e3364335a7a3f94d902e69b9ed4eac4df74a..2870feee81dd7a046703645c9ec50022d4339f39 100644 (file)
@@ -3824,6 +3824,8 @@ static void perf_event_task_event(struct perf_task_event *task_event)
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->active_pmu != pmu)
+                       goto next;
                perf_event_task_ctx(&cpuctx->ctx, task_event);
 
                ctx = task_event->task_ctx;
@@ -3959,6 +3961,8 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->active_pmu != pmu)
+                       goto next;
                perf_event_comm_ctx(&cpuctx->ctx, comm_event);
 
                ctxn = pmu->task_ctx_nr;
@@ -4144,6 +4148,8 @@ got_name:
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->active_pmu != pmu)
+                       goto next;
                perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,
                                        vma->vm_flags & VM_EXEC);
 
@@ -4713,7 +4719,7 @@ static int perf_swevent_init(struct perf_event *event)
                break;
        }
 
-       if (event_id > PERF_COUNT_SW_MAX)
+       if (event_id >= PERF_COUNT_SW_MAX)
                return -ENOENT;
 
        if (!event->parent) {
@@ -5145,20 +5151,36 @@ static void *find_pmu_context(int ctxn)
        return NULL;
 }
 
-static void free_pmu_context(void * __percpu cpu_context)
+static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu)
 {
-       struct pmu *pmu;
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               struct perf_cpu_context *cpuctx;
+
+               cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
+
+               if (cpuctx->active_pmu == old_pmu)
+                       cpuctx->active_pmu = pmu;
+       }
+}
+
+static void free_pmu_context(struct pmu *pmu)
+{
+       struct pmu *i;
 
        mutex_lock(&pmus_lock);
        /*
         * Like a real lame refcount.
         */
-       list_for_each_entry(pmu, &pmus, entry) {
-               if (pmu->pmu_cpu_context == cpu_context)
+       list_for_each_entry(i, &pmus, entry) {
+               if (i->pmu_cpu_context == pmu->pmu_cpu_context) {
+                       update_pmu_context(i, pmu);
                        goto out;
+               }
        }
 
-       free_percpu(cpu_context);
+       free_percpu(pmu->pmu_cpu_context);
 out:
        mutex_unlock(&pmus_lock);
 }
@@ -5190,6 +5212,7 @@ int perf_pmu_register(struct pmu *pmu)
                cpuctx->ctx.pmu = pmu;
                cpuctx->jiffies_interval = 1;
                INIT_LIST_HEAD(&cpuctx->rotation_list);
+               cpuctx->active_pmu = pmu;
        }
 
 got_cpu_context:
@@ -5241,7 +5264,7 @@ void perf_pmu_unregister(struct pmu *pmu)
        synchronize_rcu();
 
        free_percpu(pmu->pmu_disable_count);
-       free_pmu_context(pmu->pmu_cpu_context);
+       free_pmu_context(pmu);
 }
 
 struct pmu *perf_init_event(struct perf_event *event)
index baf667bb2794c6880a834e060fd3a32943c80d68..8c7e4832b9be0f8e031fb07645f6ad8e955c0318 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "power.h"
 
-#define HIBERNATE_SIG  "LINHIB0001"
+#define HIBERNATE_SIG  "S1SUSPEND"
 
 /*
  *     The swap map is a data structure used for keeping track of each page
index 1b2ea31e6bd8c0eca7eaaf985bc84337a1e750d0..c36c3b9e8a84f59ad5894a1e2d04c7252b656ebe 100644 (file)
@@ -137,7 +137,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)
        free_all_swap_pages(data->swap);
        if (data->frozen)
                thaw_processes();
-       pm_notifier_call_chain(data->mode == O_WRONLY ?
+       pm_notifier_call_chain(data->mode == O_RDONLY ?
                        PM_POST_HIBERNATION : PM_POST_RESTORE);
        atomic_inc(&snapshot_device_available);
 
index 9fad33efd0db50b3269572f598a1ce418731153c..798e2fae2a069645c13853f4b658dada92af8f66 100644 (file)
@@ -40,23 +40,6 @@ EXPORT_SYMBOL(iomem_resource);
 
 static DEFINE_RWLOCK(resource_lock);
 
-/*
- * By default, we allocate free space bottom-up.  The architecture can request
- * top-down by clearing this flag.  The user can override the architecture's
- * choice with the "resource_alloc_from_bottom" kernel boot option, but that
- * should only be a debugging tool.
- */
-int resource_alloc_from_bottom = 1;
-
-static __init int setup_alloc_from_bottom(char *s)
-{
-       printk(KERN_INFO
-              "resource: allocating from bottom-up; please report a bug\n");
-       resource_alloc_from_bottom = 1;
-       return 0;
-}
-early_param("resource_alloc_from_bottom", setup_alloc_from_bottom);
-
 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
 {
        struct resource *p = v;
@@ -374,6 +357,10 @@ int __weak page_is_ram(unsigned long pfn)
        return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;
 }
 
+void __weak arch_remove_reservations(struct resource *avail)
+{
+}
+
 static resource_size_t simple_align_resource(void *data,
                                             const struct resource *avail,
                                             resource_size_t size,
@@ -396,75 +383,8 @@ static bool resource_contains(struct resource *res1, struct resource *res2)
        return res1->start <= res2->start && res1->end >= res2->end;
 }
 
-/*
- * Find the resource before "child" in the sibling list of "root" children.
- */
-static struct resource *find_sibling_prev(struct resource *root, struct resource *child)
-{
-       struct resource *this;
-
-       for (this = root->child; this; this = this->sibling)
-               if (this->sibling == child)
-                       return this;
-
-       return NULL;
-}
-
 /*
  * Find empty slot in the resource tree given range and alignment.
- * This version allocates from the end of the root resource first.
- */
-static int find_resource_from_top(struct resource *root, struct resource *new,
-                                 resource_size_t size, resource_size_t min,
-                                 resource_size_t max, resource_size_t align,
-                                 resource_size_t (*alignf)(void *,
-                                                  const struct resource *,
-                                                  resource_size_t,
-                                                  resource_size_t),
-                                 void *alignf_data)
-{
-       struct resource *this;
-       struct resource tmp, avail, alloc;
-
-       tmp.start = root->end;
-       tmp.end = root->end;
-
-       this = find_sibling_prev(root, NULL);
-       for (;;) {
-               if (this) {
-                       if (this->end < root->end)
-                               tmp.start = this->end + 1;
-               } else
-                       tmp.start = root->start;
-
-               resource_clip(&tmp, min, max);
-
-               /* Check for overflow after ALIGN() */
-               avail = *new;
-               avail.start = ALIGN(tmp.start, align);
-               avail.end = tmp.end;
-               if (avail.start >= tmp.start) {
-                       alloc.start = alignf(alignf_data, &avail, size, align);
-                       alloc.end = alloc.start + size - 1;
-                       if (resource_contains(&avail, &alloc)) {
-                               new->start = alloc.start;
-                               new->end = alloc.end;
-                               return 0;
-                       }
-               }
-
-               if (!this || this->start == root->start)
-                       break;
-
-               tmp.end = this->start - 1;
-               this = find_sibling_prev(root, this);
-       }
-       return -EBUSY;
-}
-
-/*
- * Find empty slot in the resource tree given range and alignment.
- * This version allocates from the beginning of the root resource first.
  */
 static int find_resource(struct resource *root, struct resource *new,
                         resource_size_t size, resource_size_t min,
@@ -478,23 +398,24 @@ static int find_resource(struct resource *root, struct resource *new,
        struct resource *this = root->child;
        struct resource tmp = *new, avail, alloc;
 
+       tmp.flags = new->flags;
        tmp.start = root->start;
        /*
-        * Skip past an allocated resource that starts at 0, since the
-        * assignment of this->start - 1 to tmp->end below would cause an
-        * underflow.
+        * Skip past an allocated resource that starts at 0, since the assignment
+        * of this->start - 1 to tmp->end below would cause an underflow.
         */
        if (this && this->start == 0) {
                tmp.start = this->end + 1;
                this = this->sibling;
        }
-       for (;;) {
+       for(;;) {
                if (this)
                        tmp.end = this->start - 1;
                else
                        tmp.end = root->end;
 
                resource_clip(&tmp, min, max);
+               arch_remove_reservations(&tmp);
 
                /* Check for overflow after ALIGN() */
                avail = *new;
@@ -509,10 +430,8 @@ static int find_resource(struct resource *root, struct resource *new,
                                return 0;
                        }
                }
-
                if (!this)
                        break;
-
                tmp.start = this->end + 1;
                this = this->sibling;
        }
@@ -545,10 +464,7 @@ int allocate_resource(struct resource *root, struct resource *new,
                alignf = simple_align_resource;
 
        write_lock(&resource_lock);
-       if (resource_alloc_from_bottom)
-               err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
-       else
-               err = find_resource_from_top(root, new, size, min, max, align, alignf, alignf_data);
+       err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
        if (err >= 0 && __request_resource(root, new))
                err = -EBUSY;
        write_unlock(&resource_lock);
index dc91a4d09ac3b71a3c347187ff2a1691c952cebd..297d1a0eedb0e68d8b9327f530ba477c93b1222e 100644 (file)
@@ -636,22 +636,18 @@ static inline struct task_group *task_group(struct task_struct *p)
 
 #endif /* CONFIG_CGROUP_SCHED */
 
-static u64 irq_time_cpu(int cpu);
-static void sched_irq_time_avg_update(struct rq *rq, u64 irq_time);
+static void update_rq_clock_task(struct rq *rq, s64 delta);
 
-inline void update_rq_clock(struct rq *rq)
+static void update_rq_clock(struct rq *rq)
 {
-       if (!rq->skip_clock_update) {
-               int cpu = cpu_of(rq);
-               u64 irq_time;
+       s64 delta;
 
-               rq->clock = sched_clock_cpu(cpu);
-               irq_time = irq_time_cpu(cpu);
-               if (rq->clock - irq_time > rq->clock_task)
-                       rq->clock_task = rq->clock - irq_time;
+       if (rq->skip_clock_update)
+               return;
 
-               sched_irq_time_avg_update(rq, irq_time);
-       }
+       delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
+       rq->clock += delta;
+       update_rq_clock_task(rq, delta);
 }
 
 /*
@@ -1924,10 +1920,9 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
  * They are read and saved off onto struct rq in update_rq_clock().
  * This may result in other CPU reading this CPU's irq time and can
  * race with irq/account_system_vtime on this CPU. We would either get old
- * or new value (or semi updated value on 32 bit) with a side effect of
- * accounting a slice of irq time to wrong task when irq is in progress
- * while we read rq->clock. That is a worthy compromise in place of having
- * locks on each irq in account_system_time.
+ * or new value with a side effect of accounting a slice of irq time to wrong
+ * task when irq is in progress while we read rq->clock. That is a worthy
+ * compromise in place of having locks on each irq in account_system_time.
  */
 static DEFINE_PER_CPU(u64, cpu_hardirq_time);
 static DEFINE_PER_CPU(u64, cpu_softirq_time);
@@ -1945,19 +1940,58 @@ void disable_sched_clock_irqtime(void)
        sched_clock_irqtime = 0;
 }
 
-static u64 irq_time_cpu(int cpu)
+#ifndef CONFIG_64BIT
+static DEFINE_PER_CPU(seqcount_t, irq_time_seq);
+
+static inline void irq_time_write_begin(void)
 {
-       if (!sched_clock_irqtime)
-               return 0;
+       __this_cpu_inc(irq_time_seq.sequence);
+       smp_wmb();
+}
+
+static inline void irq_time_write_end(void)
+{
+       smp_wmb();
+       __this_cpu_inc(irq_time_seq.sequence);
+}
+
+static inline u64 irq_time_read(int cpu)
+{
+       u64 irq_time;
+       unsigned seq;
 
+       do {
+               seq = read_seqcount_begin(&per_cpu(irq_time_seq, cpu));
+               irq_time = per_cpu(cpu_softirq_time, cpu) +
+                          per_cpu(cpu_hardirq_time, cpu);
+       } while (read_seqcount_retry(&per_cpu(irq_time_seq, cpu), seq));
+
+       return irq_time;
+}
+#else /* CONFIG_64BIT */
+static inline void irq_time_write_begin(void)
+{
+}
+
+static inline void irq_time_write_end(void)
+{
+}
+
+static inline u64 irq_time_read(int cpu)
+{
        return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu);
 }
+#endif /* CONFIG_64BIT */
 
+/*
+ * Called before incrementing preempt_count on {soft,}irq_enter
+ * and before decrementing preempt_count on {soft,}irq_exit.
+ */
 void account_system_vtime(struct task_struct *curr)
 {
        unsigned long flags;
+       s64 delta;
        int cpu;
-       u64 now, delta;
 
        if (!sched_clock_irqtime)
                return;
@@ -1965,9 +1999,10 @@ void account_system_vtime(struct task_struct *curr)
        local_irq_save(flags);
 
        cpu = smp_processor_id();
-       now = sched_clock_cpu(cpu);
-       delta = now - per_cpu(irq_start_time, cpu);
-       per_cpu(irq_start_time, cpu) = now;
+       delta = sched_clock_cpu(cpu) - __this_cpu_read(irq_start_time);
+       __this_cpu_add(irq_start_time, delta);
+
+       irq_time_write_begin();
        /*
         * We do not account for softirq time from ksoftirqd here.
         * We want to continue accounting softirq time to ksoftirqd thread
@@ -1975,33 +2010,55 @@ void account_system_vtime(struct task_struct *curr)
         * that do not consume any time, but still wants to run.
         */
        if (hardirq_count())
-               per_cpu(cpu_hardirq_time, cpu) += delta;
+               __this_cpu_add(cpu_hardirq_time, delta);
        else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD))
-               per_cpu(cpu_softirq_time, cpu) += delta;
+               __this_cpu_add(cpu_softirq_time, delta);
 
+       irq_time_write_end();
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(account_system_vtime);
 
-static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time)
+static void update_rq_clock_task(struct rq *rq, s64 delta)
 {
-       if (sched_clock_irqtime && sched_feat(NONIRQ_POWER)) {
-               u64 delta_irq = curr_irq_time - rq->prev_irq_time;
-               rq->prev_irq_time = curr_irq_time;
-               sched_rt_avg_update(rq, delta_irq);
-       }
+       s64 irq_delta;
+
+       irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
+
+       /*
+        * Since irq_time is only updated on {soft,}irq_exit, we might run into
+        * this case when a previous update_rq_clock() happened inside a
+        * {soft,}irq region.
+        *
+        * When this happens, we stop ->clock_task and only update the
+        * prev_irq_time stamp to account for the part that fit, so that a next
+        * update will consume the rest. This ensures ->clock_task is
+        * monotonic.
+        *
+        * It does however cause some slight miss-attribution of {soft,}irq
+        * time, a more accurate solution would be to update the irq_time using
+        * the current rq->clock timestamp, except that would require using
+        * atomic ops.
+        */
+       if (irq_delta > delta)
+               irq_delta = delta;
+
+       rq->prev_irq_time += irq_delta;
+       delta -= irq_delta;
+       rq->clock_task += delta;
+
+       if (irq_delta && sched_feat(NONIRQ_POWER))
+               sched_rt_avg_update(rq, irq_delta);
 }
 
-#else
+#else /* CONFIG_IRQ_TIME_ACCOUNTING */
 
-static u64 irq_time_cpu(int cpu)
+static void update_rq_clock_task(struct rq *rq, s64 delta)
 {
-       return 0;
+       rq->clock_task += delta;
 }
 
-static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { }
-
-#endif
+#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
 
 #include "sched_idletask.c"
 #include "sched_fair.c"
@@ -2129,7 +2186,7 @@ static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
         * A queue event has occurred, and we're going to schedule.  In
         * this case, we can save a useless back to back clock update.
         */
-       if (test_tsk_need_resched(rq->curr))
+       if (rq->curr->se.on_rq && test_tsk_need_resched(rq->curr))
                rq->skip_clock_update = 1;
 }
 
@@ -3119,6 +3176,15 @@ static long calc_load_fold_active(struct rq *this_rq)
        return delta;
 }
 
+static unsigned long
+calc_load(unsigned long load, unsigned long exp, unsigned long active)
+{
+       load *= exp;
+       load += active * (FIXED_1 - exp);
+       load += 1UL << (FSHIFT - 1);
+       return load >> FSHIFT;
+}
+
 #ifdef CONFIG_NO_HZ
 /*
  * For NO_HZ we delay the active fold to the next LOAD_FREQ update.
@@ -3148,6 +3214,128 @@ static long calc_load_fold_idle(void)
 
        return delta;
 }
+
+/**
+ * fixed_power_int - compute: x^n, in O(log n) time
+ *
+ * @x:         base of the power
+ * @frac_bits: fractional bits of @x
+ * @n:         power to raise @x to.
+ *
+ * By exploiting the relation between the definition of the natural power
+ * function: x^n := x*x*...*x (x multiplied by itself for n times), and
+ * the binary encoding of numbers used by computers: n := \Sum n_i * 2^i,
+ * (where: n_i \elem {0, 1}, the binary vector representing n),
+ * we find: x^n := x^(\Sum n_i * 2^i) := \Prod x^(n_i * 2^i), which is
+ * of course trivially computable in O(log_2 n), the length of our binary
+ * vector.
+ */
+static unsigned long
+fixed_power_int(unsigned long x, unsigned int frac_bits, unsigned int n)
+{
+       unsigned long result = 1UL << frac_bits;
+
+       if (n) for (;;) {
+               if (n & 1) {
+                       result *= x;
+                       result += 1UL << (frac_bits - 1);
+                       result >>= frac_bits;
+               }
+               n >>= 1;
+               if (!n)
+                       break;
+               x *= x;
+               x += 1UL << (frac_bits - 1);
+               x >>= frac_bits;
+       }
+
+       return result;
+}
+
+/*
+ * a1 = a0 * e + a * (1 - e)
+ *
+ * a2 = a1 * e + a * (1 - e)
+ *    = (a0 * e + a * (1 - e)) * e + a * (1 - e)
+ *    = a0 * e^2 + a * (1 - e) * (1 + e)
+ *
+ * a3 = a2 * e + a * (1 - e)
+ *    = (a0 * e^2 + a * (1 - e) * (1 + e)) * e + a * (1 - e)
+ *    = a0 * e^3 + a * (1 - e) * (1 + e + e^2)
+ *
+ *  ...
+ *
+ * an = a0 * e^n + a * (1 - e) * (1 + e + ... + e^n-1) [1]
+ *    = a0 * e^n + a * (1 - e) * (1 - e^n)/(1 - e)
+ *    = a0 * e^n + a * (1 - e^n)
+ *
+ * [1] application of the geometric series:
+ *
+ *              n         1 - x^(n+1)
+ *     S_n := \Sum x^i = -------------
+ *             i=0          1 - x
+ */
+static unsigned long
+calc_load_n(unsigned long load, unsigned long exp,
+           unsigned long active, unsigned int n)
+{
+
+       return calc_load(load, fixed_power_int(exp, FSHIFT, n), active);
+}
+
+/*
+ * NO_HZ can leave us missing all per-cpu ticks calling
+ * calc_load_account_active(), but since an idle CPU folds its delta into
+ * calc_load_tasks_idle per calc_load_account_idle(), all we need to do is fold
+ * in the pending idle delta if our idle period crossed a load cycle boundary.
+ *
+ * Once we've updated the global active value, we need to apply the exponential
+ * weights adjusted to the number of cycles missed.
+ */
+static void calc_global_nohz(unsigned long ticks)
+{
+       long delta, active, n;
+
+       if (time_before(jiffies, calc_load_update))
+               return;
+
+       /*
+        * If we crossed a calc_load_update boundary, make sure to fold
+        * any pending idle changes, the respective CPUs might have
+        * missed the tick driven calc_load_account_active() update
+        * due to NO_HZ.
+        */
+       delta = calc_load_fold_idle();
+       if (delta)
+               atomic_long_add(delta, &calc_load_tasks);
+
+       /*
+        * If we were idle for multiple load cycles, apply them.
+        */
+       if (ticks >= LOAD_FREQ) {
+               n = ticks / LOAD_FREQ;
+
+               active = atomic_long_read(&calc_load_tasks);
+               active = active > 0 ? active * FIXED_1 : 0;
+
+               avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n);
+               avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
+               avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
+
+               calc_load_update += n * LOAD_FREQ;
+       }
+
+       /*
+        * Its possible the remainder of the above division also crosses
+        * a LOAD_FREQ period, the regular check in calc_global_load()
+        * which comes after this will take care of that.
+        *
+        * Consider us being 11 ticks before a cycle completion, and us
+        * sleeping for 4*LOAD_FREQ + 22 ticks, then the above code will
+        * age us 4 cycles, and the test in calc_global_load() will
+        * pick up the final one.
+        */
+}
 #else
 static void calc_load_account_idle(struct rq *this_rq)
 {
@@ -3157,6 +3345,10 @@ static inline long calc_load_fold_idle(void)
 {
        return 0;
 }
+
+static void calc_global_nohz(unsigned long ticks)
+{
+}
 #endif
 
 /**
@@ -3174,24 +3366,17 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
        loads[2] = (avenrun[2] + offset) << shift;
 }
 
-static unsigned long
-calc_load(unsigned long load, unsigned long exp, unsigned long active)
-{
-       load *= exp;
-       load += active * (FIXED_1 - exp);
-       return load >> FSHIFT;
-}
-
 /*
  * calc_load - update the avenrun load estimates 10 ticks after the
  * CPUs have updated calc_load_tasks.
  */
-void calc_global_load(void)
+void calc_global_load(unsigned long ticks)
 {
-       unsigned long upd = calc_load_update + 10;
        long active;
 
-       if (time_before(jiffies, upd))
+       calc_global_nohz(ticks);
+
+       if (time_before(jiffies, calc_load_update + 10))
                return;
 
        active = atomic_long_read(&calc_load_tasks);
@@ -3845,7 +4030,6 @@ static void put_prev_task(struct rq *rq, struct task_struct *prev)
 {
        if (prev->se.on_rq)
                update_rq_clock(rq);
-       rq->skip_clock_update = 0;
        prev->sched_class->put_prev_task(rq, prev);
 }
 
@@ -3903,7 +4087,6 @@ need_resched_nonpreemptible:
                hrtick_clear(rq);
 
        raw_spin_lock_irq(&rq->lock);
-       clear_tsk_need_resched(prev);
 
        switch_count = &prev->nivcsw;
        if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
@@ -3935,6 +4118,8 @@ need_resched_nonpreemptible:
 
        put_prev_task(rq, prev);
        next = pick_next_task(rq);
+       clear_tsk_need_resched(prev);
+       rq->skip_clock_update = 0;
 
        if (likely(prev != next)) {
                sched_info_switch(prev, next);
index 68a9ae7679b717f6eb4782ce5114ad405dec5a4c..353b9227c2ecfe11793a17b0a41f534ebdbd14f8 100644 (file)
@@ -1252,6 +1252,12 @@ unsigned long get_next_timer_interrupt(unsigned long now)
        struct tvec_base *base = __get_cpu_var(tvec_bases);
        unsigned long expires;
 
+       /*
+        * Pretend that there is no timer pending if the cpu is offline.
+        * Possible pending timers will be migrated later to an active cpu.
+        */
+       if (cpu_is_offline(smp_processor_id()))
+               return now + NEXT_TIMER_MAX_DELTA;
        spin_lock(&base->lock);
        if (time_before_eq(base->next_timer, base->timer_jiffies))
                base->next_timer = __next_timer_interrupt(base);
@@ -1319,7 +1325,7 @@ void do_timer(unsigned long ticks)
 {
        jiffies_64 += ticks;
        update_wall_time();
-       calc_global_load();
+       calc_global_load(ticks);
 }
 
 #ifdef __ARCH_WANT_SYS_ALARM
index c380612273bf75d683ddebcf5e7863b30bece806..f8cf959bad456dead3a5dec2fdd1a21e384f22bb 100644 (file)
@@ -2338,11 +2338,19 @@ tracing_write_stub(struct file *filp, const char __user *ubuf,
        return count;
 }
 
+static loff_t tracing_seek(struct file *file, loff_t offset, int origin)
+{
+       if (file->f_mode & FMODE_READ)
+               return seq_lseek(file, offset, origin);
+       else
+               return 0;
+}
+
 static const struct file_operations tracing_fops = {
        .open           = tracing_open,
        .read           = seq_read,
        .write          = tracing_write_stub,
-       .llseek         = seq_lseek,
+       .llseek         = tracing_seek,
        .release        = tracing_release,
 };
 
index 1c7a2ec4f3cc81ee608821ddf589fc0b27db4dcc..b6ff4a1519ab664c43d9bff871dc95d8efb52daa 100644 (file)
@@ -97,11 +97,9 @@ struct workqueue_struct *ceph_msgr_wq;
 int ceph_msgr_init(void)
 {
        ceph_msgr_wq = create_workqueue("ceph-msgr");
-       if (IS_ERR(ceph_msgr_wq)) {
-               int ret = PTR_ERR(ceph_msgr_wq);
-               pr_err("msgr_init failed to create workqueue: %d\n", ret);
-               ceph_msgr_wq = NULL;
-               return ret;
+       if (!ceph_msgr_wq) {
+               pr_err("msgr_init failed to create workqueue\n");
+               return -ENOMEM;
        }
        return 0;
 }
index ac34feeb2b3ab2202e02aeab2a0367f29ac6a2b2..1a040e64c69f23545f98e282bae934b3ed33baa9 100644 (file)
@@ -13,7 +13,7 @@
  * build a vector of user pages
  */
 struct page **ceph_get_direct_page_vector(const char __user *data,
-                                         int num_pages)
+                                         int num_pages, bool write_page)
 {
        struct page **pages;
        int rc;
@@ -24,24 +24,27 @@ struct page **ceph_get_direct_page_vector(const char __user *data,
 
        down_read(&current->mm->mmap_sem);
        rc = get_user_pages(current, current->mm, (unsigned long)data,
-                           num_pages, 0, 0, pages, NULL);
+                           num_pages, write_page, 0, pages, NULL);
        up_read(&current->mm->mmap_sem);
-       if (rc < 0)
+       if (rc < num_pages)
                goto fail;
        return pages;
 
 fail:
-       kfree(pages);
+       ceph_put_page_vector(pages, rc > 0 ? rc : 0, false);
        return ERR_PTR(rc);
 }
 EXPORT_SYMBOL(ceph_get_direct_page_vector);
 
-void ceph_put_page_vector(struct page **pages, int num_pages)
+void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty)
 {
        int i;
 
-       for (i = 0; i < num_pages; i++)
+       for (i = 0; i < num_pages; i++) {
+               if (dirty)
+                       set_page_dirty_lock(pages[i]);
                put_page(pages[i]);
+       }
        kfree(pages);
 }
 EXPORT_SYMBOL(ceph_put_page_vector);
index 58e933a20544a2cd379446661d01f3755494bf97..39667174971d1eb86105edd927aa92d39c0954bf 100644 (file)
@@ -119,7 +119,7 @@ static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;
 
 static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
 {
-       rp->r_info = ELF_R_INFO(sym, type);
+       rp->r_info = _w(ELF_R_INFO(sym, type));
 }
 static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
 
index 8509bb51293530fae488f60594199031cd16bf07..bbbe584d44943077a41b22684b5ecdbce18f532a 100755 (executable)
@@ -125,7 +125,9 @@ exuberant()
        -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \
        --extra=+f --c-kinds=-px                                \
        --regex-asm='/^ENTRY\(([^)]*)\).*/\1/'                  \
-       --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/'
+       --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \
+       --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/'               \
+       --regex-c++='/^DEFINE_EVENT\(([^,)]*).*/trace_\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --langdef=kconfig --language-force=kconfig              \
index 2d7d7de8498a7947bb9c6180bc757017535c343c..427da45d7906560f517e04de74c84ab971c0a50a 100644 (file)
@@ -10830,7 +10830,8 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i, err;
+       int i, err, type;
+       int type_idx = 0;
        hda_nid_t nid;
 
        for (i = 0; i < cfg->num_inputs; i++) {
@@ -10839,9 +10840,15 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
                nid = cfg->inputs[i].pin;
                if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
                        char label[32];
+                       type = cfg->inputs[i].type;
+                       if (i > 0 && type == cfg->inputs[i - 1].type)
+                               type_idx++;
+                       else
+                               type_idx = 0;
                        snprintf(label, sizeof(label), "%s Boost",
                                 hda_get_autocfg_input_label(codec, cfg, i));
-                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0,
+                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label,
+                                         type_idx,
                                  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
                        if (err < 0)
                                return err;
@@ -14800,6 +14807,8 @@ static int alc269_resume(struct hda_codec *codec)
 enum {
        ALC269_FIXUP_SONY_VAIO,
        ALC269_FIXUP_DELL_M101Z,
+       ALC269_FIXUP_LENOVO_EDGE14,
+       ALC269_FIXUP_ASUS_G73JW,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -14817,11 +14826,22 @@ static const struct alc_fixup alc269_fixups[] = {
                        {}
                }
        },
+       [ALC269_FIXUP_LENOVO_EDGE14] = {
+               .sku = ALC_FIXUP_SKU_IGNORE,
+       },
+       [ALC269_FIXUP_ASUS_G73JW] = {
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x17, 0x99130111 }, /* subwoofer */
+                       { }
+               }
+       },
 };
 
 static struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_LENOVO_EDGE14),
+       SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        {}
 };
 
index 879dff2714dd3c522211dbac3c636a5191d8ce4b..8725d4e754310d86774935b48e1a2443fe04405c 100644 (file)
 static const u16 wm8580_reg[] = {
        0x0121, 0x017e, 0x007d, 0x0014, /*R3*/
        0x0121, 0x017e, 0x007d, 0x0194, /*R7*/
-       0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/
+       0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/
        0x0182, 0x0082, 0x000a, 0x0024, /*R15*/
        0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/
        0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/
index fca60a0b57b83a807a946b86576093237b090f1f..9001cc48ba1371596c890ce12465e314d9022a81 100644 (file)
@@ -818,7 +818,8 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8904->deemph;
+       ucontrol->value.enumerated.item[0] = wm8904->deemph;
+       return 0;
 }
 
 static int wm8904_put_deemph(struct snd_kcontrol *kcontrol,
index f89ad6c9a80b9162e7040ea6fe76b434c9f743f1..9cbab8e1de0149cd8b2063406ecbae29ca0c78e5 100644 (file)
@@ -380,7 +380,8 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8955->deemph;
+       ucontrol->value.enumerated.item[0] = wm8955->deemph;
+       return 0;
 }
 
 static int wm8955_put_deemph(struct snd_kcontrol *kcontrol,
index 8d5efb333c33f260b271af07e9352b14679f0502..21986c42272f07ac693cd21d15f48cff20c43352 100644 (file)
@@ -138,7 +138,8 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8960->deemph;
+       ucontrol->value.enumerated.item[0] = wm8960->deemph;
+       return 0;
 }
 
 static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
index 75ed6491222d1d283d69d5881560a823c958d253..c721502833bcbf424855c87bcf1fddf2805bbafe 100644 (file)
@@ -944,6 +944,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
                case SND_SOC_DAPM_STREAM_RESUME:
                        sys_power = 1;
                        break;
+               case SND_SOC_DAPM_STREAM_STOP:
+                       sys_power = !!codec->active;
+                       break;
                case SND_SOC_DAPM_STREAM_SUSPEND:
                        sys_power = 0;
                        break;