From 362f391e074d84a141843ea11e84db04e617f98e Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 9 Dec 2010 09:13:46 -0600 Subject: [PATCH] --- yaml --- r: 226571 b: refs/heads/master c: fd1478cd61624479c89e35602925459d74505ff3 h: refs/heads/master i: 226569: c6d53d218ff141aeb9e4467c3f6cf615904b6266 226567: 6436234ce770d447b707896c936d397ad96cba08 v: v3 --- [refs] | 2 +- trunk/Documentation/arm/OMAP/omap_pm | 25 + trunk/Documentation/kernel-parameters.txt | 5 + trunk/Documentation/power/runtime_pm.txt | 4 +- trunk/Makefile | 2 +- trunk/arch/arm/mach-at91/Makefile | 2 +- trunk/arch/arm/mach-at91/board-pcontrol-g20.c | 98 ++- trunk/arch/arm/mach-at91/board-stamp9g20.c | 82 +- trunk/arch/arm/mach-at91/clock.c | 2 +- .../arm/mach-at91/include/mach/stamp9g20.h | 7 - trunk/arch/arm/mach-omap1/Makefile | 2 +- trunk/arch/arm/mach-omap1/dma.c | 390 -------- trunk/arch/arm/mach-omap2/Kconfig | 2 + trunk/arch/arm/mach-omap2/Makefile | 8 +- trunk/arch/arm/mach-omap2/control.c | 22 +- trunk/arch/arm/mach-omap2/control.h | 9 +- trunk/arch/arm/mach-omap2/cpuidle34xx.c | 36 +- trunk/arch/arm/mach-omap2/dma.c | 297 ------- .../arm/mach-omap2/omap_hwmod_2420_data.c | 86 -- .../arm/mach-omap2/omap_hwmod_2430_data.c | 86 -- .../arm/mach-omap2/omap_hwmod_3xxx_data.c | 97 -- .../arm/mach-omap2/omap_hwmod_44xx_data.c | 102 --- trunk/arch/arm/mach-omap2/omap_opp_data.h | 72 ++ trunk/arch/arm/mach-omap2/opp.c | 93 ++ trunk/arch/arm/mach-omap2/opp3xxx_data.c | 107 +++ trunk/arch/arm/mach-omap2/pm.c | 2 +- trunk/arch/arm/mach-omap2/pm.h | 24 +- trunk/arch/arm/mach-omap2/pm24xx.c | 16 +- trunk/arch/arm/mach-omap2/pm34xx.c | 66 +- trunk/arch/arm/mach-omap2/pm44xx.c | 16 +- trunk/arch/arm/mach-omap2/sdrc.h | 1 + trunk/arch/arm/mach-omap2/sleep34xx.S | 832 ++++++++---------- trunk/arch/arm/mach-s3c2412/Kconfig | 7 - trunk/arch/arm/mach-s3c2412/Makefile | 3 +- trunk/arch/arm/mach-s3c2416/Kconfig | 1 - trunk/arch/arm/mach-s5pv210/mach-aquila.c | 6 - trunk/arch/arm/mach-s5pv210/mach-goni.c | 6 - .../mach-shmobile/include/mach/entry-macro.S | 30 +- .../arm/mach-shmobile/include/mach/vmalloc.h | 2 +- trunk/arch/arm/plat-omap/dma.c | 697 +++++++++------ trunk/arch/arm/plat-omap/include/plat/dma.h | 232 ++--- trunk/arch/arm/plat-omap/include/plat/sram.h | 11 - trunk/arch/arm/plat-omap/sram.c | 7 +- trunk/arch/arm/plat-s3c24xx/Kconfig | 2 +- trunk/arch/mips/Kconfig | 38 +- trunk/arch/mips/alchemy/common/platform.c | 2 - trunk/arch/mips/alchemy/devboards/prom.c | 5 +- trunk/arch/mips/ar7/clock.c | 9 +- trunk/arch/mips/ar7/time.c | 3 - trunk/arch/mips/bcm47xx/setup.c | 153 +--- trunk/arch/mips/include/asm/cpu.h | 4 +- trunk/arch/mips/include/asm/elf.h | 8 +- trunk/arch/mips/include/asm/io.h | 12 +- trunk/arch/mips/include/asm/mach-ar7/ar7.h | 3 +- .../mips/include/asm/mach-bcm47xx/nvram.h | 7 - trunk/arch/mips/jz4740/board-qi_lb60.c | 4 +- trunk/arch/mips/jz4740/platform.c | 2 +- trunk/arch/mips/jz4740/prom.c | 2 +- trunk/arch/mips/kernel/cevt-r4k.c | 2 +- trunk/arch/mips/kernel/cpu-probe.c | 7 +- trunk/arch/mips/kernel/linux32.c | 13 +- trunk/arch/mips/kernel/process.c | 1 + trunk/arch/mips/kernel/prom.c | 2 +- trunk/arch/mips/kernel/smp-mt.c | 2 +- trunk/arch/mips/kernel/traps.c | 44 +- trunk/arch/mips/kernel/vpe.c | 14 +- trunk/arch/mips/lib/memset.S | 4 +- trunk/arch/mips/loongson/common/env.c | 4 +- trunk/arch/mips/math-emu/cp1emu.c | 116 +-- trunk/arch/mips/mm/dma-default.c | 4 +- trunk/arch/mips/mm/sc-mips.c | 4 - .../mips/pmc-sierra/yosemite/py-console.c | 12 +- trunk/arch/mips/sibyte/swarm/setup.c | 8 +- trunk/arch/mn10300/kernel/time.c | 10 +- trunk/arch/tile/include/asm/signal.h | 2 +- trunk/arch/tile/kernel/compat_signal.c | 6 +- trunk/arch/tile/kernel/intvec_32.S | 24 +- trunk/arch/tile/kernel/process.c | 8 - trunk/arch/tile/kernel/signal.c | 10 +- trunk/arch/x86/boot/compressed/misc.c | 2 +- trunk/arch/x86/include/asm/e820.h | 3 - trunk/arch/x86/include/asm/kvm_host.h | 2 +- trunk/arch/x86/kernel/Makefile | 1 - trunk/arch/x86/kernel/apic/apic.c | 8 - trunk/arch/x86/kernel/apic/io_apic.c | 4 +- trunk/arch/x86/kernel/apic/probe_64.c | 7 + trunk/arch/x86/kernel/head_32.S | 16 +- trunk/arch/x86/kernel/hpet.c | 26 +- trunk/arch/x86/kernel/resource.c | 48 - trunk/arch/x86/kernel/setup.c | 1 + trunk/arch/x86/kernel/xsave.c | 3 +- trunk/arch/x86/kvm/svm.c | 4 - trunk/arch/x86/kvm/vmx.c | 5 + trunk/arch/x86/kvm/x86.c | 11 +- trunk/arch/x86/kvm/x86.h | 5 - trunk/arch/x86/lguest/boot.c | 16 +- trunk/arch/x86/lguest/i386_head.S | 105 --- trunk/arch/x86/pci/i386.c | 18 +- trunk/arch/x86/vdso/Makefile | 4 +- trunk/block/blk-map.c | 5 +- trunk/block/blk-merge.c | 6 +- trunk/block/blk-settings.c | 51 +- trunk/block/blk-sysfs.c | 2 +- trunk/block/blk-throttle.c | 39 +- trunk/drivers/block/cciss.c | 2 - trunk/drivers/block/drbd/drbd_receiver.c | 14 +- trunk/drivers/block/drbd/drbd_req.h | 3 +- trunk/drivers/block/drbd/drbd_worker.c | 10 +- trunk/drivers/clocksource/sh_cmt.c | 17 +- trunk/drivers/input/evdev.c | 113 ++- trunk/drivers/input/tablet/wacom_wac.c | 3 - trunk/drivers/md/dm-table.c | 10 +- trunk/drivers/md/md.c | 3 + trunk/drivers/media/common/saa7146_hlp.c | 8 +- trunk/drivers/media/common/saa7146_video.c | 16 +- trunk/drivers/media/radio/radio-aimslab.c | 16 +- trunk/drivers/media/radio/radio-aztech.c | 6 +- trunk/drivers/media/radio/radio-cadet.c | 12 +- trunk/drivers/media/radio/radio-gemtek-pci.c | 6 +- trunk/drivers/media/radio/radio-gemtek.c | 14 +- trunk/drivers/media/radio/radio-maestro.c | 14 +- trunk/drivers/media/radio/radio-maxiradio.c | 2 +- trunk/drivers/media/radio/radio-miropcm20.c | 6 +- trunk/drivers/media/radio/radio-rtrack2.c | 10 +- trunk/drivers/media/radio/radio-sf16fmi.c | 7 +- trunk/drivers/media/radio/radio-sf16fmr2.c | 11 +- trunk/drivers/media/radio/radio-si4713.c | 3 +- trunk/drivers/media/radio/radio-tea5764.c | 49 +- trunk/drivers/media/radio/radio-terratec.c | 8 +- trunk/drivers/media/radio/radio-timb.c | 5 +- trunk/drivers/media/radio/radio-trust.c | 18 +- trunk/drivers/media/radio/radio-typhoon.c | 16 +- trunk/drivers/media/radio/radio-zoltrix.c | 30 +- trunk/drivers/media/video/arv.c | 2 +- trunk/drivers/media/video/bt8xx/bttv-driver.c | 117 ++- trunk/drivers/media/video/bw-qcam.c | 2 +- trunk/drivers/media/video/c-qcam.c | 2 +- trunk/drivers/media/video/cafe_ccic.c | 2 +- .../drivers/media/video/cx18/cx18-alsa-pcm.c | 8 +- trunk/drivers/media/video/cx18/cx18-streams.c | 2 +- .../media/video/et61x251/et61x251_core.c | 2 +- trunk/drivers/media/video/gspca/sonixj.c | 416 +++++---- trunk/drivers/media/video/meye.c | 14 +- trunk/drivers/media/video/pms.c | 2 +- trunk/drivers/media/video/sh_vou.c | 13 +- .../media/video/sn9c102/sn9c102_core.c | 2 +- trunk/drivers/media/video/uvc/uvc_ctrl.c | 48 +- trunk/drivers/media/video/uvc/uvc_queue.c | 133 +-- trunk/drivers/media/video/uvc/uvc_v4l2.c | 185 ++-- trunk/drivers/media/video/uvc/uvc_video.c | 3 + trunk/drivers/media/video/uvc/uvcvideo.h | 10 +- trunk/drivers/media/video/v4l2-dev.c | 69 +- trunk/drivers/media/video/v4l2-device.c | 1 - trunk/drivers/media/video/w9966.c | 2 +- trunk/drivers/pci/bus.c | 81 +- trunk/drivers/pci/dmar.c | 5 - trunk/drivers/pci/quirks.c | 26 - trunk/drivers/scsi/scsi_lib.c | 3 +- trunk/drivers/staging/cx25821/cx25821-video.c | 8 +- trunk/drivers/staging/cx25821/cx25821-video.h | 2 +- trunk/drivers/tty/n_gsm.c | 6 +- trunk/drivers/usb/core/Kconfig | 12 +- trunk/drivers/usb/gadget/composite.c | 18 +- trunk/drivers/usb/host/xhci-mem.c | 25 +- trunk/drivers/usb/misc/uss720.c | 4 +- trunk/drivers/usb/serial/ftdi_sio.c | 1 - trunk/drivers/usb/serial/ftdi_sio_ids.h | 5 - trunk/drivers/usb/storage/unusual_devs.h | 7 - trunk/drivers/video/omap/Kconfig | 4 +- trunk/drivers/video/omap2/vram.c | 4 +- trunk/fs/btrfs/export.c | 2 +- trunk/fs/ceph/dir.c | 3 +- trunk/fs/ceph/file.c | 39 +- trunk/fs/namei.c | 3 - trunk/fs/nilfs2/gcinode.c | 9 + trunk/fs/nilfs2/ioctl.c | 12 - trunk/fs/notify/fanotify/fanotify.c | 6 +- trunk/fs/notify/fanotify/fanotify_user.c | 81 +- trunk/fs/notify/inotify/inotify_user.c | 1 - trunk/include/linux/blkdev.h | 10 +- trunk/include/linux/bootmem.h | 2 - trunk/include/linux/ceph/libceph.h | 6 +- trunk/include/linux/cnt32_to_63.h | 20 +- trunk/include/linux/fanotify.h | 10 +- trunk/include/linux/fsnotify.h | 3 + trunk/include/linux/fsnotify_backend.h | 2 +- trunk/include/linux/input.h | 6 +- trunk/include/linux/ioport.h | 2 +- trunk/include/linux/perf_event.h | 1 - trunk/include/linux/pm_runtime.h | 3 +- trunk/include/linux/sched.h | 2 +- trunk/include/linux/ssb/ssb_driver_gige.h | 17 +- trunk/include/media/saa7146.h | 2 +- trunk/include/media/v4l2-device.h | 2 - trunk/kernel/fork.c | 1 - trunk/kernel/perf_event.c | 37 +- trunk/kernel/power/swap.c | 2 +- trunk/kernel/power/user.c | 2 +- trunk/kernel/resource.c | 104 ++- trunk/kernel/sched.c | 287 ++---- trunk/kernel/timer.c | 8 +- trunk/kernel/trace/trace.c | 10 +- trunk/net/ceph/messenger.c | 8 +- trunk/net/ceph/pagevec.c | 15 +- trunk/scripts/recordmcount.h | 2 +- trunk/scripts/tags.sh | 4 +- trunk/sound/pci/hda/patch_realtek.c | 24 +- trunk/sound/soc/codecs/wm8580.c | 2 +- trunk/sound/soc/codecs/wm8904.c | 3 +- trunk/sound/soc/codecs/wm8955.c | 3 +- trunk/sound/soc/codecs/wm8960.c | 3 +- trunk/sound/soc/soc-dapm.c | 3 - 212 files changed, 2852 insertions(+), 4128 deletions(-) delete mode 100644 trunk/arch/arm/mach-at91/include/mach/stamp9g20.h delete mode 100644 trunk/arch/arm/mach-omap1/dma.c delete mode 100644 trunk/arch/arm/mach-omap2/dma.c create mode 100644 trunk/arch/arm/mach-omap2/omap_opp_data.h create mode 100644 trunk/arch/arm/mach-omap2/opp.c create mode 100644 trunk/arch/arm/mach-omap2/opp3xxx_data.c delete mode 100644 trunk/arch/x86/kernel/resource.c diff --git a/[refs] b/[refs] index e82f15eeb686..0336da46ea4a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: bb3613aa34a81a5e2f1227ccdb801fde04a7da10 +refs/heads/master: fd1478cd61624479c89e35602925459d74505ff3 diff --git a/trunk/Documentation/arm/OMAP/omap_pm b/trunk/Documentation/arm/OMAP/omap_pm index 5389440aade3..9012bb039094 100644 --- a/trunk/Documentation/arm/OMAP/omap_pm +++ b/trunk/Documentation/arm/OMAP/omap_pm @@ -127,3 +127,28 @@ implementation needs: 10. (*pdata->cpu_set_freq)(unsigned long f) 11. (*pdata->cpu_get_freq)(void) + +Customizing OPP for platform +============================ +Defining CONFIG_PM should enable OPP layer for the silicon +and the registration of OPP table should take place automatically. +However, in special cases, the default OPP table may need to be +tweaked, for e.g.: + * enable default OPPs which are disabled by default, but which + could be enabled on a platform + * Disable an unsupported OPP on the platform + * Define and add a custom opp table entry +in these cases, the board file needs to do additional steps as follows: +arch/arm/mach-omapx/board-xyz.c + #include "pm.h" + .... + static void __init omap_xyz_init_irq(void) + { + .... + /* Initialize the default table */ + omapx_opp_init(); + /* Do customization to the defaults */ + .... + } +NOTE: omapx_opp_init will be omap3_opp_init or as required +based on the omap family. diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 8b61c9360999..cdd2a6e8a3b7 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -2175,6 +2175,11 @@ 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 diff --git a/trunk/Documentation/power/runtime_pm.txt b/trunk/Documentation/power/runtime_pm.txt index 41cc7b30d7dd..489e9bacd165 100644 --- a/trunk/Documentation/power/runtime_pm.txt +++ b/trunk/Documentation/power/runtime_pm.txt @@ -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' and its - 'power.disable_depth' field is equal to zero, or false otherwise + - return true if the device's runtime PM status is 'suspended', or false + otherwise void pm_runtime_allow(struct device *dev); - set the power.runtime_auto flag for the device and decrease its usage diff --git a/trunk/Makefile b/trunk/Makefile index 77044b7918a5..5aa44278d956 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 37 -EXTRAVERSION = -rc7 +EXTRAVERSION = -rc6 NAME = Flesh-Eating Bats with Fangs # *DOCUMENTATION* diff --git a/trunk/arch/arm/mach-at91/Makefile b/trunk/arch/arm/mach-at91/Makefile index d13add71f72a..62d686f0b426 100644 --- a/trunk/arch/arm/mach-at91/Makefile +++ b/trunk/arch/arm/mach-at91/Makefile @@ -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 board-stamp9g20.o +obj-$(CONFIG_MACH_PCONTROL_G20) += board-pcontrol-g20.o # AT91SAM9260/AT91SAM9G20 board-specific support obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o diff --git a/trunk/arch/arm/mach-at91/board-pcontrol-g20.c b/trunk/arch/arm/mach-at91/board-pcontrol-g20.c index feb65787c30b..bba5a560e02b 100644 --- a/trunk/arch/arm/mach-at91/board-pcontrol-g20.c +++ b/trunk/arch/arm/mach-at91/board-pcontrol-g20.c @@ -31,7 +31,6 @@ #include #include -#include #include "sam9_smc.h" #include "generic.h" @@ -39,7 +38,11 @@ static void __init pcontrol_g20_map_io(void) { - stamp9g20_map_io(); + /* 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); /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback A2 */ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS @@ -51,6 +54,9 @@ 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); } @@ -60,6 +66,38 @@ 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, @@ -100,6 +138,14 @@ 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 ) */ @@ -109,6 +155,23 @@ 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 */ @@ -202,13 +265,42 @@ 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) { - stamp9g20_board_init(); + 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 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)); diff --git a/trunk/arch/arm/mach-at91/board-stamp9g20.c b/trunk/arch/arm/mach-at91/board-stamp9g20.c index f8902b118960..5206eef4a67e 100644 --- a/trunk/arch/arm/mach-at91/board-stamp9g20.c +++ b/trunk/arch/arm/mach-at91/board-stamp9g20.c @@ -32,7 +32,7 @@ #include "generic.h" -void __init stamp9g20_map_io(void) +static void __init portuxg20_map_io(void) { /* Initialize processor: 18.432 MHz crystal */ at91sam9260_initialize(18432000); @@ -40,24 +40,6 @@ void __init stamp9g20_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 @@ -74,6 +56,26 @@ 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) @@ -154,7 +156,7 @@ static struct at91_udc_data __initdata portuxg20_udc_data = { .pullup_pin = 0, /* pull-up driven by UDC */ }; -static struct at91_udc_data __initdata stamp9g20evb_udc_data = { +static struct at91_udc_data __initdata stamp9g20_udc_data = { .vbus_pin = AT91_PIN_PA22, .pullup_pin = 0, /* pull-up driven by UDC */ }; @@ -188,7 +190,7 @@ static struct gpio_led portuxg20_leds[] = { } }; -static struct gpio_led stamp9g20evb_leds[] = { +static struct gpio_led stamp9g20_leds[] = { { .name = "D8", .gpio = AT91_PIN_PB18, @@ -248,7 +250,7 @@ void add_w1(void) } -void __init stamp9g20_board_init(void) +static void __init generic_board_init(void) { /* Serial */ at91_add_device_serial(); @@ -260,40 +262,34 @@ void __init stamp9g20_board_init(void) #else at91_add_device_mmc(0, &mmc_data); #endif - /* W1 */ - add_w1(); -} - -static void __init portuxg20_board_init(void) -{ - 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); + /* 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)); + /* USB Device */ + at91_add_device_udc(&portuxg20_udc_data); /* LEDs */ at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds)); } -static void __init stamp9g20evb_board_init(void) +static void __init stamp9g20_board_init(void) { - stamp9g20_board_init(); - /* USB Host */ - at91_add_device_usbh(&usbh_data); + generic_board_init(); /* USB Device */ - at91_add_device_udc(&stamp9g20evb_udc_data); - /* Ethernet */ - at91_add_device_eth(&macb_data); - /* I2C */ - at91_add_device_i2c(NULL, 0); + at91_add_device_udc(&stamp9g20_udc_data); /* LEDs */ - at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds)); + at91_gpio_leds(stamp9g20_leds, ARRAY_SIZE(stamp9g20_leds)); } MACHINE_START(PORTUXG20, "taskit PortuxG20") @@ -309,7 +305,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20") /* Maintainer: taskit GmbH */ .boot_params = AT91_SDRAM_BASE + 0x100, .timer = &at91sam926x_timer, - .map_io = stamp9g20evb_map_io, + .map_io = stamp9g20_map_io, .init_irq = init_irq, - .init_machine = stamp9g20evb_board_init, + .init_machine = stamp9g20_board_init, MACHINE_END diff --git a/trunk/arch/arm/mach-at91/clock.c b/trunk/arch/arm/mach-at91/clock.c index 9113da6845f1..7525cee3983f 100644 --- a/trunk/arch/arm/mach-at91/clock.c +++ b/trunk/arch/arm/mach-at91/clock.c @@ -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.rate_hz; + uhpck.rate_hz = utmi_clk.parent->rate_hz; uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8); } diff --git a/trunk/arch/arm/mach-at91/include/mach/stamp9g20.h b/trunk/arch/arm/mach-at91/include/mach/stamp9g20.h deleted file mode 100644 index 6120f9c46d59..000000000000 --- a/trunk/arch/arm/mach-at91/include/mach/stamp9g20.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __MACH_STAMP9G20_H -#define __MACH_STAMP9G20_H - -void stamp9g20_map_io(void); -void stamp9g20_board_init(void); - -#endif diff --git a/trunk/arch/arm/mach-omap1/Makefile b/trunk/arch/arm/mach-omap1/Makefile index 6ee19504845f..0b1c07ffa2f1 100644 --- a/trunk/arch/arm/mach-omap1/Makefile +++ b/trunk/arch/arm/mach-omap1/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o dma.o +obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o obj-y += clock.o clock_data.o opp_data.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o diff --git a/trunk/arch/arm/mach-omap1/dma.c b/trunk/arch/arm/mach-omap1/dma.c deleted file mode 100644 index d8559344c6e2..000000000000 --- a/trunk/arch/arm/mach-omap1/dma.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * OMAP1/OMAP7xx - specific DMA driver - * - * Copyright (C) 2003 - 2008 Nokia Corporation - * Author: Juha Yrjölä - * DMA channel linking for 1610 by Samuel Ortiz - * Graphics DMA and LCD DMA graphics tranformations - * by Imre Deak - * 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 - * - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include - -#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); diff --git a/trunk/arch/arm/mach-omap2/Kconfig b/trunk/arch/arm/mach-omap2/Kconfig index 92b004ba5a10..e752cb397ba7 100644 --- a/trunk/arch/arm/mach-omap2/Kconfig +++ b/trunk/arch/arm/mach-omap2/Kconfig @@ -35,6 +35,8 @@ config ARCH_OMAP3 select CPU_V7 select USB_ARCH_HAS_EHCI select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4 + select ARCH_HAS_OPP + select PM_OPP if PM config ARCH_OMAP4 bool "TI OMAP4" diff --git a/trunk/arch/arm/mach-omap2/Makefile b/trunk/arch/arm/mach-omap2/Makefile index cdfb5faaec9d..fa16806092e5 100644 --- a/trunk/arch/arm/mach-omap2/Makefile +++ b/trunk/arch/arm/mach-omap2/Makefile @@ -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 dma.o + common.o gpio.o omap-2-3-common = irq.o sdrc.o prm2xxx_3xxx.o hwmod-common = omap_hwmod.o \ @@ -49,6 +49,12 @@ obj-$(CONFIG_ARCH_OMAP4) += mux44xx.o obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o # obj-$(CONFIG_ARCH_OMAP3) += sdrc3xxx.o +# OPP table initialization +ifeq ($(CONFIG_PM_OPP),y) +obj-y += opp.o +obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o +endif + # Power Management ifeq ($(CONFIG_PM),y) obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o diff --git a/trunk/arch/arm/mach-omap2/control.c b/trunk/arch/arm/mach-omap2/control.c index 0269bb055b69..1fa3294b6048 100644 --- a/trunk/arch/arm/mach-omap2/control.c +++ b/trunk/arch/arm/mach-omap2/control.c @@ -239,19 +239,9 @@ 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 - * - * 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. - */ + /* Populate the Scratchpad contents */ scratchpad_contents.boot_config_ptr = 0x0; - if (cpu_is_omap3630()) - scratchpad_contents.public_restore_ptr = - virt_to_phys(get_omap3630_restore_pointer()); - else if (omap_rev() != OMAP3430_REV_ES3_0 && + if (omap_rev() != OMAP3430_REV_ES3_0 && omap_rev() != OMAP3430_REV_ES3_1) scratchpad_contents.public_restore_ptr = virt_to_phys(get_restore_pointer()); @@ -484,12 +474,4 @@ 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 */ diff --git a/trunk/arch/arm/mach-omap2/control.h b/trunk/arch/arm/mach-omap2/control.h index 6e5f7e512ff7..b6c6b7c450b3 100644 --- a/trunk/arch/arm/mach-omap2/control.h +++ b/trunk/arch/arm/mach-omap2/control.h @@ -204,10 +204,6 @@ #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 @@ -274,8 +270,6 @@ #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 @@ -353,11 +347,10 @@ 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 diff --git a/trunk/arch/arm/mach-omap2/cpuidle34xx.c b/trunk/arch/arm/mach-omap2/cpuidle34xx.c index 0fb619c52588..0d50b45d041c 100644 --- a/trunk/arch/arm/mach-omap2/cpuidle34xx.c +++ b/trunk/arch/arm/mach-omap2/cpuidle34xx.c @@ -293,26 +293,25 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); /** - * 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 + * omap3_cpuidle_update_states - Update the cpuidle states. * - * 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 + * 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. */ -void omap3_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state) +void omap3_cpuidle_update_states(void) { int i; for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { struct omap3_processor_cx *cx = &omap3_power_states[i]; - if ((cx->mpu_state >= mpu_deepest_state) && - (cx->core_state >= core_deepest_state)) { + if (enable_off_mode) { cx->valid = 1; } else { - cx->valid = 0; + if ((cx->mpu_state == PWRDM_POWER_OFF) || + (cx->core_state == PWRDM_POWER_OFF)) + cx->valid = 0; } } } @@ -453,18 +452,6 @@ 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 = { @@ -517,10 +504,7 @@ int __init omap3_idle_init(void) return -EINVAL; dev->state_count = count; - 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); + omap3_cpuidle_update_states(); if (cpuidle_register_device(dev)) { printk(KERN_ERR "%s: CPUidle register device failed\n", diff --git a/trunk/arch/arm/mach-omap2/dma.c b/trunk/arch/arm/mach-omap2/dma.c deleted file mode 100644 index d2f15f5cfd36..000000000000 --- a/trunk/arch/arm/mach-omap2/dma.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * OMAP2+ DMA driver - * - * Copyright (C) 2003 - 2008 Nokia Corporation - * Author: Juha Yrjölä - * DMA channel linking for 1610 by Samuel Ortiz - * Graphics DMA and LCD DMA graphics tranformations - * by Imre Deak - * 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 - * - * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ - * Converted DMA library into platform driver - * - G, Manjunath Kondaiah - * - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include - -#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); diff --git a/trunk/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/trunk/arch/arm/mach-omap2/omap_hwmod_2420_data.c index 42606f6b0cdf..d95342599793 100644 --- a/trunk/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/trunk/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -42,7 +42,6 @@ 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 = { @@ -780,88 +779,6 @@ 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, @@ -880,9 +797,6 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = { &omap2420_gpio2_hwmod, &omap2420_gpio3_hwmod, &omap2420_gpio4_hwmod, - - /* dma_system class*/ - &omap2420_dma_system_hwmod, NULL, }; diff --git a/trunk/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/trunk/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 3315d241feef..ab1d662cb072 100644 --- a/trunk/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/trunk/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -43,7 +43,6 @@ 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 = { @@ -839,88 +838,6 @@ 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, @@ -940,9 +857,6 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = { &omap2430_gpio3_hwmod, &omap2430_gpio4_hwmod, &omap2430_gpio5_hwmod, - - /* dma_system class*/ - &omap2430_dma_system_hwmod, NULL, }; diff --git a/trunk/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/trunk/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index d5acb63ba9e0..2687be10d7aa 100644 --- a/trunk/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/trunk/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -52,8 +52,6 @@ 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, @@ -1092,98 +1090,6 @@ 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, @@ -1207,9 +1113,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_gpio4_hwmod, &omap3xxx_gpio5_hwmod, &omap3xxx_gpio6_hwmod, - - /* dma_system class*/ - &omap3xxx_dma_system_hwmod, NULL, }; diff --git a/trunk/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/trunk/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index f9778fba8322..d258936410fb 100644 --- a/trunk/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/trunk/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -23,7 +23,6 @@ #include #include #include -#include #include "omap_hwmod_common_data.h" @@ -37,7 +36,6 @@ #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; @@ -218,14 +216,6 @@ 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, @@ -236,7 +226,6 @@ 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, }; @@ -1387,93 +1376,6 @@ 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, @@ -1489,10 +1391,6 @@ 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, diff --git a/trunk/arch/arm/mach-omap2/omap_opp_data.h b/trunk/arch/arm/mach-omap2/omap_opp_data.h new file mode 100644 index 000000000000..46ac27dd6c84 --- /dev/null +++ b/trunk/arch/arm/mach-omap2/omap_opp_data.h @@ -0,0 +1,72 @@ +/* + * OMAP SoC specific OPP Data helpers + * + * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * Kevin Hilman + * Copyright (C) 2010 Nokia Corporation. + * Eduardo Valentin + * + * 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H +#define __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H + +#include + +/* + * *BIG FAT WARNING*: + * USE the following ONLY in opp data initialization common to an SoC. + * DO NOT USE these in board files/pm core etc. + */ + +/** + * struct omap_opp_def - OMAP OPP Definition + * @hwmod_name: Name of the hwmod for this domain + * @freq: Frequency in hertz corresponding to this OPP + * @u_volt: Nominal voltage in microvolts corresponding to this OPP + * @default_available: True/false - is this OPP available by default + * + * OMAP SOCs have a standard set of tuples consisting of frequency and voltage + * pairs that the device will support per voltage domain. This is called + * Operating Points or OPP. The actual definitions of OMAP Operating Points + * varies over silicon within the same family of devices. For a specific + * domain, you can have a set of {frequency, voltage} pairs and this is denoted + * by an array of omap_opp_def. As the kernel boots and more information is + * available, a set of these are activated based on the precise nature of + * device the kernel boots up on. It is interesting to remember that each IP + * which belongs to a voltage domain may define their own set of OPPs on top + * of this - but this is handled by the appropriate driver. + */ +struct omap_opp_def { + char *hwmod_name; + + unsigned long freq; + unsigned long u_volt; + + bool default_available; +}; + +/* + * Initialization wrapper used to define an OPP for OMAP variants. + */ +#define OPP_INITIALIZER(_hwmod_name, _enabled, _freq, _uv) \ +{ \ + .hwmod_name = _hwmod_name, \ + .default_available = _enabled, \ + .freq = _freq, \ + .u_volt = _uv, \ +} + +/* Use this to initialize the default table */ +extern int __init omap_init_opp_table(struct omap_opp_def *opp_def, + u32 opp_def_size); + +#endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */ diff --git a/trunk/arch/arm/mach-omap2/opp.c b/trunk/arch/arm/mach-omap2/opp.c new file mode 100644 index 000000000000..ab8b35b780b5 --- /dev/null +++ b/trunk/arch/arm/mach-omap2/opp.c @@ -0,0 +1,93 @@ +/* + * OMAP SoC specific OPP wrapper function + * + * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * Kevin Hilman + * Copyright (C) 2010 Nokia Corporation. + * Eduardo Valentin + * + * 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include + +#include + +#include "omap_opp_data.h" + +/* Temp variable to allow multiple calls */ +static u8 __initdata omap_table_init; + +/** + * omap_init_opp_table() - Initialize opp table as per the CPU type + * @opp_def: opp default list for this silicon + * @opp_def_size: number of opp entries for this silicon + * + * Register the initial OPP table with the OPP library based on the CPU + * type. This is meant to be used only by SoC specific registration. + */ +int __init omap_init_opp_table(struct omap_opp_def *opp_def, + u32 opp_def_size) +{ + int i, r; + + if (!opp_def || !opp_def_size) { + pr_err("%s: invalid params!\n", __func__); + return -EINVAL; + } + + /* + * Initialize only if not already initialized even if the previous + * call failed, because, no reason we'd succeed again. + */ + if (omap_table_init) + return -EEXIST; + omap_table_init = 1; + + /* Lets now register with OPP library */ + for (i = 0; i < opp_def_size; i++) { + struct omap_hwmod *oh; + struct device *dev; + + if (!opp_def->hwmod_name) { + pr_err("%s: NULL name of omap_hwmod, failing [%d].\n", + __func__, i); + return -EINVAL; + } + oh = omap_hwmod_lookup(opp_def->hwmod_name); + if (!oh || !oh->od) { + pr_warn("%s: no hwmod or odev for %s, [%d] " + "cannot add OPPs.\n", __func__, + opp_def->hwmod_name, i); + return -EINVAL; + } + dev = &oh->od->pdev.dev; + + r = opp_add(dev, opp_def->freq, opp_def->u_volt); + if (r) { + dev_err(dev, "%s: add OPP %ld failed for %s [%d] " + "result=%d\n", + __func__, opp_def->freq, + opp_def->hwmod_name, i, r); + } else { + if (!opp_def->default_available) + r = opp_disable(dev, opp_def->freq); + if (r) + dev_err(dev, "%s: disable %ld failed for %s " + "[%d] result=%d\n", + __func__, opp_def->freq, + opp_def->hwmod_name, i, r); + } + opp_def++; + } + + return 0; +} diff --git a/trunk/arch/arm/mach-omap2/opp3xxx_data.c b/trunk/arch/arm/mach-omap2/opp3xxx_data.c new file mode 100644 index 000000000000..0486fce8a92c --- /dev/null +++ b/trunk/arch/arm/mach-omap2/opp3xxx_data.c @@ -0,0 +1,107 @@ +/* + * OMAP3 OPP table definitions. + * + * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * Kevin Hilman + * Copyright (C) 2010 Nokia Corporation. + * Eduardo Valentin + * + * 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include + +#include + +#include "omap_opp_data.h" + +static struct omap_opp_def __initdata omap34xx_opp_def_list[] = { + /* MPU OPP1 */ + OPP_INITIALIZER("mpu", true, 125000000, 975000), + /* MPU OPP2 */ + OPP_INITIALIZER("mpu", true, 250000000, 1075000), + /* MPU OPP3 */ + OPP_INITIALIZER("mpu", true, 500000000, 1200000), + /* MPU OPP4 */ + OPP_INITIALIZER("mpu", true, 550000000, 1270000), + /* MPU OPP5 */ + OPP_INITIALIZER("mpu", true, 600000000, 1350000), + + /* + * L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is + * almost the same than the one at 83MHz thus providing very little + * gain for the power point of view. In term of energy it will even + * increase the consumption due to the very negative performance + * impact that frequency will do to the MPU and the whole system in + * general. + */ + OPP_INITIALIZER("l3_main", false, 41500000, 975000), + /* L3 OPP2 */ + OPP_INITIALIZER("l3_main", true, 83000000, 1050000), + /* L3 OPP3 */ + OPP_INITIALIZER("l3_main", true, 166000000, 1150000), + + /* DSP OPP1 */ + OPP_INITIALIZER("iva", true, 90000000, 975000), + /* DSP OPP2 */ + OPP_INITIALIZER("iva", true, 180000000, 1075000), + /* DSP OPP3 */ + OPP_INITIALIZER("iva", true, 360000000, 1200000), + /* DSP OPP4 */ + OPP_INITIALIZER("iva", true, 400000000, 1270000), + /* DSP OPP5 */ + OPP_INITIALIZER("iva", true, 430000000, 1350000), +}; + +static struct omap_opp_def __initdata omap36xx_opp_def_list[] = { + /* MPU OPP1 - OPP50 */ + OPP_INITIALIZER("mpu", true, 300000000, 1012500), + /* MPU OPP2 - OPP100 */ + OPP_INITIALIZER("mpu", true, 600000000, 1200000), + /* MPU OPP3 - OPP-Turbo */ + OPP_INITIALIZER("mpu", false, 800000000, 1325000), + /* MPU OPP4 - OPP-SB */ + OPP_INITIALIZER("mpu", false, 1000000000, 1375000), + + /* L3 OPP1 - OPP50 */ + OPP_INITIALIZER("l3_main", true, 100000000, 1000000), + /* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */ + OPP_INITIALIZER("l3_main", true, 200000000, 1200000), + + /* DSP OPP1 - OPP50 */ + OPP_INITIALIZER("iva", true, 260000000, 1012500), + /* DSP OPP2 - OPP100 */ + OPP_INITIALIZER("iva", true, 520000000, 1200000), + /* DSP OPP3 - OPP-Turbo */ + OPP_INITIALIZER("iva", false, 660000000, 1325000), + /* DSP OPP4 - OPP-SB */ + OPP_INITIALIZER("iva", false, 800000000, 1375000), +}; + +/** + * omap3_opp_init() - initialize omap3 opp table + */ +static int __init omap3_opp_init(void) +{ + int r = -ENODEV; + + if (!cpu_is_omap34xx()) + return r; + + if (cpu_is_omap3630()) + r = omap_init_opp_table(omap36xx_opp_def_list, + ARRAY_SIZE(omap36xx_opp_def_list)); + else + r = omap_init_opp_table(omap34xx_opp_def_list, + ARRAY_SIZE(omap34xx_opp_def_list)); + + return r; +} +device_initcall(omap3_opp_init); diff --git a/trunk/arch/arm/mach-omap2/pm.c b/trunk/arch/arm/mach-omap2/pm.c index 6ec2ee12272a..59ca03b0e691 100644 --- a/trunk/arch/arm/mach-omap2/pm.c +++ b/trunk/arch/arm/mach-omap2/pm.c @@ -143,5 +143,5 @@ static int __init omap2_common_pm_init(void) return 0; } -postcore_initcall(omap2_common_pm_init); +device_initcall(omap2_common_pm_init); diff --git a/trunk/arch/arm/mach-omap2/pm.h b/trunk/arch/arm/mach-omap2/pm.h index c04f7b50e26f..2031f157a6ee 100644 --- a/trunk/arch/arm/mach-omap2/pm.h +++ b/trunk/arch/arm/mach-omap2/pm.h @@ -20,6 +20,15 @@ extern int omap3_can_sleep(void); extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); extern int omap3_idle_init(void); +#if defined(CONFIG_PM_OPP) +extern int omap3_opp_init(void); +#else +static inline int omap3_opp_init(void) +{ + return -EINVAL; +} +#endif + struct cpuidle_params { u8 valid; u32 sleep_latency; @@ -58,7 +67,7 @@ extern u32 sleep_while_idle; #endif #if defined(CONFIG_CPU_IDLE) -extern void omap3_cpuidle_update_states(u32, u32); +extern void omap3_cpuidle_update_states(void); #endif #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) @@ -80,20 +89,9 @@ 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 diff --git a/trunk/arch/arm/mach-omap2/pm24xx.c b/trunk/arch/arm/mach-omap2/pm24xx.c index aea7ced9a2ff..aaeea49b9bdd 100644 --- a/trunk/arch/arm/mach-omap2/pm24xx.c +++ b/trunk/arch/arm/mach-omap2/pm24xx.c @@ -301,11 +301,17 @@ static void omap2_pm_idle(void) static int omap2_pm_begin(suspend_state_t state) { - disable_hlt(); suspend_state = state; return 0; } +static int omap2_pm_prepare(void) +{ + /* We cannot sleep in idle until we have resumed */ + disable_hlt(); + return 0; +} + static int omap2_pm_suspend(void) { u32 wken_wkup, mir1; @@ -343,15 +349,21 @@ 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, }; diff --git a/trunk/arch/arm/mach-omap2/pm34xx.c b/trunk/arch/arm/mach-omap2/pm34xx.c index c45b4fa1deeb..648b8c50d024 100644 --- a/trunk/arch/arm/mach-omap2/pm34xx.c +++ b/trunk/arch/arm/mach-omap2/pm34xx.c @@ -68,9 +68,6 @@ 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; @@ -146,7 +143,7 @@ static void omap3_core_save_context(void) /* * Force write last pad into memory, as this can fail in some - * cases according to errata 1.157, 1.185 + * cases according to erratas 1.157, 1.185 */ omap_ctrl_writel(omap_ctrl_readl(OMAP343X_PADCONF_ETK_D14), OMAP343X_CONTROL_MEM_WKUP + 0x2a0); @@ -433,7 +430,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 erratum ID i443. + * of AUTO_CNT = 1 enabled. This takes care of errata 1.142. * Hence store/restore the SDRC_POWER register here. */ if (omap_rev() >= OMAP3430_REV_ES3_0 && @@ -532,6 +529,12 @@ static void omap3_pm_idle(void) } #ifdef CONFIG_SUSPEND +static int omap3_pm_prepare(void) +{ + disable_hlt(); + return 0; +} + static int omap3_pm_suspend(void) { struct power_state *pwrst; @@ -594,10 +597,14 @@ 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; @@ -607,14 +614,15 @@ 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 */ @@ -917,29 +925,12 @@ void omap3_pm_off_mode_enable(int enable) state = PWRDM_POWER_RET; #ifdef CONFIG_CPU_IDLE - /* - * 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); + omap3_cpuidle_update_states(); #endif list_for_each_entry(pwrst, &pwrst_list, node) { - 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); + pwrst->next_state = state; + omap_set_pwrdm_state(pwrst->pwrdm, state); } } @@ -1011,17 +1002,6 @@ 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; @@ -1031,8 +1011,6 @@ 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 @@ -1080,14 +1058,6 @@ 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 = diff --git a/trunk/arch/arm/mach-omap2/pm44xx.c b/trunk/arch/arm/mach-omap2/pm44xx.c index 6aff9961e35d..54544b4fc76b 100644 --- a/trunk/arch/arm/mach-omap2/pm44xx.c +++ b/trunk/arch/arm/mach-omap2/pm44xx.c @@ -31,6 +31,12 @@ 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(); @@ -53,22 +59,28 @@ 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 */ diff --git a/trunk/arch/arm/mach-omap2/sdrc.h b/trunk/arch/arm/mach-omap2/sdrc.h index b3f83799e6cf..68f57bb67fc5 100644 --- a/trunk/arch/arm/mach-omap2/sdrc.h +++ b/trunk/arch/arm/mach-omap2/sdrc.h @@ -74,4 +74,5 @@ static inline u32 sms_read_reg(u16 reg) */ #define SDRC_MPURATE_LOOPS 96 + #endif diff --git a/trunk/arch/arm/mach-omap2/sleep34xx.S b/trunk/arch/arm/mach-omap2/sleep34xx.S index e3b5cd76c54c..2fb205a7f285 100644 --- a/trunk/arch/arm/mach-omap2/sleep34xx.S +++ b/trunk/arch/arm/mach-omap2/sleep34xx.S @@ -1,4 +1,6 @@ /* + * linux/arch/arm/mach-omap2/sleep.S + * * (C) Copyright 2007 * Texas Instruments * Karthik Dasu @@ -24,7 +26,6 @@ */ #include #include -#include #include #include "cm.h" @@ -32,27 +33,21 @@ #include "sdrc.h" #include "control.h" -/* - * 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 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) #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 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 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 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) @@ -64,38 +59,48 @@ #define SDRC_DLLA_STATUS_V OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS) #define SDRC_DLLA_CTRL_V OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL) - -/* - * 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 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 .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 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 */ +/* Function call to get the restore pointer for for ES3 to resume from OFF */ ENTRY(get_es3_restore_pointer) stmfd sp!, {lr} @ save registers on stack adr r0, restore_es3 @@ -103,23 +108,54 @@ ENTRY(get_es3_restore_pointer) ENTRY(get_es3_restore_pointer_sz) .word . - get_es3_restore_pointer - .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 +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 /* 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 @@ -148,163 +184,36 @@ api_params: ENTRY(save_secure_ram_context_sz) .word . - save_secure_ram_context -/* - * ====================== - * == Idle entry point == - * ====================== - */ - /* * Forces OMAP into idle state * - * 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. - * + * omap34xx_suspend() - This bit of code just executes the WFI + * for normal idles. * - * 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. + * 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. */ ENTRY(omap34xx_cpu_suspend) - stmfd sp!, {r0-r12, lr} @ save registers on stack + 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 - /* - * 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 - 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 - + /* If context save is required, do that and execute wfi */ + bne save_context_wfi /* 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 @@ -317,30 +226,9 @@ omap3_do_wfi: nop bl wait_sdrc_ok -/* - * =================================== - * == 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 - */ + ldmfd sp!, {r0-r12, pc} @ restore regs and return restore_es3: + /*b restore_es3*/ @ Enable to debug restore code ldr r5, pm_prepwstst_core_p ldr r4, [r5] and r4, r4, #0x3 @@ -357,117 +245,82 @@ 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: - /* - * 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 + /* 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 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 invalidate L2 - .word 0xE1600070 @ Call SMI monitor (smieq) + mov r12, #0x1 @ set up to invalide L2 +smi: .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 @@ -488,33 +341,33 @@ skipl2reen: 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 */ @@ -526,27 +379,26 @@ skipl2reen: /* 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 @@ -554,25 +406,21 @@ 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 - /* r1 has the value to be written to table entry*/ - add r1, r1, r4 + add r1, r1, r4 /* r1 has value to be written to table entry*/ /* Getting the address of table entry to modify */ lsr r4, #18 - /* r2 has the location which needs to be modified */ - add r2, r4 + add r2, r4 /* r2 has the location which needs to be modified */ /* 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] @@ -581,11 +429,8 @@ 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. This enables the MMU. - * The caches and prediction are not enabled here, they - * will be enabled after restoring the MMU table entry. - */ + /* Restore control register but dont enable caches here*/ + /* Caches will be enabled after restoring MMU table entry */ ldmia r3!, {r4} /* Store previous value of control register in scratchpad */ str r4, [r5, #0xC8] @@ -593,144 +438,212 @@ usettbr0: and r4, r2 mcr p15, 0, r4, c1, c0, 0 -/* - * ============================== - * == Exit point from OFF mode == - * ============================== - */ - ldmfd sp!, {r0-r12, pc} @ restore regs and return - - -/* - * Internal functions - */ + 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} -/* 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 + /* Store current cpsr*/ + mrs r2, cpsr + stmia r8!, {r2} -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 + 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 -/* - * 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. - */ + 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} /* Make sure SDRC accesses are ok */ wait_sdrc_ok: - -/* 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 + 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] wait_dll_lock: - 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 + /* 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 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: @@ -738,7 +651,13 @@ scratchpad_base: sram_base: .word SRAM_BASE_P + 0x8000 sdrc_power: - .word SDRC_POWER_V + .word SDRC_POWER_V +clk_stabilize_delay: + .word 0x000001FF +assoc_mask: + .word 0x3ff +numset_mask: + .word 0x7fff ttbrbit_mask: .word 0xFFFFC000 table_index_mask: @@ -749,20 +668,5 @@ 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 diff --git a/trunk/arch/arm/mach-s3c2412/Kconfig b/trunk/arch/arm/mach-s3c2412/Kconfig index 6983cb4d4cae..fa2e5bffbb8e 100644 --- a/trunk/arch/arm/mach-s3c2412/Kconfig +++ b/trunk/arch/arm/mach-s3c2412/Kconfig @@ -28,16 +28,9 @@ 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 diff --git a/trunk/arch/arm/mach-s3c2412/Makefile b/trunk/arch/arm/mach-s3c2412/Makefile index 6c48a91ea39e..530ec46cbaea 100644 --- a/trunk/arch/arm/mach-s3c2412/Makefile +++ b/trunk/arch/arm/mach-s3c2412/Makefile @@ -14,8 +14,7 @@ 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 -obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep.o +obj-$(CONFIG_S3C2412_PM) += pm.o sleep.o obj-$(CONFIG_S3C2412_CPUFREQ) += cpu-freq.o # Machine support diff --git a/trunk/arch/arm/mach-s3c2416/Kconfig b/trunk/arch/arm/mach-s3c2416/Kconfig index df8d14974c90..27b3e7c9d613 100644 --- a/trunk/arch/arm/mach-s3c2416/Kconfig +++ b/trunk/arch/arm/mach-s3c2416/Kconfig @@ -27,7 +27,6 @@ config S3C2416_DMA config S3C2416_PM bool - select S3C2412_PM_SLEEP help Internal config node to apply S3C2416 power management diff --git a/trunk/arch/arm/mach-s5pv210/mach-aquila.c b/trunk/arch/arm/mach-s5pv210/mach-aquila.c index 461aa035afc0..28677caf3613 100644 --- a/trunk/arch/arm/mach-s5pv210/mach-aquila.c +++ b/trunk/arch/arm/mach-s5pv210/mach-aquila.c @@ -378,12 +378,6 @@ 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 diff --git a/trunk/arch/arm/mach-s5pv210/mach-goni.c b/trunk/arch/arm/mach-s5pv210/mach-goni.c index e22d5112fd44..b1dcf964a768 100644 --- a/trunk/arch/arm/mach-s5pv210/mach-goni.c +++ b/trunk/arch/arm/mach-s5pv210/mach-goni.c @@ -518,12 +518,6 @@ 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 diff --git a/trunk/arch/arm/mach-shmobile/include/mach/entry-macro.S b/trunk/arch/arm/mach-shmobile/include/mach/entry-macro.S index f428c4db2b60..a285d13c7416 100644 --- a/trunk/arch/arm/mach-shmobile/include/mach/entry-macro.S +++ b/trunk/arch/arm/mach-shmobile/include/mach/entry-macro.S @@ -1,5 +1,4 @@ /* - * Copyright (C) 2010 Magnus Damm * Copyright (C) 2008 Renesas Solutions Corp. * * This program is free software; you can redistribute it and/or modify @@ -15,45 +14,24 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include -#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, =INTCA_BASE + ldr \base, =INTFLGA .endm .macro arch_ret_to_user, tmp1, tmp2 .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - /* 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 */ + ldr \irqnr, [\base] cmp \irqnr, #0 beq 1000f - - /* Convert vector to irq number, same as the evt2irq() macro */ + /* intevt to irq number */ lsr \irqnr, \irqnr, #0x5 subs \irqnr, \irqnr, #16 diff --git a/trunk/arch/arm/mach-shmobile/include/mach/vmalloc.h b/trunk/arch/arm/mach-shmobile/include/mach/vmalloc.h index 2b8fd8b942fe..4aecf6e3a859 100644 --- a/trunk/arch/arm/mach-shmobile/include/mach/vmalloc.h +++ b/trunk/arch/arm/mach-shmobile/include/mach/vmalloc.h @@ -2,6 +2,6 @@ #define __ASM_MACH_VMALLOC_H /* Vmalloc at ... - 0xe5ffffff */ -#define VMALLOC_END 0xe6000000UL +#define VMALLOC_END 0xe6000000 #endif /* __ASM_MACH_VMALLOC_H */ diff --git a/trunk/arch/arm/plat-omap/dma.c b/trunk/arch/arm/plat-omap/dma.c index c4b2b478b1a5..a863f5546a6b 100644 --- a/trunk/arch/arm/plat-omap/dma.c +++ b/trunk/arch/arm/plat-omap/dma.c @@ -15,10 +15,6 @@ * * 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 - * * 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. @@ -57,11 +53,7 @@ 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; @@ -69,6 +61,27 @@ 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; @@ -124,6 +137,15 @@ 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); @@ -132,9 +154,27 @@ 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 */ -int omap_dma_in_1510_mode(void) +static int omap_dma_in_1510_mode(void) { return enable_1510_mode; } @@ -166,6 +206,16 @@ 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; @@ -198,12 +248,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority) if (cpu_class_is_omap2()) { u32 ccr; - ccr = p->dma_read(CCR, lch); + ccr = dma_read(CCR(lch)); if (priority) ccr |= (1 << 6); else ccr &= ~(1 << 6); - p->dma_write(ccr, CCR, lch); + dma_write(ccr, CCR(lch)); } } EXPORT_SYMBOL(omap_set_dma_priority); @@ -214,31 +264,31 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, { u32 l; - l = p->dma_read(CSDP, lch); + l = dma_read(CSDP(lch)); l &= ~0x03; l |= data_type; - p->dma_write(l, CSDP, lch); + dma_write(l, CSDP(lch)); if (cpu_class_is_omap1()) { u16 ccr; - ccr = p->dma_read(CCR, lch); + ccr = dma_read(CCR(lch)); ccr &= ~(1 << 5); if (sync_mode == OMAP_DMA_SYNC_FRAME) ccr |= 1 << 5; - p->dma_write(ccr, CCR, lch); + dma_write(ccr, CCR(lch)); - ccr = p->dma_read(CCR2, lch); + ccr = dma_read(CCR2(lch)); ccr &= ~(1 << 2); if (sync_mode == OMAP_DMA_SYNC_BLOCK) ccr |= 1 << 2; - p->dma_write(ccr, CCR2, lch); + dma_write(ccr, CCR2(lch)); } if (cpu_class_is_omap2() && dma_trigger) { u32 val; - val = p->dma_read(CCR, lch); + val = dma_read(CCR(lch)); /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ val &= ~((1 << 23) | (3 << 19) | 0x1f); @@ -263,11 +313,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, } else { val &= ~(1 << 24); /* dest synch */ } - p->dma_write(val, CCR, lch); + dma_write(val, CCR(lch)); } - p->dma_write(elem_count, CEN, lch); - p->dma_write(frame_count, CFN, lch); + dma_write(elem_count, CEN(lch)); + dma_write(frame_count, CFN(lch)); } EXPORT_SYMBOL(omap_set_dma_transfer_params); @@ -278,7 +328,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 = p->dma_read(CCR2, lch); + w = dma_read(CCR2(lch)); w &= ~0x03; switch (mode) { @@ -293,22 +343,23 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - p->dma_write(w, CCR2, lch); + dma_write(w, CCR2(lch)); - w = p->dma_read(LCH_CTRL, lch); + w = dma_read(LCH_CTRL(lch)); w &= ~0x0f; /* Default is channel type 2D */ if (mode) { - p->dma_write(color, COLOR, lch); + dma_write((u16)color, COLOR_L(lch)); + dma_write((u16)(color >> 16), COLOR_U(lch)); w |= 1; /* Channel type G */ } - p->dma_write(w, LCH_CTRL, lch); + dma_write(w, LCH_CTRL(lch)); } if (cpu_class_is_omap2()) { u32 val; - val = p->dma_read(CCR, lch); + val = dma_read(CCR(lch)); val &= ~((1 << 17) | (1 << 16)); switch (mode) { @@ -323,10 +374,10 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - p->dma_write(val, CCR, lch); + dma_write(val, CCR(lch)); color &= 0xffffff; - p->dma_write(color, COLOR, lch); + dma_write(color, COLOR(lch)); } } EXPORT_SYMBOL(omap_set_dma_color_mode); @@ -336,10 +387,10 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) if (cpu_class_is_omap2()) { u32 csdp; - csdp = p->dma_read(CSDP, lch); + csdp = dma_read(CSDP(lch)); csdp &= ~(0x3 << 16); csdp |= (mode << 16); - p->dma_write(csdp, CSDP, lch); + dma_write(csdp, CSDP(lch)); } } EXPORT_SYMBOL(omap_set_dma_write_mode); @@ -349,10 +400,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 = p->dma_read(LCH_CTRL, lch); + l = dma_read(LCH_CTRL(lch)); l &= ~0x7; l |= mode; - p->dma_write(l, LCH_CTRL, lch); + dma_write(l, LCH_CTRL(lch)); } } EXPORT_SYMBOL(omap_set_dma_channel_mode); @@ -367,21 +418,27 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode, if (cpu_class_is_omap1()) { u16 w; - w = p->dma_read(CSDP, lch); + w = dma_read(CSDP(lch)); w &= ~(0x1f << 2); w |= src_port << 2; - p->dma_write(w, CSDP, lch); + dma_write(w, CSDP(lch)); } - l = p->dma_read(CCR, lch); + l = dma_read(CCR(lch)); l &= ~(0x03 << 12); l |= src_amode << 12; - p->dma_write(l, CCR, lch); + 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(src_start, CSSA, lch); + if (cpu_class_is_omap2()) + dma_write(src_start, CSSA(lch)); - p->dma_write(src_ei, CSEI, lch); - p->dma_write(src_fi, CSFI, lch); + dma_write(src_ei, CSEI(lch)); + dma_write(src_fi, CSFI(lch)); } EXPORT_SYMBOL(omap_set_dma_src_params); @@ -409,8 +466,8 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; - p->dma_write(eidx, CSEI, lch); - p->dma_write(fidx, CSFI, lch); + dma_write(eidx, CSEI(lch)); + dma_write(fidx, CSFI(lch)); } EXPORT_SYMBOL(omap_set_dma_src_index); @@ -418,11 +475,11 @@ void omap_set_dma_src_data_pack(int lch, int enable) { u32 l; - l = p->dma_read(CSDP, lch); + l = dma_read(CSDP(lch)); l &= ~(1 << 6); if (enable) l |= (1 << 6); - p->dma_write(l, CSDP, lch); + dma_write(l, CSDP(lch)); } EXPORT_SYMBOL(omap_set_dma_src_data_pack); @@ -431,7 +488,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; - l = p->dma_read(CSDP, lch); + l = dma_read(CSDP(lch)); l &= ~(0x03 << 7); switch (burst_mode) { @@ -467,7 +524,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) } l |= (burst << 7); - p->dma_write(l, CSDP, lch); + dma_write(l, CSDP(lch)); } EXPORT_SYMBOL(omap_set_dma_src_burst_mode); @@ -479,21 +536,27 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, u32 l; if (cpu_class_is_omap1()) { - l = p->dma_read(CSDP, lch); + l = dma_read(CSDP(lch)); l &= ~(0x1f << 9); l |= dest_port << 9; - p->dma_write(l, CSDP, lch); + dma_write(l, CSDP(lch)); } - l = p->dma_read(CCR, lch); + l = dma_read(CCR(lch)); l &= ~(0x03 << 14); l |= dest_amode << 14; - p->dma_write(l, CCR, lch); + 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(dest_start, CDSA, lch); + if (cpu_class_is_omap2()) + dma_write(dest_start, CDSA(lch)); - p->dma_write(dst_ei, CDEI, lch); - p->dma_write(dst_fi, CDFI, lch); + dma_write(dst_ei, CDEI(lch)); + dma_write(dst_fi, CDFI(lch)); } EXPORT_SYMBOL(omap_set_dma_dest_params); @@ -502,8 +565,8 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; - p->dma_write(eidx, CDEI, lch); - p->dma_write(fidx, CDFI, lch); + dma_write(eidx, CDEI(lch)); + dma_write(fidx, CDFI(lch)); } EXPORT_SYMBOL(omap_set_dma_dest_index); @@ -511,11 +574,11 @@ void omap_set_dma_dest_data_pack(int lch, int enable) { u32 l; - l = p->dma_read(CSDP, lch); + l = dma_read(CSDP(lch)); l &= ~(1 << 13); if (enable) l |= 1 << 13; - p->dma_write(l, CSDP, lch); + dma_write(l, CSDP(lch)); } EXPORT_SYMBOL(omap_set_dma_dest_data_pack); @@ -524,7 +587,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; - l = p->dma_read(CSDP, lch); + l = dma_read(CSDP(lch)); l &= ~(0x03 << 14); switch (burst_mode) { @@ -557,7 +620,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) return; } l |= (burst << 14); - p->dma_write(l, CSDP, lch); + dma_write(l, CSDP(lch)); } EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); @@ -567,18 +630,18 @@ static inline void omap_enable_channel_irq(int lch) /* Clear CSR */ if (cpu_class_is_omap1()) - status = p->dma_read(CSR, lch); + status = dma_read(CSR(lch)); else if (cpu_class_is_omap2()) - p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); /* Enable some nice interrupts. */ - p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch); + dma_write(dma_chan[lch].enabled_irqs, CICR(lch)); } static void omap_disable_channel_irq(int lch) { if (cpu_class_is_omap2()) - p->dma_write(0, CICR, lch); + dma_write(0, CICR(lch)); } void omap_enable_dma_irq(int lch, u16 bits) @@ -597,7 +660,7 @@ static inline void enable_lnk(int lch) { u32 l; - l = p->dma_read(CLNK_CTRL, lch); + l = dma_read(CLNK_CTRL(lch)); if (cpu_class_is_omap1()) l &= ~(1 << 14); @@ -612,18 +675,18 @@ static inline void enable_lnk(int lch) l = dma_chan[lch].next_linked_ch | (1 << 15); #endif - p->dma_write(l, CLNK_CTRL, lch); + dma_write(l, CLNK_CTRL(lch)); } static inline void disable_lnk(int lch) { u32 l; - l = p->dma_read(CLNK_CTRL, lch); + l = dma_read(CLNK_CTRL(lch)); /* Disable interrupts */ if (cpu_class_is_omap1()) { - p->dma_write(0, CICR, lch); + dma_write(0, CICR(lch)); /* Set the STOP_LNK bit */ l |= 1 << 14; } @@ -634,7 +697,7 @@ static inline void disable_lnk(int lch) l &= ~(1 << 15); } - p->dma_write(l, CLNK_CTRL, lch); + dma_write(l, CLNK_CTRL(lch)); dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; } @@ -647,9 +710,9 @@ static inline void omap2_enable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); - val = p->dma_read(IRQENABLE_L0, lch); + val = dma_read(IRQENABLE_L0); val |= 1 << lch; - p->dma_write(val, IRQENABLE_L0, lch); + dma_write(val, IRQENABLE_L0); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -662,9 +725,9 @@ static inline void omap2_disable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); - val = p->dma_read(IRQENABLE_L0, lch); + val = dma_read(IRQENABLE_L0); val &= ~(1 << lch); - p->dma_write(val, IRQENABLE_L0, lch); + dma_write(val, IRQENABLE_L0); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -691,8 +754,8 @@ int omap_request_dma(int dev_id, const char *dev_name, chan = dma_chan + free_ch; chan->dev_id = dev_id; - if (p->clear_lch_regs) - p->clear_lch_regs(free_ch); + if (cpu_class_is_omap1()) + clear_lch_regs(free_ch); if (cpu_class_is_omap2()) omap_clear_dma(free_ch); @@ -729,17 +792,17 @@ int omap_request_dma(int dev_id, const char *dev_name, * Disable the 1510 compatibility mode and set the sync device * id. */ - p->dma_write(dev_id | (1 << 10), CCR, free_ch); + dma_write(dev_id | (1 << 10), CCR(free_ch)); } else if (cpu_is_omap7xx() || cpu_is_omap15xx()) { - p->dma_write(dev_id, CCR, free_ch); + 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 */ - p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch); - p->dma_write(1 << free_ch, IRQSTATUS_L0, 0); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(free_ch)); + dma_write(1 << free_ch, IRQSTATUS_L0); } *dma_ch_out = free_ch; @@ -760,23 +823,23 @@ void omap_free_dma(int lch) if (cpu_class_is_omap1()) { /* Disable all DMA interrupts for the channel. */ - p->dma_write(0, CICR, lch); + dma_write(0, CICR(lch)); /* Make sure the DMA transfer is stopped. */ - p->dma_write(0, CCR, lch); + dma_write(0, CCR(lch)); } if (cpu_class_is_omap2()) { omap2_disable_irq_lch(lch); /* Clear the CSR register and IRQ status register */ - p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); - p->dma_write(1 << lch, IRQSTATUS_L0, lch); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); + dma_write(1 << lch, IRQSTATUS_L0); /* Disable all DMA interrupts for the channel. */ - p->dma_write(0, CICR, lch); + dma_write(0, CICR(lch)); /* Make sure the DMA transfer is stopped. */ - p->dma_write(0, CCR, lch); + dma_write(0, CCR(lch)); omap_clear_dma(lch); } @@ -817,7 +880,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams) reg |= (0x3 & tparams) << 12; reg |= (arb_rate & 0xff) << 16; - p->dma_write(reg, GCR, 0); + dma_write(reg, GCR); } EXPORT_SYMBOL(omap_dma_set_global_params); @@ -840,14 +903,14 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio, printk(KERN_ERR "Invalid channel id\n"); return -EINVAL; } - l = p->dma_read(CCR, lch); + l = 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); - p->dma_write(l, CCR, lch); + dma_write(l, CCR(lch)); return 0; } @@ -862,7 +925,25 @@ void omap_clear_dma(int lch) unsigned long flags; local_irq_save(flags); - p->clear_dma(lch); + + 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); + } + local_irq_restore(flags); } EXPORT_SYMBOL(omap_clear_dma); @@ -876,13 +957,13 @@ void omap_start_dma(int lch) * before starting dma transfer. */ if (cpu_is_omap15xx()) - p->dma_write(0, CPC, lch); + dma_write(0, CPC(lch)); else - p->dma_write(0, CDAC, lch); + 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[dma_lch_count]; + char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT]; dma_chan_link_map[lch] = 1; /* Set the link register of the first channel */ @@ -904,18 +985,32 @@ void omap_start_dma(int lch) cur_lch = next_lch; } while (next_lch != -1); - } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS)) - p->dma_write(lch, CLNK_CTRL, lch); + } 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)); + } omap_enable_channel_irq(lch); - l = p->dma_read(CCR, lch); + l = dma_read(CCR(lch)); - if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING)) - l |= OMAP_DMA_CCR_BUFFERING_DISABLE; - l |= OMAP_DMA_CCR_EN; + /* + * 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; - p->dma_write(l, CCR, lch); + l |= OMAP_DMA_CCR_EN; + dma_write(l, CCR(lch)); dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } @@ -927,46 +1022,46 @@ void omap_stop_dma(int lch) /* Disable all interrupts on the channel */ if (cpu_class_is_omap1()) - p->dma_write(0, CICR, lch); + dma_write(0, CICR(lch)); - l = p->dma_read(CCR, lch); - if (IS_DMA_ERRATA(DMA_ERRATA_i541) && - (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { + 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)) { int i = 0; u32 sys_cf; /* Configure No-Standby */ - l = p->dma_read(OCP_SYSCONFIG, lch); + l = dma_read(OCP_SYSCONFIG); sys_cf = l; l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK; l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); - p->dma_write(l , OCP_SYSCONFIG, 0); + dma_write(l , OCP_SYSCONFIG); - l = p->dma_read(CCR, lch); + l = dma_read(CCR(lch)); l &= ~OMAP_DMA_CCR_EN; - p->dma_write(l, CCR, lch); + dma_write(l, CCR(lch)); /* Wait for sDMA FIFO drain */ - l = p->dma_read(CCR, lch); + l = dma_read(CCR(lch)); while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))) { udelay(5); i++; - l = p->dma_read(CCR, lch); + l = dma_read(CCR(lch)); } if (i >= 100) printk(KERN_ERR "DMA drain did not complete on " "lch %d\n", lch); /* Restore OCP_SYSCONFIG */ - p->dma_write(sys_cf, OCP_SYSCONFIG, lch); + dma_write(sys_cf, OCP_SYSCONFIG); } else { l &= ~OMAP_DMA_CCR_EN; - p->dma_write(l, CCR, lch); + 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[dma_lch_count]; + char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT]; memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map)); do { @@ -1027,15 +1122,19 @@ dma_addr_t omap_get_dma_src_pos(int lch) dma_addr_t offset = 0; if (cpu_is_omap15xx()) - offset = p->dma_read(CPC, lch); + offset = dma_read(CPC(lch)); else - offset = p->dma_read(CSAC, lch); + offset = dma_read(CSAC(lch)); - if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0) - 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 (cpu_class_is_omap1()) - offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000); + offset |= (dma_read(CSSA_U(lch)) << 16); return offset; } @@ -1054,19 +1153,19 @@ dma_addr_t omap_get_dma_dst_pos(int lch) dma_addr_t offset = 0; if (cpu_is_omap15xx()) - offset = p->dma_read(CPC, lch); + offset = dma_read(CPC(lch)); else - offset = p->dma_read(CDAC, lch); + offset = 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 = p->dma_read(CDAC, lch); + offset = dma_read(CDAC(lch)); if (cpu_class_is_omap1()) - offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000); + offset |= (dma_read(CDSA_U(lch)) << 16); return offset; } @@ -1074,7 +1173,7 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos); int omap_get_dma_active_status(int lch) { - return (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0; + return (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) != 0; } EXPORT_SYMBOL(omap_get_dma_active_status); @@ -1087,7 +1186,7 @@ int omap_dma_running(void) return 1; for (lch = 0; lch < dma_chan_count; lch++) - if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) + if (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) return 1; return 0; @@ -1102,8 +1201,8 @@ void omap_dma_link_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { - p->dma_write(p->dma_read(CCR, lch_head) | (3 << 8), - CCR, lch_head); + dma_write(dma_read(CCR(lch_head)) | (3 << 8), + CCR(lch_head)); return; } printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); @@ -1129,8 +1228,8 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { - p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8), - CCR, lch_head); + dma_write(dma_read(CCR(lch_head)) & ~(3 << 8), + CCR(lch_head)); return; } printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); @@ -1156,6 +1255,8 @@ 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) @@ -1180,15 +1281,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue) lch_queue; } - l = p->dma_read(CLNK_CTRL, lch_head); + l = dma_read(CLNK_CTRL(lch_head)); l &= ~(0x1f); l |= lch_queue; - p->dma_write(l, CLNK_CTRL, lch_head); + dma_write(l, CLNK_CTRL(lch_head)); - l = p->dma_read(CLNK_CTRL, lch_queue); + l = dma_read(CLNK_CTRL(lch_queue)); l &= ~(0x1f); l |= (dma_chan[lch_queue].next_linked_ch); - p->dma_write(l, CLNK_CTRL, lch_queue); + dma_write(l, CLNK_CTRL(lch_queue)); } /** @@ -1464,13 +1565,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) - p->dma_write(src_start, CSSA, lch); + dma_write(src_start, CSSA(lch)); if (dest_start != 0) - p->dma_write(dest_start, CDSA, lch); + dma_write(dest_start, CDSA(lch)); /* Write the buffer size */ - p->dma_write(elem_count, CEN, lch); - p->dma_write(frame_count, CFN, lch); + dma_write(elem_count, CEN(lch)); + dma_write(frame_count, CFN(lch)); /* * If the chain is dynamically linked, @@ -1503,8 +1604,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) & p->dma_read( - CCR, dma_chan[lch].prev_linked_ch))) { + if (0 == ((1 << 7) & 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"); @@ -1520,7 +1621,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, } omap_enable_channel_irq(lch); - l = p->dma_read(CCR, lch); + l = dma_read(CCR(lch)); if ((0 == (l & (1 << 24)))) l &= ~(1 << 25); @@ -1531,12 +1632,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); - p->dma_write(l, CCR, lch); + dma_write(l, CCR(lch)); } else start_dma = 0; } else { if (0 == (l & (1 << 7))) - p->dma_write(l, CCR, lch); + dma_write(l, CCR(lch)); } dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } @@ -1581,7 +1682,7 @@ int omap_start_dma_chain_transfers(int chain_id) omap_enable_channel_irq(channels[0]); } - l = p->dma_read(CCR, channels[0]); + l = 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; @@ -1590,7 +1691,7 @@ int omap_start_dma_chain_transfers(int chain_id) l &= ~(1 << 25); else l |= (1 << 25); - p->dma_write(l, CCR, channels[0]); + dma_write(l, CCR(channels[0])); dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE; @@ -1610,7 +1711,7 @@ int omap_stop_dma_chain_transfers(int chain_id) { int *channels; u32 l, i; - u32 sys_cf = 0; + u32 sys_cf; /* Check for input params */ if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { @@ -1625,20 +1726,22 @@ int omap_stop_dma_chain_transfers(int chain_id) } channels = dma_linked_lch[chain_id].linked_dmach_q; - 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); - } + /* + * 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); for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { /* Stop the Channel transmission */ - l = p->dma_read(CCR, channels[i]); + l = dma_read(CCR(channels[i])); l &= ~(1 << 7); - p->dma_write(l, CCR, channels[i]); + dma_write(l, CCR(channels[i])); /* Disable the link in all the channels */ disable_lnk(channels[i]); @@ -1650,8 +1753,8 @@ int omap_stop_dma_chain_transfers(int chain_id) /* Reset the Queue pointers */ OMAP_DMA_CHAIN_QINIT(chain_id); - if (IS_DMA_ERRATA(DMA_ERRATA_i88)) - p->dma_write(sys_cf, OCP_SYSCONFIG, 0); + /* Errata - put in the old value */ + dma_write(sys_cf, OCP_SYSCONFIG); return 0; } @@ -1693,8 +1796,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 = p->dma_read(CCEN, lch); - *fi = p->dma_read(CCFN, lch); + *ei = dma_read(CCEN(lch)); + *fi = dma_read(CCFN(lch)); return 0; } @@ -1731,7 +1834,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 p->dma_read(CDAC, lch); + return dma_read(CDAC(lch)); } EXPORT_SYMBOL(omap_get_dma_chain_dst_pos); @@ -1765,7 +1868,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 p->dma_read(CSAC, lch); + return dma_read(CSAC(lch)); } EXPORT_SYMBOL(omap_get_dma_chain_src_pos); #endif /* ifndef CONFIG_ARCH_OMAP1 */ @@ -1782,7 +1885,7 @@ static int omap1_dma_handle_ch(int ch) csr = dma_chan[ch].saved_csr; dma_chan[ch].saved_csr = 0; } else - csr = p->dma_read(CSR, ch); + csr = dma_read(CSR(ch)); if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) { dma_chan[ch + 6].saved_csr = csr >> 7; csr &= 0x7f; @@ -1835,13 +1938,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id) static int omap2_dma_handle_ch(int ch) { - u32 status = p->dma_read(CSR, ch); + u32 status = dma_read(CSR(ch)); if (!status) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch); - p->dma_write(1 << ch, IRQSTATUS_L0, ch); + dma_write(1 << ch, IRQSTATUS_L0); return 0; } if (unlikely(dma_chan[ch].dev_id == -1)) { @@ -1857,12 +1960,17 @@ 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 (IS_DMA_ERRATA(DMA_ERRATA_i378)) { + if (cpu_class_is_omap2()) { + /* + * Errata: sDMA Channel is not disabled + * after a transaction error. So we explicitely + * disable the channel + */ u32 ccr; - ccr = p->dma_read(CCR, ch); + ccr = dma_read(CCR(ch)); ccr &= ~OMAP_DMA_CCR_EN; - p->dma_write(ccr, CCR, ch); + dma_write(ccr, CCR(ch)); dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; } } @@ -1873,16 +1981,16 @@ static int omap2_dma_handle_ch(int ch) printk(KERN_INFO "DMA misaligned error with device %d\n", dma_chan[ch].dev_id); - p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch); - p->dma_write(1 << ch, IRQSTATUS_L0, ch); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch)); + dma_write(1 << ch, IRQSTATUS_L0); /* read back the register to flush the write */ - p->dma_read(IRQSTATUS_L0, ch); + dma_read(IRQSTATUS_L0); /* 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 (p->dma_read(CLNK_CTRL, ch) & (1 << 15)) + if (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 == @@ -1892,10 +2000,10 @@ static int omap2_dma_handle_ch(int ch) if (!OMAP_DMA_CHAIN_QEMPTY(chain_id)) OMAP_DMA_CHAIN_INCQHEAD(chain_id); - status = p->dma_read(CSR, ch); + status = dma_read(CSR(ch)); } - p->dma_write(status, CSR, ch); + dma_write(status, CSR(ch)); if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); @@ -1909,13 +2017,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) u32 val, enable_reg; int i; - val = p->dma_read(IRQSTATUS_L0, 0); + val = dma_read(IRQSTATUS_L0); if (val == 0) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ\n"); return IRQ_HANDLED; } - enable_reg = p->dma_read(IRQENABLE_L0, 0); + enable_reg = dma_read(IRQENABLE_L0); val &= enable_reg; /* Dispatch only relevant interrupts */ for (i = 0; i < dma_lch_count && val != 0; i++) { if (val & 1) @@ -1941,66 +2049,119 @@ static struct irqaction omap24xx_dma_irq; void omap_dma_global_context_save(void) { omap_dma_global_context.dma_irqenable_l0 = - p->dma_read(IRQENABLE_L0, 0); + dma_read(IRQENABLE_L0); omap_dma_global_context.dma_ocp_sysconfig = - p->dma_read(OCP_SYSCONFIG, 0); - omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0); + dma_read(OCP_SYSCONFIG); + omap_dma_global_context.dma_gcr = dma_read(GCR); } void omap_dma_global_context_restore(void) { int ch; - 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); + 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); - if (IS_DMA_ERRATA(DMA_ROMCODE_BUG)) - p->dma_write(0x3 , IRQSTATUS_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); for (ch = 0; ch < dma_chan_count; ch++) if (dma_chan[ch].dev_id != -1) omap_clear_dma(ch); } -static int __devinit omap_system_dma_probe(struct platform_device *pdev) +/*----------------------------------------------------------------------------*/ + +static int __init omap_init_dma(void) { - 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; + 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; } - d = p->dma_attr; - errata = p->errata; + omap_dma_base = ioremap(base, SZ_4K); + BUG_ON(!omap_dma_base); - if ((d->dev_caps & RESERVE_CHANNEL) && omap_dma_reserve_channels + if (cpu_class_is_omap2() && omap_dma_reserve_channels && (omap_dma_reserve_channels <= dma_lch_count)) - d->lch_count = omap_dma_reserve_channels; + dma_lch_count = omap_dma_reserve_channels; - 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; + dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count, + GFP_KERNEL); + if (!dma_chan) { + r = -ENOMEM; + goto out_unmap; + } if (cpu_class_is_omap2()) { dma_linked_lch = kzalloc(sizeof(struct dma_link_info) * dma_lch_count, GFP_KERNEL); if (!dma_linked_lch) { - ret = -ENOMEM; - goto exit_dma_lch_fail; + r = -ENOMEM; + goto out_free; } } + 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()) @@ -2017,23 +2178,20 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev) * request_irq() doesn't like dev_id (ie. ch) being * zero, so we have to kludge around this. */ - 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, + r = request_irq(omap1_dma_irq[ch], omap1_dma_irq_handler, 0, "DMA", (void *) (ch + 1)); - if (ret != 0) - goto exit_dma_irq_fail; + 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; + } } } @@ -2042,91 +2200,46 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev) DMA_DEFAULT_FIFO_DEPTH, 0); if (cpu_class_is_omap2()) { - 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; + 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; } } - /* 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; -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); +out_free: kfree(dma_chan); - return ret; -} -static int __devexit omap_system_dma_remove(struct platform_device *pdev) -{ - int dma_irq; +out_unmap: + iounmap(omap_dma_base); - 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); + return r; } -MODULE_DESCRIPTION("OMAP SYSTEM DMA DRIVER"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRIVER_NAME); -MODULE_AUTHOR("Texas Instruments Inc"); +arch_initcall(omap_init_dma); /* * Reserve the omap SDMA channels using cmdline bootarg diff --git a/trunk/arch/arm/plat-omap/include/plat/dma.h b/trunk/arch/arm/plat-omap/include/plat/dma.h index d1c916fcf770..0cce4ca83aa0 100644 --- a/trunk/arch/arm/plat-omap/include/plat/dma.h +++ b/trunk/arch/arm/plat-omap/include/plat/dma.h @@ -21,16 +21,142 @@ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H -#include - -/* - * 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" +/* 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 + +/*----------------------------------------------------------------------------*/ + /* DMA channels for omap1 */ #define OMAP_DMA_NO_DEVICE 0 #define OMAP_DMA_MCSI1_TX 1 @@ -279,63 +405,6 @@ #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, @@ -401,41 +470,6 @@ 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, diff --git a/trunk/arch/arm/plat-omap/include/plat/sram.h b/trunk/arch/arm/plat-omap/include/plat/sram.h index 9967d5e855c7..5905100b29a1 100644 --- a/trunk/arch/arm/plat-omap/include/plat/sram.h +++ b/trunk/arch/arm/plat-omap/include/plat/sram.h @@ -11,7 +11,6 @@ #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); @@ -75,14 +74,4 @@ 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 diff --git a/trunk/arch/arm/plat-omap/sram.c b/trunk/arch/arm/plat-omap/sram.c index 1a686c89d8dd..819ea0cfb81a 100644 --- a/trunk/arch/arm/plat-omap/sram.c +++ b/trunk/arch/arm/plat-omap/sram.c @@ -41,12 +41,15 @@ #define OMAP1_SRAM_PA 0x20000000 #define OMAP1_SRAM_VA VMALLOC_END -#define OMAP2_SRAM_PUB_PA (OMAP2_SRAM_PA + 0xf800) +#define OMAP2_SRAM_PA 0x40200000 +#define OMAP2_SRAM_PUB_PA 0x4020f800 #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 (OMAP3_SRAM_PA + 0x8000) +#define OMAP3_SRAM_PUB_PA 0x40208000 #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) diff --git a/trunk/arch/arm/plat-s3c24xx/Kconfig b/trunk/arch/arm/plat-s3c24xx/Kconfig index eb105e61c746..5a27b1b538f2 100644 --- a/trunk/arch/arm/plat-s3c24xx/Kconfig +++ b/trunk/arch/arm/plat-s3c24xx/Kconfig @@ -8,7 +8,7 @@ config PLAT_S3C24XX default y select NO_IOPORT select ARCH_REQUIRE_GPIOLIB - select S3C_DEV_NAND + select S3C_DEVICE_NAND select S3C_GPIO_CFG_S3C24XX help Base platform code for any Samsung S3C24XX device diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 0a9b5b8b2a19..67a2fa2caa49 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -19,8 +19,6 @@ 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" @@ -1666,28 +1664,6 @@ 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 @@ -1945,6 +1921,20 @@ 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 diff --git a/trunk/arch/mips/alchemy/common/platform.c b/trunk/arch/mips/alchemy/common/platform.c index 9e7814db3d03..3691630931d6 100644 --- a/trunk/arch/mips/alchemy/common/platform.c +++ b/trunk/arch/mips/alchemy/common/platform.c @@ -27,7 +27,6 @@ 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) { @@ -50,7 +49,6 @@ 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) \ diff --git a/trunk/arch/mips/alchemy/devboards/prom.c b/trunk/arch/mips/alchemy/devboards/prom.c index baeb21385058..b30df5c97ad3 100644 --- a/trunk/arch/mips/alchemy/devboards/prom.c +++ b/trunk/arch/mips/alchemy/devboards/prom.c @@ -54,9 +54,10 @@ void __init prom_init(void) prom_init_cmdline(); memsize_str = prom_getenv("memsize"); - if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize)) + if (!memsize_str) memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE; - + else + strict_strtoul(memsize_str, 0, &memsize); add_memory_region(0, memsize, BOOT_MEM_RAM); } diff --git a/trunk/arch/mips/ar7/clock.c b/trunk/arch/mips/ar7/clock.c index 2ca4ada1c291..fc0e7154e8d6 100644 --- a/trunk/arch/mips/ar7/clock.c +++ b/trunk/arch/mips/ar7/clock.c @@ -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); - mdelay(1); + msleep(1); writel(4, &clock->pll); while (readl(&clock->pll) & PLL_STATUS) ; writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll); - mdelay(75); + msleep(75); } static void __init tnetd7300_init_clocks(void) @@ -456,7 +456,7 @@ void clk_put(struct clk *clk) } EXPORT_SYMBOL(clk_put); -void __init ar7_init_clocks(void) +int __init ar7_init_clocks(void) { switch (ar7_chip_id()) { case AR7_CHIP_7100: @@ -472,4 +472,7 @@ void __init ar7_init_clocks(void) } /* adjust vbus clock rate */ vbus_clk.rate = bus_clk.rate / 2; + + return 0; } +arch_initcall(ar7_init_clocks); diff --git a/trunk/arch/mips/ar7/time.c b/trunk/arch/mips/ar7/time.c index 22c93213b233..5fb8a0134085 100644 --- a/trunk/arch/mips/ar7/time.c +++ b/trunk/arch/mips/ar7/time.c @@ -30,9 +30,6 @@ 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"); diff --git a/trunk/arch/mips/bcm47xx/setup.c b/trunk/arch/mips/bcm47xx/setup.c index c95f90bf734c..b1aee33efd11 100644 --- a/trunk/arch/mips/bcm47xx/setup.c +++ b/trunk/arch/mips/bcm47xx/setup.c @@ -32,6 +32,7 @@ #include #include #include +#include #include struct ssb_bus ssb_bcm47xx; @@ -56,112 +57,68 @@ static void bcm47xx_machine_halt(void) cpu_relax(); } -#define READ_FROM_NVRAM(_outvar, name, buf) \ - if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\ - sprom->_outvar = simple_strtoul(buf, NULL, 0); - -static void bcm47xx_fill_sprom(struct ssb_sprom *sprom) +static void str2eaddr(char *str, char *dest) { - 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; - } + int i = 0; + + if (str == NULL) { + memset(dest, 0, 6); + return; } - 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; - } + + for (;;) { + dest[i++] = (char) simple_strtoul(str, NULL, 16); + str += 2; + if (!*str++ || i == 6) + break; } } static int bcm47xx_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv) { - char buf[20]; + char buf[100]; /* Fill boardinfo structure */ memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); - 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) + 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) iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); - if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) + if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 || + nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); - bcm47xx_fill_sprom(&iv->sprom); + /* 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); - if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) - iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); + 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); return 0; } @@ -169,28 +126,12 @@ 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; diff --git a/trunk/arch/mips/include/asm/cpu.h b/trunk/arch/mips/include/asm/cpu.h index 86877539c6e8..06d59dcbe243 100644 --- a/trunk/arch/mips/include/asm/cpu.h +++ b/trunk/arch/mips/include/asm/cpu.h @@ -111,8 +111,8 @@ * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM */ -#define PRID_IMP_BMIPS32_REV4 0x4000 -#define PRID_IMP_BMIPS32_REV8 0x8000 +#define PRID_IMP_BMIPS4KC 0x4000 +#define PRID_IMP_BMIPS32 0x8000 #define PRID_IMP_BMIPS3300 0x9000 #define PRID_IMP_BMIPS3300_ALT 0x9100 #define PRID_IMP_BMIPS3300_BUG 0x0000 diff --git a/trunk/arch/mips/include/asm/elf.h b/trunk/arch/mips/include/asm/elf.h index 455c0ac7d4ea..fd1d39eb7431 100644 --- a/trunk/arch/mips/include/asm/elf.h +++ b/trunk/arch/mips/include/asm/elf.h @@ -249,8 +249,7 @@ extern struct mips_abi mips_abi_n32; #define SET_PERSONALITY(ex) \ do { \ - if (personality(current->personality) != PER_LINUX) \ - set_personality(PER_LINUX); \ + set_personality(PER_LINUX); \ \ current->thread.abi = &mips_abi; \ } while (0) @@ -297,8 +296,6 @@ do { \ #define SET_PERSONALITY(ex) \ do { \ - unsigned int p; \ - \ clear_thread_flag(TIF_32BIT_REGS); \ clear_thread_flag(TIF_32BIT_ADDR); \ \ @@ -307,8 +304,7 @@ do { \ else \ current->thread.abi = &mips_abi; \ \ - p = personality(current->personality); \ - if (p != PER_LINUX32 && p != PER_LINUX) \ + if (current->personality != PER_LINUX32) \ set_personality(PER_LINUX); \ } while (0) diff --git a/trunk/arch/mips/include/asm/io.h b/trunk/arch/mips/include/asm/io.h index 5b017f23e243..c98bf514ec7d 100644 --- a/trunk/arch/mips/include/asm/io.h +++ b/trunk/arch/mips/include/asm/io.h @@ -329,14 +329,10 @@ 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), "R" (*__mem)); \ + : "0" (__val), "m" (*__mem)); \ if (irq) \ local_irq_restore(__flags); \ } else \ @@ -359,16 +355,12 @@ 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) \ - : "R" (*__mem)); \ + : "m" (*__mem)); \ if (irq) \ local_irq_restore(__flags); \ } else { \ diff --git a/trunk/arch/mips/include/asm/mach-ar7/ar7.h b/trunk/arch/mips/include/asm/mach-ar7/ar7.h index 07d3fadb2443..7919d76186bf 100644 --- a/trunk/arch/mips/include/asm/mach-ar7/ar7.h +++ b/trunk/arch/mips/include/asm/mach-ar7/ar7.h @@ -201,6 +201,7 @@ static inline void ar7_device_off(u32 bit) } int __init ar7_gpio_init(void); -void __init ar7_init_clocks(void); + +int __init ar7_gpio_init(void); #endif /* __AR7_H__ */ diff --git a/trunk/arch/mips/include/asm/mach-bcm47xx/nvram.h b/trunk/arch/mips/include/asm/mach-bcm47xx/nvram.h index 9759588ba3cf..c58ebd8bc155 100644 --- a/trunk/arch/mips/include/asm/mach-bcm47xx/nvram.h +++ b/trunk/arch/mips/include/asm/mach-bcm47xx/nvram.h @@ -12,7 +12,6 @@ #define __NVRAM_H #include -#include struct nvram_header { u32 magic; @@ -37,10 +36,4 @@ 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 diff --git a/trunk/arch/mips/jz4740/board-qi_lb60.c b/trunk/arch/mips/jz4740/board-qi_lb60.c index 5c0a3575877c..5742bb4d78f4 100644 --- a/trunk/arch/mips/jz4740/board-qi_lb60.c +++ b/trunk/arch/mips/jz4740/board-qi_lb60.c @@ -5,7 +5,7 @@ * * Copyright (c) 2009 Qi Hardware inc., * Author: Xiangfu Liu - * Copyright 2010, Lars-Peter Clausen + * Copyright 2010, Lars-Petrer Clausen * * 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(6), + QI_LB60_GPIO_KEYIN(7), QI_LB60_GPIO_KEYIN8, }; diff --git a/trunk/arch/mips/jz4740/platform.c b/trunk/arch/mips/jz4740/platform.c index 1cc9e544d16b..95bc2b5b14f1 100644 --- a/trunk/arch/mips/jz4740/platform.c +++ b/trunk/arch/mips/jz4740/platform.c @@ -208,7 +208,7 @@ struct platform_device jz4740_i2s_device = { /* PCM */ struct platform_device jz4740_pcm_device = { - .name = "jz4740-pcm-audio", + .name = "jz4740-pcm", .id = -1, }; diff --git a/trunk/arch/mips/jz4740/prom.c b/trunk/arch/mips/jz4740/prom.c index 4a70407f55bb..cfeac15eb2e4 100644 --- a/trunk/arch/mips/jz4740/prom.c +++ b/trunk/arch/mips/jz4740/prom.c @@ -23,7 +23,7 @@ #include #include -static __init void jz4740_init_cmdline(int argc, char *argv[]) +void jz4740_init_cmdline(int argc, char *argv[]) { unsigned int count = COMMAND_LINE_SIZE - 1; int i; diff --git a/trunk/arch/mips/kernel/cevt-r4k.c b/trunk/arch/mips/kernel/cevt-r4k.c index 98c5a9737c14..2f4d7a99bcc2 100644 --- a/trunk/arch/mips/kernel/cevt-r4k.c +++ b/trunk/arch/mips/kernel/cevt-r4k.c @@ -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; } diff --git a/trunk/arch/mips/kernel/cpu-probe.c b/trunk/arch/mips/kernel/cpu-probe.c index 68dae7b6b5db..71620e19827a 100644 --- a/trunk/arch/mips/kernel/cpu-probe.c +++ b/trunk/arch/mips/kernel/cpu-probe.c @@ -905,8 +905,7 @@ 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_REV4: - case PRID_IMP_BMIPS32_REV8: + case PRID_IMP_BMIPS32: c->cputype = CPU_BMIPS32; __cpu_name[cpu] = "Broadcom BMIPS32"; break; @@ -934,6 +933,10 @@ 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; } } diff --git a/trunk/arch/mips/kernel/linux32.c b/trunk/arch/mips/kernel/linux32.c index 876a75cc376f..6343b4a5b835 100644 --- a/trunk/arch/mips/kernel/linux32.c +++ b/trunk/arch/mips/kernel/linux32.c @@ -251,15 +251,14 @@ 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(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; + personality == PER_LINUX) + personality = PER_LINUX32; + ret = sys_personality(personality); + if (ret == PER_LINUX32) + ret = PER_LINUX; return ret; } diff --git a/trunk/arch/mips/kernel/process.c b/trunk/arch/mips/kernel/process.c index ae167df73ddd..99960940d4a4 100644 --- a/trunk/arch/mips/kernel/process.c +++ b/trunk/arch/mips/kernel/process.c @@ -142,6 +142,7 @@ 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; diff --git a/trunk/arch/mips/kernel/prom.c b/trunk/arch/mips/kernel/prom.c index 9dbe58368953..e000b278f024 100644 --- a/trunk/arch/mips/kernel/prom.c +++ b/trunk/arch/mips/kernel/prom.c @@ -100,7 +100,7 @@ void __init device_tree_init(void) return; base = virt_to_phys((void *)initial_boot_params); - size = be32_to_cpu(initial_boot_params->totalsize); + size = initial_boot_params->totalsize; /* Before we do anything, lets reserve the dt blob */ reserve_mem_mach(base, size); diff --git a/trunk/arch/mips/kernel/smp-mt.c b/trunk/arch/mips/kernel/smp-mt.c index c0e81418ba21..43e7cdc5ded2 100644 --- a/trunk/arch/mips/kernel/smp-mt.c +++ b/trunk/arch/mips/kernel/smp-mt.c @@ -153,7 +153,7 @@ static void __cpuinit vsmp_init_secondary(void) { extern int gic_present; - /* This is Malta specific: IPI,performance and timer interrupts */ + /* This is Malta specific: IPI,performance and timer inetrrupts */ if (gic_present) change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP6 | STATUSF_IP7); diff --git a/trunk/arch/mips/kernel/traps.c b/trunk/arch/mips/kernel/traps.c index e97104302541..8e9fbe75894e 100644 --- a/trunk/arch/mips/kernel/traps.c +++ b/trunk/arch/mips/kernel/traps.c @@ -83,8 +83,7 @@ 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, - void *__user *fault_addr); + struct mips_fpu_struct *ctx, int has_fpu); void (*board_be_init)(void); int (*board_be_handler)(struct pt_regs *regs, int is_fixup); @@ -662,36 +661,12 @@ 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 = {0}; + siginfo_t info; if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP) @@ -700,7 +675,6 @@ 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 @@ -716,8 +690,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) lose_fpu(1); /* Run the emulator */ - sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, - &fault_addr); + sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1); /* * We can't allow the emulated instruction to leave any of @@ -729,7 +702,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) own_fpu(1); /* Using the FPU again. */ /* If something went wrong, signal */ - process_fpemu_return(sig, fault_addr); + if (sig) + force_sig(sig, current); return; } else if (fcr31 & FPU_CSR_INV_X) @@ -1022,11 +996,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, - ¤t->thread.fpu, - 0, &fault_addr); - if (!process_fpemu_return(sig, fault_addr)) + ¤t->thread.fpu, 0); + if (sig) + force_sig(sig, current); + else mt_ase_fp_affinity(); } diff --git a/trunk/arch/mips/kernel/vpe.c b/trunk/arch/mips/kernel/vpe.c index 6a1fdfef8fde..3eb3cde2f661 100644 --- a/trunk/arch/mips/kernel/vpe.c +++ b/trunk/arch/mips/kernel/vpe.c @@ -1092,10 +1092,6 @@ 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; @@ -1153,9 +1149,10 @@ static int vpe_release(struct inode *inode, struct file *filp) if (ret < 0) v->shared_ptr = NULL; - vfree(v->pbuffer); + // cleanup any temp buffers + if (v->pbuffer) + vfree(v->pbuffer); v->plen = 0; - return ret; } @@ -1172,6 +1169,11 @@ 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"); diff --git a/trunk/arch/mips/lib/memset.S b/trunk/arch/mips/lib/memset.S index 606c8a9efe3b..77dc3b20110a 100644 --- a/trunk/arch/mips/lib/memset.S +++ b/trunk/arch/mips/lib/memset.S @@ -161,16 +161,16 @@ FEXPORT(__bzero) .Lfwd_fixup: PTR_L t0, TI_TASK($28) - andi a2, 0x3f LONG_L t0, THREAD_BUADDR(t0) + andi a2, 0x3f LONG_ADDU a2, t1 jr ra LONG_SUBU a2, t0 .Lpartial_fixup: PTR_L t0, TI_TASK($28) - andi a2, LONGMASK LONG_L t0, THREAD_BUADDR(t0) + andi a2, LONGMASK LONG_ADDU a2, t1 jr ra LONG_SUBU a2, t0 diff --git a/trunk/arch/mips/loongson/common/env.c b/trunk/arch/mips/loongson/common/env.c index 11b193f848f8..ae4cff97a56c 100644 --- a/trunk/arch/mips/loongson/common/env.c +++ b/trunk/arch/mips/loongson/common/env.c @@ -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) \ - ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \ + strict_strtol((char *)p + strlen(option"="), \ + 10, &res); \ } while (0) void __init prom_init_env(void) diff --git a/trunk/arch/mips/math-emu/cp1emu.c b/trunk/arch/mips/math-emu/cp1emu.c index d32cb0503110..b2ad1b0910ff 100644 --- a/trunk/arch/mips/math-emu/cp1emu.c +++ b/trunk/arch/mips/math-emu/cp1emu.c @@ -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, void *__user *); + struct mips_fpu_struct *, mips_instruction); #endif /* Further private data for which no space exists in mips_fpu_struct */ @@ -208,23 +208,16 @@ 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, - void *__user *fault_addr) +static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) { mips_instruction ir; unsigned long emulpc, contpc; unsigned int cond; - if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) { + 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 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)) @@ -252,16 +245,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, #endif return SIGILL; } - if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) { + if (get_user(ir, (mips_instruction __user *) emulpc)) { 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 */ @@ -282,17 +269,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, u64 val; MIPS_FPU_EMU_INC_STATS(loads); - - if (!access_ok(VERIFY_READ, va, sizeof(u64))) { + if (get_user(val, va)) { 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; } @@ -304,16 +284,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, MIPS_FPU_EMU_INC_STATS(stores); DIFROMREG(val, MIPSInst_RT(ir)); - if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { + if (put_user(val, va)) { 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; } @@ -323,16 +297,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, u32 val; MIPS_FPU_EMU_INC_STATS(loads); - if (!access_ok(VERIFY_READ, va, sizeof(u32))) { + if (get_user(val, va)) { 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; } @@ -344,16 +312,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, MIPS_FPU_EMU_INC_STATS(stores); SIFROMREG(val, MIPSInst_RT(ir)); - if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) { + if (put_user(val, va)) { 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; } @@ -478,17 +440,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, contpc = (xcp->cp0_epc + (MIPSInst_SIMM(ir) << 2)); - 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, + 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; + return SIGBUS; } switch (MIPSInst_OPCODE(ir)) { @@ -551,8 +506,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, #if __mips >= 4 && __mips != 32 case cop1x_op:{ - int sig = fpux_emu(xcp, ctx, ir, fault_addr); - if (sig) + int sig; + + if ((sig = fpux_emu(xcp, ctx, ir))) return sig; break; } @@ -648,7 +604,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, void *__user *fault_addr) + mips_instruction ir) { unsigned rcsr = 0; /* resulting csr */ @@ -668,16 +624,10 @@ 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 (!access_ok(VERIFY_READ, va, sizeof(u32))) { + if (get_user(val, va)) { 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; @@ -688,15 +638,9 @@ 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 (!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; + return SIGBUS; } break; @@ -757,16 +701,10 @@ 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 (!access_ok(VERIFY_READ, va, sizeof(u64))) { + if (get_user(val, va)) { 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; @@ -776,16 +714,10 @@ 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 (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { + if (put_user(val, va)) { 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: @@ -1310,7 +1242,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, void *__user *fault_addr) + int has_fpu) { unsigned long oldepc, prevepc; mips_instruction insn; @@ -1320,16 +1252,10 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, do { prevepc = xcp->cp0_epc; - if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) { + 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 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 { @@ -1341,7 +1267,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, fault_addr); + sig = cop1Emulate(xcp, ctx); /* revert to mips rounding mode */ ieee754_csr.rm = mips_rm[ieee754_csr.rm]; } diff --git a/trunk/arch/mips/mm/dma-default.c b/trunk/arch/mips/mm/dma-default.c index 21ea14efb837..4fc1a0fbe007 100644 --- a/trunk/arch/mips/mm/dma-default.c +++ b/trunk/arch/mips/mm/dma-default.c @@ -288,7 +288,7 @@ int mips_dma_supported(struct device *dev, u64 mask) return plat_dma_supported(dev, mask); } -void dma_cache_sync(struct device *dev, void *vaddr, size_t size, +void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); @@ -298,8 +298,6 @@ void 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, diff --git a/trunk/arch/mips/mm/sc-mips.c b/trunk/arch/mips/mm/sc-mips.c index 9cca8de00545..505fecad4684 100644 --- a/trunk/arch/mips/mm/sc-mips.c +++ b/trunk/arch/mips/mm/sc-mips.c @@ -68,9 +68,6 @@ 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: @@ -86,7 +83,6 @@ 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) diff --git a/trunk/arch/mips/pmc-sierra/yosemite/py-console.c b/trunk/arch/mips/pmc-sierra/yosemite/py-console.c index 434d7b1a8c6a..b7f1d9c4a8a3 100644 --- a/trunk/arch/mips/pmc-sierra/yosemite/py-console.c +++ b/trunk/arch/mips/pmc-sierra/yosemite/py-console.c @@ -65,15 +65,11 @@ 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) - : "R" (vaddr)); + : "m" (vaddr)); write_c0_status(sr); ssnop_4(); @@ -93,15 +89,11 @@ 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) - : "R" (vaddr), "r" (c)); + : "m" (vaddr), "r" (c)); write_c0_status(sr); ssnop_4(); diff --git a/trunk/arch/mips/sibyte/swarm/setup.c b/trunk/arch/mips/sibyte/swarm/setup.c index 41707a245dea..c308989fc464 100644 --- a/trunk/arch/mips/sibyte/swarm/setup.c +++ b/trunk/arch/mips/sibyte/swarm/setup.c @@ -82,7 +82,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup) enum swarm_rtc_type { RTC_NONE, RTC_XICOR, - RTC_M41T81, + RTC_M4LT81 }; 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_M41T81: + case RTC_M4LT81: 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_M41T81: + case RTC_M4LT81: 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_M41T81; + swarm_rtc_type = RTC_M4LT81; #ifdef CONFIG_VT screen_info = (struct screen_info) { diff --git a/trunk/arch/mn10300/kernel/time.c b/trunk/arch/mn10300/kernel/time.c index 75da468090b9..f860a340acc9 100644 --- a/trunk/arch/mn10300/kernel/time.c +++ b/trunk/arch/mn10300/kernel/time.c @@ -40,17 +40,21 @@ unsigned long long sched_clock(void) unsigned long long ll; unsigned l[2]; } tsc64, result; - unsigned long tmp; + unsigned long tsc, tmp; unsigned product[3]; /* 96-bit intermediate value */ /* cnt32_to_63() is not safe with preemption */ preempt_disable(); - /* expand the tsc to 64-bits. + /* read the TSC value + */ + tsc = get_cycles(); + + /* expand 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(get_cycles()) & 0x7fffffffffffffffULL; + tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL; preempt_enable(); diff --git a/trunk/arch/tile/include/asm/signal.h b/trunk/arch/tile/include/asm/signal.h index 81d92a45cd4b..c1ee1d61d44c 100644 --- a/trunk/arch/tile/include/asm/signal.h +++ b/trunk/arch/tile/include/asm/signal.h @@ -25,7 +25,7 @@ #if defined(__KERNEL__) && !defined(__ASSEMBLY__) struct pt_regs; -int restore_sigcontext(struct pt_regs *, struct sigcontext __user *); +int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); void do_signal(struct pt_regs *regs); #endif diff --git a/trunk/arch/tile/kernel/compat_signal.c b/trunk/arch/tile/kernel/compat_signal.c index dbb0dfc7bece..543d6a33aa26 100644 --- a/trunk/arch/tile/kernel/compat_signal.c +++ b/trunk/arch/tile/kernel/compat_signal.c @@ -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(¤t->sighand->siglock); - if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) goto badframe; if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) goto badframe; - return 0; + return r0; badframe: force_sig(SIGSEGV, current); diff --git a/trunk/arch/tile/kernel/intvec_32.S b/trunk/arch/tile/kernel/intvec_32.S index 5eed4a02bf62..f5821626247f 100644 --- a/trunk/arch/tile/kernel/intvec_32.S +++ b/trunk/arch/tile/kernel/intvec_32.S @@ -1342,8 +1342,8 @@ handle_syscall: lw r20, r20 /* Jump to syscall handler. */ - jalr r20 -.Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */ + jalr r20; .Lhandle_syscall_link: + FEEDBACK_REENTER(handle_syscall) /* * Write our r0 onto the stack so it gets restored instead @@ -1352,9 +1352,6 @@ 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 @@ -1539,24 +1536,9 @@ 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_SIGRETURN(sys_rt_sigreturn, r0) +PTREGS_SYSCALL(sys_rt_sigreturn, r0) PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ diff --git a/trunk/arch/tile/kernel/process.c b/trunk/arch/tile/kernel/process.c index e90eb53173b0..8430f45daea6 100644 --- a/trunk/arch/tile/kernel/process.c +++ b/trunk/arch/tile/kernel/process.c @@ -211,13 +211,6 @@ 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. @@ -546,7 +539,6 @@ 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) diff --git a/trunk/arch/tile/kernel/signal.c b/trunk/arch/tile/kernel/signal.c index 1260321155f1..757407e36696 100644 --- a/trunk/arch/tile/kernel/signal.c +++ b/trunk/arch/tile/kernel/signal.c @@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, */ int restore_sigcontext(struct pt_regs *regs, - struct sigcontext __user *sc) + struct sigcontext __user *sc, long *pr0) { int err = 0; int i; @@ -75,15 +75,17 @@ int restore_sigcontext(struct pt_regs *regs, regs->faultnum = INT_SWINT_1_SIGRETURN; + err |= __get_user(*pr0, &sc->gregs[0]); return err; } -/* The assembly shim for this function arranges to ignore the return value. */ +/* sigreturn() returns long since it restores r0 in the interrupted code. */ 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; @@ -96,13 +98,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) goto badframe; if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) goto badframe; - return 0; + return r0; badframe: force_sig(SIGSEGV, current); diff --git a/trunk/arch/x86/boot/compressed/misc.c b/trunk/arch/x86/boot/compressed/misc.c index 325c05294fc4..23f315c9f215 100644 --- a/trunk/arch/x86/boot/compressed/misc.c +++ b/trunk/arch/x86/boot/compressed/misc.c @@ -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-(128<<20)-1) & 0x7fffffff)) + if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff)) error("Destination address too large"); #endif #ifndef CONFIG_RELOCATABLE diff --git a/trunk/arch/x86/include/asm/e820.h b/trunk/arch/x86/include/asm/e820.h index e99d55d74df5..5be1542fbfaf 100644 --- a/trunk/arch/x86/include/asm/e820.h +++ b/trunk/arch/x86/include/asm/e820.h @@ -72,9 +72,6 @@ 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; diff --git a/trunk/arch/x86/include/asm/kvm_host.h b/trunk/arch/x86/include/asm/kvm_host.h index f702f82aa1eb..9e6fe391094e 100644 --- a/trunk/arch/x86/include/asm/kvm_host.h +++ b/trunk/arch/x86/include/asm/kvm_host.h @@ -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 80 +#define KVM_MAX_CPUID_ENTRIES 40 #define KVM_NR_FIXED_MTRR_REGION 88 #define KVM_NR_VAR_MTRR 8 diff --git a/trunk/arch/x86/kernel/Makefile b/trunk/arch/x86/kernel/Makefile index 1e994754d323..9e13763b6092 100644 --- a/trunk/arch/x86/kernel/Makefile +++ b/trunk/arch/x86/kernel/Makefile @@ -45,7 +45,6 @@ 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 diff --git a/trunk/arch/x86/kernel/apic/apic.c b/trunk/arch/x86/kernel/apic/apic.c index 78218135b48e..3f838d537392 100644 --- a/trunk/arch/x86/kernel/apic/apic.c +++ b/trunk/arch/x86/kernel/apic/apic.c @@ -1389,14 +1389,6 @@ 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 diff --git a/trunk/arch/x86/kernel/apic/io_apic.c b/trunk/arch/x86/kernel/apic/io_apic.c index fadcd743a74f..7cc0a721f628 100644 --- a/trunk/arch/x86/kernel/apic/io_apic.c +++ b/trunk/arch/x86/kernel/apic/io_apic.c @@ -2430,12 +2430,13 @@ 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(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) { + if (unlikely(desc->status & IRQ_MOVE_PENDING)) { do_unmask_irq = 1; mask_ioapic(cfg); } @@ -3412,7 +3413,6 @@ 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); diff --git a/trunk/arch/x86/kernel/apic/probe_64.c b/trunk/arch/x86/kernel/apic/probe_64.c index d8c4a6feb286..f9e4e6a54073 100644 --- a/trunk/arch/x86/kernel/apic/probe_64.c +++ b/trunk/arch/x86/kernel/apic/probe_64.c @@ -79,6 +79,13 @@ 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. */ diff --git a/trunk/arch/x86/kernel/head_32.S b/trunk/arch/x86/kernel/head_32.S index c0dbd9ac24f0..bcece91dd311 100644 --- a/trunk/arch/x86/kernel/head_32.S +++ b/trunk/arch/x86/kernel/head_32.S @@ -60,18 +60,16 @@ #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(LOWMEM_PAGES) << PAGE_SHIFT +MAPPING_BEYOND_END = \ + PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT /* * Worst-case size of the kernel mapping we need to make: - * a relocatable kernel can live anywhere in lowmem, so we need to be able - * to map all of lowmem. + * the worst-case size of the kernel itself, plus the extra we need + * to map for the linear map. */ -KERNEL_PAGES = LOWMEM_PAGES +KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm RESERVE_BRK(pagetables, INIT_MAP_SIZE) @@ -622,13 +620,13 @@ ENTRY(initial_code) __PAGE_ALIGNED_BSS .align PAGE_SIZE_asm #ifdef CONFIG_X86_PAE -ENTRY(initial_pg_pmd) +initial_pg_pmd: .fill 1024*KPMDS,4,0 #else ENTRY(initial_page_table) .fill 1024,4,0 #endif -ENTRY(initial_pg_fixmap) +initial_pg_fixmap: .fill 1024,4,0 ENTRY(empty_zero_page) .fill 4096,1,0 diff --git a/trunk/arch/x86/kernel/hpet.c b/trunk/arch/x86/kernel/hpet.c index 4ff5968f12d2..ae03cab4352e 100644 --- a/trunk/arch/x86/kernel/hpet.c +++ b/trunk/arch/x86/kernel/hpet.c @@ -27,9 +27,6 @@ #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) /* @@ -302,9 +299,8 @@ static void hpet_legacy_clockevent_register(void) /* Calculate the min / max delta */ hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, &hpet_clockevent); - /* Setup minimum reprogramming delta. */ - hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, - &hpet_clockevent); + /* 5 usec minimum reprogramming delta. */ + hpet_clockevent.min_delta_ns = 5000; /* * Start hpet with the boot cpu mask and make it @@ -397,24 +393,22 @@ 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). 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 + * 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 * 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 HPET_MIN_CYCLES + * counter value after the write is less than 8 HPET cycles * away from the event or if the counter is already ahead of - * the event. The minimum programming delta for the generic - * clockevents code is set to 1.5 * HPET_MIN_CYCLES. + * the event. */ res = (s32)(cnt - hpet_readl(HPET_COUNTER)); - return res < HPET_MIN_CYCLES ? -ETIME : 0; + return res < 8 ? -ETIME : 0; } static void hpet_legacy_set_mode(enum clock_event_mode mode, diff --git a/trunk/arch/x86/kernel/resource.c b/trunk/arch/x86/kernel/resource.c deleted file mode 100644 index 2a26819bb6a8..000000000000 --- a/trunk/arch/x86/kernel/resource.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include - -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); - } -} diff --git a/trunk/arch/x86/kernel/setup.c b/trunk/arch/x86/kernel/setup.c index 85268f8eadf6..21c6746338af 100644 --- a/trunk/arch/x86/kernel/setup.c +++ b/trunk/arch/x86/kernel/setup.c @@ -769,6 +769,7 @@ 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(); diff --git a/trunk/arch/x86/kernel/xsave.c b/trunk/arch/x86/kernel/xsave.c index 547128546cc3..9c253bd65e24 100644 --- a/trunk/arch/x86/kernel/xsave.c +++ b/trunk/arch/x86/kernel/xsave.c @@ -394,8 +394,7 @@ 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_align(xstate_size, - __alignof__(struct xsave_struct)); + init_xstate_buf = alloc_bootmem(xstate_size); init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; clts(); diff --git a/trunk/arch/x86/kvm/svm.c b/trunk/arch/x86/kvm/svm.c index b81a9b7c2ca4..1ca12298ffc7 100644 --- a/trunk/arch/x86/kvm/svm.c +++ b/trunk/arch/x86/kvm/svm.c @@ -3494,10 +3494,6 @@ 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 */ diff --git a/trunk/arch/x86/kvm/vmx.c b/trunk/arch/x86/kvm/vmx.c index 81fcbe9515c5..ff21fdda0c53 100644 --- a/trunk/arch/x86/kvm/vmx.c +++ b/trunk/arch/x86/kvm/vmx.c @@ -4227,6 +4227,11 @@ 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; diff --git a/trunk/arch/x86/kvm/x86.c b/trunk/arch/x86/kvm/x86.c index b989e1f1e5d3..cdac9e592aa5 100644 --- a/trunk/arch/x86/kvm/x86.c +++ b/trunk/arch/x86/kvm/x86.c @@ -155,6 +155,11 @@ 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; @@ -4564,11 +4569,9 @@ static void kvm_timer_init(void) #ifdef CONFIG_CPU_FREQ struct cpufreq_policy policy; memset(&policy, 0, sizeof(policy)); - cpu = get_cpu(); - cpufreq_get_policy(&policy, cpu); + cpufreq_get_policy(&policy, get_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); @@ -5519,8 +5522,6 @@ 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; diff --git a/trunk/arch/x86/kvm/x86.h b/trunk/arch/x86/kvm/x86.h index c600da830ce0..2cea414489f3 100644 --- a/trunk/arch/x86/kvm/x86.h +++ b/trunk/arch/x86/kvm/x86.h @@ -70,11 +70,6 @@ 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); diff --git a/trunk/arch/x86/lguest/boot.c b/trunk/arch/x86/lguest/boot.c index 4996cf5f73a0..73b1e1a1f489 100644 --- a/trunk/arch/x86/lguest/boot.c +++ b/trunk/arch/x86/lguest/boot.c @@ -531,10 +531,7 @@ static void lguest_write_cr3(unsigned long cr3) { lguest_data.pgdir = cr3; lazy_hcall1(LHCALL_NEW_PGTABLE, cr3); - - /* 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; + cr3_changed = true; } static unsigned long lguest_read_cr3(void) @@ -706,9 +703,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: 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. + * 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. */ static void lguest_set_pte(pte_t *ptep, pte_t pteval) { @@ -1005,7 +1002,7 @@ static void lguest_time_init(void) clockevents_register_device(&lguest_clockevent); /* Finally, we unblock the timer interrupt. */ - clear_bit(0, lguest_data.blocked_interrupts); + enable_lguest_irq(0); } /* @@ -1352,6 +1349,9 @@ __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: diff --git a/trunk/arch/x86/lguest/i386_head.S b/trunk/arch/x86/lguest/i386_head.S index e7d5382ef263..4f420c2f2d55 100644 --- a/trunk/arch/x86/lguest/i386_head.S +++ b/trunk/arch/x86/lguest/i386_head.S @@ -4,7 +4,6 @@ #include #include #include -#include /*G:020 * Our story starts with the kernel booting into startup_32 in @@ -38,113 +37,9 @@ 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 diff --git a/trunk/arch/x86/pci/i386.c b/trunk/arch/x86/pci/i386.c index b1805b78842f..c4bb261c106e 100644 --- a/trunk/arch/x86/pci/i386.c +++ b/trunk/arch/x86/pci/i386.c @@ -65,13 +65,21 @@ 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 = res->start; + resource_size_t start = round_down(res->end - size + 1, align); if (res->flags & IORESOURCE_IO) { - if (skip_isa_ioresource_align(dev)) - return start; - if (start & 0x300) - start = (start + 0x3ff) & ~0x3ff; + + /* + * 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 */ } return start; } diff --git a/trunk/arch/x86/vdso/Makefile b/trunk/arch/x86/vdso/Makefile index b6552b189bcd..4a2afa1bac51 100644 --- a/trunk/arch/x86/vdso/Makefile +++ b/trunk/arch/x86/vdso/Makefile @@ -25,7 +25,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y) export CPPFLAGS_vdso.lds += -P -C -VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ +VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -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 = -m32 -Wl,-soname=linux-gate.so.1 +VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1 # This makes sure the $(obj) subdirectory exists even though vdso32/ # is not a kbuild sub-make subdirectory. diff --git a/trunk/block/blk-map.c b/trunk/block/blk-map.c index e663ac2d8e68..5d5dbe47c228 100644 --- a/trunk/block/blk-map.c +++ b/trunk/block/blk-map.c @@ -201,13 +201,12 @@ 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) diff --git a/trunk/block/blk-merge.c b/trunk/block/blk-merge.c index 74bc4a768f32..77b7c26df6b5 100644 --- a/trunk/block/blk-merge.c +++ b/trunk/block/blk-merge.c @@ -21,7 +21,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, return 0; fbio = bio; - cluster = blk_queue_cluster(q); + cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); 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 (!blk_queue_cluster(q)) + if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) 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 = blk_queue_cluster(q); + cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); /* * for each bio in rq diff --git a/trunk/block/blk-settings.c b/trunk/block/blk-settings.c index 36c8c1f2af18..701859fb9647 100644 --- a/trunk/block/blk-settings.c +++ b/trunk/block/blk-settings.c @@ -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->cluster = 1; + lim->no_cluster = 0; } 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_limits_max_hw_sectors - set hard and soft limit of max sectors for request - * @limits: the queue limits + * 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: @@ -244,7 +244,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit); * per-device basis in /sys/block//queue/max_sectors_kb. * The soft limit can not exceed max_hw_sectors. **/ -void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_sectors) +void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors) { if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) { max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9); @@ -252,23 +252,9 @@ void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_ __func__, max_hw_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); + q->limits.max_hw_sectors = max_hw_sectors; + q->limits.max_sectors = min_t(unsigned int, max_hw_sectors, + BLK_DEF_MAX_SECTORS); } EXPORT_SYMBOL(blk_queue_max_hw_sectors); @@ -478,6 +464,15 @@ 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); @@ -550,7 +545,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->cluster &= b->cluster; + t->no_cluster |= b->no_cluster; t->discard_zeroes_data &= b->discard_zeroes_data; /* Physical block size a multiple of the logical block size? */ @@ -646,6 +641,7 @@ 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]; @@ -656,6 +652,17 @@ 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); diff --git a/trunk/block/blk-sysfs.c b/trunk/block/blk-sysfs.c index 41fb69150b4d..013457f47fdc 100644 --- a/trunk/block/blk-sysfs.c +++ b/trunk/block/blk-sysfs.c @@ -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 (blk_queue_cluster(q)) + if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) return queue_var_show(queue_max_segment_size(q), (page)); return queue_var_show(PAGE_CACHE_SIZE, (page)); diff --git a/trunk/block/blk-throttle.c b/trunk/block/blk-throttle.c index 381b09bb562b..004be80fd894 100644 --- a/trunk/block/blk-throttle.c +++ b/trunk/block/blk-throttle.c @@ -355,12 +355,6 @@ 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) { @@ -397,16 +391,6 @@ 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; @@ -725,21 +709,26 @@ 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)); - /* - * 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) { + /* + * 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. + */ + 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], diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index 8e0f9256eb58..f291587d753e 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -2834,8 +2834,6 @@ 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; diff --git a/trunk/drivers/block/drbd/drbd_receiver.c b/trunk/drivers/block/drbd/drbd_receiver.c index 24487d4fb202..89d8a7cc4054 100644 --- a/trunk/drivers/block/drbd/drbd_receiver.c +++ b/trunk/drivers/block/drbd/drbd_receiver.c @@ -3627,17 +3627,15 @@ static void drbdd(struct drbd_conf *mdev) } shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header); - 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); + 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 (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; - } + 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; } rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs); diff --git a/trunk/drivers/block/drbd/drbd_req.h b/trunk/drivers/block/drbd/drbd_req.h index ab2bd09d54b4..181ea0364822 100644 --- a/trunk/drivers/block/drbd/drbd_req.h +++ b/trunk/drivers/block/drbd/drbd_req.h @@ -339,8 +339,7 @@ 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! - * Which means: don't use from bio endio callback. */ + * If you need it irqsave, do it your self! */ static inline int req_mod(struct drbd_request *req, enum drbd_req_event what) { diff --git a/trunk/drivers/block/drbd/drbd_worker.c b/trunk/drivers/block/drbd/drbd_worker.c index 34f224b018b3..47d223c2409c 100644 --- a/trunk/drivers/block/drbd/drbd_worker.c +++ b/trunk/drivers/block/drbd/drbd_worker.c @@ -193,10 +193,8 @@ 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); @@ -222,13 +220,7 @@ void drbd_endio_pri(struct bio *bio, int error) bio_put(req->private_bio); req->private_bio = ERR_PTR(error); - /* 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); + req_mod(req, what); } int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel) diff --git a/trunk/drivers/clocksource/sh_cmt.c b/trunk/drivers/clocksource/sh_cmt.c index f975d24890fa..d68d3aa1814b 100644 --- a/trunk/drivers/clocksource/sh_cmt.c +++ b/trunk/drivers/clocksource/sh_cmt.c @@ -283,21 +283,16 @@ 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); } @@ -364,7 +359,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); @@ -386,7 +381,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); } diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c index 68f09a868434..e3f7fc6f9565 100644 --- a/trunk/drivers/input/evdev.c +++ b/trunk/drivers/input/evdev.c @@ -534,73 +534,76 @@ 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) +static int evdev_handle_get_keycode(struct input_dev *dev, + void __user *p, size_t size) { - struct input_keymap_entry ke = { - .len = sizeof(unsigned int), - .flags = 0, - }; - int __user *ip = (int __user *)p; + struct input_keymap_entry ke; int error; - /* legacy case */ - if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) - return -EFAULT; + memset(&ke, 0, sizeof(ke)); - error = input_get_keycode(dev, &ke); - if (error) - return error; + if (size == sizeof(unsigned int[2])) { + /* legacy case */ + int __user *ip = (int __user *)p; - if (put_user(ke.keycode, ip + 1)) - return -EFAULT; + if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) + return -EFAULT; - return 0; -} + ke.len = sizeof(unsigned int); + ke.flags = 0; -static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p) -{ - struct input_keymap_entry ke; - int error; + error = input_get_keycode(dev, &ke); + if (error) + return error; - if (copy_from_user(&ke, p, sizeof(ke))) - return -EFAULT; + if (put_user(ke.keycode, ip + 1)) + return -EFAULT; - error = input_get_keycode(dev, &ke); - if (error) - return error; + } else { + size = min(size, sizeof(ke)); - if (copy_to_user(p, &ke, sizeof(ke))) - return -EFAULT; + if (copy_from_user(&ke, p, size)) + return -EFAULT; + error = input_get_keycode(dev, &ke); + if (error) + return error; + + if (copy_to_user(p, &ke, size)) + return -EFAULT; + } return 0; } -static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p) +static int evdev_handle_set_keycode(struct input_dev *dev, + void __user *p, size_t size) { - struct input_keymap_entry ke = { - .len = sizeof(unsigned int), - .flags = 0, - }; - int __user *ip = (int __user *)p; + struct input_keymap_entry ke; - if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) - return -EFAULT; + memset(&ke, 0, sizeof(ke)); - if (get_user(ke.keycode, ip + 1)) - return -EFAULT; + if (size == sizeof(unsigned int[2])) { + /* legacy case */ + int __user *ip = (int __user *)p; - return input_set_keycode(dev, &ke); -} + if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) + return -EFAULT; -static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) -{ - struct input_keymap_entry ke; + if (get_user(ke.keycode, ip + 1)) + return -EFAULT; - if (copy_from_user(&ke, p, sizeof(ke))) - return -EFAULT; + ke.len = sizeof(unsigned int); + ke.flags = 0; - if (ke.len > sizeof(ke.scancode)) - return -EINVAL; + } else { + size = min(size, sizeof(ke)); + + if (copy_from_user(&ke, p, size)) + return -EFAULT; + + if (ke.len > sizeof(ke.scancode)) + return -EINVAL; + } return input_set_keycode(dev, &ke); } @@ -666,18 +669,6 @@ 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); @@ -717,6 +708,12 @@ 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 */ diff --git a/trunk/drivers/input/tablet/wacom_wac.c b/trunk/drivers/input/tablet/wacom_wac.c index 435b0af401e4..4852b440960a 100644 --- a/trunk/drivers/input/tablet/wacom_wac.c +++ b/trunk/drivers/input/tablet/wacom_wac.c @@ -1436,8 +1436,6 @@ 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 = @@ -1512,7 +1510,6 @@ 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) }, diff --git a/trunk/drivers/md/dm-table.c b/trunk/drivers/md/dm-table.c index 4d705cea0f8c..90267f8d64ee 100644 --- a/trunk/drivers/md/dm-table.c +++ b/trunk/drivers/md/dm-table.c @@ -517,8 +517,9 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, */ if (q->merge_bvec_fn && !ti->type->merge) - blk_limits_max_hw_sectors(limits, - (unsigned int) (PAGE_SIZE >> 9)); + limits->max_sectors = + min_not_zero(limits->max_sectors, + (unsigned int) (PAGE_SIZE >> 9)); return 0; } EXPORT_SYMBOL_GPL(dm_set_device_limits); @@ -1130,6 +1131,11 @@ 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 diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index 175c424f201f..e71c5fa527f5 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -4295,6 +4295,9 @@ 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); diff --git a/trunk/drivers/media/common/saa7146_hlp.c b/trunk/drivers/media/common/saa7146_hlp.c index 1d1d8d200755..05bde9ccb770 100644 --- a/trunk/drivers/media/common/saa7146_hlp.c +++ b/trunk/drivers/media/common/saa7146_hlp.c @@ -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 = saa7146_format_by_fourcc(dev, pixelformat); + struct saa7146_format *sfmt = 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 = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); + struct saa7146_format *sfmt = 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 = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); + struct saa7146_format *sfmt = 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 = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); + struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); struct saa7146_vv *vv = dev->vv_data; u32 vdma1_prot_addr; diff --git a/trunk/drivers/media/common/saa7146_video.c b/trunk/drivers/media/common/saa7146_video.c index d246910129e8..741c5732b430 100644 --- a/trunk/drivers/media/common/saa7146_video.c +++ b/trunk/drivers/media/common/saa7146_video.c @@ -84,7 +84,7 @@ static struct saa7146_format formats[] = { static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format); -struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc) +struct saa7146_format* 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 = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); + struct saa7146_format *sfmt = 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 = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat); + fmt = 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 = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat); + fmt = 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 = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat); + fmt = 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 = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat); + fmt = 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 = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); + sfmt = 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 = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat); + sfmt = 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, diff --git a/trunk/drivers/media/radio/radio-aimslab.c b/trunk/drivers/media/radio/radio-aimslab.c index 05e832f61c3e..5bf4985daede 100644 --- a/trunk/drivers/media/radio/radio-aimslab.c +++ b/trunk/drivers/media/radio/radio-aimslab.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops rtrack_ioctl_ops = { @@ -412,6 +412,13 @@ 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); @@ -423,13 +430,6 @@ 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; } diff --git a/trunk/drivers/media/radio/radio-aztech.c b/trunk/drivers/media/radio/radio-aztech.c index dd8a6ab0d437..c22311393624 100644 --- a/trunk/drivers/media/radio/radio-aztech.c +++ b/trunk/drivers/media/radio/radio-aztech.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops aztech_ioctl_ops = { @@ -375,8 +375,6 @@ 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); @@ -385,6 +383,8 @@ 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; } diff --git a/trunk/drivers/media/radio/radio-cadet.c b/trunk/drivers/media/radio/radio-cadet.c index bc9ad0897c55..b701ea6e7c73 100644 --- a/trunk/drivers/media/radio/radio-cadet.c +++ b/trunk/drivers/media/radio/radio-cadet.c @@ -328,10 +328,11 @@ 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; @@ -339,15 +340,12 @@ 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; @@ -527,11 +525,9 @@ 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; } @@ -539,13 +535,11 @@ 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; } @@ -565,7 +559,7 @@ static const struct v4l2_file_operations cadet_fops = { .open = cadet_open, .release = cadet_release, .read = cadet_read, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, .poll = cadet_poll, }; diff --git a/trunk/drivers/media/radio/radio-gemtek-pci.c b/trunk/drivers/media/radio/radio-gemtek-pci.c index 28fa85ba2087..79039674a0e0 100644 --- a/trunk/drivers/media/radio/radio-gemtek-pci.c +++ b/trunk/drivers/media/radio/radio-gemtek-pci.c @@ -361,7 +361,7 @@ MODULE_DEVICE_TABLE(pci, gemtek_pci_id); static const struct v4l2_file_operations gemtek_pci_fops = { .owner = THIS_MODULE, - .unlocked_ioctl = video_ioctl2, + .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); diff --git a/trunk/drivers/media/radio/radio-gemtek.c b/trunk/drivers/media/radio/radio-gemtek.c index 259936422e49..73985f641f07 100644 --- a/trunk/drivers/media/radio/radio-gemtek.c +++ b/trunk/drivers/media/radio/radio-gemtek.c @@ -378,7 +378,7 @@ static int gemtek_probe(struct gemtek *gt) static const struct v4l2_file_operations gemtek_fops = { .owner = THIS_MODULE, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static int vidioc_querycap(struct file *file, void *priv, @@ -577,6 +577,12 @@ static int __init gemtek_init(void) gt->vdev.release = video_device_release_empty; video_set_drvdata(>->vdev, gt); + if (video_register_device(>->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; @@ -584,12 +590,6 @@ static int __init gemtek_init(void) if (initmute) gemtek_mute(gt); - if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { - v4l2_device_unregister(v4l2_dev); - release_region(gt->io, 1); - return -EBUSY; - } - return 0; } diff --git a/trunk/drivers/media/radio/radio-maestro.c b/trunk/drivers/media/radio/radio-maestro.c index 6af61bfeb178..08f1051979ca 100644 --- a/trunk/drivers/media/radio/radio-maestro.c +++ b/trunk/drivers/media/radio/radio-maestro.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops maestro_ioctl_ops = { @@ -383,20 +383,22 @@ 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: diff --git a/trunk/drivers/media/radio/radio-maxiradio.c b/trunk/drivers/media/radio/radio-maxiradio.c index 6459a220b0dd..255d40df4b46 100644 --- a/trunk/drivers/media/radio/radio-maxiradio.c +++ b/trunk/drivers/media/radio/radio-maxiradio.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { diff --git a/trunk/drivers/media/radio/radio-miropcm20.c b/trunk/drivers/media/radio/radio-miropcm20.c index 3fb76e3834c9..4ff885445fd4 100644 --- a/trunk/drivers/media/radio/radio-miropcm20.c +++ b/trunk/drivers/media/radio/radio-miropcm20.c @@ -33,7 +33,6 @@ struct pcm20 { unsigned long freq; int muted; struct snd_miro_aci *aci; - struct mutex lock; }; static struct pcm20 pcm20_card = { @@ -73,7 +72,7 @@ static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq) static const struct v4l2_file_operations pcm20_fops = { .owner = THIS_MODULE, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static int vidioc_querycap(struct file *file, void *priv, @@ -230,7 +229,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) { @@ -243,7 +242,6 @@ 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) diff --git a/trunk/drivers/media/radio/radio-rtrack2.c b/trunk/drivers/media/radio/radio-rtrack2.c index 8d6ea591bd18..a79296aac9a9 100644 --- a/trunk/drivers/media/radio/radio-rtrack2.c +++ b/trunk/drivers/media/radio/radio-rtrack2.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { @@ -315,10 +315,6 @@ 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); @@ -328,6 +324,10 @@ 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; } diff --git a/trunk/drivers/media/radio/radio-sf16fmi.c b/trunk/drivers/media/radio/radio-sf16fmi.c index b5a5f89e238a..985359d18aa5 100644 --- a/trunk/drivers/media/radio/radio-sf16fmi.c +++ b/trunk/drivers/media/radio/radio-sf16fmi.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops fmi_ioctl_ops = { @@ -382,9 +382,6 @@ 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); @@ -394,6 +391,8 @@ 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; } diff --git a/trunk/drivers/media/radio/radio-sf16fmr2.c b/trunk/drivers/media/radio/radio-sf16fmr2.c index dc3f04c52d5e..52c7bbb32b8b 100644 --- a/trunk/drivers/media/radio/radio-sf16fmr2.c +++ b/trunk/drivers/media/radio/radio-sf16fmr2.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops fmr2_ioctl_ops = { @@ -424,10 +424,6 @@ 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); @@ -435,6 +431,11 @@ 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; } diff --git a/trunk/drivers/media/radio/radio-si4713.c b/trunk/drivers/media/radio/radio-si4713.c index 726d367ad8d0..03829e6818bd 100644 --- a/trunk/drivers/media/radio/radio-si4713.c +++ b/trunk/drivers/media/radio/radio-si4713.c @@ -53,8 +53,7 @@ struct radio_si4713_device { /* radio_si4713_fops - file operations interface */ static const struct v4l2_file_operations radio_si4713_fops = { .owner = THIS_MODULE, - /* Note: locking is done at the subdev level in the i2c driver. */ - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; /* Video4Linux Interface */ diff --git a/trunk/drivers/media/radio/radio-tea5764.c b/trunk/drivers/media/radio/radio-tea5764.c index 0e71d816c725..789d2ec66e19 100644 --- a/trunk/drivers/media/radio/radio-tea5764.c +++ b/trunk/drivers/media/radio/radio-tea5764.c @@ -142,6 +142,7 @@ struct tea5764_device { struct video_device *videodev; struct tea5764_regs regs; struct mutex mutex; + int users; }; /* I2C code related */ @@ -457,10 +458,41 @@ 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, - .unlocked_ioctl = video_ioctl2, + .open = tea5764_open, + .release = tea5764_close, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops tea5764_ioctl_ops = { @@ -495,7 +527,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client, int ret; PDEBUG("probe"); - radio = kzalloc(sizeof(struct tea5764_device), GFP_KERNEL); + radio = kmalloc(sizeof(struct tea5764_device), GFP_KERNEL); if (!radio) return -ENOMEM; @@ -523,13 +555,6 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client, i2c_set_clientdata(client, radio); video_set_drvdata(radio->videodev, radio); - radio->videodev->lock = &radio->mutex; - - /* initialize and power off the chip */ - tea5764_i2c_read(radio); - tea5764_set_audout_mode(radio, V4L2_TUNER_MODE_STEREO); - tea5764_mute(radio, 1); - tea5764_power_down(radio); ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); if (ret < 0) { @@ -537,6 +562,12 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client, goto errrel; } + /* initialize and power off the chip */ + tea5764_i2c_read(radio); + tea5764_set_audout_mode(radio, V4L2_TUNER_MODE_STEREO); + tea5764_mute(radio, 1); + tea5764_power_down(radio); + PINFO("registered."); return 0; errrel: diff --git a/trunk/drivers/media/radio/radio-terratec.c b/trunk/drivers/media/radio/radio-terratec.c index a32663917059..fc1c860fd438 100644 --- a/trunk/drivers/media/radio/radio-terratec.c +++ b/trunk/drivers/media/radio/radio-terratec.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops terratec_ioctl_ops = { @@ -389,9 +389,6 @@ 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); @@ -399,6 +396,9 @@ 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; } diff --git a/trunk/drivers/media/radio/radio-timb.c b/trunk/drivers/media/radio/radio-timb.c index a185610b376b..b8bb3ef47df5 100644 --- a/trunk/drivers/media/radio/radio-timb.c +++ b/trunk/drivers/media/radio/radio-timb.c @@ -34,7 +34,6 @@ struct timbradio { struct v4l2_subdev *sd_dsp; struct video_device video_dev; struct v4l2_device v4l2_dev; - struct mutex lock; }; @@ -143,7 +142,7 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = { static const struct v4l2_file_operations timbradio_fops = { .owner = THIS_MODULE, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static int __devinit timbradio_probe(struct platform_device *pdev) @@ -165,7 +164,6 @@ 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)); @@ -173,7 +171,6 @@ 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); diff --git a/trunk/drivers/media/radio/radio-trust.c b/trunk/drivers/media/radio/radio-trust.c index 22fa9cc28abe..9d6dcf8af5b0 100644 --- a/trunk/drivers/media/radio/radio-trust.c +++ b/trunk/drivers/media/radio/radio-trust.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops trust_ioctl_ops = { @@ -396,6 +396,14 @@ 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 */ @@ -410,14 +418,6 @@ 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; } diff --git a/trunk/drivers/media/radio/radio-typhoon.c b/trunk/drivers/media/radio/radio-typhoon.c index 8dbbf08f2207..b1f630527dc1 100644 --- a/trunk/drivers/media/radio/radio-typhoon.c +++ b/trunk/drivers/media/radio/radio-typhoon.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .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 (mutefreq < 87000 || mutefreq > 108500) { + if (dev->mutefreq < 87000 || dev->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", mutefreq); + v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq); + dev->mutefreq <<= 4; + + /* mute card - prevents noisy bootups */ + typhoon_mute(dev); return 0; } diff --git a/trunk/drivers/media/radio/radio-zoltrix.c b/trunk/drivers/media/radio/radio-zoltrix.c index af99c5bd88c1..f31eab99c943 100644 --- a/trunk/drivers/media/radio/radio-zoltrix.c +++ b/trunk/drivers/media/radio/radio-zoltrix.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = { @@ -424,20 +424,6 @@ static int __init zoltrix_init(void) return res; } - mutex_init(&zol->lock); - - /* mute card - prevents noisy bootups */ - - /* this ensures that the volume is all the way down */ - - outb(0, zol->io); - outb(0, zol->io); - msleep(20); - inb(zol->io + 3); - - 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; @@ -452,6 +438,20 @@ static int __init zoltrix_init(void) } v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); + mutex_init(&zol->lock); + + /* mute card - prevents noisy bootups */ + + /* this ensures that the volume is all the way down */ + + outb(0, zol->io); + outb(0, zol->io); + msleep(20); + inb(zol->io + 3); + + zol->curvol = 0; + zol->stereo = 1; + return 0; } diff --git a/trunk/drivers/media/video/arv.c b/trunk/drivers/media/video/arv.c index f989f2820d88..31e7a123d19a 100644 --- a/trunk/drivers/media/video/arv.c +++ b/trunk/drivers/media/video/arv.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops ar_ioctl_ops = { diff --git a/trunk/drivers/media/video/bt8xx/bttv-driver.c b/trunk/drivers/media/video/bt8xx/bttv-driver.c index 0902ec041c7a..a529619e51f6 100644 --- a/trunk/drivers/media/video/bt8xx/bttv-driver.c +++ b/trunk/drivers/media/video/bt8xx/bttv-driver.c @@ -854,6 +854,7 @@ 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; @@ -883,9 +884,11 @@ 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; } @@ -937,6 +940,7 @@ 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; @@ -947,6 +951,8 @@ 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); } /* ----------------------------------------------------------------------- */ @@ -1707,20 +1713,28 @@ 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) @@ -1844,6 +1858,7 @@ 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; @@ -1859,6 +1874,7 @@ 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; } @@ -1882,6 +1898,7 @@ 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; @@ -1911,6 +1928,7 @@ static int bttv_enum_input(struct file *file, void *priv, i->std = BTTV_NORMS; err: + mutex_unlock(&btv->lock); return rc; } @@ -1920,7 +1938,9 @@ 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; } @@ -1932,6 +1952,7 @@ 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; @@ -1944,6 +1965,7 @@ 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; } @@ -1957,6 +1979,7 @@ 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; @@ -1972,6 +1995,7 @@ static int bttv_s_tuner(struct file *file, void *priv, btv->audio_mode_gpio(btv, t, 1); err: + mutex_unlock(&btv->lock); return 0; } @@ -1982,8 +2006,10 @@ 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; } @@ -1998,6 +2024,7 @@ 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; @@ -2012,6 +2039,7 @@ 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; } @@ -2144,6 +2172,7 @@ 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; @@ -2221,6 +2250,7 @@ limit_scaled_size_lock (struct bttv_fh * fh, rc = 0; /* success */ fail: + mutex_unlock(&btv->lock); return rc; } @@ -2252,7 +2282,9 @@ 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; @@ -2328,6 +2360,7 @@ 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, @@ -2358,6 +2391,13 @@ 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; @@ -2372,6 +2412,7 @@ 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; } @@ -2485,7 +2526,9 @@ 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; @@ -2571,6 +2614,7 @@ 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; @@ -2579,6 +2623,7 @@ 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; } @@ -2604,9 +2649,11 @@ 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; } @@ -2618,6 +2665,7 @@ 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 @@ -2727,8 +2775,10 @@ 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)) { @@ -2737,11 +2787,13 @@ 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)); @@ -2753,6 +2805,7 @@ 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; } @@ -2791,6 +2844,7 @@ 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; @@ -2822,6 +2876,7 @@ 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; } @@ -2900,6 +2955,7 @@ 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 { @@ -2907,6 +2963,7 @@ static int bttv_queryctrl(struct file *file, void *priv, *c = (NULL != ctrl) ? *ctrl : no_ctl; } + mutex_unlock(&btv->lock); return 0; } @@ -2917,8 +2974,10 @@ 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; } @@ -2934,6 +2993,7 @@ 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"); @@ -2945,6 +3005,7 @@ 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; } @@ -2953,7 +3014,9 @@ 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; } @@ -2965,7 +3028,9 @@ 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; } @@ -2980,7 +3045,9 @@ 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; } @@ -2998,7 +3065,9 @@ 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; } @@ -3022,14 +3091,17 @@ 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; } @@ -3041,6 +3113,7 @@ 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; } @@ -3063,8 +3136,12 @@ 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; @@ -3081,6 +3158,8 @@ 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; } @@ -3148,6 +3227,7 @@ 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)) @@ -3182,6 +3262,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) else rc = 0; err: + mutex_unlock(&fh->cap.vb_lock); return rc; } @@ -3212,11 +3293,23 @@ 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, @@ -3224,13 +3317,13 @@ static int bttv_open(struct file *file) V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct bttv_buffer), - fh, &btv->lock); + fh, NULL); 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, &btv->lock); + fh, NULL); set_tvnorm(btv,btv->tvnorm); set_input(btv, btv->input, btv->tvnorm); @@ -3253,6 +3346,7 @@ 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; } @@ -3261,6 +3355,7 @@ 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); @@ -3286,8 +3381,14 @@ 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); @@ -3297,6 +3398,7 @@ static int bttv_release(struct file *file) if (!btv->users) audio_mute(btv, 1); + mutex_unlock(&btv->lock); return 0; } @@ -3400,8 +3502,11 @@ 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++; @@ -3409,6 +3514,7 @@ 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; } @@ -3418,6 +3524,7 @@ 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); @@ -3425,6 +3532,7 @@ 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; } @@ -3453,6 +3561,7 @@ 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; @@ -3461,6 +3570,8 @@ 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; } @@ -3581,7 +3692,7 @@ static const struct v4l2_file_operations radio_fops = .open = radio_open, .read = radio_read, .release = radio_release, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, .poll = radio_poll, }; diff --git a/trunk/drivers/media/video/bw-qcam.c b/trunk/drivers/media/video/bw-qcam.c index c1193506131c..935e0c9a9674 100644 --- a/trunk/drivers/media/video/bw-qcam.c +++ b/trunk/drivers/media/video/bw-qcam.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, .read = qcam_read, }; diff --git a/trunk/drivers/media/video/c-qcam.c b/trunk/drivers/media/video/c-qcam.c index 24fc00965a12..6e4b19698c13 100644 --- a/trunk/drivers/media/video/c-qcam.c +++ b/trunk/drivers/media/video/c-qcam.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, .read = qcam_read, }; diff --git a/trunk/drivers/media/video/cafe_ccic.c b/trunk/drivers/media/video/cafe_ccic.c index 0dfff50891e4..260c666ce931 100644 --- a/trunk/drivers/media/video/cafe_ccic.c +++ b/trunk/drivers/media/video/cafe_ccic.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = { diff --git a/trunk/drivers/media/video/cx18/cx18-alsa-pcm.c b/trunk/drivers/media/video/cx18/cx18-alsa-pcm.c index 82d195be9197..8f55692db36d 100644 --- a/trunk/drivers/media/video/cx18/cx18-alsa-pcm.c +++ b/trunk/drivers/media/video/cx18/cx18-alsa-pcm.c @@ -218,13 +218,7 @@ 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) { - 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; + return snd_pcm_lib_ioctl(substream, cmd, arg); } diff --git a/trunk/drivers/media/video/cx18/cx18-streams.c b/trunk/drivers/media/video/cx18/cx18-streams.c index ab461e27d9dd..9045f1ece0eb 100644 --- a/trunk/drivers/media/video/cx18/cx18-streams.c +++ b/trunk/drivers/media/video/cx18/cx18-streams.c @@ -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 */ - .unlocked_ioctl = cx18_v4l2_ioctl, + .ioctl = cx18_v4l2_ioctl, .release = cx18_v4l2_close, .poll = cx18_v4l2_enc_poll, }; diff --git a/trunk/drivers/media/video/et61x251/et61x251_core.c b/trunk/drivers/media/video/et61x251/et61x251_core.c index bb164099ea2c..a5cfc76b40b7 100644 --- a/trunk/drivers/media/video/et61x251/et61x251_core.c +++ b/trunk/drivers/media/video/et61x251/et61x251_core.c @@ -2530,7 +2530,7 @@ static const struct v4l2_file_operations et61x251_fops = { .owner = THIS_MODULE, .open = et61x251_open, .release = et61x251_release, - .unlocked_ioctl = et61x251_ioctl, + .ioctl = et61x251_ioctl, .read = et61x251_read, .poll = et61x251_poll, .mmap = et61x251_mmap, diff --git a/trunk/drivers/media/video/gspca/sonixj.c b/trunk/drivers/media/video/gspca/sonixj.c index e23de57e2c73..330dadc00106 100644 --- a/trunk/drivers/media/video/gspca/sonixj.c +++ b/trunk/drivers/media/video/gspca/sonixj.c @@ -63,10 +63,7 @@ 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 @@ -99,22 +96,6 @@ 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); @@ -1774,6 +1755,141 @@ 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) @@ -1782,8 +1898,7 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; sd->bridge = id->driver_info >> 16; - sd->sensor = id->driver_info >> 8; - sd->flags = id->driver_info; + sd->sensor = id->driver_info; cam = &gspca_dev->cam; if (sd->sensor == SENSOR_ADCM1700) { @@ -1814,7 +1929,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, 0x00); + reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]); reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */ regF1 = gspca_dev->usb_buf[0]; if (gspca_dev->usb_err < 0) @@ -2308,17 +2423,10 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; - u8 reg01, reg17; - u8 reg0102[2]; + u8 reg1, reg17; 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[] = @@ -2340,85 +2448,7 @@ static int sd_start(struct gspca_dev *gspca_dev) /* initialize the bridge */ sn9c1xx = sn_tb[sd->sensor]; - - /* 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; - } + bridge_init(gspca_dev, sn9c1xx); /* initialize the sensor */ i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); @@ -2446,11 +2476,30 @@ static int sd_start(struct gspca_dev *gspca_dev) } reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); switch (sd->sensor) { - case SENSOR_OM6802: -/* case SENSOR_OV7648: * fixme: sometimes */ + 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; break; default: - reg17 |= DEF_EN; + reg17 = 0x60; break; } reg_w1(gspca_dev, 0x17, reg17); @@ -2497,67 +2546,95 @@ static int sd_start(struct gspca_dev *gspca_dev) init = NULL; mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - reg01 |= SYS_SEL_48M | V_TX_EN; - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x02; /* clock / 2 */ + 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 */ switch (sd->sensor) { case SENSOR_ADCM1700: init = adcm1700_sensor_param1; + reg1 = 0x46; + reg17 = 0xe2; break; case SENSOR_GC0307: init = gc0307_sensor_param1; - 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 */ + reg17 = 0xa2; + reg1 = 0x44; 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) { /* if 320x240 */ - reg01 &= ~SYS_SEL_48M; /* clk 24Mz */ - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x01; /* clock / 1 */ + if (mode) { +/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ + reg1 = 0x06; /* clk 24Mz */ + } else { + reg17 = 0x22; /* 640 MCKSIZE */ +/* reg1 = 0x06; * 640 clk 24Mz (done) */ } 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; - if (!mode) { /* if 640x480 */ - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x01; /* clock / 4 */ - } + reg17 = 0x64; /* 640 MCKSIZE */ break; case SENSOR_OV7630: init = ov7630_sensor_param1; + reg17 = 0xe2; + reg1 = 0x44; break; case SENSOR_OV7648: init = ov7648_sensor_param1; - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x01; /* clock / 1 */ + reg17 = 0x21; +/* reg1 = 0x42; * 42 - 46? */ 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; } @@ -2607,9 +2684,7 @@ static int sd_start(struct gspca_dev *gspca_dev) setjpegqual(gspca_dev); reg_w1(gspca_dev, 0x17, reg17); - reg_w1(gspca_dev, 0x01, reg01); - sd->reg01 = reg01; - sd->reg17 = reg17; + reg_w1(gspca_dev, 0x01, reg1); sethvflip(gspca_dev); setbrightness(gspca_dev); @@ -2631,64 +2706,41 @@ 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 reg01; - u8 reg17; + u8 data; + const u8 *sn9c1xx; - reg01 = sd->reg01; - reg17 = sd->reg17 & ~SEN_CLK_EN; + data = 0x0b; switch (sd->sensor) { - case SENSOR_ADCM1700: case SENSOR_GC0307: - 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 ? */ + data = 0x29; 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_MT9V111: - case SENSOR_OM6802: - case SENSOR_PO1030: - 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); + /* fall thru */ + case SENSOR_MT9V111: + case SENSOR_OV7630: + case SENSOR_PO1030: + data = 0x29; break; case SENSOR_SOI768: i2c_w8(gspca_dev, stopsoi768); + data = 0x29; break; } - - 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); + 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); /* Don't disable sensor clock as that disables the button on the cam */ /* reg_w1(gspca_dev, 0xf1, 0x01); */ } @@ -2902,18 +2954,14 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ #define BS(bridge, sensor) \ .driver_info = (BRIDGE_ ## bridge << 16) \ - | (SENSOR_ ## sensor << 8) -#define BSF(bridge, sensor, flags) \ - .driver_info = (BRIDGE_ ## bridge << 16) \ - | (SENSOR_ ## sensor << 8) \ - | (flags) + | SENSOR_ ## sensor 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), BSF(SN9C105, OV7660, PDN_INV)}, - {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)}, + {USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)}, + {USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)}, {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)}, {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)}, {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)}, diff --git a/trunk/drivers/media/video/meye.c b/trunk/drivers/media/video/meye.c index 48d2c2419c13..2be23bccd3c8 100644 --- a/trunk/drivers/media/video/meye.c +++ b/trunk/drivers/media/video/meye.c @@ -1659,7 +1659,7 @@ static const struct v4l2_file_operations meye_fops = { .open = meye_open, .release = meye_release, .mmap = meye_mmap, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, .poll = meye_poll, }; @@ -1831,6 +1831,12 @@ 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; @@ -1852,12 +1858,6 @@ 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", diff --git a/trunk/drivers/media/video/pms.c b/trunk/drivers/media/video/pms.c index 7551907f8c28..7129b50757db 100644 --- a/trunk/drivers/media/video/pms.c +++ b/trunk/drivers/media/video/pms.c @@ -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, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, .read = pms_read, }; diff --git a/trunk/drivers/media/video/sh_vou.c b/trunk/drivers/media/video/sh_vou.c index 07cf0c6c7c1f..4e5a8cf76ded 100644 --- a/trunk/drivers/media/video/sh_vou.c +++ b/trunk/drivers/media/video/sh_vou.c @@ -75,7 +75,6 @@ struct sh_vou_device { int pix_idx; struct videobuf_buffer *active; enum sh_vou_status status; - struct mutex fop_lock; }; struct sh_vou_file { @@ -236,7 +235,7 @@ static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb) vb->state = VIDEOBUF_NEEDS_INIT; } -/* Locking: caller holds fop_lock mutex */ +/* Locking: caller holds vq->vb_lock mutex */ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { @@ -258,7 +257,7 @@ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count, return 0; } -/* Locking: caller holds fop_lock mutex */ +/* Locking: caller holds vq->vb_lock mutex */ static int sh_vou_buf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field) @@ -307,7 +306,7 @@ static int sh_vou_buf_prepare(struct videobuf_queue *vq, return 0; } -/* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */ +/* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */ static void sh_vou_buf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { @@ -1191,7 +1190,7 @@ static int sh_vou_open(struct file *file) V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_FIELD_NONE, sizeof(struct videobuf_buffer), vdev, - &vou_dev->fop_lock); + NULL); return 0; } @@ -1293,7 +1292,7 @@ static const struct v4l2_file_operations sh_vou_fops = { .owner = THIS_MODULE, .open = sh_vou_open, .release = sh_vou_release, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, .mmap = sh_vou_mmap, .poll = sh_vou_poll, }; @@ -1332,7 +1331,6 @@ 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; @@ -1390,7 +1388,6 @@ 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); diff --git a/trunk/drivers/media/video/sn9c102/sn9c102_core.c b/trunk/drivers/media/video/sn9c102/sn9c102_core.c index f49fbfb7dc13..28e19daadec9 100644 --- a/trunk/drivers/media/video/sn9c102/sn9c102_core.c +++ b/trunk/drivers/media/video/sn9c102/sn9c102_core.c @@ -3238,7 +3238,7 @@ static const struct v4l2_file_operations sn9c102_fops = { .owner = THIS_MODULE, .open = sn9c102_open, .release = sn9c102_release, - .unlocked_ioctl = sn9c102_ioctl, + .ioctl = sn9c102_ioctl, .read = sn9c102_read, .poll = sn9c102_poll, .mmap = sn9c102_mmap, diff --git a/trunk/drivers/media/video/uvc/uvc_ctrl.c b/trunk/drivers/media/video/uvc/uvc_ctrl.c index 59f8a9ad3796..f169f7736677 100644 --- a/trunk/drivers/media/video/uvc/uvc_ctrl.c +++ b/trunk/drivers/media/video/uvc/uvc_ctrl.c @@ -785,7 +785,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id, } } -static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, +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,52 +944,6 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, 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 diff --git a/trunk/drivers/media/video/uvc/uvc_queue.c b/trunk/drivers/media/video/uvc/uvc_queue.c index f14581bd707f..ed6d5449741c 100644 --- a/trunk/drivers/media/video/uvc/uvc_queue.c +++ b/trunk/drivers/media/video/uvc/uvc_queue.c @@ -89,39 +89,6 @@ 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. * @@ -143,7 +110,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. */ @@ -184,6 +151,28 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, 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. */ @@ -379,82 +368,6 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue, 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. * diff --git a/trunk/drivers/media/video/uvc/uvc_v4l2.c b/trunk/drivers/media/video/uvc/uvc_v4l2.c index 8cf61e8a634f..6d15de9b5204 100644 --- a/trunk/drivers/media/video/uvc/uvc_v4l2.c +++ b/trunk/drivers/media/video/uvc/uvc_v4l2.c @@ -100,6 +100,40 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain, * 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 @@ -226,14 +260,12 @@ 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; @@ -257,21 +289,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, static int uvc_v4l2_get_format(struct uvc_streaming *stream, struct v4l2_format *fmt) { - struct uvc_format *format; - struct uvc_frame *frame; - int ret = 0; + struct uvc_format *format = stream->cur_format; + struct uvc_frame *frame = stream->cur_frame; if (fmt->type != stream->type) return -EINVAL; - mutex_lock(&stream->mutex); - format = stream->cur_format; - frame = stream->cur_frame; - - if (format == NULL || frame == NULL) { - ret = -EINVAL; - goto done; - } + if (format == NULL || frame == NULL) + return -EINVAL; fmt->fmt.pix.pixelformat = format->fcc; fmt->fmt.pix.width = frame->wWidth; @@ -282,9 +307,7 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream, fmt->fmt.pix.colorspace = format->colorspace; fmt->fmt.pix.priv = 0; -done: - mutex_unlock(&stream->mutex); - return ret; + return 0; } static int uvc_v4l2_set_format(struct uvc_streaming *stream, @@ -298,24 +321,18 @@ 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; -done: - mutex_unlock(&stream->mutex); - return ret; + return 0; } static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, @@ -326,10 +343,7 @@ 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); @@ -356,6 +370,7 @@ 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; @@ -364,36 +379,28 @@ 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); - - 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.dwFrameInterval = uvc_try_frame_interval(frame, interval); /* Probe the device with the new settings. */ ret = uvc_probe_video(stream, &probe); - if (ret < 0) { - mutex_unlock(&stream->mutex); + if (ret < 0) return ret; - } memcpy(&stream->ctrl, &probe, sizeof probe); - mutex_unlock(&stream->mutex); /* Return the actual frame period. */ timeperframe.numerator = probe.dwFrameInterval; @@ -521,9 +528,11 @@ 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. */ @@ -615,7 +624,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) } case VIDIOC_QUERYMENU: - return uvc_query_v4l2_menu(chain, arg); + return uvc_v4l2_query_menu(chain, arg); case VIDIOC_G_EXT_CTRLS: { @@ -896,17 +905,15 @@ 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; - - mutex_lock(&stream->mutex); - ccap->bounds.width = stream->cur_frame->wWidth; - ccap->bounds.height = stream->cur_frame->wHeight; - mutex_unlock(&stream->mutex); + ccap->bounds.width = frame->wWidth; + ccap->bounds.height = frame->wHeight; ccap->defrect = ccap->bounds; @@ -923,6 +930,8 @@ 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) @@ -931,10 +940,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - mutex_lock(&stream->mutex); - ret = uvc_alloc_buffers(&stream->queue, rb->count, - stream->ctrl.dwMaxVideoFrameSize); - mutex_unlock(&stream->mutex); + ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize); if (ret < 0) return ret; @@ -982,9 +988,7 @@ 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; @@ -1064,14 +1068,79 @@ 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"); - return uvc_queue_mmap(&stream->queue, vma); + 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; } static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) @@ -1088,7 +1157,7 @@ const struct v4l2_file_operations uvc_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, .release = uvc_v4l2_release, - .unlocked_ioctl = uvc_v4l2_ioctl, + .ioctl = uvc_v4l2_ioctl, .read = uvc_v4l2_read, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, diff --git a/trunk/drivers/media/video/uvc/uvc_video.c b/trunk/drivers/media/video/uvc/uvc_video.c index 5673d673504b..5555f0102838 100644 --- a/trunk/drivers/media/video/uvc/uvc_video.c +++ b/trunk/drivers/media/video/uvc/uvc_video.c @@ -293,6 +293,8 @@ 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 @@ -344,6 +346,7 @@ int uvc_probe_video(struct uvc_streaming *stream, } done: + mutex_unlock(&stream->mutex); return ret; } diff --git a/trunk/drivers/media/video/uvc/uvcvideo.h b/trunk/drivers/media/video/uvc/uvcvideo.h index 45f01e7e13d2..d97cf6d6a4f9 100644 --- a/trunk/drivers/media/video/uvc/uvcvideo.h +++ b/trunk/drivers/media/video/uvc/uvcvideo.h @@ -436,9 +436,7 @@ 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; @@ -576,8 +574,6 @@ 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); @@ -610,10 +606,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); diff --git a/trunk/drivers/media/video/v4l2-dev.c b/trunk/drivers/media/video/v4l2-dev.c index 359e23290a7e..03f7f4670e9b 100644 --- a/trunk/drivers/media/video/v4l2-dev.c +++ b/trunk/drivers/media/video/v4l2-dev.c @@ -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 = -ENODEV; + int ret = -EIO; if (!vdev->fops->read) return -EINVAL; - if (vdev->lock && mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; + if (vdev->lock) + mutex_lock(vdev->lock); 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 = -ENODEV; + int ret = -EIO; if (!vdev->fops->write) return -EINVAL; - if (vdev->lock && mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; + if (vdev->lock) + mutex_lock(vdev->lock); 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 = POLLERR | POLLHUP; + int ret = DEFAULT_POLLMASK; if (!vdev->fops->poll) - return DEFAULT_POLLMASK; + return ret; if (vdev->lock) mutex_lock(vdev->lock); if (video_is_registered(vdev)) @@ -238,45 +238,20 @@ 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_interruptible(vdev->lock)) - return -ERESTARTSYS; + if (vdev->lock) + mutex_lock(vdev->lock); 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) { - /* 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. - */ + /* TODO: convert all drivers to unlocked_ioctl */ static DEFINE_MUTEX(v4l2_ioctl_mutex); - struct mutex *m = vdev->v4l2_dev ? - &vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex; - if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m)) - return -ERESTARTSYS; + mutex_lock(&v4l2_ioctl_mutex); if (video_is_registered(vdev)) ret = vdev->fops->ioctl(filp, cmd, arg); - if (cmd != VIDIOC_DQBUF) - mutex_unlock(m); + mutex_unlock(&v4l2_ioctl_mutex); } else ret = -ENOTTY; @@ -290,8 +265,8 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) if (!vdev->fops->mmap) return ret; - if (vdev->lock && mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; + if (vdev->lock) + mutex_lock(vdev->lock); if (video_is_registered(vdev)) ret = vdev->fops->mmap(filp, vm); if (vdev->lock) @@ -309,7 +284,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 || !video_is_registered(vdev)) { + if (vdev == NULL) { mutex_unlock(&videodev_lock); return -ENODEV; } @@ -317,10 +292,8 @@ 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_interruptible(vdev->lock)) { - ret = -ERESTARTSYS; - goto err; - } + if (vdev->lock) + mutex_lock(vdev->lock); if (video_is_registered(vdev)) ret = vdev->fops->open(filp); else @@ -329,7 +302,6 @@ 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); @@ -624,12 +596,7 @@ 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); diff --git a/trunk/drivers/media/video/v4l2-device.c b/trunk/drivers/media/video/v4l2-device.c index 7fe6f92af480..0b08f96b74a5 100644 --- a/trunk/drivers/media/video/v4l2-device.c +++ b/trunk/drivers/media/video/v4l2-device.c @@ -35,7 +35,6 @@ 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 */ diff --git a/trunk/drivers/media/video/w9966.c b/trunk/drivers/media/video/w9966.c index 019ee206cbee..635420d8d84a 100644 --- a/trunk/drivers/media/video/w9966.c +++ b/trunk/drivers/media/video/w9966.c @@ -815,7 +815,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, static const struct v4l2_file_operations w9966_fops = { .owner = THIS_MODULE, - .unlocked_ioctl = video_ioctl2, + .ioctl = video_ioctl2, .read = w9966_v4l_read, }; diff --git a/trunk/drivers/pci/bus.c b/trunk/drivers/pci/bus.c index 69546e9213dd..003170ea2e39 100644 --- a/trunk/drivers/pci/bus.c +++ b/trunk/drivers/pci/bus.c @@ -64,6 +64,77 @@ 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 @@ -89,9 +160,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t), void *alignf_data) { - int i, ret = -ENOMEM; + int ret = -ENOMEM; struct resource *r; resource_size_t max = -1; + unsigned int type = res->flags & IORESOURCE_TYPE_BITS; type_mask |= IORESOURCE_IO | IORESOURCE_MEM; @@ -99,10 +171,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, if (!(res->flags & IORESOURCE_MEM_64)) max = PCIBIOS_MAX_MEM_32; - pci_bus_for_each_resource(bus, r, i) { - if (!r) - continue; - + /* 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)) { /* type_mask must match */ if ((res->flags ^ r->flags) & type_mask) continue; diff --git a/trunk/drivers/pci/dmar.c b/trunk/drivers/pci/dmar.c index 09933eb9126b..0157708d474d 100644 --- a/trunk/drivers/pci/dmar.c +++ b/trunk/drivers/pci/dmar.c @@ -1417,11 +1417,6 @@ 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; diff --git a/trunk/drivers/pci/quirks.c b/trunk/drivers/pci/quirks.c index 53a786fd0d40..6f9350cabbd5 100644 --- a/trunk/drivers/pci/quirks.c +++ b/trunk/drivers/pci/quirks.c @@ -2329,9 +2329,6 @@ 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))) { @@ -2767,29 +2764,6 @@ 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) diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index 4a3842212c50..5b6bbaea59fe 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -1637,8 +1637,9 @@ 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) - q->limits.cluster = 0; + queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); /* * set a reasonable default alignment on word boundaries: the diff --git a/trunk/drivers/staging/cx25821/cx25821-video.c b/trunk/drivers/staging/cx25821/cx25821-video.c index 52389308f333..e7f1d5778cec 100644 --- a/trunk/drivers/staging/cx25821/cx25821-video.c +++ b/trunk/drivers/staging/cx25821/cx25821-video.c @@ -92,7 +92,7 @@ int cx25821_get_format_size(void) return ARRAY_SIZE(formats); } -struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc) +struct cx25821_fmt *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 = cx25821_format_by_fourcc(pix_format); + fh->fmt = 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 = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); + fh->fmt = 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 = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); + fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (NULL == fmt) return -EINVAL; diff --git a/trunk/drivers/staging/cx25821/cx25821-video.h b/trunk/drivers/staging/cx25821/cx25821-video.h index a2415d33235b..cc6034b1a95d 100644 --- a/trunk/drivers/staging/cx25821/cx25821-video.h +++ b/trunk/drivers/staging/cx25821/cx25821-video.h @@ -87,7 +87,7 @@ extern unsigned int vid_limit; #define FORMAT_FLAGS_PACKED 0x01 extern struct cx25821_fmt formats[]; -extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc); +extern struct cx25821_fmt *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, diff --git a/trunk/drivers/tty/n_gsm.c b/trunk/drivers/tty/n_gsm.c index c5f8e5bda2b2..81b46585edf7 100644 --- a/trunk/drivers/tty/n_gsm.c +++ b/trunk/drivers/tty/n_gsm.c @@ -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 >> 7); /* bits 7 - 15 */ - *--dp = (msg->len & 127) << 1; /* bits 0 - 6 */ + *--dp = ((msg->len & 127) << 1) | EA; + *--dp = (msg->len >> 6) & 0xfe; } } @@ -968,8 +968,6 @@ 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); diff --git a/trunk/drivers/usb/core/Kconfig b/trunk/drivers/usb/core/Kconfig index bcc24779ba0e..9eed5b52d9de 100644 --- a/trunk/drivers/usb/core/Kconfig +++ b/trunk/drivers/usb/core/Kconfig @@ -107,19 +107,11 @@ config USB_SUSPEND If you are unsure about this, say N here. config USB_OTG - bool "OTG support" + bool 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" diff --git a/trunk/drivers/usb/gadget/composite.c b/trunk/drivers/usb/gadget/composite.c index 8572dad5ecbb..7b5cc16e4a0b 100644 --- a/trunk/drivers/usb/gadget/composite.c +++ b/trunk/drivers/usb/gadget/composite.c @@ -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,6 +1107,14 @@ 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 @@ -1118,14 +1126,6 @@ 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 && diff --git a/trunk/drivers/usb/host/xhci-mem.c b/trunk/drivers/usb/host/xhci-mem.c index 1d0f45f0e7a6..0fae58ef8afe 100644 --- a/trunk/drivers/usb/host/xhci-mem.c +++ b/trunk/drivers/usb/host/xhci-mem.c @@ -1680,7 +1680,6 @@ 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) @@ -1759,20 +1758,16 @@ 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->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++; - } + 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++; + } } if (xhci->num_usb3_ports) { xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)* diff --git a/trunk/drivers/usb/misc/uss720.c b/trunk/drivers/usb/misc/uss720.c index 4ff21587ab03..796e2f68f749 100644 --- a/trunk/drivers/usb/misc/uss720.c +++ b/trunk/drivers/usb/misc/uss720.c @@ -3,7 +3,7 @@ /* * uss720.c -- USS720 USB Parport Cable. * - * Copyright (C) 1999, 2005, 2010 + * Copyright (C) 1999, 2005 * Thomas Sailer (t.sailer@alumni.ethz.ch) * * This program is free software; you can redistribute it and/or modify @@ -776,8 +776,6 @@ 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 */ }; diff --git a/trunk/drivers/usb/serial/ftdi_sio.c b/trunk/drivers/usb/serial/ftdi_sio.c index 2dec50013528..6a50965e23f2 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.c +++ b/trunk/drivers/usb/serial/ftdi_sio.c @@ -796,7 +796,6 @@ 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 */ diff --git a/trunk/drivers/usb/serial/ftdi_sio_ids.h b/trunk/drivers/usb/serial/ftdi_sio_ids.h index bf0867285481..1286f1e23d8c 100644 --- a/trunk/drivers/usb/serial/ftdi_sio_ids.h +++ b/trunk/drivers/usb/serial/ftdi_sio_ids.h @@ -1080,11 +1080,6 @@ #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/) */ diff --git a/trunk/drivers/usb/storage/unusual_devs.h b/trunk/drivers/usb/storage/unusual_devs.h index fcc1e32ce256..6ccdd3dd5259 100644 --- a/trunk/drivers/usb/storage/unusual_devs.h +++ b/trunk/drivers/usb/storage/unusual_devs.h @@ -481,13 +481,6 @@ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64), -/* Reported by Vitaly Kuznetsov */ -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 . * Device uses standards-violating 32-byte Bulk Command Block Wrappers and * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. diff --git a/trunk/drivers/video/omap/Kconfig b/trunk/drivers/video/omap/Kconfig index 083c8fe53e24..455c6055325d 100644 --- a/trunk/drivers/video/omap/Kconfig +++ b/trunk/drivers/video/omap/Kconfig @@ -1,7 +1,7 @@ config FB_OMAP tristate "OMAP frame buffer support (EXPERIMENTAL)" - depends on FB && (OMAP2_DSS = "n") - depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3 + depends on FB && ARCH_OMAP && (OMAP2_DSS = "n") + select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/trunk/drivers/video/omap2/vram.c b/trunk/drivers/video/omap2/vram.c index 9441e2eb3dee..2fd7e5271be9 100644 --- a/trunk/drivers/video/omap2/vram.c +++ b/trunk/drivers/video/omap2/vram.c @@ -551,7 +551,7 @@ void __init omap_vram_reserve_sdram_memblock(void) if (!size) return; - size = ALIGN(size, SZ_2M); + size = PAGE_ALIGN(size); if (paddr) { if (paddr & ~PAGE_MASK) { @@ -576,7 +576,7 @@ void __init omap_vram_reserve_sdram_memblock(void) return; } } else { - paddr = memblock_alloc(size, SZ_2M); + paddr = memblock_alloc(size, PAGE_SIZE); } memblock_free(paddr, size); diff --git a/trunk/fs/btrfs/export.c b/trunk/fs/btrfs/export.c index 659f532d26a0..6f0444473594 100644 --- a/trunk/fs/btrfs/export.c +++ b/trunk/fs/btrfs/export.c @@ -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; - struct dentry *dentry; + static struct dentry *dentry; struct btrfs_root *root = BTRFS_I(dir)->root; struct btrfs_path *path; struct extent_buffer *leaf; diff --git a/trunk/fs/ceph/dir.c b/trunk/fs/ceph/dir.c index d902948a90d8..158c700fdca5 100644 --- a/trunk/fs/ceph/dir.c +++ b/trunk/fs/ceph/dir.c @@ -40,8 +40,7 @@ int ceph_init_dentry(struct dentry *dentry) if (dentry->d_fsdata) return 0; - if (dentry->d_parent == NULL || /* nfs fh_to_dentry */ - ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP) + if (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; diff --git a/trunk/fs/ceph/file.c b/trunk/fs/ceph/file.c index 7d0e4a82d898..8d79b8912e31 100644 --- a/trunk/fs/ceph/file.c +++ b/trunk/fs/ceph/file.c @@ -282,8 +282,7 @@ 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, - unsigned long buf_align) + int *checkeof, bool align_to_pages) { struct ceph_fs_client *fsc = ceph_inode_to_client(inode); struct ceph_inode_info *ci = ceph_inode(inode); @@ -308,7 +307,7 @@ static int striped_read(struct inode *inode, more: if (align_to_pages) - page_align = (pos - io_align + buf_align) & ~PAGE_MASK; + page_align = (pos - io_align) & ~PAGE_MASK; else page_align = pos & ~PAGE_MASK; this_len = left; @@ -377,18 +376,16 @@ 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, ret; + int num_pages = calc_pages_for(off, len); + int 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) { - 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); + if (file->f_flags & O_DIRECT) + pages = ceph_get_direct_page_vector(data, num_pages); + else pages = ceph_alloc_page_vector(num_pages, GFP_NOFS); - } if (IS_ERR(pages)) return PTR_ERR(pages); @@ -403,8 +400,7 @@ 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, - (unsigned long)data & ~PAGE_MASK); + file->f_flags & O_DIRECT); if (ret >= 0 && (file->f_flags & O_DIRECT) == 0) ret = ceph_copy_page_vector_to_user(pages, data, off, ret); @@ -413,7 +409,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, true); + ceph_put_page_vector(pages, num_pages); else ceph_release_page_vector(pages, num_pages); dout("sync_read result %d\n", ret); @@ -460,7 +456,6 @@ 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; @@ -476,7 +471,6 @@ 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) @@ -502,15 +496,12 @@ 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 + buf_align) & ~PAGE_MASK; - num_pages = calc_pages_for((unsigned long)data, len); - } else { + page_align = (pos - io_align) & ~PAGE_MASK; + 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, @@ -521,8 +512,10 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data, 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, false); + pages = ceph_get_direct_page_vector(data, num_pages); if (IS_ERR(pages)) { ret = PTR_ERR(pages); goto out; @@ -572,7 +565,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data, } if (file->f_flags & O_DIRECT) - ceph_put_page_vector(pages, num_pages, false); + ceph_put_page_vector(pages, num_pages); else if (file->f_flags & O_SYNC) ceph_release_page_vector(pages, num_pages); diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 4ff7ca530533..5362af9b7372 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -1748,9 +1748,6 @@ 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 diff --git a/trunk/fs/nilfs2/gcinode.c b/trunk/fs/nilfs2/gcinode.c index caf9a6a3fb54..33ad25ddd5c4 100644 --- a/trunk/fs/nilfs2/gcinode.c +++ b/trunk/fs/nilfs2/gcinode.c @@ -176,6 +176,7 @@ 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); @@ -185,6 +186,14 @@ 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; } diff --git a/trunk/fs/nilfs2/ioctl.c b/trunk/fs/nilfs2/ioctl.c index b185e937a335..e00d9457c256 100644 --- a/trunk/fs/nilfs2/ioctl.c +++ b/trunk/fs/nilfs2/ioctl.c @@ -337,7 +337,6 @@ 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; @@ -354,17 +353,6 @@ 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); diff --git a/trunk/fs/notify/fanotify/fanotify.c b/trunk/fs/notify/fanotify/fanotify.c index f35794b97e8e..b04f88eed09e 100644 --- a/trunk/fs/notify/fanotify/fanotify.c +++ b/trunk/fs/notify/fanotify/fanotify.c @@ -92,11 +92,7 @@ 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 || - atomic_read(&group->fanotify_data.bypass_perm)); - - if (!event->response) /* bypass_perm set */ - return 0; + wait_event(group->fanotify_data.access_waitq, event->response); /* userspace responded, convert to something usable */ spin_lock(&event->lock); diff --git a/trunk/fs/notify/fanotify/fanotify_user.c b/trunk/fs/notify/fanotify/fanotify_user.c index 8b61220cffc5..063224812b7e 100644 --- a/trunk/fs/notify/fanotify/fanotify_user.c +++ b/trunk/fs/notify/fanotify/fanotify_user.c @@ -106,29 +106,20 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) return client_fd; } -static int fill_event_metadata(struct fsnotify_group *group, +static ssize_t 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); - 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; - } + metadata->fd = create_fd(group, event); - return ret; + return metadata->fd; } #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS @@ -209,7 +200,7 @@ static int prepare_for_access_response(struct fsnotify_group *group, mutex_lock(&group->fanotify_data.access_mutex); - if (atomic_read(&group->fanotify_data.bypass_perm)) { + if (group->fanotify_data.bypass_perm) { mutex_unlock(&group->fanotify_data.access_mutex); kmem_cache_free(fanotify_response_event_cache, re); event->response = FAN_ALLOW; @@ -266,34 +257,24 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, pr_debug("%s: group=%p event=%p\n", __func__, group, event); - ret = fill_event_metadata(group, &fanotify_event_metadata, event); - if (ret < 0) - goto out; + fd = fill_event_metadata(group, &fanotify_event_metadata, event); + if (fd < 0) + return fd; - 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, - fanotify_event_metadata.event_len)) + if (copy_to_user(buf, &fanotify_event_metadata, FAN_EVENT_METADATA_LEN)) goto out_kill_access_response; - return fanotify_event_metadata.event_len; + return FAN_EVENT_METADATA_LEN; out_kill_access_response: remove_access_response(group, event, fd); out_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 + sys_close(fd); return ret; } @@ -401,7 +382,7 @@ static int fanotify_release(struct inode *ignored, struct file *file) mutex_lock(&group->fanotify_data.access_mutex); - atomic_inc(&group->fanotify_data.bypass_perm); + group->fanotify_data.bypass_perm = true; 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, @@ -605,10 +586,11 @@ 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; @@ -618,16 +600,17 @@ 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) - goto err; + if (ret) { + fanotify_free_mark(fsn_mark); + return ret; + } } 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); -err: - fsnotify_put_mark(fsn_mark); - return ret; + + return 0; } static int fanotify_add_inode_mark(struct fsnotify_group *group, @@ -636,7 +619,6 @@ 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); @@ -652,6 +634,8 @@ 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; @@ -661,16 +645,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) - goto err; + if (ret) { + fanotify_free_mark(fsn_mark); + return ret; + } } 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); -err: - fsnotify_put_mark(fsn_mark); - return ret; + return 0; } /* fanotify syscalls */ @@ -703,10 +687,8 @@ 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)) { - free_uid(user); + if (IS_ERR(group)) return PTR_ERR(group); - } group->fanotify_data.user = user; atomic_inc(&user->fanotify_listeners); @@ -716,7 +698,6 @@ 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: @@ -783,10 +764,8 @@ 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: /* fallthrough */ + case FAN_MARK_ADD: case FAN_MARK_REMOVE: - if (!mask) - return -EINVAL; case FAN_MARK_FLUSH: break; default: diff --git a/trunk/fs/notify/inotify/inotify_user.c b/trunk/fs/notify/inotify/inotify_user.c index 4cd5d5d78f9f..444c305a468c 100644 --- a/trunk/fs/notify/inotify/inotify_user.c +++ b/trunk/fs/notify/inotify/inotify_user.c @@ -752,7 +752,6 @@ 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); diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index 36ab42c9bb99..aae86fd10c4f 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -250,7 +250,7 @@ struct queue_limits { unsigned char misaligned; unsigned char discard_misaligned; - unsigned char cluster; + unsigned char no_cluster; signed char discard_zeroes_data; }; @@ -380,6 +380,7 @@ 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 */ @@ -402,6 +403,7 @@ 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)) @@ -508,11 +510,6 @@ 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 */ @@ -808,7 +805,6 @@ 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); diff --git a/trunk/include/linux/bootmem.h b/trunk/include/linux/bootmem.h index 499dfe982a0e..266ab9291232 100644 --- a/trunk/include/linux/bootmem.h +++ b/trunk/include/linux/bootmem.h @@ -105,8 +105,6 @@ 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) \ diff --git a/trunk/include/linux/ceph/libceph.h b/trunk/include/linux/ceph/libceph.h index 72c72bfccb88..9e76d35670d2 100644 --- a/trunk/include/linux/ceph/libceph.h +++ b/trunk/include/linux/ceph/libceph.h @@ -227,10 +227,8 @@ 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, - bool write_page); -extern void ceph_put_page_vector(struct page **pages, int num_pages, - bool dirty); + int num_pages); +extern void ceph_put_page_vector(struct page **pages, int num_pages); 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, diff --git a/trunk/include/linux/cnt32_to_63.h b/trunk/include/linux/cnt32_to_63.h index e3d8bf26e5eb..7605fdd1eb65 100644 --- a/trunk/include/linux/cnt32_to_63.h +++ b/trunk/include/linux/cnt32_to_63.h @@ -61,31 +61,13 @@ 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 diff --git a/trunk/include/linux/fanotify.h b/trunk/include/linux/fanotify.h index 6c6133f76e16..0f0121467fc4 100644 --- a/trunk/include/linux/fanotify.h +++ b/trunk/include/linux/fanotify.h @@ -83,13 +83,11 @@ FAN_ALL_PERM_EVENTS |\ FAN_Q_OVERFLOW) -#define FANOTIFY_METADATA_VERSION 3 +#define FANOTIFY_METADATA_VERSION 2 struct fanotify_event_metadata { __u32 event_len; - __u8 vers; - __u8 reserved; - __u16 metadata_len; + __u32 vers; __aligned_u64 mask; __s32 fd; __s32 pid; @@ -98,13 +96,11 @@ 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)) diff --git a/trunk/include/linux/fsnotify.h b/trunk/include/linux/fsnotify.h index b10bcdeaef76..5c185fa27089 100644 --- a/trunk/include/linux/fsnotify.h +++ b/trunk/include/linux/fsnotify.h @@ -235,6 +235,9 @@ 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); } diff --git a/trunk/include/linux/fsnotify_backend.h b/trunk/include/linux/fsnotify_backend.h index 7380763595d3..0a68f924f06f 100644 --- a/trunk/include/linux/fsnotify_backend.h +++ b/trunk/include/linux/fsnotify_backend.h @@ -166,7 +166,7 @@ struct fsnotify_group { struct mutex access_mutex; struct list_head access_list; wait_queue_head_t access_waitq; - atomic_t bypass_perm; + bool bypass_perm; /* protected by access_mutex */ #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */ int f_flags; unsigned int max_marks; diff --git a/trunk/include/linux/input.h b/trunk/include/linux/input.h index 9777668883be..a8af21d42bc1 100644 --- a/trunk/include/linux/input.h +++ b/trunk/include/linux/input.h @@ -104,10 +104,8 @@ 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, 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 EVIOCGKEYCODE _IOR('E', 0x04, struct input_keymap_entry) /* get keycode */ +#define EVIOCSKEYCODE _IOW('E', 0x04, struct input_keymap_entry) /* set keycode */ #define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ #define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */ diff --git a/trunk/include/linux/ioport.h b/trunk/include/linux/ioport.h index e9bb22cba764..d377ea815d45 100644 --- a/trunk/include/linux/ioport.h +++ b/trunk/include/linux/ioport.h @@ -112,6 +112,7 @@ 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); @@ -123,7 +124,6 @@ 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, diff --git a/trunk/include/linux/perf_event.h b/trunk/include/linux/perf_event.h index 4f1279e105ee..de2c41758e29 100644 --- a/trunk/include/linux/perf_event.h +++ b/trunk/include/linux/perf_event.h @@ -887,7 +887,6 @@ struct perf_cpu_context { int exclusive; struct list_head rotation_list; int jiffies_interval; - struct pmu *active_pmu; }; struct perf_output_handle { diff --git a/trunk/include/linux/pm_runtime.h b/trunk/include/linux/pm_runtime.h index d19f1cca7f74..3ec2358f8692 100644 --- a/trunk/include/linux/pm_runtime.h +++ b/trunk/include/linux/pm_runtime.h @@ -77,8 +77,7 @@ 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 - && !dev->power.disable_depth; + return dev->power.runtime_status == RPM_SUSPENDED; } static inline void pm_runtime_mark_last_busy(struct device *dev) diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 223874538b33..2c79e921a68b 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -143,7 +143,7 @@ extern unsigned long nr_iowait_cpu(int cpu); extern unsigned long this_cpu_load(void); -extern void calc_global_load(unsigned long ticks); +extern void calc_global_load(void); extern unsigned long get_parent_ip(unsigned long addr); diff --git a/trunk/include/linux/ssb/ssb_driver_gige.h b/trunk/include/linux/ssb/ssb_driver_gige.h index eba52a100533..942e38736901 100644 --- a/trunk/include/linux/ssb/ssb_driver_gige.h +++ b/trunk/include/linux/ssb/ssb_driver_gige.h @@ -96,21 +96,16 @@ static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev) return 0; } -#ifdef CONFIG_BCM47XX -#include +extern char * nvram_get(const char *name); /* Get the device MAC address */ static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) { - 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) -{ -} +#ifdef CONFIG_BCM47XX + char *res = nvram_get("et0macaddr"); + if (res) + memcpy(macaddr, res, 6); #endif +} extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev, struct pci_dev *pdev); diff --git a/trunk/include/media/saa7146.h b/trunk/include/media/saa7146.h index ac7ce00f39cf..7a9f76ecbbbd 100644 --- a/trunk/include/media/saa7146.h +++ b/trunk/include/media/saa7146.h @@ -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* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc); +struct saa7146_format* 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 ); diff --git a/trunk/include/media/v4l2-device.h b/trunk/include/media/v4l2-device.h index b16f307d471a..6648036b728d 100644 --- a/trunk/include/media/v4l2-device.h +++ b/trunk/include/media/v4l2-device.h @@ -51,8 +51,6 @@ 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. diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index 5447dc7defa9..3b159c5991b7 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -273,7 +273,6 @@ 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 */ diff --git a/trunk/kernel/perf_event.c b/trunk/kernel/perf_event.c index 2870feee81dd..eac7e3364335 100644 --- a/trunk/kernel/perf_event.c +++ b/trunk/kernel/perf_event.c @@ -3824,8 +3824,6 @@ 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; @@ -3961,8 +3959,6 @@ 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; @@ -4148,8 +4144,6 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_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_mmap_ctx(&cpuctx->ctx, mmap_event, vma->vm_flags & VM_EXEC); @@ -4719,7 +4713,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) { @@ -5151,36 +5145,20 @@ static void *find_pmu_context(int ctxn) return NULL; } -static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu) +static void free_pmu_context(void * __percpu cpu_context) { - 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; + struct pmu *pmu; mutex_lock(&pmus_lock); /* * Like a real lame refcount. */ - list_for_each_entry(i, &pmus, entry) { - if (i->pmu_cpu_context == pmu->pmu_cpu_context) { - update_pmu_context(i, pmu); + list_for_each_entry(pmu, &pmus, entry) { + if (pmu->pmu_cpu_context == cpu_context) goto out; - } } - free_percpu(pmu->pmu_cpu_context); + free_percpu(cpu_context); out: mutex_unlock(&pmus_lock); } @@ -5212,7 +5190,6 @@ 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: @@ -5264,7 +5241,7 @@ void perf_pmu_unregister(struct pmu *pmu) synchronize_rcu(); free_percpu(pmu->pmu_disable_count); - free_pmu_context(pmu); + free_pmu_context(pmu->pmu_cpu_context); } struct pmu *perf_init_event(struct perf_event *event) diff --git a/trunk/kernel/power/swap.c b/trunk/kernel/power/swap.c index 8c7e4832b9be..baf667bb2794 100644 --- a/trunk/kernel/power/swap.c +++ b/trunk/kernel/power/swap.c @@ -30,7 +30,7 @@ #include "power.h" -#define HIBERNATE_SIG "S1SUSPEND" +#define HIBERNATE_SIG "LINHIB0001" /* * The swap map is a data structure used for keeping track of each page diff --git a/trunk/kernel/power/user.c b/trunk/kernel/power/user.c index c36c3b9e8a84..1b2ea31e6bd8 100644 --- a/trunk/kernel/power/user.c +++ b/trunk/kernel/power/user.c @@ -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_RDONLY ? + pm_notifier_call_chain(data->mode == O_WRONLY ? PM_POST_HIBERNATION : PM_POST_RESTORE); atomic_inc(&snapshot_device_available); diff --git a/trunk/kernel/resource.c b/trunk/kernel/resource.c index 798e2fae2a06..9fad33efd0db 100644 --- a/trunk/kernel/resource.c +++ b/trunk/kernel/resource.c @@ -40,6 +40,23 @@ 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; @@ -357,10 +374,6 @@ 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, @@ -383,8 +396,75 @@ 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, @@ -398,24 +478,23 @@ 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; @@ -430,8 +509,10 @@ static int find_resource(struct resource *root, struct resource *new, return 0; } } + if (!this) break; + tmp.start = this->end + 1; this = this->sibling; } @@ -464,7 +545,10 @@ int allocate_resource(struct resource *root, struct resource *new, alignf = simple_align_resource; write_lock(&resource_lock); - err = find_resource(root, new, size, min, max, align, alignf, alignf_data); + 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); if (err >= 0 && __request_resource(root, new)) err = -EBUSY; write_unlock(&resource_lock); diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 297d1a0eedb0..dc91a4d09ac3 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -636,18 +636,22 @@ static inline struct task_group *task_group(struct task_struct *p) #endif /* CONFIG_CGROUP_SCHED */ -static void update_rq_clock_task(struct rq *rq, s64 delta); +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(struct rq *rq) +inline void update_rq_clock(struct rq *rq) { - s64 delta; + if (!rq->skip_clock_update) { + int cpu = cpu_of(rq); + u64 irq_time; - if (rq->skip_clock_update) - return; + 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; - delta = sched_clock_cpu(cpu_of(rq)) - rq->clock; - rq->clock += delta; - update_rq_clock_task(rq, delta); + sched_irq_time_avg_update(rq, irq_time); + } } /* @@ -1920,9 +1924,10 @@ 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 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 (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. */ static DEFINE_PER_CPU(u64, cpu_hardirq_time); static DEFINE_PER_CPU(u64, cpu_softirq_time); @@ -1940,58 +1945,19 @@ void disable_sched_clock_irqtime(void) sched_clock_irqtime = 0; } -#ifndef CONFIG_64BIT -static DEFINE_PER_CPU(seqcount_t, irq_time_seq); - -static inline void irq_time_write_begin(void) +static u64 irq_time_cpu(int cpu) { - __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) -{ -} + if (!sched_clock_irqtime) + return 0; -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; @@ -1999,10 +1965,9 @@ void account_system_vtime(struct task_struct *curr) local_irq_save(flags); cpu = smp_processor_id(); - delta = sched_clock_cpu(cpu) - __this_cpu_read(irq_start_time); - __this_cpu_add(irq_start_time, delta); - - irq_time_write_begin(); + now = sched_clock_cpu(cpu); + delta = now - per_cpu(irq_start_time, cpu); + per_cpu(irq_start_time, cpu) = now; /* * We do not account for softirq time from ksoftirqd here. * We want to continue accounting softirq time to ksoftirqd thread @@ -2010,55 +1975,33 @@ void account_system_vtime(struct task_struct *curr) * that do not consume any time, but still wants to run. */ if (hardirq_count()) - __this_cpu_add(cpu_hardirq_time, delta); + per_cpu(cpu_hardirq_time, cpu) += delta; else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD)) - __this_cpu_add(cpu_softirq_time, delta); + per_cpu(cpu_softirq_time, cpu) += delta; - irq_time_write_end(); local_irq_restore(flags); } EXPORT_SYMBOL_GPL(account_system_vtime); -static void update_rq_clock_task(struct rq *rq, s64 delta) +static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { - 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); + 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); + } } -#else /* CONFIG_IRQ_TIME_ACCOUNTING */ +#else -static void update_rq_clock_task(struct rq *rq, s64 delta) +static u64 irq_time_cpu(int cpu) { - rq->clock_task += delta; + return 0; } -#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ +static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { } + +#endif #include "sched_idletask.c" #include "sched_fair.c" @@ -2186,7 +2129,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 (rq->curr->se.on_rq && test_tsk_need_resched(rq->curr)) + if (test_tsk_need_resched(rq->curr)) rq->skip_clock_update = 1; } @@ -3176,15 +3119,6 @@ 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. @@ -3214,128 +3148,6 @@ 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) { @@ -3345,10 +3157,6 @@ static inline long calc_load_fold_idle(void) { return 0; } - -static void calc_global_nohz(unsigned long ticks) -{ -} #endif /** @@ -3366,17 +3174,24 @@ 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(unsigned long ticks) +void calc_global_load(void) { + unsigned long upd = calc_load_update + 10; long active; - calc_global_nohz(ticks); - - if (time_before(jiffies, calc_load_update + 10)) + if (time_before(jiffies, upd)) return; active = atomic_long_read(&calc_load_tasks); @@ -4030,6 +3845,7 @@ 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); } @@ -4087,6 +3903,7 @@ asmlinkage void __sched schedule(void) 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)) { @@ -4118,8 +3935,6 @@ asmlinkage void __sched schedule(void) 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); diff --git a/trunk/kernel/timer.c b/trunk/kernel/timer.c index 353b9227c2ec..68a9ae7679b7 100644 --- a/trunk/kernel/timer.c +++ b/trunk/kernel/timer.c @@ -1252,12 +1252,6 @@ 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); @@ -1325,7 +1319,7 @@ void do_timer(unsigned long ticks) { jiffies_64 += ticks; update_wall_time(); - calc_global_load(ticks); + calc_global_load(); } #ifdef __ARCH_WANT_SYS_ALARM diff --git a/trunk/kernel/trace/trace.c b/trunk/kernel/trace/trace.c index f8cf959bad45..c380612273bf 100644 --- a/trunk/kernel/trace/trace.c +++ b/trunk/kernel/trace/trace.c @@ -2338,19 +2338,11 @@ 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 = tracing_seek, + .llseek = seq_lseek, .release = tracing_release, }; diff --git a/trunk/net/ceph/messenger.c b/trunk/net/ceph/messenger.c index b6ff4a1519ab..1c7a2ec4f3cc 100644 --- a/trunk/net/ceph/messenger.c +++ b/trunk/net/ceph/messenger.c @@ -97,9 +97,11 @@ struct workqueue_struct *ceph_msgr_wq; int ceph_msgr_init(void) { ceph_msgr_wq = create_workqueue("ceph-msgr"); - if (!ceph_msgr_wq) { - pr_err("msgr_init failed to create workqueue\n"); - return -ENOMEM; + 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; } return 0; } diff --git a/trunk/net/ceph/pagevec.c b/trunk/net/ceph/pagevec.c index 1a040e64c69f..ac34feeb2b3a 100644 --- a/trunk/net/ceph/pagevec.c +++ b/trunk/net/ceph/pagevec.c @@ -13,7 +13,7 @@ * build a vector of user pages */ struct page **ceph_get_direct_page_vector(const char __user *data, - int num_pages, bool write_page) + int num_pages) { struct page **pages; int rc; @@ -24,27 +24,24 @@ struct page **ceph_get_direct_page_vector(const char __user *data, down_read(¤t->mm->mmap_sem); rc = get_user_pages(current, current->mm, (unsigned long)data, - num_pages, write_page, 0, pages, NULL); + num_pages, 0, 0, pages, NULL); up_read(¤t->mm->mmap_sem); - if (rc < num_pages) + if (rc < 0) goto fail; return pages; fail: - ceph_put_page_vector(pages, rc > 0 ? rc : 0, false); + kfree(pages); return ERR_PTR(rc); } EXPORT_SYMBOL(ceph_get_direct_page_vector); -void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty) +void ceph_put_page_vector(struct page **pages, int num_pages) { int i; - for (i = 0; i < num_pages; i++) { - if (dirty) - set_page_dirty_lock(pages[i]); + for (i = 0; i < num_pages; i++) put_page(pages[i]); - } kfree(pages); } EXPORT_SYMBOL(ceph_put_page_vector); diff --git a/trunk/scripts/recordmcount.h b/trunk/scripts/recordmcount.h index 39667174971d..58e933a20544 100644 --- a/trunk/scripts/recordmcount.h +++ b/trunk/scripts/recordmcount.h @@ -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 = _w(ELF_R_INFO(sym, type)); + rp->r_info = ELF_R_INFO(sym, type); } static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; diff --git a/trunk/scripts/tags.sh b/trunk/scripts/tags.sh index bbbe584d4494..8509bb512935 100755 --- a/trunk/scripts/tags.sh +++ b/trunk/scripts/tags.sh @@ -125,9 +125,7 @@ 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++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ - --regex-c++='/^DEFINE_EVENT\(([^,)]*).*/trace_\1/' + --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' all_kconfigs | xargs $1 -a \ --langdef=kconfig --language-force=kconfig \ diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index 427da45d7906..2d7d7de8498a 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -10830,8 +10830,7 @@ 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, type; - int type_idx = 0; + int i, err; hda_nid_t nid; for (i = 0; i < cfg->num_inputs; i++) { @@ -10840,15 +10839,9 @@ 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, - type_idx, + err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0, HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); if (err < 0) return err; @@ -14807,8 +14800,6 @@ 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[] = { @@ -14826,22 +14817,11 @@ 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), {} }; diff --git a/trunk/sound/soc/codecs/wm8580.c b/trunk/sound/soc/codecs/wm8580.c index 8725d4e75431..879dff2714dd 100644 --- a/trunk/sound/soc/codecs/wm8580.c +++ b/trunk/sound/soc/codecs/wm8580.c @@ -161,7 +161,7 @@ static const u16 wm8580_reg[] = { 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ - 0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/ + 0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/ 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ diff --git a/trunk/sound/soc/codecs/wm8904.c b/trunk/sound/soc/codecs/wm8904.c index 9001cc48ba13..fca60a0b57b8 100644 --- a/trunk/sound/soc/codecs/wm8904.c +++ b/trunk/sound/soc/codecs/wm8904.c @@ -818,8 +818,7 @@ 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); - ucontrol->value.enumerated.item[0] = wm8904->deemph; - return 0; + return wm8904->deemph; } static int wm8904_put_deemph(struct snd_kcontrol *kcontrol, diff --git a/trunk/sound/soc/codecs/wm8955.c b/trunk/sound/soc/codecs/wm8955.c index 9cbab8e1de01..f89ad6c9a80b 100644 --- a/trunk/sound/soc/codecs/wm8955.c +++ b/trunk/sound/soc/codecs/wm8955.c @@ -380,8 +380,7 @@ 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); - ucontrol->value.enumerated.item[0] = wm8955->deemph; - return 0; + return wm8955->deemph; } static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, diff --git a/trunk/sound/soc/codecs/wm8960.c b/trunk/sound/soc/codecs/wm8960.c index 21986c42272f..8d5efb333c33 100644 --- a/trunk/sound/soc/codecs/wm8960.c +++ b/trunk/sound/soc/codecs/wm8960.c @@ -138,8 +138,7 @@ 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); - ucontrol->value.enumerated.item[0] = wm8960->deemph; - return 0; + return wm8960->deemph; } static int wm8960_put_deemph(struct snd_kcontrol *kcontrol, diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index c721502833bc..75ed6491222d 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -944,9 +944,6 @@ 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;