From fc770d16f45512edbb942bdb249f88c89d97ac18 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 May 2011 09:48:22 +0200 Subject: [PATCH] --- yaml --- r: 252212 b: refs/heads/master c: 902050bcdece6191565c055539e82c5cc534feed h: refs/heads/master v: v3 --- [refs] | 2 +- .../ABI/{removed => obsolete}/o2cb | 9 +- .../ABI/testing/sysfs-kernel-mm-cleancache | 11 - .../Documentation/DocBook/dvb/dvbproperty.xml | 5 +- .../Documentation/DocBook/media-entities.tmpl | 7 +- .../DocBook/v4l/media-controller.xml | 6 +- trunk/Documentation/DocBook/v4l/pixfmt.xml | 1 - .../DocBook/v4l/subdev-formats.xml | 10 +- trunk/Documentation/accounting/getdelays.c | 38 +- trunk/Documentation/atomic_ops.txt | 2 +- trunk/Documentation/cgroups/cgroups.txt | 41 +- .../feature-removal-schedule.txt | 10 + .../configfs/configfs_example_explicit.c | 6 +- .../configfs/configfs_example_macros.c | 6 +- trunk/Documentation/filesystems/ext4.txt | 4 + trunk/Documentation/filesystems/ocfs2.txt | 8 +- trunk/Documentation/filesystems/xfs.txt | 6 - .../Documentation/power/regulator/machine.txt | 4 +- trunk/Documentation/sysctl/kernel.txt | 3 +- trunk/Documentation/vm/cleancache.txt | 278 ---- trunk/MAINTAINERS | 25 +- trunk/arch/alpha/Kconfig | 4 + trunk/arch/arm/configs/omap2plus_defconfig | 83 +- trunk/arch/arm/include/asm/bitops.h | 46 +- trunk/arch/arm/mach-omap2/Kconfig | 1 - trunk/arch/arm/mach-omap2/Makefile | 4 +- trunk/arch/arm/mach-omap2/board-2430sdp.c | 27 +- trunk/arch/arm/mach-omap2/board-3430sdp.c | 151 +- trunk/arch/arm/mach-omap2/board-4430sdp.c | 114 +- trunk/arch/arm/mach-omap2/board-am3517crane.c | 10 +- trunk/arch/arm/mach-omap2/board-am3517evm.c | 56 +- trunk/arch/arm/mach-omap2/board-apollon.c | 29 +- trunk/arch/arm/mach-omap2/board-cm-t35.c | 236 ++- trunk/arch/arm/mach-omap2/board-cm-t3517.c | 9 +- trunk/arch/arm/mach-omap2/board-devkit8000.c | 131 +- trunk/arch/arm/mach-omap2/board-igep0020.c | 449 +++--- trunk/arch/arm/mach-omap2/board-igep0030.c | 458 ++++++ trunk/arch/arm/mach-omap2/board-ldp.c | 138 +- trunk/arch/arm/mach-omap2/board-n8x0.c | 28 +- trunk/arch/arm/mach-omap2/board-omap3beagle.c | 194 ++- trunk/arch/arm/mach-omap2/board-omap3evm.c | 242 ++- trunk/arch/arm/mach-omap2/board-omap3logic.c | 14 +- .../arch/arm/mach-omap2/board-omap3pandora.c | 90 +- .../arch/arm/mach-omap2/board-omap3stalker.c | 133 +- .../arm/mach-omap2/board-omap3touchbook.c | 121 +- trunk/arch/arm/mach-omap2/board-omap4panda.c | 79 +- trunk/arch/arm/mach-omap2/board-overo.c | 265 ++- trunk/arch/arm/mach-omap2/board-rm680.c | 21 +- .../arm/mach-omap2/board-rx51-peripherals.c | 71 +- trunk/arch/arm/mach-omap2/board-rx51-video.c | 5 +- trunk/arch/arm/mach-omap2/board-rx51.c | 18 +- .../arm/mach-omap2/board-zoom-debugboard.c | 65 +- .../arch/arm/mach-omap2/board-zoom-display.c | 31 +- .../arm/mach-omap2/board-zoom-peripherals.c | 29 +- .../arm/mach-omap2/common-board-devices.c | 163 -- .../arm/mach-omap2/common-board-devices.h | 35 - trunk/arch/arm/mach-omap2/cpuidle34xx.c | 436 +++-- trunk/arch/arm/mach-omap2/gpmc-smc91x.c | 11 +- trunk/arch/arm/mach-omap2/gpmc-smsc911x.c | 44 +- trunk/arch/arm/mach-omap2/omap_l3_noc.c | 51 +- trunk/arch/arm/mach-omap2/omap_l3_smx.c | 42 +- trunk/arch/arm/mach-omap2/omap_phy_internal.c | 9 +- trunk/arch/arm/mach-omap2/pm.h | 17 +- trunk/arch/arm/mach-omap2/pm34xx.c | 14 + trunk/arch/arm/mach-omap2/pm44xx.c | 2 + trunk/arch/arm/mach-omap2/smartreflex.c | 23 +- trunk/arch/arm/mach-omap2/usb-musb.c | 22 +- trunk/arch/arm/mach-omap2/usb-tusb6010.c | 3 +- trunk/arch/arm/mach-omap2/voltage.c | 1 + .../plat-omap/include/plat/gpmc-smsc911x.h | 4 +- .../arm/plat-omap/include/plat/uncompress.h | 1 + trunk/arch/arm/plat-omap/include/plat/usb.h | 2 +- trunk/arch/avr32/include/asm/bitops.h | 15 - trunk/arch/blackfin/Kconfig | 3 + trunk/arch/blackfin/include/asm/kgdb.h | 1 - trunk/arch/blackfin/include/asm/ptrace.h | 5 +- trunk/arch/cris/Kconfig | 4 + trunk/arch/frv/Kconfig | 8 + trunk/arch/h8300/Kconfig | 8 + trunk/arch/ia64/Kconfig | 4 + trunk/arch/ia64/kernel/time.c | 2 +- trunk/arch/m32r/Kconfig | 8 + trunk/arch/m32r/include/asm/smp.h | 4 +- trunk/arch/m32r/kernel/smp.c | 64 +- trunk/arch/m32r/kernel/smpboot.c | 48 +- trunk/arch/m68k/Kconfig.nommu | 4 + trunk/arch/m68k/include/asm/bitops_mm.h | 8 - trunk/arch/m68k/include/asm/bitops_no.h | 4 - trunk/arch/microblaze/Kconfig | 6 + trunk/arch/mips/Kconfig | 8 + trunk/arch/mips/configs/bcm47xx_defconfig | 1 + trunk/arch/mn10300/Kconfig | 3 + trunk/arch/mn10300/configs/asb2364_defconfig | 1 + trunk/arch/parisc/Kconfig | 8 + trunk/arch/powerpc/Kconfig | 9 +- trunk/arch/powerpc/boot/dts/canyonlands.dts | 18 - trunk/arch/powerpc/boot/dts/katmai.dts | 18 - trunk/arch/powerpc/boot/dts/kilauea.dts | 28 - trunk/arch/powerpc/boot/dts/redwood.dts | 20 - trunk/arch/powerpc/configs/ppc6xx_defconfig | 1 + trunk/arch/powerpc/configs/pseries_defconfig | 1 + trunk/arch/powerpc/include/asm/fsl_lbc.h | 2 - trunk/arch/powerpc/include/asm/ftrace.h | 14 - trunk/arch/powerpc/include/asm/hvcall.h | 2 +- trunk/arch/powerpc/include/asm/rio.h | 5 - trunk/arch/powerpc/include/asm/smp.h | 2 + trunk/arch/powerpc/include/asm/syscall.h | 5 - trunk/arch/powerpc/include/asm/thread_info.h | 7 +- trunk/arch/powerpc/kernel/Makefile | 1 - trunk/arch/powerpc/kernel/ftrace.c | 8 - trunk/arch/powerpc/kernel/irq.c | 46 +- trunk/arch/powerpc/kernel/ptrace.c | 10 - trunk/arch/powerpc/kernel/smp.c | 2 +- trunk/arch/powerpc/kernel/traps.c | 13 - trunk/arch/powerpc/oprofile/op_model_power4.c | 24 +- trunk/arch/powerpc/platforms/40x/Kconfig | 2 - trunk/arch/powerpc/platforms/44x/Kconfig | 6 - trunk/arch/powerpc/platforms/cell/interrupt.c | 55 +- trunk/arch/powerpc/platforms/cell/interrupt.h | 2 +- trunk/arch/powerpc/platforms/cell/smp.c | 2 +- trunk/arch/powerpc/sysdev/Kconfig | 7 - trunk/arch/powerpc/sysdev/Makefile | 1 - trunk/arch/powerpc/sysdev/fsl_lbc.c | 9 +- trunk/arch/powerpc/sysdev/fsl_rio.c | 100 +- trunk/arch/powerpc/sysdev/ppc4xx_msi.c | 276 ---- trunk/arch/s390/include/asm/bitops.h | 45 +- trunk/arch/s390/mm/fault.c | 3 +- trunk/arch/score/Kconfig | 3 + trunk/arch/sh/Kconfig | 6 + trunk/arch/sh/configs/apsh4ad0a_defconfig | 1 + trunk/arch/sh/configs/sdk7786_defconfig | 1 + trunk/arch/sh/configs/se7206_defconfig | 1 + trunk/arch/sh/configs/shx3_defconfig | 1 + trunk/arch/sh/configs/urquell_defconfig | 1 + trunk/arch/sh/include/asm/kgdb.h | 1 - trunk/arch/sh/include/asm/ptrace.h | 6 +- trunk/arch/sparc/Kconfig | 8 + trunk/arch/tile/Kconfig | 1 + trunk/arch/um/Kconfig.x86 | 1 + trunk/arch/x86/Kconfig | 1 + trunk/arch/x86/configs/i386_defconfig | 1 + trunk/arch/x86/configs/x86_64_defconfig | 1 + trunk/arch/x86/include/asm/kgdb.h | 1 - trunk/arch/x86/include/asm/ptrace.h | 18 +- trunk/arch/x86/include/asm/tsc.h | 4 - trunk/arch/x86/include/asm/vdso.h | 14 + trunk/arch/x86/include/asm/vgtod.h | 2 + trunk/arch/x86/include/asm/vsyscall.h | 12 +- trunk/arch/x86/include/asm/vvar.h | 52 - trunk/arch/x86/include/asm/xen/hypercall.h | 7 - trunk/arch/x86/kernel/Makefile | 8 +- trunk/arch/x86/kernel/time.c | 2 +- trunk/arch/x86/kernel/tsc.c | 19 + trunk/arch/x86/kernel/vmlinux.lds.S | 34 +- trunk/arch/x86/kernel/vread_tsc_64.c | 36 - trunk/arch/x86/kernel/vsyscall_64.c | 48 +- trunk/arch/x86/vdso/Makefile | 17 +- trunk/arch/x86/vdso/vclock_gettime.c | 74 +- trunk/arch/x86/vdso/vdso.lds.S | 9 +- trunk/arch/x86/vdso/vextern.h | 16 + trunk/arch/x86/vdso/vgetcpu.c | 3 +- trunk/arch/x86/vdso/vma.c | 27 + trunk/arch/x86/vdso/vvar.c | 12 + trunk/arch/x86/xen/mmu.c | 284 +++- trunk/arch/x86/xen/mmu.h | 37 + trunk/arch/xtensa/Kconfig | 6 + trunk/block/blk-cgroup.c | 18 +- trunk/drivers/bcma/host_pci.c | 1 - trunk/drivers/char/ipmi/ipmi_msghandler.c | 138 +- trunk/drivers/char/ipmi/ipmi_si_intf.c | 88 +- trunk/drivers/char/mspec.c | 5 +- trunk/drivers/char/ppdev.c | 1 - trunk/drivers/dma/timb_dma.c | 3 +- trunk/drivers/edac/amd76x_edac.c | 2 +- trunk/drivers/edac/amd8111_edac.c | 2 +- trunk/drivers/edac/amd8131_edac.c | 2 +- trunk/drivers/edac/cpc925_edac.c | 2 +- trunk/drivers/edac/e752x_edac.c | 2 +- trunk/drivers/edac/e7xxx_edac.c | 2 +- trunk/drivers/edac/edac_core.h | 12 + trunk/drivers/edac/edac_device.c | 24 +- trunk/drivers/edac/edac_mc.c | 16 +- trunk/drivers/edac/edac_module.c | 2 +- trunk/drivers/edac/edac_pci.c | 21 +- trunk/drivers/edac/i5000_edac.c | 2 +- trunk/drivers/edac/i5400_edac.c | 2 +- trunk/drivers/edac/i7300_edac.c | 2 +- trunk/drivers/edac/i7core_edac.c | 2 +- trunk/drivers/edac/i82860_edac.c | 2 +- trunk/drivers/edac/i82875p_edac.c | 2 +- trunk/drivers/edac/i82975x_edac.c | 2 +- trunk/drivers/edac/mpc85xx_edac.h | 2 +- trunk/drivers/edac/mv64x60_edac.h | 2 +- trunk/drivers/edac/ppc4xx_edac.c | 2 +- trunk/drivers/edac/r82600_edac.c | 2 +- trunk/drivers/gpio/Kconfig | 30 +- trunk/drivers/gpio/Makefile | 8 +- trunk/drivers/gpio/basic_mmio_gpio.c | 517 ++---- trunk/drivers/gpio/gpiolib.c | 19 +- trunk/drivers/gpio/janz-ttl.c | 3 +- trunk/drivers/gpio/pca953x.c | 2 +- trunk/drivers/gpio/rdc321x-gpio.c | 3 +- trunk/drivers/gpio/timbgpio.c | 6 +- trunk/drivers/gpio/tps65910-gpio.c | 100 -- trunk/drivers/hwmon/coretemp.c | 16 +- trunk/drivers/hwmon/pmbus_core.c | 1 - trunk/drivers/i2c/busses/i2c-ocores.c | 3 +- trunk/drivers/i2c/busses/i2c-xiic.c | 3 +- trunk/drivers/infiniband/Kconfig | 1 - trunk/drivers/infiniband/core/Makefile | 2 +- trunk/drivers/infiniband/core/cm.c | 8 - trunk/drivers/infiniband/core/cma.c | 308 ++-- trunk/drivers/infiniband/core/device.c | 25 +- trunk/drivers/infiniband/core/mad.c | 7 - trunk/drivers/infiniband/core/netlink.c | 190 --- trunk/drivers/infiniband/core/ucma.c | 35 +- trunk/drivers/infiniband/core/user_mad.c | 7 - trunk/drivers/infiniband/core/uverbs_main.c | 8 - trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c | 26 +- .../infiniband/hw/cxgb3/iwch_provider.h | 2 +- trunk/drivers/infiniband/hw/cxgb3/iwch_qp.c | 6 +- trunk/drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 18 +- trunk/drivers/infiniband/hw/nes/nes.c | 4 +- trunk/drivers/infiniband/hw/qib/Kconfig | 2 +- .../drivers/infiniband/ulp/iser/iser_verbs.c | 2 +- trunk/drivers/infiniband/ulp/srp/ib_srp.c | 4 +- trunk/drivers/input/keyboard/Kconfig | 11 - trunk/drivers/input/keyboard/Makefile | 1 - .../drivers/input/keyboard/pmic8xxx-keypad.c | 799 ---------- trunk/drivers/input/misc/Kconfig | 11 - trunk/drivers/input/misc/Makefile | 1 - trunk/drivers/input/misc/pmic8xxx-pwrkey.c | 231 --- trunk/drivers/input/misc/twl4030-vibra.c | 3 +- trunk/drivers/isdn/hardware/eicon/divasfunc.c | 5 +- trunk/drivers/leds/Kconfig | 10 - trunk/drivers/leds/Makefile | 1 - trunk/drivers/leds/leds-88pm860x.c | 7 +- trunk/drivers/leds/leds-asic3.c | 165 -- trunk/drivers/leds/leds-mc13783.c | 7 +- trunk/drivers/media/dvb/dm1105/dm1105.c | 272 +--- trunk/drivers/media/dvb/dvb-usb/lmedm04.c | 107 +- .../media/dvb/frontends/stb0899_algo.c | 2 +- trunk/drivers/media/dvb/frontends/tda8261.c | 1 + trunk/drivers/media/radio/radio-maxiradio.c | 3 +- trunk/drivers/media/radio/radio-timb.c | 3 +- trunk/drivers/media/radio/radio-wl1273.c | 4 +- trunk/drivers/media/radio/wl128x/fmdrv_v4l2.c | 2 +- trunk/drivers/media/rc/Kconfig | 12 - trunk/drivers/media/rc/Makefile | 1 - trunk/drivers/media/rc/fintek-cir.c | 684 -------- trunk/drivers/media/rc/fintek-cir.h | 243 --- trunk/drivers/media/rc/keymaps/rc-lme2510.c | 134 +- trunk/drivers/media/video/Kconfig | 6 +- trunk/drivers/media/video/Makefile | 1 - trunk/drivers/media/video/cpia2/cpia2_v4l.c | 4 +- .../media/video/cx231xx/cx231xx-avcore.c | 2 +- trunk/drivers/media/video/gspca/kinect.c | 2 +- trunk/drivers/media/video/m5mols/Kconfig | 5 - trunk/drivers/media/video/m5mols/Makefile | 3 - trunk/drivers/media/video/m5mols/m5mols.h | 296 ---- .../media/video/m5mols/m5mols_capture.c | 191 --- .../media/video/m5mols/m5mols_controls.c | 299 ---- .../drivers/media/video/m5mols/m5mols_core.c | 1004 ------------ trunk/drivers/media/video/m5mols/m5mols_reg.h | 399 ----- trunk/drivers/media/video/timblogiw.c | 3 +- trunk/drivers/media/video/uvc/Makefile | 3 - trunk/drivers/media/video/uvc/uvc_driver.c | 66 +- trunk/drivers/media/video/uvc/uvc_entity.c | 118 -- trunk/drivers/media/video/uvc/uvcvideo.h | 20 - trunk/drivers/mfd/88pm860x-core.c | 155 +- trunk/drivers/mfd/Kconfig | 93 +- trunk/drivers/mfd/Makefile | 3 - trunk/drivers/mfd/ab3100-core.c | 6 +- trunk/drivers/mfd/ab3550-core.c | 6 +- trunk/drivers/mfd/ab8500-core.c | 32 +- trunk/drivers/mfd/ab8500-gpadc.c | 34 +- trunk/drivers/mfd/asic3.c | 83 +- trunk/drivers/mfd/davinci_voicecodec.c | 6 +- trunk/drivers/mfd/htc-pasic3.c | 5 +- trunk/drivers/mfd/janz-cmodio.c | 3 +- trunk/drivers/mfd/max8925-core.c | 2 +- trunk/drivers/mfd/mc13xxx-core.c | 12 +- trunk/drivers/mfd/mfd-core.c | 7 - trunk/drivers/mfd/omap-usb-host.c | 152 +- trunk/drivers/mfd/pm8921-core.c | 212 --- trunk/drivers/mfd/pm8xxx-irq.c | 371 ----- trunk/drivers/mfd/rdc321x-southbridge.c | 6 +- trunk/drivers/mfd/t7l66xb.c | 6 +- trunk/drivers/mfd/tc6387xb.c | 3 +- trunk/drivers/mfd/tc6393xb.c | 10 +- trunk/drivers/mfd/timberdale.c | 81 +- trunk/drivers/mfd/tps6105x.c | 3 +- trunk/drivers/mfd/tps6586x.c | 4 +- trunk/drivers/mfd/tps65910-irq.c | 218 --- trunk/drivers/mfd/tps65910.c | 229 --- trunk/drivers/mfd/tps65911-comparator.c | 188 --- trunk/drivers/mfd/twl-core.c | 252 +-- trunk/drivers/mfd/twl4030-codec.c | 10 +- trunk/drivers/mfd/twl4030-power.c | 6 +- trunk/drivers/mfd/twl6030-irq.c | 4 +- trunk/drivers/mfd/wl1273-core.c | 7 +- trunk/drivers/mfd/wm831x-core.c | 13 +- trunk/drivers/mfd/wm831x-irq.c | 27 +- trunk/drivers/mfd/wm8400-core.c | 3 +- trunk/drivers/misc/kgdbts.c | 29 +- trunk/drivers/mmc/host/tmio_mmc.c | 2 +- trunk/drivers/mtd/nand/tmio_nand.c | 2 +- trunk/drivers/net/can/janz-ican3.c | 3 +- trunk/drivers/net/hamradio/baycom_epp.c | 2 +- trunk/drivers/net/hamradio/baycom_par.c | 2 +- trunk/drivers/net/hamradio/baycom_ser_fdx.c | 2 +- trunk/drivers/net/hamradio/baycom_ser_hdx.c | 2 +- trunk/drivers/net/hamradio/hdlcdrv.c | 2 +- trunk/drivers/net/ks8842.c | 3 +- trunk/drivers/net/wan/pc300_drv.c | 3 +- trunk/drivers/parport/parport_ip32.c | 1 + trunk/drivers/power/Kconfig | 16 - trunk/drivers/power/Makefile | 2 - trunk/drivers/power/bq27x00_battery.c | 11 +- trunk/drivers/power/ds2760_battery.c | 6 +- trunk/drivers/power/ds2780_battery.c | 853 ---------- trunk/drivers/power/gpio-charger.c | 15 - trunk/drivers/power/isp1704_charger.c | 22 - trunk/drivers/power/max8903_charger.c | 391 ----- trunk/drivers/power/max8925_power.c | 10 +- trunk/drivers/power/test_power.c | 276 +--- trunk/drivers/power/z2_battery.c | 20 +- trunk/drivers/regulator/88pm8607.c | 30 +- trunk/drivers/regulator/Kconfig | 6 - trunk/drivers/regulator/Makefile | 1 - trunk/drivers/regulator/ab3100.c | 3 +- trunk/drivers/regulator/core.c | 93 +- trunk/drivers/regulator/db8500-prcmu.c | 4 +- trunk/drivers/regulator/max8925-regulator.c | 11 +- trunk/drivers/regulator/max8997.c | 13 +- trunk/drivers/regulator/max8998.c | 22 +- trunk/drivers/regulator/mc13783-regulator.c | 7 +- trunk/drivers/regulator/mc13892-regulator.c | 25 +- .../regulator/mc13xxx-regulator-core.c | 2 +- trunk/drivers/regulator/tps6105x-regulator.c | 5 +- trunk/drivers/regulator/tps65023-regulator.c | 3 +- trunk/drivers/regulator/tps6507x-regulator.c | 3 +- trunk/drivers/regulator/tps65910-regulator.c | 993 ------------ trunk/drivers/regulator/twl-regulator.c | 564 +------ trunk/drivers/regulator/wm831x-dcdc.c | 2 + trunk/drivers/regulator/wm8400-regulator.c | 12 +- trunk/drivers/rtc/Kconfig | 52 - trunk/drivers/rtc/Makefile | 6 - trunk/drivers/rtc/rtc-88pm860x.c | 427 ----- trunk/drivers/rtc/rtc-em3027.c | 161 -- trunk/drivers/rtc/rtc-m41t93.c | 225 --- trunk/drivers/rtc/rtc-mrst.c | 4 +- trunk/drivers/rtc/rtc-mxc.c | 6 + trunk/drivers/rtc/rtc-pcf50633.c | 23 +- trunk/drivers/rtc/rtc-rv3029c2.c | 454 ------ trunk/drivers/rtc/rtc-spear.c | 534 ------- trunk/drivers/rtc/rtc-vt8500.c | 366 ----- trunk/drivers/scsi/aacraid/linit.c | 3 +- trunk/drivers/scsi/in2000.c | 2 +- trunk/drivers/scsi/pmcraid.c | 9 +- trunk/drivers/scsi/pmcraid.h | 1 + trunk/drivers/scsi/wd33c93.c | 7 +- trunk/drivers/spi/Kconfig | 4 +- trunk/drivers/spi/amba-pl022.c | 35 +- trunk/drivers/spi/dw_spi.c | 202 ++- trunk/drivers/spi/dw_spi.h | 2 + trunk/drivers/spi/spi.c | 4 +- trunk/drivers/spi/spi_nuc900.c | 2 +- trunk/drivers/spi/spi_s3c24xx.c | 2 +- trunk/drivers/spi/spi_sh.c | 2 +- trunk/drivers/spi/spi_tegra.c | 2 +- trunk/drivers/spi/xilinx_spi.c | 3 +- .../staging/generic_serial/rio/rioinit.c | 2 +- trunk/drivers/tty/cyclades.c | 3 +- trunk/drivers/tty/nozomi.c | 3 +- trunk/drivers/tty/serial/m32r_sio.c | 3 +- trunk/drivers/usb/otg/twl6030-usb.c | 10 +- trunk/drivers/video/backlight/88pm860x_bl.c | 7 +- trunk/drivers/video/mb862xx/mb862xxfbdrv.c | 1 - trunk/drivers/video/omap/Makefile | 1 + trunk/drivers/video/omap/lcd_omap2evm.c | 192 +++ trunk/drivers/video/tmiofb.c | 12 +- trunk/drivers/video/via/via-gpio.c | 49 +- trunk/drivers/w1/masters/Kconfig | 2 +- trunk/drivers/w1/masters/ds1wm.c | 333 ++-- trunk/drivers/w1/slaves/Kconfig | 20 - trunk/drivers/w1/slaves/Makefile | 2 - trunk/drivers/w1/slaves/w1_ds2408.c | 402 ----- trunk/drivers/w1/slaves/w1_ds2780.c | 217 --- trunk/drivers/w1/slaves/w1_ds2780.h | 129 -- trunk/drivers/w1/w1.c | 12 +- trunk/drivers/w1/w1.h | 6 +- trunk/drivers/w1/w1_family.h | 2 - trunk/drivers/w1/w1_io.c | 26 - trunk/drivers/w1/w1_netlink.c | 5 +- trunk/drivers/watchdog/rdc321x_wdt.c | 3 +- trunk/drivers/xen/Makefile | 1 - trunk/drivers/xen/tmem.c | 264 --- trunk/fs/9p/vfs_inode.c | 4 - trunk/fs/Kconfig | 2 +- trunk/fs/affs/namei.c | 5 - trunk/fs/afs/dir.c | 5 - trunk/fs/autofs4/root.c | 2 - trunk/fs/bfs/dir.c | 3 - trunk/fs/btrfs/extent_io.c | 9 - trunk/fs/btrfs/super.c | 2 - trunk/fs/buffer.c | 64 +- trunk/fs/coda/dir.c | 5 - trunk/fs/configfs/dir.c | 2 - trunk/fs/dlm/main.c | 2 +- trunk/fs/ecryptfs/inode.c | 5 - trunk/fs/exec.c | 39 +- trunk/fs/ext3/super.c | 2 - trunk/fs/ext4/Makefile | 3 +- trunk/fs/ext4/balloc.c | 146 +- trunk/fs/ext4/ext4.h | 127 +- trunk/fs/ext4/ext4_jbd2.c | 14 + trunk/fs/ext4/ext4_jbd2.h | 5 + trunk/fs/ext4/extents.c | 1416 +++++++---------- trunk/fs/ext4/file.c | 1 + trunk/fs/ext4/fsync.c | 25 +- trunk/fs/ext4/inode.c | 114 +- trunk/fs/ext4/mballoc.c | 459 +++--- trunk/fs/ext4/mballoc.h | 6 + trunk/fs/ext4/migrate.c | 2 +- trunk/fs/ext4/mmp.c | 351 ---- trunk/fs/ext4/move_extent.c | 3 +- trunk/fs/ext4/namei.c | 82 +- trunk/fs/ext4/page-io.c | 39 +- trunk/fs/ext4/super.c | 206 +-- trunk/fs/ext4/xattr.c | 4 +- trunk/fs/fat/namei_msdos.c | 5 - trunk/fs/fat/namei_vfat.c | 5 - trunk/fs/fuse/dir.c | 6 - trunk/fs/gfs2/main.c | 2 +- trunk/fs/hfs/dir.c | 6 - trunk/fs/hfsplus/dir.c | 8 +- trunk/fs/hostfs/hostfs_kern.c | 5 - trunk/fs/hpfs/namei.c | 9 +- trunk/fs/hugetlbfs/inode.c | 3 +- trunk/fs/jbd2/commit.c | 22 +- trunk/fs/jbd2/journal.c | 58 +- trunk/fs/jbd2/transaction.c | 22 +- trunk/fs/jffs2/dir.c | 5 - trunk/fs/jfs/namei.c | 5 - trunk/fs/logfs/dir.c | 5 - trunk/fs/minix/namei.c | 5 - trunk/fs/mpage.c | 7 - trunk/fs/namei.c | 380 +++-- trunk/fs/namespace.c | 2 +- trunk/fs/ncpfs/dir.c | 5 - trunk/fs/ncpfs/mmap.c | 2 - trunk/fs/nilfs2/namei.c | 5 - trunk/fs/ocfs2/Makefile | 1 - trunk/fs/ocfs2/alloc.c | 166 -- trunk/fs/ocfs2/alloc.h | 1 - trunk/fs/ocfs2/cluster/sys.c | 9 + trunk/fs/ocfs2/dlm/dlmcommon.h | 14 - trunk/fs/ocfs2/dlm/dlmdebug.c | 6 - trunk/fs/ocfs2/dlm/dlmdomain.c | 94 +- trunk/fs/ocfs2/dlm/dlmmaster.c | 255 +-- trunk/fs/ocfs2/dlm/dlmrecovery.c | 1 - trunk/fs/ocfs2/dlmfs/dlmfs.c | 2 +- trunk/fs/ocfs2/file.c | 1 - trunk/fs/ocfs2/ioctl.c | 492 +----- trunk/fs/ocfs2/move_extents.c | 1153 -------------- trunk/fs/ocfs2/move_extents.h | 22 - trunk/fs/ocfs2/ocfs2_ioctl.h | 68 - trunk/fs/ocfs2/ocfs2_trace.h | 25 - trunk/fs/ocfs2/refcounttree.c | 58 +- trunk/fs/ocfs2/refcounttree.h | 11 - trunk/fs/ocfs2/super.c | 4 +- trunk/fs/omfs/dir.c | 11 +- trunk/fs/partitions/efi.c | 9 - trunk/fs/proc/array.c | 4 +- trunk/fs/proc/base.c | 83 +- trunk/fs/proc/stat.c | 6 +- trunk/fs/proc/task_mmu.c | 29 +- trunk/fs/proc/vmcore.c | 52 +- trunk/fs/reiserfs/namei.c | 5 - trunk/fs/reiserfs/xattr.c | 1 + trunk/fs/squashfs/block.c | 2 +- trunk/fs/squashfs/cache.c | 31 +- trunk/fs/squashfs/decompressor.c | 2 +- trunk/fs/squashfs/decompressor.h | 2 +- trunk/fs/squashfs/dir.c | 2 +- trunk/fs/squashfs/export.c | 42 +- trunk/fs/squashfs/file.c | 2 +- trunk/fs/squashfs/fragment.c | 37 +- trunk/fs/squashfs/id.c | 42 +- trunk/fs/squashfs/inode.c | 2 +- trunk/fs/squashfs/namei.c | 2 +- trunk/fs/squashfs/squashfs.h | 10 +- trunk/fs/squashfs/squashfs_fs.h | 2 +- trunk/fs/squashfs/squashfs_fs_i.h | 2 +- trunk/fs/squashfs/squashfs_fs_sb.h | 2 +- trunk/fs/squashfs/super.c | 112 +- trunk/fs/squashfs/symlink.c | 2 +- trunk/fs/squashfs/xattr.c | 2 +- trunk/fs/squashfs/xattr.h | 3 +- trunk/fs/squashfs/xattr_id.c | 47 +- trunk/fs/squashfs/xz_wrapper.c | 2 +- trunk/fs/squashfs/zlib_wrapper.c | 2 +- trunk/fs/super.c | 3 - trunk/fs/sysv/namei.c | 5 - trunk/fs/ubifs/dir.c | 5 - trunk/fs/udf/namei.c | 5 - trunk/fs/ufs/balloc.c | 9 +- trunk/fs/ufs/namei.c | 5 - trunk/fs/ufs/truncate.c | 2 +- trunk/fs/xfs/linux-2.6/xfs_discard.c | 29 - trunk/fs/xfs/linux-2.6/xfs_discard.h | 2 - trunk/fs/xfs/linux-2.6/xfs_super.c | 18 +- trunk/fs/xfs/xfs_ag.h | 3 - trunk/fs/xfs/xfs_alloc.c | 35 +- trunk/fs/xfs/xfs_alloc.h | 5 +- trunk/fs/xfs/xfs_alloc_btree.c | 3 +- trunk/fs/xfs/xfs_bmap.c | 549 ++++--- trunk/fs/xfs/xfs_bmap.h | 2 + trunk/fs/xfs/xfs_inode.c | 15 +- trunk/fs/xfs/xfs_inode.h | 1 + trunk/fs/xfs/xfs_log_cil.c | 13 +- trunk/fs/xfs/xfs_mount.h | 1 - trunk/fs/xfs/xfs_trans.c | 2 +- trunk/include/asm-generic/bitops/find.h | 4 - trunk/include/asm-generic/bitops/le.h | 7 - trunk/include/asm-generic/ptrace.h | 74 - trunk/include/linux/basic_mmio_gpio.h | 56 - trunk/include/linux/bitops.h | 4 +- trunk/include/linux/buffer_head.h | 16 - trunk/include/linux/cgroup.h | 13 +- trunk/include/linux/cgroup_subsys.h | 6 + trunk/include/linux/cleancache.h | 122 -- trunk/include/linux/crash_dump.h | 5 - trunk/include/linux/flex_array.h | 2 - trunk/include/linux/fs.h | 5 - trunk/include/linux/hugetlb.h | 7 +- trunk/include/linux/hugetlb_inline.h | 2 +- trunk/include/linux/i2c/twl.h | 54 +- trunk/include/linux/init_task.h | 9 - trunk/include/linux/input/pmic8xxx-keypad.h | 52 - trunk/include/linux/input/pmic8xxx-pwrkey.h | 31 - trunk/include/linux/ipmi_smi.h | 2 +- trunk/include/linux/jbd2.h | 8 +- trunk/include/linux/memcontrol.h | 24 +- trunk/include/linux/mfd/88pm860x.h | 6 - trunk/include/linux/mfd/abx500.h | 8 - trunk/include/linux/mfd/asic3.h | 23 +- trunk/include/linux/mfd/core.h | 23 +- trunk/include/linux/mfd/max8997-private.h | 4 + trunk/include/linux/mfd/pm8xxx/core.h | 81 - trunk/include/linux/mfd/pm8xxx/irq.h | 59 - trunk/include/linux/mfd/pm8xxx/pm8921.h | 31 - trunk/include/linux/mfd/tps65910.h | 800 ---------- trunk/include/linux/mfd/twl4030-codec.h | 2 +- trunk/include/linux/mfd/wm831x/core.h | 26 + trunk/include/linux/mfd/wm831x/pdata.h | 4 - trunk/include/linux/mm.h | 16 +- trunk/include/linux/mm_types.h | 6 +- trunk/include/linux/mmzone.h | 5 + trunk/include/linux/netlink.h | 1 - trunk/include/linux/nsproxy.h | 9 + trunk/include/linux/pid.h | 2 +- trunk/include/linux/power/isp1704_charger.h | 29 - trunk/include/linux/power/max8903_charger.h | 57 - trunk/include/linux/proc_fs.h | 19 + trunk/include/linux/regulator/machine.h | 7 +- trunk/include/linux/rtc.h | 8 +- trunk/include/linux/sched.h | 36 - trunk/include/linux/seqlock.h | 3 + trunk/include/linux/smp.h | 10 + trunk/include/linux/spi/spi.h | 8 +- trunk/include/linux/swap.h | 3 +- trunk/include/linux/vm_event_item.h | 64 - trunk/include/linux/vmstat.h | 62 +- trunk/include/media/m5mols.h | 35 - trunk/include/media/videobuf-dvb.h | 4 - trunk/include/rdma/Kbuild | 5 - trunk/include/rdma/ib_user_cm.h | 1 - trunk/include/rdma/rdma_cm.h | 19 +- trunk/include/rdma/rdma_netlink.h | 92 -- trunk/include/trace/events/gpio.h | 56 - trunk/include/xen/interface/xen.h | 22 - trunk/init/Kconfig | 8 + trunk/ipc/shm.c | 2 +- trunk/kernel/Makefile | 1 + trunk/kernel/cgroup.c | 587 ++----- trunk/kernel/cgroup_freezer.c | 26 +- trunk/kernel/cpuset.c | 103 +- trunk/kernel/fork.c | 68 +- trunk/kernel/irq/proc.c | 1 - trunk/kernel/ns_cgroup.c | 118 ++ trunk/kernel/nsproxy.c | 4 + trunk/kernel/profile.c | 16 +- trunk/kernel/sched.c | 38 +- trunk/lib/Kconfig | 10 + trunk/lib/Makefile | 8 +- trunk/lib/find_last_bit.c | 4 - trunk/lib/find_next_bit.c | 18 +- trunk/lib/flex_array.c | 51 +- trunk/mm/Kconfig | 23 - trunk/mm/Makefile | 1 - trunk/mm/cleancache.c | 244 --- trunk/mm/filemap.c | 12 - trunk/mm/fremap.c | 2 +- trunk/mm/hugetlb.c | 4 +- trunk/mm/memcontrol.c | 364 +---- trunk/mm/memory.c | 4 +- trunk/mm/mlock.c | 8 +- trunk/mm/mmap.c | 8 +- trunk/mm/page_alloc.c | 4 +- trunk/mm/page_cgroup.c | 28 +- trunk/mm/shmem.c | 11 +- trunk/mm/truncate.c | 6 - trunk/mm/vmalloc.c | 4 + trunk/mm/vmscan.c | 104 +- trunk/net/9p/trans_rdma.c | 3 +- trunk/net/atm/lec.c | 2 +- trunk/net/atm/mpc.c | 2 +- trunk/net/ipv4/inet_connection_sock.c | 2 +- trunk/net/rds/ib.c | 2 +- trunk/net/rds/ib_cm.c | 2 +- trunk/net/rds/iw.c | 2 +- trunk/net/rds/iw_cm.c | 2 +- trunk/net/rds/rdma_transport.c | 3 +- .../net/sunrpc/xprtrdma/svc_rdma_transport.c | 3 +- trunk/net/sunrpc/xprtrdma/verbs.c | 2 +- trunk/security/device_cgroup.c | 3 +- trunk/security/keys/process_keys.c | 1 - trunk/security/selinux/avc.c | 12 +- trunk/security/selinux/ss/services.c | 3 +- trunk/sound/core/control.c | 3 +- trunk/sound/core/init.c | 3 + trunk/sound/core/oss/linear.c | 3 + trunk/sound/core/pcm_lib.c | 17 +- trunk/sound/core/pcm_native.c | 21 +- trunk/sound/core/seq/seq_queue.c | 2 + trunk/sound/pci/hda/hda_codec.c | 2 +- trunk/sound/pci/hda/hda_eld.c | 21 +- trunk/sound/pci/hda/hda_intel.c | 206 +-- trunk/sound/pci/hda/patch_analog.c | 1 - trunk/sound/pci/hda/patch_conexant.c | 42 +- trunk/sound/pci/hda/patch_hdmi.c | 123 +- trunk/sound/soc/atmel/sam9g20_wm8731.c | 2 +- trunk/sound/soc/codecs/cq93vc.c | 3 +- trunk/sound/soc/codecs/twl4030.c | 6 +- trunk/sound/soc/codecs/wl1273.c | 3 +- trunk/sound/soc/codecs/wm1250-ev1.c | 2 +- trunk/sound/soc/codecs/wm8400.c | 2 +- trunk/sound/soc/codecs/wm8731.c | 2 +- trunk/sound/soc/codecs/wm8915.c | 1 + trunk/sound/soc/davinci/davinci-vcif.c | 2 +- trunk/sound/soc/omap/Kconfig | 8 + trunk/sound/soc/omap/Makefile | 1 + trunk/sound/soc/omap/omap2evm.c | 139 ++ trunk/sound/soc/pxa/raumfeld.c | 92 +- trunk/sound/soc/soc-core.c | 8 +- trunk/sound/soc/soc-dapm.c | 2 +- trunk/sound/usb/card.c | 17 +- trunk/sound/usb/mixer.c | 32 +- trunk/sound/usb/mixer.h | 14 +- trunk/sound/usb/mixer_quirks.c | 70 - trunk/sound/usb/quirks-table.h | 4 +- trunk/sound/usb/quirks.c | 18 +- trunk/sound/usb/usbaudio.h | 1 - 665 files changed, 9222 insertions(+), 26400 deletions(-) rename trunk/Documentation/ABI/{removed => obsolete}/o2cb (65%) delete mode 100644 trunk/Documentation/ABI/testing/sysfs-kernel-mm-cleancache delete mode 100644 trunk/Documentation/vm/cleancache.txt create mode 100644 trunk/arch/arm/mach-omap2/board-igep0030.c delete mode 100644 trunk/arch/arm/mach-omap2/common-board-devices.c delete mode 100644 trunk/arch/arm/mach-omap2/common-board-devices.h delete mode 100644 trunk/arch/powerpc/sysdev/ppc4xx_msi.c delete mode 100644 trunk/arch/x86/include/asm/vvar.h delete mode 100644 trunk/arch/x86/kernel/vread_tsc_64.c create mode 100644 trunk/arch/x86/vdso/vextern.h create mode 100644 trunk/arch/x86/vdso/vvar.c delete mode 100644 trunk/drivers/gpio/tps65910-gpio.c delete mode 100644 trunk/drivers/infiniband/core/netlink.c delete mode 100644 trunk/drivers/input/keyboard/pmic8xxx-keypad.c delete mode 100644 trunk/drivers/input/misc/pmic8xxx-pwrkey.c delete mode 100644 trunk/drivers/leds/leds-asic3.c delete mode 100644 trunk/drivers/media/rc/fintek-cir.c delete mode 100644 trunk/drivers/media/rc/fintek-cir.h delete mode 100644 trunk/drivers/media/video/m5mols/Kconfig delete mode 100644 trunk/drivers/media/video/m5mols/Makefile delete mode 100644 trunk/drivers/media/video/m5mols/m5mols.h delete mode 100644 trunk/drivers/media/video/m5mols/m5mols_capture.c delete mode 100644 trunk/drivers/media/video/m5mols/m5mols_controls.c delete mode 100644 trunk/drivers/media/video/m5mols/m5mols_core.c delete mode 100644 trunk/drivers/media/video/m5mols/m5mols_reg.h delete mode 100644 trunk/drivers/media/video/uvc/uvc_entity.c delete mode 100644 trunk/drivers/mfd/pm8921-core.c delete mode 100644 trunk/drivers/mfd/pm8xxx-irq.c delete mode 100644 trunk/drivers/mfd/tps65910-irq.c delete mode 100644 trunk/drivers/mfd/tps65910.c delete mode 100644 trunk/drivers/mfd/tps65911-comparator.c delete mode 100644 trunk/drivers/power/ds2780_battery.c delete mode 100644 trunk/drivers/power/max8903_charger.c delete mode 100644 trunk/drivers/regulator/tps65910-regulator.c delete mode 100644 trunk/drivers/rtc/rtc-88pm860x.c delete mode 100644 trunk/drivers/rtc/rtc-em3027.c delete mode 100644 trunk/drivers/rtc/rtc-m41t93.c delete mode 100644 trunk/drivers/rtc/rtc-rv3029c2.c delete mode 100644 trunk/drivers/rtc/rtc-spear.c delete mode 100644 trunk/drivers/rtc/rtc-vt8500.c create mode 100644 trunk/drivers/video/omap/lcd_omap2evm.c delete mode 100644 trunk/drivers/w1/slaves/w1_ds2408.c delete mode 100644 trunk/drivers/w1/slaves/w1_ds2780.c delete mode 100644 trunk/drivers/w1/slaves/w1_ds2780.h delete mode 100644 trunk/drivers/xen/tmem.c delete mode 100644 trunk/fs/ext4/mmp.c delete mode 100644 trunk/fs/ocfs2/move_extents.c delete mode 100644 trunk/fs/ocfs2/move_extents.h delete mode 100644 trunk/include/asm-generic/ptrace.h delete mode 100644 trunk/include/linux/cleancache.h delete mode 100644 trunk/include/linux/input/pmic8xxx-keypad.h delete mode 100644 trunk/include/linux/input/pmic8xxx-pwrkey.h delete mode 100644 trunk/include/linux/mfd/pm8xxx/core.h delete mode 100644 trunk/include/linux/mfd/pm8xxx/irq.h delete mode 100644 trunk/include/linux/mfd/pm8xxx/pm8921.h delete mode 100644 trunk/include/linux/mfd/tps65910.h delete mode 100644 trunk/include/linux/power/isp1704_charger.h delete mode 100644 trunk/include/linux/power/max8903_charger.h delete mode 100644 trunk/include/linux/vm_event_item.h delete mode 100644 trunk/include/media/m5mols.h delete mode 100644 trunk/include/rdma/rdma_netlink.h delete mode 100644 trunk/include/trace/events/gpio.h create mode 100644 trunk/kernel/ns_cgroup.c delete mode 100644 trunk/mm/cleancache.c create mode 100644 trunk/sound/soc/omap/omap2evm.c diff --git a/[refs] b/[refs] index 551b0519db64..223b7e34ad68 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 45acab01ca6389371ec39e16844768a60f5f1380 +refs/heads/master: 902050bcdece6191565c055539e82c5cc534feed diff --git a/trunk/Documentation/ABI/removed/o2cb b/trunk/Documentation/ABI/obsolete/o2cb similarity index 65% rename from trunk/Documentation/ABI/removed/o2cb rename to trunk/Documentation/ABI/obsolete/o2cb index 7f5daa465093..9c49d8e6c0cc 100644 --- a/trunk/Documentation/ABI/removed/o2cb +++ b/trunk/Documentation/ABI/obsolete/o2cb @@ -1,10 +1,11 @@ What: /sys/o2cb symlink -Date: May 2011 -KernelVersion: 2.6.40 +Date: Dec 2005 +KernelVersion: 2.6.16 Contact: ocfs2-devel@oss.oracle.com -Description: This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink is - removed when new versions of ocfs2-tools which know to look +Description: This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink will + be removed when new versions of ocfs2-tools which know to look in /sys/fs/o2cb are sufficiently prevalent. Don't code new software to look here, it should try /sys/fs/o2cb instead. + See Documentation/ABI/stable/o2cb for more information on usage. Users: ocfs2-tools. It's sufficient to mail proposed changes to ocfs2-devel@oss.oracle.com. diff --git a/trunk/Documentation/ABI/testing/sysfs-kernel-mm-cleancache b/trunk/Documentation/ABI/testing/sysfs-kernel-mm-cleancache deleted file mode 100644 index 662ae646ea12..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-kernel-mm-cleancache +++ /dev/null @@ -1,11 +0,0 @@ -What: /sys/kernel/mm/cleancache/ -Date: April 2011 -Contact: Dan Magenheimer -Description: - /sys/kernel/mm/cleancache/ contains a number of files which - record a count of various cleancache operations - (sum across all filesystems): - succ_gets - failed_gets - puts - flushes diff --git a/trunk/Documentation/DocBook/dvb/dvbproperty.xml b/trunk/Documentation/DocBook/dvb/dvbproperty.xml index b5365f61d69b..52d5e3c7cf6c 100644 --- a/trunk/Documentation/DocBook/dvb/dvbproperty.xml +++ b/trunk/Documentation/DocBook/dvb/dvbproperty.xml @@ -141,15 +141,13 @@ struct dtv_properties { -
- Property types On FE_GET_PROPERTY/FE_SET_PROPERTY, the actual action is determined by the dtv_property cmd/data pairs. With one single ioctl, is possible to get/set up to 64 properties. The actual meaning of each property is described on the next sections. -The available frontend property types are: +The Available frontend property types are: #define DTV_UNDEFINED 0 #define DTV_TUNE 1 @@ -195,7 +193,6 @@ get/set up to 64 properties. The actual meaning of each property is described on #define DTV_ISDBT_LAYER_ENABLED 41 #define DTV_ISDBS_TS_ID 42 -
Parameters that are common to all Digital TV standards diff --git a/trunk/Documentation/DocBook/media-entities.tmpl b/trunk/Documentation/DocBook/media-entities.tmpl index e5fe09430fd9..c8abb23ef1e7 100644 --- a/trunk/Documentation/DocBook/media-entities.tmpl +++ b/trunk/Documentation/DocBook/media-entities.tmpl @@ -293,7 +293,6 @@ - @@ -374,9 +373,9 @@ - - - + + + diff --git a/trunk/Documentation/DocBook/v4l/media-controller.xml b/trunk/Documentation/DocBook/v4l/media-controller.xml index 873ac3a621f0..2dc25e1d4089 100644 --- a/trunk/Documentation/DocBook/v4l/media-controller.xml +++ b/trunk/Documentation/DocBook/v4l/media-controller.xml @@ -78,9 +78,9 @@ Function Reference - &sub-media-func-open; - &sub-media-func-close; - &sub-media-func-ioctl; + &sub-media-open; + &sub-media-close; + &sub-media-ioctl; &sub-media-ioc-device-info; &sub-media-ioc-enum-entities; diff --git a/trunk/Documentation/DocBook/v4l/pixfmt.xml b/trunk/Documentation/DocBook/v4l/pixfmt.xml index deb660207f94..dbfe3b08435f 100644 --- a/trunk/Documentation/DocBook/v4l/pixfmt.xml +++ b/trunk/Documentation/DocBook/v4l/pixfmt.xml @@ -673,7 +673,6 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.< &sub-srggb8; &sub-sbggr16; &sub-srggb10; - &sub-srggb12;
diff --git a/trunk/Documentation/DocBook/v4l/subdev-formats.xml b/trunk/Documentation/DocBook/v4l/subdev-formats.xml index 8d3409d2c632..a26b10c07857 100644 --- a/trunk/Documentation/DocBook/v4l/subdev-formats.xml +++ b/trunk/Documentation/DocBook/v4l/subdev-formats.xml @@ -2531,13 +2531,13 @@ _JPEG prefix the format code is made of the following information. - The number of bus samples per entropy encoded byte. - The bus width. + The number of bus samples per entropy encoded byte. + The bus width. - - For instance, for a JPEG baseline process and an 8-bit bus width - the format will be named V4L2_MBUS_FMT_JPEG_1X8. + For instance, for a JPEG baseline process and an 8-bit bus width + the format will be named V4L2_MBUS_FMT_JPEG_1X8. + The following table lists existing JPEG compressed formats. diff --git a/trunk/Documentation/accounting/getdelays.c b/trunk/Documentation/accounting/getdelays.c index f6318f6d7baf..e9c77788a39d 100644 --- a/trunk/Documentation/accounting/getdelays.c +++ b/trunk/Documentation/accounting/getdelays.c @@ -177,8 +177,6 @@ static int get_family_id(int sd) rc = send_cmd(sd, GENL_ID_CTRL, getpid(), CTRL_CMD_GETFAMILY, CTRL_ATTR_FAMILY_NAME, (void *)name, strlen(TASKSTATS_GENL_NAME)+1); - if (rc < 0) - return 0; /* sendto() failure? */ rep_len = recv(sd, &ans, sizeof(ans), 0); if (ans.n.nlmsg_type == NLMSG_ERROR || @@ -193,37 +191,30 @@ static int get_family_id(int sd) return id; } -#define average_ms(t, c) (t / 1000000ULL / (c ? c : 1)) - static void print_delayacct(struct taskstats *t) { - printf("\n\nCPU %15s%15s%15s%15s%15s\n" - " %15llu%15llu%15llu%15llu%15.3fms\n" - "IO %15s%15s%15s\n" - " %15llu%15llu%15llums\n" - "SWAP %15s%15s%15s\n" - " %15llu%15llu%15llums\n" - "RECLAIM %12s%15s%15s\n" - " %15llu%15llu%15llums\n", - "count", "real total", "virtual total", - "delay total", "delay average", + printf("\n\nCPU %15s%15s%15s%15s\n" + " %15llu%15llu%15llu%15llu\n" + "IO %15s%15s\n" + " %15llu%15llu\n" + "SWAP %15s%15s\n" + " %15llu%15llu\n" + "RECLAIM %12s%15s\n" + " %15llu%15llu\n", + "count", "real total", "virtual total", "delay total", (unsigned long long)t->cpu_count, (unsigned long long)t->cpu_run_real_total, (unsigned long long)t->cpu_run_virtual_total, (unsigned long long)t->cpu_delay_total, - average_ms((double)t->cpu_delay_total, t->cpu_count), - "count", "delay total", "delay average", + "count", "delay total", (unsigned long long)t->blkio_count, (unsigned long long)t->blkio_delay_total, - average_ms(t->blkio_delay_total, t->blkio_count), - "count", "delay total", "delay average", + "count", "delay total", (unsigned long long)t->swapin_count, (unsigned long long)t->swapin_delay_total, - average_ms(t->swapin_delay_total, t->swapin_count), - "count", "delay total", "delay average", + "count", "delay total", (unsigned long long)t->freepages_count, - (unsigned long long)t->freepages_delay_total, - average_ms(t->freepages_delay_total, t->freepages_count)); + (unsigned long long)t->freepages_delay_total); } static void task_context_switch_counts(struct taskstats *t) @@ -442,6 +433,8 @@ int main(int argc, char *argv[]) } do { + int i; + rep_len = recv(nl_sd, &msg, sizeof(msg), 0); PRINTF("received %d bytes\n", rep_len); @@ -466,6 +459,7 @@ int main(int argc, char *argv[]) na = (struct nlattr *) GENLMSG_DATA(&msg); len = 0; + i = 0; while (len < rep_len) { len += NLA_ALIGN(na->nla_len); switch (na->nla_type) { diff --git a/trunk/Documentation/atomic_ops.txt b/trunk/Documentation/atomic_ops.txt index 3bd585b44927..ac4d47187122 100644 --- a/trunk/Documentation/atomic_ops.txt +++ b/trunk/Documentation/atomic_ops.txt @@ -12,7 +12,7 @@ Also, it should be made opaque such that any kind of cast to a normal C integer type will fail. Something like the following should suffice: - typedef struct { int counter; } atomic_t; + typedef struct { volatile int counter; } atomic_t; Historically, counter has been declared volatile. This is now discouraged. See Documentation/volatile-considered-harmful.txt for the complete rationale. diff --git a/trunk/Documentation/cgroups/cgroups.txt b/trunk/Documentation/cgroups/cgroups.txt index 0ed99f08f1f3..aedf1bd02fdd 100644 --- a/trunk/Documentation/cgroups/cgroups.txt +++ b/trunk/Documentation/cgroups/cgroups.txt @@ -236,8 +236,7 @@ containing the following files describing that cgroup: - cgroup.procs: list of tgids in the cgroup. This list is not guaranteed to be sorted or free of duplicate tgids, and userspace should sort/uniquify the list if this property is required. - Writing a thread group id into this file moves all threads in that - group into this cgroup. + This is a read-only file, for now. - notify_on_release flag: run the release agent on exit? - release_agent: the path to use for release notifications (this file exists in the top cgroup only) @@ -431,12 +430,6 @@ You can attach the current shell task by echoing 0: # echo 0 > tasks -You can use the cgroup.procs file instead of the tasks file to move all -threads in a threadgroup at once. Echoing the pid of any task in a -threadgroup to cgroup.procs causes all tasks in that threadgroup to be -be attached to the cgroup. Writing 0 to cgroup.procs moves all tasks -in the writing task's threadgroup. - Note: Since every task is always a member of exactly one cgroup in each mounted hierarchy, to remove a task from its current cgroup you must move it into a new cgroup (possibly the root cgroup) by writing to the @@ -582,7 +575,7 @@ rmdir() will fail with it. From this behavior, pre_destroy() can be called multiple times against a cgroup. int can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp, - struct task_struct *task) + struct task_struct *task, bool threadgroup) (cgroup_mutex held by caller) Called prior to moving a task into a cgroup; if the subsystem @@ -591,14 +584,9 @@ task is passed, then a successful result indicates that *any* unspecified task can be moved into the cgroup. Note that this isn't called on a fork. If this method returns 0 (success) then this should remain valid while the caller holds cgroup_mutex and it is ensured that either -attach() or cancel_attach() will be called in future. - -int can_attach_task(struct cgroup *cgrp, struct task_struct *tsk); -(cgroup_mutex held by caller) - -As can_attach, but for operations that must be run once per task to be -attached (possibly many when using cgroup_attach_proc). Called after -can_attach. +attach() or cancel_attach() will be called in future. If threadgroup is +true, then a successful result indicates that all threads in the given +thread's threadgroup can be moved together. void cancel_attach(struct cgroup_subsys *ss, struct cgroup *cgrp, struct task_struct *task, bool threadgroup) @@ -610,24 +598,15 @@ function, so that the subsystem can implement a rollback. If not, not necessary. This will be called only about subsystems whose can_attach() operation have succeeded. -void pre_attach(struct cgroup *cgrp); -(cgroup_mutex held by caller) - -For any non-per-thread attachment work that needs to happen before -attach_task. Needed by cpuset. - void attach(struct cgroup_subsys *ss, struct cgroup *cgrp, - struct cgroup *old_cgrp, struct task_struct *task) + struct cgroup *old_cgrp, struct task_struct *task, + bool threadgroup) (cgroup_mutex held by caller) Called after the task has been attached to the cgroup, to allow any post-attachment activity that requires memory allocations or blocking. - -void attach_task(struct cgroup *cgrp, struct task_struct *tsk); -(cgroup_mutex held by caller) - -As attach, but for operations that must be run once per task to be attached, -like can_attach_task. Called before attach. Currently does not support any +If threadgroup is true, the subsystem should take care of all threads +in the specified thread's threadgroup. Currently does not support any subsystem that might need the old_cgrp for every thread in the group. void fork(struct cgroup_subsy *ss, struct task_struct *task) @@ -651,7 +630,7 @@ always handled well. void post_clone(struct cgroup_subsys *ss, struct cgroup *cgrp) (cgroup_mutex held by caller) -Called during cgroup_create() to do any parameter +Called at the end of cgroup_clone() to do any parameter initialization which might be required before a task could attach. For example in cpusets, no task may attach before 'cpus' and 'mems' are set up. diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index ff31b1cc50aa..95788ad2506c 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -262,6 +262,16 @@ Who: Michael Buesch --------------------------- +What: /sys/o2cb symlink +When: January 2010 +Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb + exists as a symlink for backwards compatibility for old versions of + ocfs2-tools. 2 years should be sufficient time to phase in new versions + which know to look in /sys/fs/o2cb. +Who: ocfs2-devel@oss.oracle.com + +--------------------------- + What: Ability for non root users to shm_get hugetlb pages based on mlock resource limits When: 2.6.31 diff --git a/trunk/Documentation/filesystems/configfs/configfs_example_explicit.c b/trunk/Documentation/filesystems/configfs/configfs_example_explicit.c index 1420233dfa55..fd53869f5633 100644 --- a/trunk/Documentation/filesystems/configfs/configfs_example_explicit.c +++ b/trunk/Documentation/filesystems/configfs/configfs_example_explicit.c @@ -464,8 +464,9 @@ static int __init configfs_example_init(void) return 0; out_unregister: - for (i--; i >= 0; i--) + for (; i >= 0; i--) { configfs_unregister_subsystem(example_subsys[i]); + } return ret; } @@ -474,8 +475,9 @@ static void __exit configfs_example_exit(void) { int i; - for (i = 0; example_subsys[i]; i++) + for (i = 0; example_subsys[i]; i++) { configfs_unregister_subsystem(example_subsys[i]); + } } module_init(configfs_example_init); diff --git a/trunk/Documentation/filesystems/configfs/configfs_example_macros.c b/trunk/Documentation/filesystems/configfs/configfs_example_macros.c index 327dfbc640a9..d8e30a0378aa 100644 --- a/trunk/Documentation/filesystems/configfs/configfs_example_macros.c +++ b/trunk/Documentation/filesystems/configfs/configfs_example_macros.c @@ -427,8 +427,9 @@ static int __init configfs_example_init(void) return 0; out_unregister: - for (i--; i >= 0; i--) + for (; i >= 0; i--) { configfs_unregister_subsystem(example_subsys[i]); + } return ret; } @@ -437,8 +438,9 @@ static void __exit configfs_example_exit(void) { int i; - for (i = 0; example_subsys[i]; i++) + for (i = 0; example_subsys[i]; i++) { configfs_unregister_subsystem(example_subsys[i]); + } } module_init(configfs_example_init); diff --git a/trunk/Documentation/filesystems/ext4.txt b/trunk/Documentation/filesystems/ext4.txt index 3ae9bc94352a..c79ec58fd7f6 100644 --- a/trunk/Documentation/filesystems/ext4.txt +++ b/trunk/Documentation/filesystems/ext4.txt @@ -226,6 +226,10 @@ acl Enables POSIX Access Control Lists support. noacl This option disables POSIX Access Control List support. +reservation + +noreservation + bsddf (*) Make 'df' act like BSD. minixdf Make 'df' act like Minix. diff --git a/trunk/Documentation/filesystems/ocfs2.txt b/trunk/Documentation/filesystems/ocfs2.txt index 7618a287aa41..9ed920a8cd79 100644 --- a/trunk/Documentation/filesystems/ocfs2.txt +++ b/trunk/Documentation/filesystems/ocfs2.txt @@ -46,15 +46,9 @@ errors=panic Panic and halt the machine if an error occurs. intr (*) Allow signals to interrupt cluster operations. nointr Do not allow signals to interrupt cluster operations. -noatime Do not update access time. -relatime(*) Update atime if the previous atime is older than - mtime or ctime -strictatime Always update atime, but the minimum update interval - is specified by atime_quantum. atime_quantum=60(*) OCFS2 will not update atime unless this number of seconds has passed since the last update. - Set to zero to always update atime. This option need - work with strictatime. + Set to zero to always update atime. data=ordered (*) All data are forced directly out to the main file system prior to its metadata being committed to the journal. diff --git a/trunk/Documentation/filesystems/xfs.txt b/trunk/Documentation/filesystems/xfs.txt index 3fc0c31a6f5d..7bff3e4f35df 100644 --- a/trunk/Documentation/filesystems/xfs.txt +++ b/trunk/Documentation/filesystems/xfs.txt @@ -39,12 +39,6 @@ When mounting an XFS filesystem, the following options are accepted. drive level write caching to be enabled, for devices that support write barriers. - discard - Issue command to let the block device reclaim space freed by the - filesystem. This is useful for SSD devices, thinly provisioned - LUNs and virtual machine images, but may have a performance - impact. This option is incompatible with the nodelaylog option. - dmapi Enable the DMAPI (Data Management API) event callouts. Use with the "mtpt" option. diff --git a/trunk/Documentation/power/regulator/machine.txt b/trunk/Documentation/power/regulator/machine.txt index b42419b52e44..bdec39b9bd75 100644 --- a/trunk/Documentation/power/regulator/machine.txt +++ b/trunk/Documentation/power/regulator/machine.txt @@ -53,11 +53,11 @@ static struct regulator_init_data regulator1_data = { Regulator-1 supplies power to Regulator-2. This relationship must be registered with the core so that Regulator-1 is also enabled when Consumer A enables its -supply (Regulator-2). The supply regulator is set by the supply_regulator +supply (Regulator-2). The supply regulator is set by the supply_regulator_dev field below:- static struct regulator_init_data regulator2_data = { - .supply_regulator = "regulator_name", + .supply_regulator_dev = &platform_regulator1_device.dev, .constraints = { .min_uV = 1800000, .max_uV = 2000000, diff --git a/trunk/Documentation/sysctl/kernel.txt b/trunk/Documentation/sysctl/kernel.txt index 5e7cb39ad195..36f007514db3 100644 --- a/trunk/Documentation/sysctl/kernel.txt +++ b/trunk/Documentation/sysctl/kernel.txt @@ -161,8 +161,7 @@ core_pattern is used to specify a core dumpfile pattern name. %s signal number %t UNIX time of dump %h hostname - %e executable filename (may be shortened) - %E executable path + %e executable filename % both are dropped . If the first character of the pattern is a '|', the kernel will treat the rest of the pattern as a command to run. The core dump will be diff --git a/trunk/Documentation/vm/cleancache.txt b/trunk/Documentation/vm/cleancache.txt deleted file mode 100644 index 36c367c73084..000000000000 --- a/trunk/Documentation/vm/cleancache.txt +++ /dev/null @@ -1,278 +0,0 @@ -MOTIVATION - -Cleancache is a new optional feature provided by the VFS layer that -potentially dramatically increases page cache effectiveness for -many workloads in many environments at a negligible cost. - -Cleancache can be thought of as a page-granularity victim cache for clean -pages that the kernel's pageframe replacement algorithm (PFRA) would like -to keep around, but can't since there isn't enough memory. So when the -PFRA "evicts" a page, it first attempts to use cleancache code to -put the data contained in that page into "transcendent memory", memory -that is not directly accessible or addressable by the kernel and is -of unknown and possibly time-varying size. - -Later, when a cleancache-enabled filesystem wishes to access a page -in a file on disk, it first checks cleancache to see if it already -contains it; if it does, the page of data is copied into the kernel -and a disk access is avoided. - -Transcendent memory "drivers" for cleancache are currently implemented -in Xen (using hypervisor memory) and zcache (using in-kernel compressed -memory) and other implementations are in development. - -FAQs are included below. - -IMPLEMENTATION OVERVIEW - -A cleancache "backend" that provides transcendent memory registers itself -to the kernel's cleancache "frontend" by calling cleancache_register_ops, -passing a pointer to a cleancache_ops structure with funcs set appropriately. -Note that cleancache_register_ops returns the previous settings so that -chaining can be performed if desired. The functions provided must conform to -certain semantics as follows: - -Most important, cleancache is "ephemeral". Pages which are copied into -cleancache have an indefinite lifetime which is completely unknowable -by the kernel and so may or may not still be in cleancache at any later time. -Thus, as its name implies, cleancache is not suitable for dirty pages. -Cleancache has complete discretion over what pages to preserve and what -pages to discard and when. - -Mounting a cleancache-enabled filesystem should call "init_fs" to obtain a -pool id which, if positive, must be saved in the filesystem's superblock; -a negative return value indicates failure. A "put_page" will copy a -(presumably about-to-be-evicted) page into cleancache and associate it with -the pool id, a file key, and a page index into the file. (The combination -of a pool id, a file key, and an index is sometimes called a "handle".) -A "get_page" will copy the page, if found, from cleancache into kernel memory. -A "flush_page" will ensure the page no longer is present in cleancache; -a "flush_inode" will flush all pages associated with the specified file; -and, when a filesystem is unmounted, a "flush_fs" will flush all pages in -all files specified by the given pool id and also surrender the pool id. - -An "init_shared_fs", like init_fs, obtains a pool id but tells cleancache -to treat the pool as shared using a 128-bit UUID as a key. On systems -that may run multiple kernels (such as hard partitioned or virtualized -systems) that may share a clustered filesystem, and where cleancache -may be shared among those kernels, calls to init_shared_fs that specify the -same UUID will receive the same pool id, thus allowing the pages to -be shared. Note that any security requirements must be imposed outside -of the kernel (e.g. by "tools" that control cleancache). Or a -cleancache implementation can simply disable shared_init by always -returning a negative value. - -If a get_page is successful on a non-shared pool, the page is flushed (thus -making cleancache an "exclusive" cache). On a shared pool, the page -is NOT flushed on a successful get_page so that it remains accessible to -other sharers. The kernel is responsible for ensuring coherency between -cleancache (shared or not), the page cache, and the filesystem, using -cleancache flush operations as required. - -Note that cleancache must enforce put-put-get coherency and get-get -coherency. For the former, if two puts are made to the same handle but -with different data, say AAA by the first put and BBB by the second, a -subsequent get can never return the stale data (AAA). For get-get coherency, -if a get for a given handle fails, subsequent gets for that handle will -never succeed unless preceded by a successful put with that handle. - -Last, cleancache provides no SMP serialization guarantees; if two -different Linux threads are simultaneously putting and flushing a page -with the same handle, the results are indeterminate. Callers must -lock the page to ensure serial behavior. - -CLEANCACHE PERFORMANCE METRICS - -Cleancache monitoring is done by sysfs files in the -/sys/kernel/mm/cleancache directory. The effectiveness of cleancache -can be measured (across all filesystems) with: - -succ_gets - number of gets that were successful -failed_gets - number of gets that failed -puts - number of puts attempted (all "succeed") -flushes - number of flushes attempted - -A backend implementatation may provide additional metrics. - -FAQ - -1) Where's the value? (Andrew Morton) - -Cleancache provides a significant performance benefit to many workloads -in many environments with negligible overhead by improving the -effectiveness of the pagecache. Clean pagecache pages are -saved in transcendent memory (RAM that is otherwise not directly -addressable to the kernel); fetching those pages later avoids "refaults" -and thus disk reads. - -Cleancache (and its sister code "frontswap") provide interfaces for -this transcendent memory (aka "tmem"), which conceptually lies between -fast kernel-directly-addressable RAM and slower DMA/asynchronous devices. -Disallowing direct kernel or userland reads/writes to tmem -is ideal when data is transformed to a different form and size (such -as with compression) or secretly moved (as might be useful for write- -balancing for some RAM-like devices). Evicted page-cache pages (and -swap pages) are a great use for this kind of slower-than-RAM-but-much- -faster-than-disk transcendent memory, and the cleancache (and frontswap) -"page-object-oriented" specification provides a nice way to read and -write -- and indirectly "name" -- the pages. - -In the virtual case, the whole point of virtualization is to statistically -multiplex physical resources across the varying demands of multiple -virtual machines. This is really hard to do with RAM and efforts to -do it well with no kernel change have essentially failed (except in some -well-publicized special-case workloads). Cleancache -- and frontswap -- -with a fairly small impact on the kernel, provide a huge amount -of flexibility for more dynamic, flexible RAM multiplexing. -Specifically, the Xen Transcendent Memory backend allows otherwise -"fallow" hypervisor-owned RAM to not only be "time-shared" between multiple -virtual machines, but the pages can be compressed and deduplicated to -optimize RAM utilization. And when guest OS's are induced to surrender -underutilized RAM (e.g. with "self-ballooning"), page cache pages -are the first to go, and cleancache allows those pages to be -saved and reclaimed if overall host system memory conditions allow. - -And the identical interface used for cleancache can be used in -physical systems as well. The zcache driver acts as a memory-hungry -device that stores pages of data in a compressed state. And -the proposed "RAMster" driver shares RAM across multiple physical -systems. - -2) Why does cleancache have its sticky fingers so deep inside the - filesystems and VFS? (Andrew Morton and Christoph Hellwig) - -The core hooks for cleancache in VFS are in most cases a single line -and the minimum set are placed precisely where needed to maintain -coherency (via cleancache_flush operations) between cleancache, -the page cache, and disk. All hooks compile into nothingness if -cleancache is config'ed off and turn into a function-pointer- -compare-to-NULL if config'ed on but no backend claims the ops -functions, or to a compare-struct-element-to-negative if a -backend claims the ops functions but a filesystem doesn't enable -cleancache. - -Some filesystems are built entirely on top of VFS and the hooks -in VFS are sufficient, so don't require an "init_fs" hook; the -initial implementation of cleancache didn't provide this hook. -But for some filesystems (such as btrfs), the VFS hooks are -incomplete and one or more hooks in fs-specific code are required. -And for some other filesystems, such as tmpfs, cleancache may -be counterproductive. So it seemed prudent to require a filesystem -to "opt in" to use cleancache, which requires adding a hook in -each filesystem. Not all filesystems are supported by cleancache -only because they haven't been tested. The existing set should -be sufficient to validate the concept, the opt-in approach means -that untested filesystems are not affected, and the hooks in the -existing filesystems should make it very easy to add more -filesystems in the future. - -The total impact of the hooks to existing fs and mm files is only -about 40 lines added (not counting comments and blank lines). - -3) Why not make cleancache asynchronous and batched so it can - more easily interface with real devices with DMA instead - of copying each individual page? (Minchan Kim) - -The one-page-at-a-time copy semantics simplifies the implementation -on both the frontend and backend and also allows the backend to -do fancy things on-the-fly like page compression and -page deduplication. And since the data is "gone" (copied into/out -of the pageframe) before the cleancache get/put call returns, -a great deal of race conditions and potential coherency issues -are avoided. While the interface seems odd for a "real device" -or for real kernel-addressable RAM, it makes perfect sense for -transcendent memory. - -4) Why is non-shared cleancache "exclusive"? And where is the - page "flushed" after a "get"? (Minchan Kim) - -The main reason is to free up space in transcendent memory and -to avoid unnecessary cleancache_flush calls. If you want inclusive, -the page can be "put" immediately following the "get". If -put-after-get for inclusive becomes common, the interface could -be easily extended to add a "get_no_flush" call. - -The flush is done by the cleancache backend implementation. - -5) What's the performance impact? - -Performance analysis has been presented at OLS'09 and LCA'10. -Briefly, performance gains can be significant on most workloads, -especially when memory pressure is high (e.g. when RAM is -overcommitted in a virtual workload); and because the hooks are -invoked primarily in place of or in addition to a disk read/write, -overhead is negligible even in worst case workloads. Basically -cleancache replaces I/O with memory-copy-CPU-overhead; on older -single-core systems with slow memory-copy speeds, cleancache -has little value, but in newer multicore machines, especially -consolidated/virtualized machines, it has great value. - -6) How do I add cleancache support for filesystem X? (Boaz Harrash) - -Filesystems that are well-behaved and conform to certain -restrictions can utilize cleancache simply by making a call to -cleancache_init_fs at mount time. Unusual, misbehaving, or -poorly layered filesystems must either add additional hooks -and/or undergo extensive additional testing... or should just -not enable the optional cleancache. - -Some points for a filesystem to consider: - -- The FS should be block-device-based (e.g. a ram-based FS such - as tmpfs should not enable cleancache) -- To ensure coherency/correctness, the FS must ensure that all - file removal or truncation operations either go through VFS or - add hooks to do the equivalent cleancache "flush" operations -- To ensure coherency/correctness, either inode numbers must - be unique across the lifetime of the on-disk file OR the - FS must provide an "encode_fh" function. -- The FS must call the VFS superblock alloc and deactivate routines - or add hooks to do the equivalent cleancache calls done there. -- To maximize performance, all pages fetched from the FS should - go through the do_mpag_readpage routine or the FS should add - hooks to do the equivalent (cf. btrfs) -- Currently, the FS blocksize must be the same as PAGESIZE. This - is not an architectural restriction, but no backends currently - support anything different. -- A clustered FS should invoke the "shared_init_fs" cleancache - hook to get best performance for some backends. - -7) Why not use the KVA of the inode as the key? (Christoph Hellwig) - -If cleancache would use the inode virtual address instead of -inode/filehandle, the pool id could be eliminated. But, this -won't work because cleancache retains pagecache data pages -persistently even when the inode has been pruned from the -inode unused list, and only flushes the data page if the file -gets removed/truncated. So if cleancache used the inode kva, -there would be potential coherency issues if/when the inode -kva is reused for a different file. Alternately, if cleancache -flushed the pages when the inode kva was freed, much of the value -of cleancache would be lost because the cache of pages in cleanache -is potentially much larger than the kernel pagecache and is most -useful if the pages survive inode cache removal. - -8) Why is a global variable required? - -The cleancache_enabled flag is checked in all of the frequently-used -cleancache hooks. The alternative is a function call to check a static -variable. Since cleancache is enabled dynamically at runtime, systems -that don't enable cleancache would suffer thousands (possibly -tens-of-thousands) of unnecessary function calls per second. So the -global variable allows cleancache to be enabled by default at compile -time, but have insignificant performance impact when cleancache remains -disabled at runtime. - -9) Does cleanache work with KVM? - -The memory model of KVM is sufficiently different that a cleancache -backend may have less value for KVM. This remains to be tested, -especially in an overcommitted system. - -10) Does cleancache work in userspace? It sounds useful for - memory hungry caches like web browsers. (Jamie Lokier) - -No plans yet, though we agree it sounds useful, at least for -apps that bypass the page cache (e.g. O_DIRECT). - -Last updated: Dan Magenheimer, April 13 2011 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 572b5b20ba48..1ab17de642e5 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -931,8 +931,6 @@ F: drivers/mmc/host/msm_sdcc.h F: drivers/tty/serial/msm_serial.h F: drivers/tty/serial/msm_serial.c F: drivers/platform/msm/ -F: drivers/*/pm8???-* -F: include/linux/mfd/pm8xxx/ T: git git://codeaurora.org/quic/kernel/davidb/linux-msm.git S: Maintained @@ -2584,13 +2582,6 @@ S: Maintained F: drivers/hwmon/f75375s.c F: include/linux/f75375s.h -FIREWIRE AUDIO DRIVERS -M: Clemens Ladisch -L: alsa-devel@alsa-project.org (moderated for non-subscribers) -T: git git://git.alsa-project.org/alsa-kernel.git -S: Maintained -F: sound/firewire/ - FIREWIRE SUBSYSTEM M: Stefan Richter L: linux1394-devel@lists.sourceforge.net @@ -3581,16 +3572,9 @@ M: Andrew Morton M: Jan Kara L: linux-ext4@vger.kernel.org S: Maintained -F: fs/jbd/ -F: include/linux/ext3_jbd.h -F: include/linux/jbd.h - -JOURNALLING LAYER FOR BLOCK DEVICES (JBD2) -M: "Theodore Ts'o" -L: linux-ext4@vger.kernel.org -S: Maintained -F: fs/jbd2/ -F: include/linux/jbd2.h +F: fs/jbd*/ +F: include/linux/ext*jbd*.h +F: include/linux/jbd*.h JSM Neo PCI based serial card M: Breno Leitao @@ -4154,7 +4138,6 @@ M: KAMEZAWA Hiroyuki L: linux-mm@kvack.org S: Maintained F: mm/memcontrol.c -F: mm/page_cgroup.c MEMORY TECHNOLOGY DEVICES (MTD) M: David Woodhouse @@ -6008,7 +5991,7 @@ F: Documentation/filesystems/spufs.txt F: arch/powerpc/platforms/cell/spufs/ SQUASHFS FILE SYSTEM -M: Phillip Lougher +M: Phillip Lougher L: squashfs-devel@lists.sourceforge.net (subscribers-only) W: http://squashfs.org.uk S: Maintained diff --git a/trunk/arch/alpha/Kconfig b/trunk/arch/alpha/Kconfig index 60219bf94198..e3a82775f9da 100644 --- a/trunk/arch/alpha/Kconfig +++ b/trunk/arch/alpha/Kconfig @@ -41,6 +41,10 @@ config ARCH_HAS_ILOG2_U64 bool default n +config GENERIC_FIND_NEXT_BIT + bool + default y + config GENERIC_CALIBRATE_DELAY bool default y diff --git a/trunk/arch/arm/configs/omap2plus_defconfig b/trunk/arch/arm/configs/omap2plus_defconfig index d5f00d7eb075..076db52ff672 100644 --- a/trunk/arch/arm/configs/omap2plus_defconfig +++ b/trunk/arch/arm/configs/omap2plus_defconfig @@ -21,22 +21,58 @@ CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set CONFIG_ARCH_OMAP=y +CONFIG_ARCH_OMAP2=y +CONFIG_ARCH_OMAP3=y +CONFIG_ARCH_OMAP4=y CONFIG_OMAP_RESET_CLOCKS=y CONFIG_OMAP_MUX_DEBUG=y +CONFIG_OMAP_32K_TIMER=y +CONFIG_MACH_OMAP_GENERIC=y +CONFIG_ARCH_OMAP2420=y +CONFIG_ARCH_OMAP2430=y +CONFIG_ARCH_OMAP3430=y +CONFIG_MACH_OMAP_H4=y +CONFIG_MACH_OMAP_APOLLON=y +CONFIG_MACH_OMAP_2430SDP=y +CONFIG_MACH_OMAP3_BEAGLE=y +CONFIG_MACH_DEVKIT8000=y +CONFIG_MACH_OMAP_LDP=y +CONFIG_MACH_OVERO=y +CONFIG_MACH_OMAP3EVM=y +CONFIG_MACH_OMAP3517EVM=y +CONFIG_MACH_OMAP3_PANDORA=y +CONFIG_MACH_OMAP3_TOUCHBOOK=y +CONFIG_MACH_OMAP_3430SDP=y +CONFIG_MACH_NOKIA_N8X0=y +CONFIG_MACH_NOKIA_RX51=y +CONFIG_MACH_OMAP_ZOOM2=y +CONFIG_MACH_OMAP_ZOOM3=y +CONFIG_MACH_CM_T35=y +CONFIG_MACH_IGEP0020=y +CONFIG_MACH_SBC3530=y +CONFIG_MACH_OMAP_3630SDP=y +CONFIG_MACH_OMAP_4430SDP=y CONFIG_ARM_THUMBEE=y +CONFIG_ARM_L1_CACHE_SHIFT=5 CONFIG_ARM_ERRATA_411920=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y CONFIG_NR_CPUS=2 +# CONFIG_LOCAL_TIMERS is not set +CONFIG_AEABI=y CONFIG_LEDS=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200" CONFIG_KEXEC=y CONFIG_FPE_NWFPE=y +CONFIG_VFP=y +CONFIG_NEON=y CONFIG_BINFMT_MISC=y +CONFIG_PM=y CONFIG_PM_DEBUG=y +CONFIG_PM_RUNTIME=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -53,6 +89,14 @@ CONFIG_IP_PNP_RARP=y # CONFIG_IPV6 is not set CONFIG_NETFILTER=y CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m CONFIG_BT_HCIUART=m CONFIG_BT_HCIUART_H4=y CONFIG_BT_HCIUART_BCSP=y @@ -63,9 +107,11 @@ CONFIG_CFG80211=m CONFIG_MAC80211=m CONFIG_MAC80211_RC_PID=y CONFIG_MAC80211_RC_DEFAULT_PID=y +CONFIG_MAC80211_LEDS=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_CONNECTOR=y CONFIG_MTD=y +CONFIG_MTD_CONCAT=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y @@ -81,6 +127,7 @@ CONFIG_MTD_UBI=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_EEPROM_LEGACY=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_SCSI_MULTI_LUN=y @@ -111,15 +158,19 @@ CONFIG_TOUCHSCREEN_ADS7846=y CONFIG_INPUT_MISC=y CONFIG_INPUT_TWL4030_PWRBUTTON=y CONFIG_VT_HW_CONSOLE_BINDING=y -# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=32 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_8250_RSA=y +# CONFIG_LEGACY_PTYS is not set CONFIG_HW_RANDOM=y +CONFIG_I2C=y CONFIG_I2C_CHARDEV=y +CONFIG_I2C_OMAP=y CONFIG_SPI=y CONFIG_SPI_OMAP24XX=y CONFIG_DEBUG_GPIO=y @@ -130,6 +181,10 @@ CONFIG_POWER_SUPPLY=y CONFIG_WATCHDOG=y CONFIG_OMAP_WATCHDOG=y CONFIG_TWL4030_WATCHDOG=y +CONFIG_MENELAUS=y +CONFIG_TWL4030_CORE=y +CONFIG_TWL4030_POWER=y +CONFIG_REGULATOR=y CONFIG_REGULATOR_TWL4030=y CONFIG_REGULATOR_TPS65023=y CONFIG_REGULATOR_TPS6507X=y @@ -153,6 +208,7 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_PLATFORM=y CONFIG_DISPLAY_SUPPORT=y +# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y CONFIG_FONTS=y @@ -161,20 +217,25 @@ CONFIG_FONT_8x16=y CONFIG_LOGO=y CONFIG_SOUND=m CONFIG_SND=m -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y -CONFIG_SND_USB_AUDIO=m -CONFIG_SND_SOC=m -CONFIG_SND_OMAP_SOC=m -CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y CONFIG_USB=y CONFIG_USB_DEBUG=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_DEVICEFS=y CONFIG_USB_SUSPEND=y +# CONFIG_USB_OTG_WHITELIST is not set CONFIG_USB_MON=y +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_MUSB_OTG is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set +CONFIG_USB_MUSB_DEBUG=y CONFIG_USB_WDM=y CONFIG_USB_STORAGE=y CONFIG_USB_LIBUSUAL=y @@ -189,12 +250,18 @@ CONFIG_MMC_UNSAFE_RESUME=y CONFIG_SDIO_UART=y CONFIG_MMC_OMAP=y CONFIG_MMC_OMAP_HS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_TWL92330=y CONFIG_RTC_DRV_TWL4030=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set +CONFIG_INOTIFY=y CONFIG_QUOTA=y CONFIG_QFMT_V2=y CONFIG_MSDOS_FS=y @@ -218,10 +285,12 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y CONFIG_SCHEDSTATS=y CONFIG_TIMER_STATS=y CONFIG_PROVE_LOCKING=y +# CONFIG_LOCK_STAT is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO=y diff --git a/trunk/arch/arm/include/asm/bitops.h b/trunk/arch/arm/include/asm/bitops.h index b4892a06442c..6b7403fd8f54 100644 --- a/trunk/arch/arm/include/asm/bitops.h +++ b/trunk/arch/arm/include/asm/bitops.h @@ -203,6 +203,8 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset); #define find_first_bit(p,sz) _find_first_bit_le(p,sz) #define find_next_bit(p,sz,off) _find_next_bit_le(p,sz,off) +#define WORD_BITOFF_TO_LE(x) ((x)) + #else /* * These are the big endian, atomic definitions. @@ -212,6 +214,8 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset); #define find_first_bit(p,sz) _find_first_bit_be(p,sz) #define find_next_bit(p,sz,off) _find_next_bit_be(p,sz,off) +#define WORD_BITOFF_TO_LE(x) ((x) ^ 0x18) + #endif #if __LINUX_ARM_ARCH__ < 5 @@ -283,29 +287,55 @@ static inline int fls(int x) #include #include -#ifdef __ARMEB__ +static inline void __set_bit_le(int nr, void *addr) +{ + __set_bit(WORD_BITOFF_TO_LE(nr), addr); +} + +static inline void __clear_bit_le(int nr, void *addr) +{ + __clear_bit(WORD_BITOFF_TO_LE(nr), addr); +} + +static inline int __test_and_set_bit_le(int nr, void *addr) +{ + return __test_and_set_bit(WORD_BITOFF_TO_LE(nr), addr); +} + +static inline int test_and_set_bit_le(int nr, void *addr) +{ + return test_and_set_bit(WORD_BITOFF_TO_LE(nr), addr); +} + +static inline int __test_and_clear_bit_le(int nr, void *addr) +{ + return __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), addr); +} + +static inline int test_and_clear_bit_le(int nr, void *addr) +{ + return test_and_clear_bit(WORD_BITOFF_TO_LE(nr), addr); +} + +static inline int test_bit_le(int nr, const void *addr) +{ + return test_bit(WORD_BITOFF_TO_LE(nr), addr); +} static inline int find_first_zero_bit_le(const void *p, unsigned size) { return _find_first_zero_bit_le(p, size); } -#define find_first_zero_bit_le find_first_zero_bit_le static inline int find_next_zero_bit_le(const void *p, int size, int offset) { return _find_next_zero_bit_le(p, size, offset); } -#define find_next_zero_bit_le find_next_zero_bit_le static inline int find_next_bit_le(const void *p, int size, int offset) { return _find_next_bit_le(p, size, offset); } -#define find_next_bit_le find_next_bit_le - -#endif - -#include /* * Ext2 is defined to use little-endian byte ordering. diff --git a/trunk/arch/arm/mach-omap2/Kconfig b/trunk/arch/arm/mach-omap2/Kconfig index 19d5891c48e3..b997a35830fc 100644 --- a/trunk/arch/arm/mach-omap2/Kconfig +++ b/trunk/arch/arm/mach-omap2/Kconfig @@ -288,7 +288,6 @@ config MACH_IGEP0030 depends on ARCH_OMAP3 default y select OMAP_PACKAGE_CBB - select MACH_IGEP0020 config MACH_SBC3530 bool "OMAP3 SBC STALKER board" diff --git a/trunk/arch/arm/mach-omap2/Makefile b/trunk/arch/arm/mach-omap2/Makefile index b14807794401..66dfbccacd25 100644 --- a/trunk/arch/arm/mach-omap2/Makefile +++ b/trunk/arch/arm/mach-omap2/Makefile @@ -229,6 +229,8 @@ obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o \ obj-$(CONFIG_MACH_CM_T3517) += board-cm-t3517.o obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o \ hsmmc.o +obj-$(CONFIG_MACH_IGEP0030) += board-igep0030.o \ + hsmmc.o obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o \ hsmmc.o obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o \ @@ -268,5 +270,3 @@ obj-$(CONFIG_ARCH_OMAP4) += hwspinlock.o disp-$(CONFIG_OMAP2_DSS) := display.o obj-y += $(disp-m) $(disp-y) - -obj-y += common-board-devices.o diff --git a/trunk/arch/arm/mach-omap2/board-2430sdp.c b/trunk/arch/arm/mach-omap2/board-2430sdp.c index d54969be0a54..1fa6bb896f41 100644 --- a/trunk/arch/arm/mach-omap2/board-2430sdp.c +++ b/trunk/arch/arm/mach-omap2/board-2430sdp.c @@ -41,7 +41,6 @@ #include "mux.h" #include "hsmmc.h" -#include "common-board-devices.h" #define SDP2430_CS0_BASE 0x04000000 #define SECONDARY_LCD_GPIO 147 @@ -181,6 +180,15 @@ static struct twl4030_platform_data sdp2430_twldata = { .vmmc1 = &sdp2430_vmmc1, }; +static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_24XX_SYS_NIRQ, + .platform_data = &sdp2430_twldata, + }, +}; + static struct i2c_board_info __initdata sdp2430_i2c1_boardinfo[] = { { I2C_BOARD_INFO("isp1301_omap", 0x2D), @@ -193,7 +201,8 @@ static int __init omap2430_i2c_init(void) { omap_register_i2c_bus(1, 100, sdp2430_i2c1_boardinfo, ARRAY_SIZE(sdp2430_i2c1_boardinfo)); - omap2_pmic_init("twl4030", &sdp2430_twldata); + omap_register_i2c_bus(2, 2600, sdp2430_i2c_boardinfo, + ARRAY_SIZE(sdp2430_i2c_boardinfo)); return 0; } @@ -208,6 +217,11 @@ static struct omap2_hsmmc_info mmc[] __initdata = { {} /* Terminator */ }; +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; static struct omap_usb_config sdp2430_usb_config __initdata = { .otg = 1, #ifdef CONFIG_USB_GADGET_OMAP @@ -226,6 +240,8 @@ static struct omap_board_mux board_mux[] __initdata = { static void __init omap_2430sdp_init(void) { + int ret; + omap2430_mux_init(board_mux, OMAP_PACKAGE_ZAC); omap_board_config = sdp2430_config; @@ -239,13 +255,14 @@ static void __init omap_2430sdp_init(void) omap2_usbfs_init(&sdp2430_usb_config); omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP); - usb_musb_init(NULL); + usb_musb_init(&musb_board_data); board_smc91x_init(); /* Turn off secondary LCD backlight */ - gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW, - "Secondary LCD backlight"); + ret = gpio_request(SECONDARY_LCD_GPIO, "Secondary LCD backlight"); + if (ret == 0) + gpio_direction_output(SECONDARY_LCD_GPIO, 0); } static void __init omap_2430sdp_map_io(void) diff --git a/trunk/arch/arm/mach-omap2/board-3430sdp.c b/trunk/arch/arm/mach-omap2/board-3430sdp.c index ae2963a98041..23244cd0a5b6 100644 --- a/trunk/arch/arm/mach-omap2/board-3430sdp.c +++ b/trunk/arch/arm/mach-omap2/board-3430sdp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -47,7 +48,6 @@ #include "hsmmc.h" #include "pm.h" #include "control.h" -#include "common-board-devices.h" #define CONFIG_DISABLE_HFCLK 1 @@ -59,6 +59,24 @@ #define TWL4030_MSECURE_GPIO 22 +/* FIXME: These values need to be updated based on more profiling on 3430sdp*/ +static struct cpuidle_params omap3_cpuidle_params_table[] = { + /* C1 */ + {1, 2, 2, 5}, + /* C2 */ + {1, 10, 10, 30}, + /* C3 */ + {1, 50, 50, 300}, + /* C4 */ + {1, 1500, 1800, 4000}, + /* C5 */ + {1, 2500, 7500, 12000}, + /* C6 */ + {1, 3000, 8500, 15000}, + /* C7 */ + {1, 10000, 30000, 300000}, +}; + static uint32_t board_keymap[] = { KEY(0, 0, KEY_LEFT), KEY(0, 1, KEY_RIGHT), @@ -105,14 +123,63 @@ static struct twl4030_keypad_data sdp3430_kp_data = { .rep = 1, }; -#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8 -#define SDP3430_LCD_PANEL_ENABLE_GPIO 5 +static int ts_gpio; /* Needed for ads7846_get_pendown_state */ + +/** + * @brief ads7846_dev_init : Requests & sets GPIO line for pen-irq + * + * @return - void. If request gpio fails then Flag KERN_ERR. + */ +static void ads7846_dev_init(void) +{ + if (gpio_request(ts_gpio, "ADS7846 pendown") < 0) { + printk(KERN_ERR "can't get ads746 pen down GPIO\n"); + return; + } -static struct gpio sdp3430_dss_gpios[] __initdata = { - {SDP3430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW, "LCD reset" }, - {SDP3430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW, "LCD Backlight"}, + gpio_direction_input(ts_gpio); + gpio_set_debounce(ts_gpio, 310); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(ts_gpio); +} + +static struct ads7846_platform_data tsc2046_config __initdata = { + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, + .wakeup = true, }; + +static struct omap2_mcspi_device_config tsc2046_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info sdp3430_spi_board_info[] __initdata = { + [0] = { + /* + * TSC2046 operates at a max freqency of 2MHz, so + * operate slightly below at 1.5MHz + */ + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &tsc2046_mcspi_config, + .irq = 0, + .platform_data = &tsc2046_config, + }, +}; + + +#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8 +#define SDP3430_LCD_PANEL_ENABLE_GPIO 5 + +static unsigned backlight_gpio; +static unsigned enable_gpio; static int lcd_enabled; static int dvi_enabled; @@ -120,11 +187,29 @@ static void __init sdp3430_display_init(void) { int r; - r = gpio_request_array(sdp3430_dss_gpios, - ARRAY_SIZE(sdp3430_dss_gpios)); - if (r) - printk(KERN_ERR "failed to get LCD control GPIOs\n"); + enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO; + backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; + + r = gpio_request(enable_gpio, "LCD reset"); + if (r) { + printk(KERN_ERR "failed to get LCD reset GPIO\n"); + goto err0; + } + + r = gpio_request(backlight_gpio, "LCD Backlight"); + if (r) { + printk(KERN_ERR "failed to get LCD backlight GPIO\n"); + goto err1; + } + + gpio_direction_output(enable_gpio, 0); + gpio_direction_output(backlight_gpio, 0); + return; +err1: + gpio_free(enable_gpio); +err0: + return; } static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev) @@ -134,8 +219,8 @@ static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev) return -EINVAL; } - gpio_direction_output(SDP3430_LCD_PANEL_ENABLE_GPIO, 1); - gpio_direction_output(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, 1); + gpio_direction_output(enable_gpio, 1); + gpio_direction_output(backlight_gpio, 1); lcd_enabled = 1; @@ -146,8 +231,8 @@ static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev) { lcd_enabled = 0; - gpio_direction_output(SDP3430_LCD_PANEL_ENABLE_GPIO, 0); - gpio_direction_output(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, 0); + gpio_direction_output(enable_gpio, 0); + gpio_direction_output(backlight_gpio, 0); } static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev) @@ -275,10 +360,12 @@ static int sdp3430_twl_gpio_setup(struct device *dev, omap2_hsmmc_init(mmc); /* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */ - gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "sub_lcd_en_bkl"); + gpio_request(gpio + 7, "sub_lcd_en_bkl"); + gpio_direction_output(gpio + 7, 0); /* gpio + 15 is "sub_lcd_nRST" (output) */ - gpio_request_one(gpio + 15, GPIOF_OUT_INIT_LOW, "sub_lcd_nRST"); + gpio_request(gpio + 15, "sub_lcd_nRST"); + gpio_direction_output(gpio + 15, 0); return 0; } @@ -493,10 +580,20 @@ static struct twl4030_platform_data sdp3430_twldata = { .vpll2 = &sdp3430_vpll2, }; +static struct i2c_board_info __initdata sdp3430_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &sdp3430_twldata, + }, +}; + static int __init omap3430_i2c_init(void) { /* i2c1 for PMIC only */ - omap3_pmic_init("twl4030", &sdp3430_twldata); + omap_register_i2c_bus(1, 2600, sdp3430_i2c_boardinfo, + ARRAY_SIZE(sdp3430_i2c_boardinfo)); /* i2c2 on camera connector (for sensor control) and optional isp1301 */ omap_register_i2c_bus(2, 400, NULL, 0); /* i2c3 on display connector (for DVI, tfp410) */ @@ -775,22 +872,30 @@ static struct flash_partitions sdp_flash_partitions[] = { }, }; +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + static void __init omap_3430sdp_init(void) { - int gpio_pendown; - omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap_board_config = sdp3430_config; omap_board_config_size = ARRAY_SIZE(sdp3430_config); + omap3_pm_init_cpuidle(omap3_cpuidle_params_table); omap3430_i2c_init(); omap_display_init(&sdp3430_dss_data); if (omap_rev() > OMAP3430_REV_ES1_0) - gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV2; + ts_gpio = SDP3430_TS_GPIO_IRQ_SDPV2; else - gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1; - omap_ads7846_init(1, gpio_pendown, 310, NULL); + ts_gpio = SDP3430_TS_GPIO_IRQ_SDPV1; + sdp3430_spi_board_info[0].irq = gpio_to_irq(ts_gpio); + spi_register_board_info(sdp3430_spi_board_info, + ARRAY_SIZE(sdp3430_spi_board_info)); + ads7846_dev_init(); board_serial_init(); - usb_musb_init(NULL); + usb_musb_init(&musb_board_data); board_smc91x_init(); board_flash_init(sdp_flash_partitions, chip_sel_3430, 0); sdp3430_display_init(); diff --git a/trunk/arch/arm/mach-omap2/board-4430sdp.c b/trunk/arch/arm/mach-omap2/board-4430sdp.c index 73fa90bb6953..93edd7fcf451 100644 --- a/trunk/arch/arm/mach-omap2/board-4430sdp.c +++ b/trunk/arch/arm/mach-omap2/board-4430sdp.c @@ -42,7 +42,6 @@ #include "hsmmc.h" #include "timer-gp.h" #include "control.h" -#include "common-board-devices.h" #define ETH_KS8851_IRQ 34 #define ETH_KS8851_POWER_ON 48 @@ -252,22 +251,58 @@ static struct spi_board_info sdp4430_spi_board_info[] __initdata = { }, }; -static struct gpio sdp4430_eth_gpios[] __initdata = { - { ETH_KS8851_POWER_ON, GPIOF_OUT_INIT_HIGH, "eth_power" }, - { ETH_KS8851_QUART, GPIOF_OUT_INIT_HIGH, "quart" }, - { ETH_KS8851_IRQ, GPIOF_IN, "eth_irq" }, -}; - static int omap_ethernet_init(void) { int status; /* Request of GPIO lines */ - status = gpio_request_array(sdp4430_eth_gpios, - ARRAY_SIZE(sdp4430_eth_gpios)); - if (status) - pr_err("Cannot request ETH GPIOs\n"); + status = gpio_request(ETH_KS8851_POWER_ON, "eth_power"); + if (status) { + pr_err("Cannot request GPIO %d\n", ETH_KS8851_POWER_ON); + return status; + } + + status = gpio_request(ETH_KS8851_QUART, "quart"); + if (status) { + pr_err("Cannot request GPIO %d\n", ETH_KS8851_QUART); + goto error1; + } + + status = gpio_request(ETH_KS8851_IRQ, "eth_irq"); + if (status) { + pr_err("Cannot request GPIO %d\n", ETH_KS8851_IRQ); + goto error2; + } + + /* Configuration of requested GPIO lines */ + + status = gpio_direction_output(ETH_KS8851_POWER_ON, 1); + if (status) { + pr_err("Cannot set output GPIO %d\n", ETH_KS8851_IRQ); + goto error3; + } + + status = gpio_direction_output(ETH_KS8851_QUART, 1); + if (status) { + pr_err("Cannot set output GPIO %d\n", ETH_KS8851_QUART); + goto error3; + } + + status = gpio_direction_input(ETH_KS8851_IRQ); + if (status) { + pr_err("Cannot set input GPIO %d\n", ETH_KS8851_IRQ); + goto error3; + } + + return 0; + +error3: + gpio_free(ETH_KS8851_IRQ); +error2: + gpio_free(ETH_KS8851_QUART); +error1: + gpio_free(ETH_KS8851_POWER_ON); return status; } @@ -540,6 +575,14 @@ static struct twl4030_platform_data sdp4430_twldata = { .usb = &omap4_usbphy_data }; +static struct i2c_board_info __initdata sdp4430_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl6030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = OMAP44XX_IRQ_SYS_1N, + .platform_data = &sdp4430_twldata, + }, +}; static struct i2c_board_info __initdata sdp4430_i2c_3_boardinfo[] = { { I2C_BOARD_INFO("tmp105", 0x48), @@ -555,7 +598,12 @@ static struct i2c_board_info __initdata sdp4430_i2c_4_boardinfo[] = { }; static int __init omap4_i2c_init(void) { - omap4_pmic_init("twl6030", &sdp4430_twldata); + /* + * Phoenix Audio IC needs I2C1 to + * start with 400 KHz or less + */ + omap_register_i2c_bus(1, 400, sdp4430_i2c_boardinfo, + ARRAY_SIZE(sdp4430_i2c_boardinfo)); omap_register_i2c_bus(2, 400, NULL, 0); omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo, ARRAY_SIZE(sdp4430_i2c_3_boardinfo)); @@ -566,13 +614,21 @@ static int __init omap4_i2c_init(void) static void __init omap_sfh7741prox_init(void) { - int error; + int error; - error = gpio_request_one(OMAP4_SFH7741_ENABLE_GPIO, - GPIOF_OUT_INIT_LOW, "sfh7741"); - if (error < 0) + error = gpio_request(OMAP4_SFH7741_ENABLE_GPIO, "sfh7741"); + if (error < 0) { pr_err("%s:failed to request GPIO %d, error %d\n", __func__, OMAP4_SFH7741_ENABLE_GPIO, error); + return; + } + + error = gpio_direction_output(OMAP4_SFH7741_ENABLE_GPIO , 0); + if (error < 0) { + pr_err("%s: GPIO configuration failed: GPIO %d,error %d\n", + __func__, OMAP4_SFH7741_ENABLE_GPIO, error); + gpio_free(OMAP4_SFH7741_ENABLE_GPIO); + } } static void sdp4430_hdmi_mux_init(void) @@ -589,19 +645,27 @@ static void sdp4430_hdmi_mux_init(void) OMAP_PIN_INPUT_PULLUP); } -static struct gpio sdp4430_hdmi_gpios[] = { - { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" }, - { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, -}; - static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev) { int status; - status = gpio_request_array(sdp4430_hdmi_gpios, - ARRAY_SIZE(sdp4430_hdmi_gpios)); - if (status) - pr_err("%s: Cannot request HDMI GPIOs\n", __func__); + status = gpio_request_one(HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, + "hdmi_gpio_hpd"); + if (status) { + pr_err("Cannot request GPIO %d\n", HDMI_GPIO_HPD); + return status; + } + status = gpio_request_one(HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, + "hdmi_gpio_ls_oe"); + if (status) { + pr_err("Cannot request GPIO %d\n", HDMI_GPIO_LS_OE); + goto error1; + } + + return 0; + +error1: + gpio_free(HDMI_GPIO_HPD); return status; } diff --git a/trunk/arch/arm/mach-omap2/board-am3517crane.c b/trunk/arch/arm/mach-omap2/board-am3517crane.c index 5e438a77cd72..a890d244fec6 100644 --- a/trunk/arch/arm/mach-omap2/board-am3517crane.c +++ b/trunk/arch/arm/mach-omap2/board-am3517crane.c @@ -89,13 +89,19 @@ static void __init am3517_crane_init(void) return; } - ret = gpio_request_one(GPIO_USB_POWER, GPIOF_OUT_INIT_HIGH, - "usb_ehci_enable"); + ret = gpio_request(GPIO_USB_POWER, "usb_ehci_enable"); if (ret < 0) { pr_err("Can not request GPIO %d\n", GPIO_USB_POWER); return; } + ret = gpio_direction_output(GPIO_USB_POWER, 1); + if (ret < 0) { + gpio_free(GPIO_USB_POWER); + pr_err("Unable to initialize EHCI power\n"); + return; + } + usbhs_init(&usbhs_bdata); } diff --git a/trunk/arch/arm/mach-omap2/board-am3517evm.c b/trunk/arch/arm/mach-omap2/board-am3517evm.c index 63af4171c043..ff8c59be36e5 100644 --- a/trunk/arch/arm/mach-omap2/board-am3517evm.c +++ b/trunk/arch/arm/mach-omap2/board-am3517evm.c @@ -174,14 +174,19 @@ static void __init am3517_evm_rtc_init(void) int r; omap_mux_init_gpio(GPIO_RTCS35390A_IRQ, OMAP_PIN_INPUT_PULLUP); - - r = gpio_request_one(GPIO_RTCS35390A_IRQ, GPIOF_IN, "rtcs35390a-irq"); + r = gpio_request(GPIO_RTCS35390A_IRQ, "rtcs35390a-irq"); if (r < 0) { printk(KERN_WARNING "failed to request GPIO#%d\n", GPIO_RTCS35390A_IRQ); return; } - + r = gpio_direction_input(GPIO_RTCS35390A_IRQ); + if (r < 0) { + printk(KERN_WARNING "GPIO#%d cannot be configured as input\n", + GPIO_RTCS35390A_IRQ); + gpio_free(GPIO_RTCS35390A_IRQ); + return; + } am3517evm_i2c1_boardinfo[0].irq = gpio_to_irq(GPIO_RTCS35390A_IRQ); } @@ -237,15 +242,6 @@ static int dvi_enabled; #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \ defined(CONFIG_PANEL_SHARP_LQ043T1DG01_MODULE) -static struct gpio am3517_evm_dss_gpios[] __initdata = { - /* GPIO 182 = LCD Backlight Power */ - { LCD_PANEL_BKLIGHT_PWR, GPIOF_OUT_INIT_HIGH, "lcd_backlight_pwr" }, - /* GPIO 181 = LCD Panel PWM */ - { LCD_PANEL_PWM, GPIOF_OUT_INIT_HIGH, "lcd bl enable" }, - /* GPIO 176 = LCD Panel Power enable pin */ - { LCD_PANEL_PWR, GPIOF_OUT_INIT_HIGH, "dvi enable" }, -}; - static void __init am3517_evm_display_init(void) { int r; @@ -253,15 +249,41 @@ static void __init am3517_evm_display_init(void) omap_mux_init_gpio(LCD_PANEL_PWR, OMAP_PIN_INPUT_PULLUP); omap_mux_init_gpio(LCD_PANEL_BKLIGHT_PWR, OMAP_PIN_INPUT_PULLDOWN); omap_mux_init_gpio(LCD_PANEL_PWM, OMAP_PIN_INPUT_PULLDOWN); - - r = gpio_request_array(am3517_evm_dss_gpios, - ARRAY_SIZE(am3517_evm_dss_gpios)); + /* + * Enable GPIO 182 = LCD Backlight Power + */ + r = gpio_request(LCD_PANEL_BKLIGHT_PWR, "lcd_backlight_pwr"); if (r) { - printk(KERN_ERR "failed to get DSS panel control GPIOs\n"); + printk(KERN_ERR "failed to get lcd_backlight_pwr\n"); return; } + gpio_direction_output(LCD_PANEL_BKLIGHT_PWR, 1); + /* + * Enable GPIO 181 = LCD Panel PWM + */ + r = gpio_request(LCD_PANEL_PWM, "lcd_pwm"); + if (r) { + printk(KERN_ERR "failed to get lcd_pwm\n"); + goto err_1; + } + gpio_direction_output(LCD_PANEL_PWM, 1); + /* + * Enable GPIO 176 = LCD Panel Power enable pin + */ + r = gpio_request(LCD_PANEL_PWR, "lcd_panel_pwr"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_pwr\n"); + goto err_2; + } + gpio_direction_output(LCD_PANEL_PWR, 1); printk(KERN_INFO "Display initialized successfully\n"); + return; + +err_2: + gpio_free(LCD_PANEL_PWM); +err_1: + gpio_free(LCD_PANEL_BKLIGHT_PWR); } #else static void __init am3517_evm_display_init(void) {} @@ -374,7 +396,7 @@ static struct omap_musb_board_data musb_board_data = { .power = 500, .set_phy_power = am35x_musb_phy_power, .clear_irq = am35x_musb_clear_irq, - .set_mode = am35x_set_mode, + .set_mode = am35x_musb_set_mode, .reset = am35x_musb_reset, }; diff --git a/trunk/arch/arm/mach-omap2/board-apollon.c b/trunk/arch/arm/mach-omap2/board-apollon.c index f3beb8eeef77..f4f8374a0298 100644 --- a/trunk/arch/arm/mach-omap2/board-apollon.c +++ b/trunk/arch/arm/mach-omap2/board-apollon.c @@ -202,7 +202,6 @@ static inline void __init apollon_init_smc91x(void) unsigned int rate; struct clk *gpmc_fck; int eth_cs; - int err; gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */ if (IS_ERR(gpmc_fck)) { @@ -246,13 +245,15 @@ static inline void __init apollon_init_smc91x(void) apollon_smc91x_resources[0].end = base + 0x30f; udelay(100); - omap_mux_init_gpio(APOLLON_ETHR_GPIO_IRQ, 0); - err = gpio_request_one(APOLLON_ETHR_GPIO_IRQ, GPIOF_IN, "SMC91x irq"); - if (err) { + omap_mux_init_gpio(74, 0); + if (gpio_request(APOLLON_ETHR_GPIO_IRQ, "SMC91x irq") < 0) { printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", APOLLON_ETHR_GPIO_IRQ); gpmc_cs_free(APOLLON_ETH_CS); + goto out; } + gpio_direction_input(APOLLON_ETHR_GPIO_IRQ); + out: clk_disable(gpmc_fck); clk_put(gpmc_fck); @@ -279,19 +280,20 @@ static void __init omap_apollon_init_early(void) omap2_init_common_devices(NULL, NULL); } -static struct gpio apollon_gpio_leds[] __initdata = { - { LED0_GPIO13, GPIOF_OUT_INIT_LOW, "LED0" }, /* LED0 - AA10 */ - { LED1_GPIO14, GPIOF_OUT_INIT_LOW, "LED1" }, /* LED1 - AA6 */ - { LED2_GPIO15, GPIOF_OUT_INIT_LOW, "LED2" }, /* LED2 - AA4 */ -}; - static void __init apollon_led_init(void) { + /* LED0 - AA10 */ omap_mux_init_signal("vlynq_clk.gpio_13", 0); + gpio_request(LED0_GPIO13, "LED0"); + gpio_direction_output(LED0_GPIO13, 0); + /* LED1 - AA6 */ omap_mux_init_signal("vlynq_rx1.gpio_14", 0); + gpio_request(LED1_GPIO14, "LED1"); + gpio_direction_output(LED1_GPIO14, 0); + /* LED2 - AA4 */ omap_mux_init_signal("vlynq_rx0.gpio_15", 0); - - gpio_request_array(apollon_gpio_leds, ARRAY_SIZE(apollon_gpio_leds)); + gpio_request(LED2_GPIO15, "LED2"); + gpio_direction_output(LED2_GPIO15, 0); } static void __init apollon_usb_init(void) @@ -299,7 +301,8 @@ static void __init apollon_usb_init(void) /* USB device */ /* DEVICE_SUSPEND */ omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0); - gpio_request_one(12, GPIOF_OUT_INIT_LOW, "USB suspend"); + gpio_request(12, "USB suspend"); + gpio_direction_output(12, 0); omap2_usbfs_init(&apollon_usb_config); } diff --git a/trunk/arch/arm/mach-omap2/board-cm-t35.c b/trunk/arch/arm/mach-omap2/board-cm-t35.c index c63115bc1536..9340f6a06f4a 100644 --- a/trunk/arch/arm/mach-omap2/board-cm-t35.c +++ b/trunk/arch/arm/mach-omap2/board-cm-t35.c @@ -54,7 +54,6 @@ #include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" -#include "common-board-devices.h" #define CM_T35_GPIO_PENDOWN 57 @@ -67,28 +66,86 @@ #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include -#include -static struct omap_smsc911x_platform_data cm_t35_smsc911x_cfg = { - .id = 0, - .cs = CM_T35_SMSC911X_CS, - .gpio_irq = CM_T35_SMSC911X_GPIO, - .gpio_reset = -EINVAL, +static struct smsc911x_platform_config cm_t35_smsc911x_config = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct resource cm_t35_smsc911x_resources[] = { + { + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP_GPIO_IRQ(CM_T35_SMSC911X_GPIO), + .end = OMAP_GPIO_IRQ(CM_T35_SMSC911X_GPIO), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, +}; + +static struct platform_device cm_t35_smsc911x_device = { + .name = "smsc911x", + .id = 0, + .num_resources = ARRAY_SIZE(cm_t35_smsc911x_resources), + .resource = cm_t35_smsc911x_resources, + .dev = { + .platform_data = &cm_t35_smsc911x_config, + }, +}; + +static struct resource sb_t35_smsc911x_resources[] = { + { + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP_GPIO_IRQ(SB_T35_SMSC911X_GPIO), + .end = OMAP_GPIO_IRQ(SB_T35_SMSC911X_GPIO), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, }; -static struct omap_smsc911x_platform_data sb_t35_smsc911x_cfg = { +static struct platform_device sb_t35_smsc911x_device = { + .name = "smsc911x", .id = 1, - .cs = SB_T35_SMSC911X_CS, - .gpio_irq = SB_T35_SMSC911X_GPIO, - .gpio_reset = -EINVAL, - .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS, + .num_resources = ARRAY_SIZE(sb_t35_smsc911x_resources), + .resource = sb_t35_smsc911x_resources, + .dev = { + .platform_data = &cm_t35_smsc911x_config, + }, }; +static void __init cm_t35_init_smsc911x(struct platform_device *dev, + int cs, int irq_gpio) +{ + unsigned long cs_mem_base; + + if (gpmc_cs_request(cs, SZ_16M, &cs_mem_base) < 0) { + pr_err("CM-T35: Failed request for GPMC mem for smsc911x\n"); + return; + } + + dev->resource[0].start = cs_mem_base + 0x0; + dev->resource[0].end = cs_mem_base + 0xff; + + if ((gpio_request(irq_gpio, "ETH IRQ") == 0) && + (gpio_direction_input(irq_gpio) == 0)) { + gpio_export(irq_gpio, 0); + } else { + pr_err("CM-T35: could not obtain gpio for SMSC911X IRQ\n"); + return; + } + + platform_device_register(dev); +} + static void __init cm_t35_init_ethernet(void) { - gpmc_smsc911x_init(&cm_t35_smsc911x_cfg); - gpmc_smsc911x_init(&sb_t35_smsc911x_cfg); + cm_t35_init_smsc911x(&cm_t35_smsc911x_device, + CM_T35_SMSC911X_CS, CM_T35_SMSC911X_GPIO); + cm_t35_init_smsc911x(&sb_t35_smsc911x_device, + SB_T35_SMSC911X_CS, SB_T35_SMSC911X_GPIO); } #else static inline void __init cm_t35_init_ethernet(void) { return; } @@ -178,10 +235,69 @@ static void __init cm_t35_init_nand(void) static inline void cm_t35_init_nand(void) {} #endif +#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ + defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) +#include + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(CM_T35_GPIO_PENDOWN); +} + +static struct ads7846_platform_data ads7846_config = { + .x_max = 0x0fff, + .y_max = 0x0fff, + .x_plate_ohms = 180, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 3, + .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, +}; + +static struct spi_board_info cm_t35_spi_board_info[] __initdata = { + { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(CM_T35_GPIO_PENDOWN), + .platform_data = &ads7846_config, + }, +}; + +static void __init cm_t35_init_ads7846(void) +{ + if ((gpio_request(CM_T35_GPIO_PENDOWN, "ADS7846_PENDOWN") == 0) && + (gpio_direction_input(CM_T35_GPIO_PENDOWN) == 0)) { + gpio_export(CM_T35_GPIO_PENDOWN, 0); + } else { + pr_err("CM-T35: could not obtain gpio for ADS7846_PENDOWN\n"); + return; + } + + spi_register_board_info(cm_t35_spi_board_info, + ARRAY_SIZE(cm_t35_spi_board_info)); +} +#else +static inline void cm_t35_init_ads7846(void) {} +#endif + #define CM_T35_LCD_EN_GPIO 157 #define CM_T35_LCD_BL_GPIO 58 #define CM_T35_DVI_EN_GPIO 54 +static int lcd_bl_gpio; +static int lcd_en_gpio; +static int dvi_en_gpio; + static int lcd_enabled; static int dvi_enabled; @@ -192,8 +308,8 @@ static int cm_t35_panel_enable_lcd(struct omap_dss_device *dssdev) return -EINVAL; } - gpio_set_value(CM_T35_LCD_EN_GPIO, 1); - gpio_set_value(CM_T35_LCD_BL_GPIO, 1); + gpio_set_value(lcd_en_gpio, 1); + gpio_set_value(lcd_bl_gpio, 1); lcd_enabled = 1; @@ -204,8 +320,8 @@ static void cm_t35_panel_disable_lcd(struct omap_dss_device *dssdev) { lcd_enabled = 0; - gpio_set_value(CM_T35_LCD_BL_GPIO, 0); - gpio_set_value(CM_T35_LCD_EN_GPIO, 0); + gpio_set_value(lcd_bl_gpio, 0); + gpio_set_value(lcd_en_gpio, 0); } static int cm_t35_panel_enable_dvi(struct omap_dss_device *dssdev) @@ -215,7 +331,7 @@ static int cm_t35_panel_enable_dvi(struct omap_dss_device *dssdev) return -EINVAL; } - gpio_set_value(CM_T35_DVI_EN_GPIO, 0); + gpio_set_value(dvi_en_gpio, 0); dvi_enabled = 1; return 0; @@ -223,7 +339,7 @@ static int cm_t35_panel_enable_dvi(struct omap_dss_device *dssdev) static void cm_t35_panel_disable_dvi(struct omap_dss_device *dssdev) { - gpio_set_value(CM_T35_DVI_EN_GPIO, 1); + gpio_set_value(dvi_en_gpio, 1); dvi_enabled = 0; } @@ -305,38 +421,62 @@ static struct spi_board_info cm_t35_lcd_spi_board_info[] __initdata = { }, }; -static struct gpio cm_t35_dss_gpios[] __initdata = { - { CM_T35_LCD_EN_GPIO, GPIOF_OUT_INIT_LOW, "lcd enable" }, - { CM_T35_LCD_BL_GPIO, GPIOF_OUT_INIT_LOW, "lcd bl enable" }, - { CM_T35_DVI_EN_GPIO, GPIOF_OUT_INIT_HIGH, "dvi enable" }, -}; - static void __init cm_t35_init_display(void) { int err; + lcd_en_gpio = CM_T35_LCD_EN_GPIO; + lcd_bl_gpio = CM_T35_LCD_BL_GPIO; + dvi_en_gpio = CM_T35_DVI_EN_GPIO; + spi_register_board_info(cm_t35_lcd_spi_board_info, ARRAY_SIZE(cm_t35_lcd_spi_board_info)); - err = gpio_request_array(cm_t35_dss_gpios, - ARRAY_SIZE(cm_t35_dss_gpios)); + err = gpio_request(lcd_en_gpio, "LCD RST"); if (err) { - pr_err("CM-T35: failed to request DSS control GPIOs\n"); - return; + pr_err("CM-T35: failed to get LCD reset GPIO\n"); + goto out; + } + + err = gpio_request(lcd_bl_gpio, "LCD BL"); + if (err) { + pr_err("CM-T35: failed to get LCD backlight control GPIO\n"); + goto err_lcd_bl; } - gpio_export(CM_T35_LCD_EN_GPIO, 0); - gpio_export(CM_T35_LCD_BL_GPIO, 0); - gpio_export(CM_T35_DVI_EN_GPIO, 0); + err = gpio_request(dvi_en_gpio, "DVI EN"); + if (err) { + pr_err("CM-T35: failed to get DVI reset GPIO\n"); + goto err_dvi_en; + } + + gpio_export(lcd_en_gpio, 0); + gpio_export(lcd_bl_gpio, 0); + gpio_export(dvi_en_gpio, 0); + gpio_direction_output(lcd_en_gpio, 0); + gpio_direction_output(lcd_bl_gpio, 0); + gpio_direction_output(dvi_en_gpio, 1); msleep(50); - gpio_set_value(CM_T35_LCD_EN_GPIO, 1); + gpio_set_value(lcd_en_gpio, 1); err = omap_display_init(&cm_t35_dss_data); if (err) { pr_err("CM-T35: failed to register DSS device\n"); - gpio_free_array(cm_t35_dss_gpios, ARRAY_SIZE(cm_t35_dss_gpios)); + goto err_dev_reg; } + + return; + +err_dev_reg: + gpio_free(dvi_en_gpio); +err_dvi_en: + gpio_free(lcd_bl_gpio); +err_lcd_bl: + gpio_free(lcd_en_gpio); +out: + + return; } static struct regulator_consumer_supply cm_t35_vmmc1_supply = { @@ -469,8 +609,10 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio, { int wlan_rst = gpio + 2; - if (gpio_request_one(wlan_rst, GPIOF_OUT_INIT_HIGH, "WLAN RST") == 0) { + if ((gpio_request(wlan_rst, "WLAN RST") == 0) && + (gpio_direction_output(wlan_rst, 1) == 0)) { gpio_export(wlan_rst, 0); + udelay(10); gpio_set_value(wlan_rst, 0); udelay(10); @@ -511,9 +653,19 @@ static struct twl4030_platform_data cm_t35_twldata = { .vpll2 = &cm_t35_vpll2, }; +static struct i2c_board_info __initdata cm_t35_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("tps65930", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &cm_t35_twldata, + }, +}; + static void __init cm_t35_init_i2c(void) { - omap3_pmic_init("tps65930", &cm_t35_twldata); + omap_register_i2c_bus(1, 2600, cm_t35_i2c_boardinfo, + ARRAY_SIZE(cm_t35_i2c_boardinfo)); } static void __init cm_t35_init_early(void) @@ -623,6 +775,12 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + static struct omap_board_config_kernel cm_t35_config[] __initdata = { }; @@ -634,12 +792,12 @@ static void __init cm_t35_init(void) omap_serial_init(); cm_t35_init_i2c(); cm_t35_init_nand(); - omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL); + cm_t35_init_ads7846(); cm_t35_init_ethernet(); cm_t35_init_led(); cm_t35_init_display(); - usb_musb_init(NULL); + usb_musb_init(&musb_board_data); usbhs_init(&usbhs_bdata); } diff --git a/trunk/arch/arm/mach-omap2/board-cm-t3517.c b/trunk/arch/arm/mach-omap2/board-cm-t3517.c index 08f08e812492..a27e3eee8292 100644 --- a/trunk/arch/arm/mach-omap2/board-cm-t3517.c +++ b/trunk/arch/arm/mach-omap2/board-cm-t3517.c @@ -148,13 +148,14 @@ static void __init cm_t3517_init_rtc(void) { int err; - err = gpio_request_one(RTC_CS_EN_GPIO, GPIOF_OUT_INIT_HIGH, - "rtc cs en"); + err = gpio_request(RTC_CS_EN_GPIO, "rtc cs en"); if (err) { pr_err("CM-T3517: rtc cs en gpio request failed: %d\n", err); return; } + gpio_direction_output(RTC_CS_EN_GPIO, 1); + platform_device_register(&cm_t3517_rtc_device); } #else @@ -181,11 +182,11 @@ static int cm_t3517_init_usbh(void) { int err; - err = gpio_request_one(USB_HUB_RESET_GPIO, GPIOF_OUT_INIT_LOW, - "usb hub rst"); + err = gpio_request(USB_HUB_RESET_GPIO, "usb hub rst"); if (err) { pr_err("CM-T3517: usb hub rst gpio request failed: %d\n", err); } else { + gpio_direction_output(USB_HUB_RESET_GPIO, 0); udelay(10); gpio_set_value(USB_HUB_RESET_GPIO, 1); msleep(1); diff --git a/trunk/arch/arm/mach-omap2/board-devkit8000.c b/trunk/arch/arm/mach-omap2/board-devkit8000.c index cf520d7dd614..1d1b56a29fb1 100644 --- a/trunk/arch/arm/mach-omap2/board-devkit8000.c +++ b/trunk/arch/arm/mach-omap2/board-devkit8000.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -59,7 +60,6 @@ #include "mux.h" #include "hsmmc.h" #include "timer-gp.h" -#include "common-board-devices.h" #define NAND_BLOCK_SIZE SZ_128K @@ -97,6 +97,13 @@ static struct mtd_partition devkit8000_nand_partitions[] = { }, }; +static struct omap_nand_platform_data devkit8000_nand_data = { + .options = NAND_BUSWIDTH_16, + .parts = devkit8000_nand_partitions, + .nr_parts = ARRAY_SIZE(devkit8000_nand_partitions), + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ +}; + static struct omap2_hsmmc_info mmc[] = { { .mmc = 1, @@ -242,7 +249,7 @@ static int devkit8000_twl_gpio_setup(struct device *dev, /* TWL4030_GPIO_MAX + 0 is "LCD_PWREN" (out, active high) */ devkit8000_lcd_device.reset_gpio = gpio + TWL4030_GPIO_MAX + 0; ret = gpio_request_one(devkit8000_lcd_device.reset_gpio, - GPIOF_OUT_INIT_LOW, "LCD_PWREN"); + GPIOF_DIR_OUT | GPIOF_INIT_LOW, "LCD_PWREN"); if (ret < 0) { devkit8000_lcd_device.reset_gpio = -EINVAL; printk(KERN_ERR "Failed to request GPIO for LCD_PWRN\n"); @@ -251,7 +258,7 @@ static int devkit8000_twl_gpio_setup(struct device *dev, /* gpio + 7 is "DVI_PD" (out, active low) */ devkit8000_dvi_device.reset_gpio = gpio + 7; ret = gpio_request_one(devkit8000_dvi_device.reset_gpio, - GPIOF_OUT_INIT_LOW, "DVI PowerDown"); + GPIOF_DIR_OUT | GPIOF_INIT_LOW, "DVI PowerDown"); if (ret < 0) { devkit8000_dvi_device.reset_gpio = -EINVAL; printk(KERN_ERR "Failed to request GPIO for DVI PowerDown\n"); @@ -359,9 +366,19 @@ static struct twl4030_platform_data devkit8000_twldata = { .keypad = &devkit8000_kp_data, }; +static struct i2c_board_info __initdata devkit8000_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("tps65930", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &devkit8000_twldata, + }, +}; + static int __init devkit8000_i2c_init(void) { - omap3_pmic_init("tps65930", &devkit8000_twldata); + omap_register_i2c_bus(1, 2600, devkit8000_i2c_boardinfo, + ARRAY_SIZE(devkit8000_i2c_boardinfo)); /* Bus 3 is attached to the DVI port where devices like the pico DLP * projector don't work reliably with 400kHz */ omap_register_i2c_bus(3, 400, NULL, 0); @@ -446,6 +463,56 @@ static void __init devkit8000_init_irq(void) #endif } +static void __init devkit8000_ads7846_init(void) +{ + int gpio = OMAP3_DEVKIT_TS_GPIO; + int ret; + + ret = gpio_request(gpio, "ads7846_pen_down"); + if (ret < 0) { + printk(KERN_ERR "Failed to request GPIO %d for " + "ads7846 pen down IRQ\n", gpio); + return; + } + + gpio_direction_input(gpio); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(OMAP3_DEVKIT_TS_GPIO); +} + +static struct ads7846_platform_data ads7846_config = { + .x_max = 0x0fff, + .y_max = 0x0fff, + .x_plate_ohms = 180, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 5, + .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, + .settle_delay_usecs = 150, +}; + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info devkit8000_spi_board_info[] __initdata = { + { + .modalias = "ads7846", + .bus_num = 2, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OMAP3_DEVKIT_TS_GPIO), + .platform_data = &ads7846_config, + } +}; + #define OMAP_DM9000_BASE 0x2c000000 static struct resource omap_dm9000_resources[] = { @@ -483,14 +550,14 @@ static void __init omap_dm9000_init(void) { unsigned char *eth_addr = omap_dm9000_platdata.dev_addr; struct omap_die_id odi; - int ret; - ret = gpio_request_one(OMAP_DM9000_GPIO_IRQ, GPIOF_IN, "dm9000 irq"); - if (ret < 0) { + if (gpio_request(OMAP_DM9000_GPIO_IRQ, "dm9000 irq") < 0) { printk(KERN_ERR "Failed to request GPIO%d for dm9000 IRQ\n", OMAP_DM9000_GPIO_IRQ); return; - } + } + + gpio_direction_input(OMAP_DM9000_GPIO_IRQ); /* init the mac address using DIE id */ omap_get_die_id(&odi); @@ -509,6 +576,45 @@ static struct platform_device *devkit8000_devices[] __initdata = { &omap_dm9000_dev, }; +static void __init devkit8000_flash_init(void) +{ + u8 cs = 0; + u8 nandcs = GPMC_CS_NUM + 1; + + /* find out the chip-select on which NAND exists */ + while (cs < GPMC_CS_NUM) { + u32 ret = 0; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + if ((ret & 0xC00) == 0x800) { + printk(KERN_INFO "Found NAND on CS%d\n", cs); + if (nandcs > GPMC_CS_NUM) + nandcs = cs; + } + cs++; + } + + if (nandcs > GPMC_CS_NUM) { + printk(KERN_INFO "NAND: Unable to find configuration " + "in GPMC\n "); + return; + } + + if (nandcs < GPMC_CS_NUM) { + devkit8000_nand_data.cs = nandcs; + + printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); + if (gpmc_nand_init(&devkit8000_nand_data) < 0) + printk(KERN_ERR "Unable to register NAND device\n"); + } +} + +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + static const struct usbhs_omap_board_data usbhs_bdata __initconst = { .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, @@ -689,13 +795,14 @@ static void __init devkit8000_init(void) ARRAY_SIZE(devkit8000_devices)); omap_display_init(&devkit8000_dss_data); + spi_register_board_info(devkit8000_spi_board_info, + ARRAY_SIZE(devkit8000_spi_board_info)); - omap_ads7846_init(2, OMAP3_DEVKIT_TS_GPIO, 0, NULL); + devkit8000_ads7846_init(); - usb_musb_init(NULL); + usb_musb_init(&musb_board_data); usbhs_init(&usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, - ARRAY_SIZE(devkit8000_nand_partitions)); + devkit8000_flash_init(); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); diff --git a/trunk/arch/arm/mach-omap2/board-igep0020.c b/trunk/arch/arm/mach-omap2/board-igep0020.c index 0c1bfca3f731..3da64d361651 100644 --- a/trunk/arch/arm/mach-omap2/board-igep0020.c +++ b/trunk/arch/arm/mach-omap2/board-igep0020.c @@ -38,7 +38,6 @@ #include "mux.h" #include "hsmmc.h" #include "sdram-numonyx-m65kxxxxam.h" -#include "common-board-devices.h" #define IGEP2_SMSC911X_CS 5 #define IGEP2_SMSC911X_GPIO 176 @@ -55,11 +54,6 @@ #define IGEP2_RC_GPIO_WIFI_NRESET 139 #define IGEP2_RC_GPIO_BT_NRESET 137 -#define IGEP3_GPIO_LED0_GREEN 54 -#define IGEP3_GPIO_LED0_RED 53 -#define IGEP3_GPIO_LED1_RED 16 -#define IGEP3_GPIO_USBH_NRESET 183 - /* * IGEP2 Hardware Revision Table * @@ -74,7 +68,6 @@ #define IGEP2_BOARD_HWREV_B 0 #define IGEP2_BOARD_HWREV_C 1 -#define IGEP3_BOARD_HWREV 2 static u8 hwrev; @@ -82,29 +75,24 @@ static void __init igep2_get_revision(void) { u8 ret; - if (machine_is_igep0030()) { - hwrev = IGEP3_BOARD_HWREV; - return; - } - omap_mux_init_gpio(IGEP2_GPIO_LED1_RED, OMAP_PIN_INPUT); - if (gpio_request_one(IGEP2_GPIO_LED1_RED, GPIOF_IN, "GPIO_HW0_REV")) { - pr_warning("IGEP2: Could not obtain gpio GPIO_HW0_REV\n"); - pr_err("IGEP2: Unknown Hardware Revision\n"); - return; - } - - ret = gpio_get_value(IGEP2_GPIO_LED1_RED); - if (ret == 0) { - pr_info("IGEP2: Hardware Revision C (B-NON compatible)\n"); - hwrev = IGEP2_BOARD_HWREV_C; - } else if (ret == 1) { - pr_info("IGEP2: Hardware Revision B/C (B compatible)\n"); - hwrev = IGEP2_BOARD_HWREV_B; + if ((gpio_request(IGEP2_GPIO_LED1_RED, "GPIO_HW0_REV") == 0) && + (gpio_direction_input(IGEP2_GPIO_LED1_RED) == 0)) { + ret = gpio_get_value(IGEP2_GPIO_LED1_RED); + if (ret == 0) { + pr_info("IGEP2: Hardware Revision C (B-NON compatible)\n"); + hwrev = IGEP2_BOARD_HWREV_C; + } else if (ret == 1) { + pr_info("IGEP2: Hardware Revision B/C (B compatible)\n"); + hwrev = IGEP2_BOARD_HWREV_B; + } else { + pr_err("IGEP2: Unknown Hardware Revision\n"); + hwrev = -1; + } } else { + pr_warning("IGEP2: Could not obtain gpio GPIO_HW0_REV\n"); pr_err("IGEP2: Unknown Hardware Revision\n"); - hwrev = -1; } gpio_free(IGEP2_GPIO_LED1_RED); @@ -123,7 +111,7 @@ static void __init igep2_get_revision(void) * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048) */ -static struct mtd_partition igep_onenand_partitions[] = { +static struct mtd_partition igep2_onenand_partitions[] = { { .name = "X-Loader", .offset = 0, @@ -151,21 +139,21 @@ static struct mtd_partition igep_onenand_partitions[] = { }, }; -static struct omap_onenand_platform_data igep_onenand_data = { - .parts = igep_onenand_partitions, - .nr_parts = ARRAY_SIZE(igep_onenand_partitions), +static struct omap_onenand_platform_data igep2_onenand_data = { + .parts = igep2_onenand_partitions, + .nr_parts = ARRAY_SIZE(igep2_onenand_partitions), .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */ }; -static struct platform_device igep_onenand_device = { +static struct platform_device igep2_onenand_device = { .name = "omap2-onenand", .id = -1, .dev = { - .platform_data = &igep_onenand_data, + .platform_data = &igep2_onenand_data, }, }; -static void __init igep_flash_init(void) +static void __init igep2_flash_init(void) { u8 cs = 0; u8 onenandcs = GPMC_CS_NUM + 1; @@ -177,7 +165,7 @@ static void __init igep_flash_init(void) /* Check if NAND/oneNAND is configured */ if ((ret & 0xC00) == 0x800) /* NAND found */ - pr_err("IGEP: Unsupported NAND found\n"); + pr_err("IGEP2: Unsupported NAND found\n"); else { ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); if ((ret & 0x3F) == (ONENAND_MAP >> 24)) @@ -187,46 +175,85 @@ static void __init igep_flash_init(void) } if (onenandcs > GPMC_CS_NUM) { - pr_err("IGEP: Unable to find configuration in GPMC\n"); + pr_err("IGEP2: Unable to find configuration in GPMC\n"); return; } - igep_onenand_data.cs = onenandcs; + igep2_onenand_data.cs = onenandcs; - if (platform_device_register(&igep_onenand_device) < 0) - pr_err("IGEP: Unable to register OneNAND device\n"); + if (platform_device_register(&igep2_onenand_device) < 0) + pr_err("IGEP2: Unable to register OneNAND device\n"); } #else -static void __init igep_flash_init(void) {} +static void __init igep2_flash_init(void) {} #endif #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include -#include -static struct omap_smsc911x_platform_data smsc911x_cfg = { - .cs = IGEP2_SMSC911X_CS, - .gpio_irq = IGEP2_SMSC911X_GPIO, - .gpio_reset = -EINVAL, - .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS, +static struct smsc911x_platform_config igep2_smsc911x_config = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, + .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS , + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct resource igep2_smsc911x_resources[] = { + { + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP_GPIO_IRQ(IGEP2_SMSC911X_GPIO), + .end = OMAP_GPIO_IRQ(IGEP2_SMSC911X_GPIO), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, +}; + +static struct platform_device igep2_smsc911x_device = { + .name = "smsc911x", + .id = 0, + .num_resources = ARRAY_SIZE(igep2_smsc911x_resources), + .resource = igep2_smsc911x_resources, + .dev = { + .platform_data = &igep2_smsc911x_config, + }, }; static inline void __init igep2_init_smsc911x(void) { - gpmc_smsc911x_init(&smsc911x_cfg); + unsigned long cs_mem_base; + + if (gpmc_cs_request(IGEP2_SMSC911X_CS, SZ_16M, &cs_mem_base) < 0) { + pr_err("IGEP v2: Failed request for GPMC mem for smsc911x\n"); + gpmc_cs_free(IGEP2_SMSC911X_CS); + return; + } + + igep2_smsc911x_resources[0].start = cs_mem_base + 0x0; + igep2_smsc911x_resources[0].end = cs_mem_base + 0xff; + + if ((gpio_request(IGEP2_SMSC911X_GPIO, "SMSC911X IRQ") == 0) && + (gpio_direction_input(IGEP2_SMSC911X_GPIO) == 0)) { + gpio_export(IGEP2_SMSC911X_GPIO, 0); + } else { + pr_err("IGEP v2: Could not obtain gpio for for SMSC911X IRQ\n"); + return; + } + + platform_device_register(&igep2_smsc911x_device); } #else static inline void __init igep2_init_smsc911x(void) { } #endif -static struct regulator_consumer_supply igep_vmmc1_supply = +static struct regulator_consumer_supply igep2_vmmc1_supply = REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"); /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */ -static struct regulator_init_data igep_vmmc1 = { +static struct regulator_init_data igep2_vmmc1 = { .constraints = { .min_uV = 1850000, .max_uV = 3150000, @@ -237,13 +264,13 @@ static struct regulator_init_data igep_vmmc1 = { | REGULATOR_CHANGE_STATUS, }, .num_consumer_supplies = 1, - .consumer_supplies = &igep_vmmc1_supply, + .consumer_supplies = &igep2_vmmc1_supply, }; -static struct regulator_consumer_supply igep_vio_supply = +static struct regulator_consumer_supply igep2_vio_supply = REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1"); -static struct regulator_init_data igep_vio = { +static struct regulator_init_data igep2_vio = { .constraints = { .min_uV = 1800000, .max_uV = 1800000, @@ -255,34 +282,34 @@ static struct regulator_init_data igep_vio = { | REGULATOR_CHANGE_STATUS, }, .num_consumer_supplies = 1, - .consumer_supplies = &igep_vio_supply, + .consumer_supplies = &igep2_vio_supply, }; -static struct regulator_consumer_supply igep_vmmc2_supply = +static struct regulator_consumer_supply igep2_vmmc2_supply = REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"); -static struct regulator_init_data igep_vmmc2 = { +static struct regulator_init_data igep2_vmmc2 = { .constraints = { .valid_modes_mask = REGULATOR_MODE_NORMAL, .always_on = 1, }, .num_consumer_supplies = 1, - .consumer_supplies = &igep_vmmc2_supply, + .consumer_supplies = &igep2_vmmc2_supply, }; -static struct fixed_voltage_config igep_vwlan = { +static struct fixed_voltage_config igep2_vwlan = { .supply_name = "vwlan", .microvolts = 3300000, .gpio = -EINVAL, .enabled_at_boot = 1, - .init_data = &igep_vmmc2, + .init_data = &igep2_vmmc2, }; -static struct platform_device igep_vwlan_device = { +static struct platform_device igep2_vwlan_device = { .name = "reg-fixed-voltage", .id = 0, .dev = { - .platform_data = &igep_vwlan, + .platform_data = &igep2_vwlan, }, }; @@ -307,17 +334,20 @@ static struct omap2_hsmmc_info mmc[] = { #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) #include -static struct gpio_led igep_gpio_leds[] = { +static struct gpio_led igep2_gpio_leds[] = { [0] = { .name = "gpio-led:red:d0", + .gpio = IGEP2_GPIO_LED0_RED, .default_trigger = "default-off" }, [1] = { .name = "gpio-led:green:d0", + .gpio = IGEP2_GPIO_LED0_GREEN, .default_trigger = "default-off", }, [2] = { .name = "gpio-led:red:d1", + .gpio = IGEP2_GPIO_LED1_RED, .default_trigger = "default-off", }, [3] = { @@ -328,119 +358,94 @@ static struct gpio_led igep_gpio_leds[] = { }, }; -static struct gpio_led_platform_data igep_led_pdata = { - .leds = igep_gpio_leds, - .num_leds = ARRAY_SIZE(igep_gpio_leds), +static struct gpio_led_platform_data igep2_led_pdata = { + .leds = igep2_gpio_leds, + .num_leds = ARRAY_SIZE(igep2_gpio_leds), }; -static struct platform_device igep_led_device = { +static struct platform_device igep2_led_device = { .name = "leds-gpio", .id = -1, .dev = { - .platform_data = &igep_led_pdata, + .platform_data = &igep2_led_pdata, }, }; -static void __init igep_leds_init(void) +static void __init igep2_leds_init(void) { - if (machine_is_igep0020()) { - igep_gpio_leds[0].gpio = IGEP2_GPIO_LED0_RED; - igep_gpio_leds[1].gpio = IGEP2_GPIO_LED0_GREEN; - igep_gpio_leds[2].gpio = IGEP2_GPIO_LED1_RED; - } else { - igep_gpio_leds[0].gpio = IGEP3_GPIO_LED0_RED; - igep_gpio_leds[1].gpio = IGEP3_GPIO_LED0_GREEN; - igep_gpio_leds[2].gpio = IGEP3_GPIO_LED1_RED; - } - - platform_device_register(&igep_led_device); + platform_device_register(&igep2_led_device); } #else -static struct gpio igep_gpio_leds[] __initdata = { - { -EINVAL, GPIOF_OUT_INIT_LOW, "gpio-led:red:d0" }, - { -EINVAL, GPIOF_OUT_INIT_LOW, "gpio-led:green:d0" }, - { -EINVAL, GPIOF_OUT_INIT_LOW, "gpio-led:red:d1" }, -}; - -static inline void igep_leds_init(void) +static inline void igep2_leds_init(void) { - int i; + if ((gpio_request(IGEP2_GPIO_LED0_RED, "gpio-led:red:d0") == 0) && + (gpio_direction_output(IGEP2_GPIO_LED0_RED, 0) == 0)) + gpio_export(IGEP2_GPIO_LED0_RED, 0); + else + pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n"); - if (machine_is_igep0020()) { - igep_gpio_leds[0].gpio = IGEP2_GPIO_LED0_RED; - igep_gpio_leds[1].gpio = IGEP2_GPIO_LED0_GREEN; - igep_gpio_leds[2].gpio = IGEP2_GPIO_LED1_RED; - } else { - igep_gpio_leds[0].gpio = IGEP3_GPIO_LED0_RED; - igep_gpio_leds[1].gpio = IGEP3_GPIO_LED0_GREEN; - igep_gpio_leds[2].gpio = IGEP3_GPIO_LED1_RED; - } + if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "gpio-led:green:d0") == 0) && + (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 0) == 0)) + gpio_export(IGEP2_GPIO_LED0_GREEN, 0); + else + pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n"); - if (gpio_request_array(igep_gpio_leds, ARRAY_SIZE(igep_gpio_leds))) { - pr_warning("IGEP v2: Could not obtain leds gpios\n"); - return; - } + if ((gpio_request(IGEP2_GPIO_LED1_RED, "gpio-led:red:d1") == 0) && + (gpio_direction_output(IGEP2_GPIO_LED1_RED, 0) == 0)) + gpio_export(IGEP2_GPIO_LED1_RED, 0); + else + pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n"); - for (i = 0; i < ARRAY_SIZE(igep_gpio_leds); i++) - gpio_export(igep_gpio_leds[i].gpio, 0); } #endif -static struct gpio igep2_twl_gpios[] = { - { -EINVAL, GPIOF_IN, "GPIO_EHCI_NOC" }, - { -EINVAL, GPIOF_OUT_INIT_LOW, "GPIO_USBH_CPEN" }, -}; - -static int igep_twl_gpio_setup(struct device *dev, +static int igep2_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { - int ret; - /* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0].gpio_cd = gpio + 0; omap2_hsmmc_init(mmc); - /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */ -#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE) - ret = gpio_request_one(gpio + TWL4030_GPIO_MAX + 1, GPIOF_OUT_INIT_HIGH, - "gpio-led:green:d1"); - if (ret == 0) - gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0); - else - pr_warning("IGEP: Could not obtain gpio GPIO_LED1_GREEN\n"); -#else - igep_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1; -#endif - - if (machine_is_igep0030()) - return 0; - /* * REVISIT: need ehci-omap hooks for external VBUS * power switch and overcurrent detect */ - igep2_twl_gpios[0].gpio = gpio + 1; + if ((gpio_request(gpio + 1, "GPIO_EHCI_NOC") < 0) || + (gpio_direction_input(gpio + 1) < 0)) + pr_err("IGEP2: Could not obtain gpio for EHCI NOC"); - /* TWL4030_GPIO_MAX + 0 == ledA, GPIO_USBH_CPEN (out, active low) */ - igep2_twl_gpios[1].gpio = gpio + TWL4030_GPIO_MAX; - - ret = gpio_request_array(igep2_twl_gpios, ARRAY_SIZE(igep2_twl_gpios)); - if (ret < 0) + /* + * TWL4030_GPIO_MAX + 0 == ledA, GPIO_USBH_CPEN + * (out, active low) + */ + if ((gpio_request(gpio + TWL4030_GPIO_MAX, "GPIO_USBH_CPEN") < 0) || + (gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0) < 0)) pr_err("IGEP2: Could not obtain gpio for USBH_CPEN"); + /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */ +#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE) + if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0) + && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) + gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0); + else + pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_GREEN\n"); +#else + igep2_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1; +#endif + return 0; }; -static struct twl4030_gpio_platform_data igep_twl4030_gpio_pdata = { +static struct twl4030_gpio_platform_data igep2_twl4030_gpio_pdata = { .gpio_base = OMAP_MAX_GPIO_LINES, .irq_base = TWL4030_GPIO_IRQ_BASE, .irq_end = TWL4030_GPIO_IRQ_END, .use_leds = true, - .setup = igep_twl_gpio_setup, + .setup = igep2_twl_gpio_setup, }; -static struct twl4030_usb_data igep_usb_data = { +static struct twl4030_usb_data igep2_usb_data = { .usb_mode = T2_USB_MODE_ULPI, }; @@ -502,17 +507,16 @@ static struct regulator_init_data igep2_vpll2 = { static void __init igep2_display_init(void) { - int err = gpio_request_one(IGEP2_GPIO_DVI_PUP, GPIOF_OUT_INIT_HIGH, - "GPIO_DVI_PUP"); - if (err) + if (gpio_request(IGEP2_GPIO_DVI_PUP, "GPIO_DVI_PUP") && + gpio_direction_output(IGEP2_GPIO_DVI_PUP, 1)) pr_err("IGEP v2: Could not obtain gpio GPIO_DVI_PUP\n"); } -static struct platform_device *igep_devices[] __initdata = { - &igep_vwlan_device, +static struct platform_device *igep2_devices[] __initdata = { + &igep2_vwlan_device, }; -static void __init igep_init_early(void) +static void __init igep2_init_early(void) { omap2_init_common_infrastructure(); omap2_init_common_devices(m65kxxxxam_sdrc_params, @@ -557,15 +561,27 @@ static struct twl4030_keypad_data igep2_keypad_pdata = { .rep = 1, }; -static struct twl4030_platform_data igep_twldata = { +static struct twl4030_platform_data igep2_twldata = { .irq_base = TWL4030_IRQ_BASE, .irq_end = TWL4030_IRQ_END, /* platform_data for children goes here */ - .usb = &igep_usb_data, - .gpio = &igep_twl4030_gpio_pdata, - .vmmc1 = &igep_vmmc1, - .vio = &igep_vio, + .usb = &igep2_usb_data, + .codec = &igep2_codec_data, + .gpio = &igep2_twl4030_gpio_pdata, + .keypad = &igep2_keypad_pdata, + .vmmc1 = &igep2_vmmc1, + .vpll2 = &igep2_vpll2, + .vio = &igep2_vio, +}; + +static struct i2c_board_info __initdata igep2_i2c1_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &igep2_twldata, + }, }; static struct i2c_board_info __initdata igep2_i2c3_boardinfo[] = { @@ -574,29 +590,32 @@ static struct i2c_board_info __initdata igep2_i2c3_boardinfo[] = { }, }; -static void __init igep_i2c_init(void) +static void __init igep2_i2c_init(void) { int ret; - if (machine_is_igep0020()) { - /* - * Bus 3 is attached to the DVI port where devices like the - * pico DLP projector don't work reliably with 400kHz - */ - ret = omap_register_i2c_bus(3, 100, igep2_i2c3_boardinfo, - ARRAY_SIZE(igep2_i2c3_boardinfo)); - if (ret) - pr_warning("IGEP2: Could not register I2C3 bus (%d)\n", ret); - - igep_twldata.codec = &igep2_codec_data; - igep_twldata.keypad = &igep2_keypad_pdata; - igep_twldata.vpll2 = &igep2_vpll2; - } + ret = omap_register_i2c_bus(1, 2600, igep2_i2c1_boardinfo, + ARRAY_SIZE(igep2_i2c1_boardinfo)); + if (ret) + pr_warning("IGEP2: Could not register I2C1 bus (%d)\n", ret); - omap3_pmic_init("twl4030", &igep_twldata); + /* + * Bus 3 is attached to the DVI port where devices like the pico DLP + * projector don't work reliably with 400kHz + */ + ret = omap_register_i2c_bus(3, 100, igep2_i2c3_boardinfo, + ARRAY_SIZE(igep2_i2c3_boardinfo)); + if (ret) + pr_warning("IGEP2: Could not register I2C3 bus (%d)\n", ret); } -static const struct usbhs_omap_board_data igep2_usbhs_bdata __initconst = { +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + +static const struct usbhs_omap_board_data usbhs_bdata __initconst = { .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED, .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED, @@ -607,17 +626,6 @@ static const struct usbhs_omap_board_data igep2_usbhs_bdata __initconst = { .reset_gpio_port[2] = -EINVAL, }; -static const struct usbhs_omap_board_data igep3_usbhs_bdata __initconst = { - .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED, - .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY, - .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED, - - .phy_reset = true, - .reset_gpio_port[0] = -EINVAL, - .reset_gpio_port[1] = IGEP3_GPIO_USBH_NRESET, - .reset_gpio_port[2] = -EINVAL, -}; - #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { { .reg_offset = OMAP_MUX_TERMINATOR }, @@ -625,95 +633,82 @@ static struct omap_board_mux board_mux[] __initdata = { #endif #if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE) -static struct gpio igep_wlan_bt_gpios[] __initdata = { - { -EINVAL, GPIOF_OUT_INIT_HIGH, "GPIO_WIFI_NPD" }, - { -EINVAL, GPIOF_OUT_INIT_HIGH, "GPIO_WIFI_NRESET" }, - { -EINVAL, GPIOF_OUT_INIT_HIGH, "GPIO_BT_NRESET" }, -}; -static void __init igep_wlan_bt_init(void) +static void __init igep2_wlan_bt_init(void) { - int err; + unsigned npd, wreset, btreset; /* GPIO's for WLAN-BT combo depends on hardware revision */ if (hwrev == IGEP2_BOARD_HWREV_B) { - igep_wlan_bt_gpios[0].gpio = IGEP2_RB_GPIO_WIFI_NPD; - igep_wlan_bt_gpios[1].gpio = IGEP2_RB_GPIO_WIFI_NRESET; - igep_wlan_bt_gpios[2].gpio = IGEP2_RB_GPIO_BT_NRESET; - } else if (hwrev == IGEP2_BOARD_HWREV_C || machine_is_igep0030()) { - igep_wlan_bt_gpios[0].gpio = IGEP2_RC_GPIO_WIFI_NPD; - igep_wlan_bt_gpios[1].gpio = IGEP2_RC_GPIO_WIFI_NRESET; - igep_wlan_bt_gpios[2].gpio = IGEP2_RC_GPIO_BT_NRESET; + npd = IGEP2_RB_GPIO_WIFI_NPD; + wreset = IGEP2_RB_GPIO_WIFI_NRESET; + btreset = IGEP2_RB_GPIO_BT_NRESET; + } else if (hwrev == IGEP2_BOARD_HWREV_C) { + npd = IGEP2_RC_GPIO_WIFI_NPD; + wreset = IGEP2_RC_GPIO_WIFI_NRESET; + btreset = IGEP2_RC_GPIO_BT_NRESET; } else return; - err = gpio_request_array(igep_wlan_bt_gpios, - ARRAY_SIZE(igep_wlan_bt_gpios)); - if (err) { - pr_warning("IGEP2: Could not obtain WIFI/BT gpios\n"); - return; - } - - gpio_export(igep_wlan_bt_gpios[0].gpio, 0); - gpio_export(igep_wlan_bt_gpios[1].gpio, 0); - gpio_export(igep_wlan_bt_gpios[2].gpio, 0); - - gpio_set_value(igep_wlan_bt_gpios[1].gpio, 0); - udelay(10); - gpio_set_value(igep_wlan_bt_gpios[1].gpio, 1); + /* Set GPIO's for WLAN-BT combo module */ + if ((gpio_request(npd, "GPIO_WIFI_NPD") == 0) && + (gpio_direction_output(npd, 1) == 0)) { + gpio_export(npd, 0); + } else + pr_warning("IGEP2: Could not obtain gpio GPIO_WIFI_NPD\n"); + + if ((gpio_request(wreset, "GPIO_WIFI_NRESET") == 0) && + (gpio_direction_output(wreset, 1) == 0)) { + gpio_export(wreset, 0); + gpio_set_value(wreset, 0); + udelay(10); + gpio_set_value(wreset, 1); + } else + pr_warning("IGEP2: Could not obtain gpio GPIO_WIFI_NRESET\n"); + if ((gpio_request(btreset, "GPIO_BT_NRESET") == 0) && + (gpio_direction_output(btreset, 1) == 0)) { + gpio_export(btreset, 0); + } else + pr_warning("IGEP2: Could not obtain gpio GPIO_BT_NRESET\n"); } #else -static inline void __init igep_wlan_bt_init(void) { } +static inline void __init igep2_wlan_bt_init(void) { } #endif -static void __init igep_init(void) +static void __init igep2_init(void) { omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); /* Get IGEP2 hardware revision */ igep2_get_revision(); /* Register I2C busses and drivers */ - igep_i2c_init(); - platform_add_devices(igep_devices, ARRAY_SIZE(igep_devices)); + igep2_i2c_init(); + platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices)); + omap_display_init(&igep2_dss_data); omap_serial_init(); - usb_musb_init(NULL); + usb_musb_init(&musb_board_data); + usbhs_init(&usbhs_bdata); - igep_flash_init(); - igep_leds_init(); + igep2_flash_init(); + igep2_leds_init(); + igep2_display_init(); + igep2_init_smsc911x(); /* * WLAN-BT combo module from MuRata which has a Marvell WLAN * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface. */ - igep_wlan_bt_init(); + igep2_wlan_bt_init(); - if (machine_is_igep0020()) { - omap_display_init(&igep2_dss_data); - igep2_display_init(); - igep2_init_smsc911x(); - usbhs_init(&igep2_usbhs_bdata); - } else { - usbhs_init(&igep3_usbhs_bdata); - } } MACHINE_START(IGEP0020, "IGEP v2 board") .boot_params = 0x80000100, .reserve = omap_reserve, .map_io = omap3_map_io, - .init_early = igep_init_early, - .init_irq = omap_init_irq, - .init_machine = igep_init, - .timer = &omap_timer, -MACHINE_END - -MACHINE_START(IGEP0030, "IGEP OMAP3 module") - .boot_params = 0x80000100, - .reserve = omap_reserve, - .map_io = omap3_map_io, - .init_early = igep_init_early, + .init_early = igep2_init_early, .init_irq = omap_init_irq, - .init_machine = igep_init, + .init_machine = igep2_init, .timer = &omap_timer, MACHINE_END diff --git a/trunk/arch/arm/mach-omap2/board-igep0030.c b/trunk/arch/arm/mach-omap2/board-igep0030.c new file mode 100644 index 000000000000..2cf86c3cb1a3 --- /dev/null +++ b/trunk/arch/arm/mach-omap2/board-igep0030.c @@ -0,0 +1,458 @@ +/* + * Copyright (C) 2010 - ISEE 2007 SL + * + * Modified from mach-omap2/board-generic.c + * + * 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 + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "mux.h" +#include "hsmmc.h" +#include "sdram-numonyx-m65kxxxxam.h" + +#define IGEP3_GPIO_LED0_GREEN 54 +#define IGEP3_GPIO_LED0_RED 53 +#define IGEP3_GPIO_LED1_RED 16 + +#define IGEP3_GPIO_WIFI_NPD 138 +#define IGEP3_GPIO_WIFI_NRESET 139 +#define IGEP3_GPIO_BT_NRESET 137 + +#define IGEP3_GPIO_USBH_NRESET 183 + + +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \ + defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) + +#define ONENAND_MAP 0x20000000 + +/* + * x2 Flash built-in COMBO POP MEMORY + * Since the device is equipped with two DataRAMs, and two-plane NAND + * Flash memory array, these two component enables simultaneous program + * of 4KiB. Plane1 has only even blocks such as block0, block2, block4 + * while Plane2 has only odd blocks such as block1, block3, block5. + * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048) + */ + +static struct mtd_partition igep3_onenand_partitions[] = { + { + .name = "X-Loader", + .offset = 0, + .size = 2 * (64*(2*2048)) + }, + { + .name = "U-Boot", + .offset = MTDPART_OFS_APPEND, + .size = 6 * (64*(2*2048)), + }, + { + .name = "Environment", + .offset = MTDPART_OFS_APPEND, + .size = 2 * (64*(2*2048)), + }, + { + .name = "Kernel", + .offset = MTDPART_OFS_APPEND, + .size = 12 * (64*(2*2048)), + }, + { + .name = "File System", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct omap_onenand_platform_data igep3_onenand_pdata = { + .parts = igep3_onenand_partitions, + .nr_parts = ARRAY_SIZE(igep3_onenand_partitions), + .onenand_setup = NULL, + .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */ +}; + +static struct platform_device igep3_onenand_device = { + .name = "omap2-onenand", + .id = -1, + .dev = { + .platform_data = &igep3_onenand_pdata, + }, +}; + +static void __init igep3_flash_init(void) +{ + u8 cs = 0; + u8 onenandcs = GPMC_CS_NUM + 1; + + for (cs = 0; cs < GPMC_CS_NUM; cs++) { + u32 ret; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + /* Check if NAND/oneNAND is configured */ + if ((ret & 0xC00) == 0x800) + /* NAND found */ + pr_err("IGEP3: Unsupported NAND found\n"); + else { + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); + + if ((ret & 0x3F) == (ONENAND_MAP >> 24)) + /* OneNAND found */ + onenandcs = cs; + } + } + + if (onenandcs > GPMC_CS_NUM) { + pr_err("IGEP3: Unable to find configuration in GPMC\n"); + return; + } + + igep3_onenand_pdata.cs = onenandcs; + + if (platform_device_register(&igep3_onenand_device) < 0) + pr_err("IGEP3: Unable to register OneNAND device\n"); +} + +#else +static void __init igep3_flash_init(void) {} +#endif + +static struct regulator_consumer_supply igep3_vmmc1_supply = + REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"); + +/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */ +static struct regulator_init_data igep3_vmmc1 = { + .constraints = { + .min_uV = 1850000, + .max_uV = 3150000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &igep3_vmmc1_supply, +}; + +static struct regulator_consumer_supply igep3_vio_supply = + REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1"); + +static struct regulator_init_data igep3_vio = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = 1, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &igep3_vio_supply, +}; + +static struct regulator_consumer_supply igep3_vmmc2_supply = + REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"); + +static struct regulator_init_data igep3_vmmc2 = { + .constraints = { + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .always_on = 1, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &igep3_vmmc2_supply, +}; + +static struct fixed_voltage_config igep3_vwlan = { + .supply_name = "vwlan", + .microvolts = 3300000, + .gpio = -EINVAL, + .enabled_at_boot = 1, + .init_data = &igep3_vmmc2, +}; + +static struct platform_device igep3_vwlan_device = { + .name = "reg-fixed-voltage", + .id = 0, + .dev = { + .platform_data = &igep3_vwlan, + }, +}; + +static struct omap2_hsmmc_info mmc[] = { + [0] = { + .mmc = 1, + .caps = MMC_CAP_4_BIT_DATA, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + }, +#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE) + [1] = { + .mmc = 2, + .caps = MMC_CAP_4_BIT_DATA, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + }, +#endif + {} /* Terminator */ +}; + +#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +#include + +static struct gpio_led igep3_gpio_leds[] = { + [0] = { + .name = "gpio-led:red:d0", + .gpio = IGEP3_GPIO_LED0_RED, + .default_trigger = "default-off" + }, + [1] = { + .name = "gpio-led:green:d0", + .gpio = IGEP3_GPIO_LED0_GREEN, + .default_trigger = "default-off", + }, + [2] = { + .name = "gpio-led:red:d1", + .gpio = IGEP3_GPIO_LED1_RED, + .default_trigger = "default-off", + }, + [3] = { + .name = "gpio-led:green:d1", + .default_trigger = "heartbeat", + .gpio = -EINVAL, /* gets replaced */ + }, +}; + +static struct gpio_led_platform_data igep3_led_pdata = { + .leds = igep3_gpio_leds, + .num_leds = ARRAY_SIZE(igep3_gpio_leds), +}; + +static struct platform_device igep3_led_device = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &igep3_led_pdata, + }, +}; + +static void __init igep3_leds_init(void) +{ + platform_device_register(&igep3_led_device); +} + +#else +static inline void igep3_leds_init(void) +{ + if ((gpio_request(IGEP3_GPIO_LED0_RED, "gpio-led:red:d0") == 0) && + (gpio_direction_output(IGEP3_GPIO_LED0_RED, 1) == 0)) { + gpio_export(IGEP3_GPIO_LED0_RED, 0); + gpio_set_value(IGEP3_GPIO_LED0_RED, 1); + } else + pr_warning("IGEP3: Could not obtain gpio GPIO_LED0_RED\n"); + + if ((gpio_request(IGEP3_GPIO_LED0_GREEN, "gpio-led:green:d0") == 0) && + (gpio_direction_output(IGEP3_GPIO_LED0_GREEN, 1) == 0)) { + gpio_export(IGEP3_GPIO_LED0_GREEN, 0); + gpio_set_value(IGEP3_GPIO_LED0_GREEN, 1); + } else + pr_warning("IGEP3: Could not obtain gpio GPIO_LED0_GREEN\n"); + + if ((gpio_request(IGEP3_GPIO_LED1_RED, "gpio-led:red:d1") == 0) && + (gpio_direction_output(IGEP3_GPIO_LED1_RED, 1) == 0)) { + gpio_export(IGEP3_GPIO_LED1_RED, 0); + gpio_set_value(IGEP3_GPIO_LED1_RED, 1); + } else + pr_warning("IGEP3: Could not obtain gpio GPIO_LED1_RED\n"); +} +#endif + +static int igep3_twl4030_gpio_setup(struct device *dev, + unsigned gpio, unsigned ngpio) +{ + /* gpio + 0 is "mmc0_cd" (input/IRQ) */ + mmc[0].gpio_cd = gpio + 0; + omap2_hsmmc_init(mmc); + + /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */ +#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE) + if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0) + && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) { + gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0); + gpio_set_value(gpio + TWL4030_GPIO_MAX + 1, 0); + } else + pr_warning("IGEP3: Could not obtain gpio GPIO_LED1_GREEN\n"); +#else + igep3_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1; +#endif + + return 0; +}; + +static struct twl4030_gpio_platform_data igep3_twl4030_gpio_pdata = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, + .use_leds = true, + .setup = igep3_twl4030_gpio_setup, +}; + +static struct twl4030_usb_data igep3_twl4030_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; + +static struct platform_device *igep3_devices[] __initdata = { + &igep3_vwlan_device, +}; + +static void __init igep3_init_early(void) +{ + omap2_init_common_infrastructure(); + omap2_init_common_devices(m65kxxxxam_sdrc_params, + m65kxxxxam_sdrc_params); +} + +static struct twl4030_platform_data igep3_twl4030_pdata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + + /* platform_data for children goes here */ + .usb = &igep3_twl4030_usb_data, + .gpio = &igep3_twl4030_gpio_pdata, + .vmmc1 = &igep3_vmmc1, + .vio = &igep3_vio, +}; + +static struct i2c_board_info __initdata igep3_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &igep3_twl4030_pdata, + }, +}; + +static int __init igep3_i2c_init(void) +{ + omap_register_i2c_bus(1, 2600, igep3_i2c_boardinfo, + ARRAY_SIZE(igep3_i2c_boardinfo)); + + return 0; +} + +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + +#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE) + +static void __init igep3_wifi_bt_init(void) +{ + /* Configure MUX values for W-LAN + Bluetooth GPIO's */ + omap_mux_init_gpio(IGEP3_GPIO_WIFI_NPD, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(IGEP3_GPIO_WIFI_NRESET, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(IGEP3_GPIO_BT_NRESET, OMAP_PIN_OUTPUT); + + /* Set GPIO's for W-LAN + Bluetooth combo module */ + if ((gpio_request(IGEP3_GPIO_WIFI_NPD, "GPIO_WIFI_NPD") == 0) && + (gpio_direction_output(IGEP3_GPIO_WIFI_NPD, 1) == 0)) { + gpio_export(IGEP3_GPIO_WIFI_NPD, 0); + } else + pr_warning("IGEP3: Could not obtain gpio GPIO_WIFI_NPD\n"); + + if ((gpio_request(IGEP3_GPIO_WIFI_NRESET, "GPIO_WIFI_NRESET") == 0) && + (gpio_direction_output(IGEP3_GPIO_WIFI_NRESET, 1) == 0)) { + gpio_export(IGEP3_GPIO_WIFI_NRESET, 0); + gpio_set_value(IGEP3_GPIO_WIFI_NRESET, 0); + udelay(10); + gpio_set_value(IGEP3_GPIO_WIFI_NRESET, 1); + } else + pr_warning("IGEP3: Could not obtain gpio GPIO_WIFI_NRESET\n"); + + if ((gpio_request(IGEP3_GPIO_BT_NRESET, "GPIO_BT_NRESET") == 0) && + (gpio_direction_output(IGEP3_GPIO_BT_NRESET, 1) == 0)) { + gpio_export(IGEP3_GPIO_BT_NRESET, 0); + } else + pr_warning("IGEP3: Could not obtain gpio GPIO_BT_NRESET\n"); +} +#else +void __init igep3_wifi_bt_init(void) {} +#endif + +static const struct usbhs_omap_board_data usbhs_bdata __initconst = { + .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED, + .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY, + .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED, + + .phy_reset = true, + .reset_gpio_port[0] = -EINVAL, + .reset_gpio_port[1] = IGEP3_GPIO_USBH_NRESET, + .reset_gpio_port[2] = -EINVAL, +}; + +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + OMAP3_MUX(I2C2_SDA, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT), + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#endif + +static void __init igep3_init(void) +{ + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); + + /* Register I2C busses and drivers */ + igep3_i2c_init(); + platform_add_devices(igep3_devices, ARRAY_SIZE(igep3_devices)); + omap_serial_init(); + usb_musb_init(&musb_board_data); + usbhs_init(&usbhs_bdata); + + igep3_flash_init(); + igep3_leds_init(); + + /* + * WLAN-BT combo module from MuRata which has a Marvell WLAN + * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface. + */ + igep3_wifi_bt_init(); + +} + +MACHINE_START(IGEP0030, "IGEP OMAP3 module") + .boot_params = 0x80000100, + .reserve = omap_reserve, + .map_io = omap3_map_io, + .init_early = igep3_init_early, + .init_irq = omap_init_irq, + .init_machine = igep3_init, + .timer = &omap_timer, +MACHINE_END diff --git a/trunk/arch/arm/mach-omap2/board-ldp.c b/trunk/arch/arm/mach-omap2/board-ldp.c index f7d6038075f0..e2ba77957a8c 100644 --- a/trunk/arch/arm/mach-omap2/board-ldp.c +++ b/trunk/arch/arm/mach-omap2/board-ldp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -42,19 +43,47 @@ #include #include -#include #include "board-flash.h" #include "mux.h" #include "hsmmc.h" #include "control.h" -#include "common-board-devices.h" #define LDP_SMSC911X_CS 1 #define LDP_SMSC911X_GPIO 152 #define DEBUG_BASE 0x08000000 #define LDP_ETHR_START DEBUG_BASE +static struct resource ldp_smsc911x_resources[] = { + [0] = { + .start = LDP_ETHR_START, + .end = LDP_ETHR_START + SZ_4K, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, +}; + +static struct smsc911x_platform_config ldp_smsc911x_config = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, + .flags = SMSC911X_USE_32BIT, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct platform_device ldp_smsc911x_device = { + .name = "smsc911x", + .id = -1, + .num_resources = ARRAY_SIZE(ldp_smsc911x_resources), + .resource = ldp_smsc911x_resources, + .dev = { + .platform_data = &ldp_smsc911x_config, + }, +}; + static uint32_t board_keymap[] = { KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), @@ -168,16 +197,82 @@ static struct platform_device ldp_gpio_keys_device = { }, }; -static struct omap_smsc911x_platform_data smsc911x_cfg = { - .cs = LDP_SMSC911X_CS, - .gpio_irq = LDP_SMSC911X_GPIO, - .gpio_reset = -EINVAL, - .flags = SMSC911X_USE_32BIT, +static int ts_gpio; + +/** + * @brief ads7846_dev_init : Requests & sets GPIO line for pen-irq + * + * @return - void. If request gpio fails then Flag KERN_ERR. + */ +static void ads7846_dev_init(void) +{ + if (gpio_request(ts_gpio, "ads7846 irq") < 0) { + printk(KERN_ERR "can't get ads746 pen down GPIO\n"); + return; + } + + gpio_direction_input(ts_gpio); + gpio_set_debounce(ts_gpio, 310); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(ts_gpio); +} + +static struct ads7846_platform_data tsc2046_config __initdata = { + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, +}; + +static struct omap2_mcspi_device_config tsc2046_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info ldp_spi_board_info[] __initdata = { + [0] = { + /* + * TSC2046 operates at a max freqency of 2MHz, so + * operate slightly below at 1.5MHz + */ + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &tsc2046_mcspi_config, + .irq = 0, + .platform_data = &tsc2046_config, + }, }; static inline void __init ldp_init_smsc911x(void) { - gpmc_smsc911x_init(&smsc911x_cfg); + int eth_cs; + unsigned long cs_mem_base; + int eth_gpio = 0; + + eth_cs = LDP_SMSC911X_CS; + + if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) { + printk(KERN_ERR "Failed to request GPMC mem for smsc911x\n"); + return; + } + + ldp_smsc911x_resources[0].start = cs_mem_base + 0x0; + ldp_smsc911x_resources[0].end = cs_mem_base + 0xff; + udelay(100); + + eth_gpio = LDP_SMSC911X_GPIO; + + ldp_smsc911x_resources[1].start = OMAP_GPIO_IRQ(eth_gpio); + + if (gpio_request(eth_gpio, "smsc911x irq") < 0) { + printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n", + eth_gpio); + return; + } + gpio_direction_input(eth_gpio); } static struct platform_device ldp_lcd_device = { @@ -265,9 +360,19 @@ static struct twl4030_platform_data ldp_twldata = { .keypad = &ldp_kp_twl4030_data, }; +static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &ldp_twldata, + }, +}; + static int __init omap_i2c_init(void) { - omap3_pmic_init("twl4030", &ldp_twldata); + omap_register_i2c_bus(1, 2600, ldp_i2c_boardinfo, + ARRAY_SIZE(ldp_i2c_boardinfo)); omap_register_i2c_bus(2, 400, NULL, 0); omap_register_i2c_bus(3, 400, NULL, 0); return 0; @@ -284,6 +389,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = { }; static struct platform_device *ldp_devices[] __initdata = { + &ldp_smsc911x_device, &ldp_lcd_device, &ldp_gpio_keys_device, }; @@ -294,6 +400,12 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + static struct mtd_partition ldp_nand_partitions[] = { /* All the partition sizes are listed in terms of NAND block size */ { @@ -334,9 +446,13 @@ static void __init omap_ldp_init(void) ldp_init_smsc911x(); omap_i2c_init(); platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices)); - omap_ads7846_init(1, 54, 310, NULL); + ts_gpio = 54; + ldp_spi_board_info[0].irq = gpio_to_irq(ts_gpio); + spi_register_board_info(ldp_spi_board_info, + ARRAY_SIZE(ldp_spi_board_info)); + ads7846_dev_init(); omap_serial_init(); - usb_musb_init(NULL); + usb_musb_init(&musb_board_data); board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0); diff --git a/trunk/arch/arm/mach-omap2/board-n8x0.c b/trunk/arch/arm/mach-omap2/board-n8x0.c index 8d74318ed495..e710cd9e079b 100644 --- a/trunk/arch/arm/mach-omap2/board-n8x0.c +++ b/trunk/arch/arm/mach-omap2/board-n8x0.c @@ -106,13 +106,14 @@ static void __init n8x0_usb_init(void) static char announce[] __initdata = KERN_INFO "TUSB 6010\n"; /* PM companion chip power control pin */ - ret = gpio_request_one(TUSB6010_GPIO_ENABLE, GPIOF_OUT_INIT_LOW, - "TUSB6010 enable"); + ret = gpio_request(TUSB6010_GPIO_ENABLE, "TUSB6010 enable"); if (ret != 0) { printk(KERN_ERR "Could not get TUSB power GPIO%i\n", TUSB6010_GPIO_ENABLE); return; } + gpio_direction_output(TUSB6010_GPIO_ENABLE, 0); + tusb_set_power(0); ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2, @@ -493,12 +494,8 @@ static struct omap_mmc_platform_data mmc1_data = { static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC]; -static struct gpio n810_emmc_gpios[] __initdata = { - { N810_EMMC_VSD_GPIO, GPIOF_OUT_INIT_LOW, "MMC slot 2 Vddf" }, - { N810_EMMC_VIO_GPIO, GPIOF_OUT_INIT_LOW, "MMC slot 2 Vdd" }, -}; - static void __init n8x0_mmc_init(void) + { int err; @@ -515,18 +512,27 @@ static void __init n8x0_mmc_init(void) mmc1_data.slots[1].ban_openended = 1; } - err = gpio_request_one(N8X0_SLOT_SWITCH_GPIO, GPIOF_OUT_INIT_LOW, - "MMC slot switch"); + err = gpio_request(N8X0_SLOT_SWITCH_GPIO, "MMC slot switch"); if (err) return; + gpio_direction_output(N8X0_SLOT_SWITCH_GPIO, 0); + if (machine_is_nokia_n810()) { - err = gpio_request_array(n810_emmc_gpios, - ARRAY_SIZE(n810_emmc_gpios)); + err = gpio_request(N810_EMMC_VSD_GPIO, "MMC slot 2 Vddf"); + if (err) { + gpio_free(N8X0_SLOT_SWITCH_GPIO); + return; + } + gpio_direction_output(N810_EMMC_VSD_GPIO, 0); + + err = gpio_request(N810_EMMC_VIO_GPIO, "MMC slot 2 Vdd"); if (err) { gpio_free(N8X0_SLOT_SWITCH_GPIO); + gpio_free(N810_EMMC_VSD_GPIO); return; } + gpio_direction_output(N810_EMMC_VIO_GPIO, 0); } mmc_data[0] = &mmc1_data; diff --git a/trunk/arch/arm/mach-omap2/board-omap3beagle.c b/trunk/arch/arm/mach-omap2/board-omap3beagle.c index be71426359f2..97750d483a70 100644 --- a/trunk/arch/arm/mach-omap2/board-omap3beagle.c +++ b/trunk/arch/arm/mach-omap2/board-omap3beagle.c @@ -52,7 +52,6 @@ #include "hsmmc.h" #include "timer-gp.h" #include "pm.h" -#include "common-board-devices.h" #define NAND_BLOCK_SIZE SZ_128K @@ -80,12 +79,6 @@ static u8 omap3_beagle_get_rev(void) return omap3_beagle_version; } -static struct gpio omap3_beagle_rev_gpios[] __initdata = { - { 171, GPIOF_IN, "rev_id_0" }, - { 172, GPIOF_IN, "rev_id_1" }, - { 173, GPIOF_IN, "rev_id_2" }, -}; - static void __init omap3_beagle_init_rev(void) { int ret; @@ -95,13 +88,21 @@ static void __init omap3_beagle_init_rev(void) omap_mux_init_gpio(172, OMAP_PIN_INPUT_PULLUP); omap_mux_init_gpio(173, OMAP_PIN_INPUT_PULLUP); - ret = gpio_request_array(omap3_beagle_rev_gpios, - ARRAY_SIZE(omap3_beagle_rev_gpios)); - if (ret < 0) { - printk(KERN_ERR "Unable to get revision detection GPIO pins\n"); - omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN; - return; - } + ret = gpio_request(171, "rev_id_0"); + if (ret < 0) + goto fail0; + + ret = gpio_request(172, "rev_id_1"); + if (ret < 0) + goto fail1; + + ret = gpio_request(173, "rev_id_2"); + if (ret < 0) + goto fail2; + + gpio_direction_input(171); + gpio_direction_input(172); + gpio_direction_input(173); beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1) | (gpio_get_value(173) << 2); @@ -127,6 +128,18 @@ static void __init omap3_beagle_init_rev(void) printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev); omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN; } + + return; + +fail2: + gpio_free(172); +fail1: + gpio_free(171); +fail0: + printk(KERN_ERR "Unable to get revision detection GPIO pins\n"); + omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN; + + return; } static struct mtd_partition omap3beagle_nand_partitions[] = { @@ -160,6 +173,15 @@ static struct mtd_partition omap3beagle_nand_partitions[] = { }, }; +static struct omap_nand_platform_data omap3beagle_nand_data = { + .options = NAND_BUSWIDTH_16, + .parts = omap3beagle_nand_partitions, + .nr_parts = ARRAY_SIZE(omap3beagle_nand_partitions), + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ + .nand_setup = NULL, + .dev_ready = NULL, +}; + /* DSS */ static int beagle_enable_dvi(struct omap_dss_device *dssdev) @@ -221,10 +243,13 @@ static void __init beagle_display_init(void) { int r; - r = gpio_request_one(beagle_dvi_device.reset_gpio, GPIOF_OUT_INIT_LOW, - "DVI reset"); - if (r < 0) + r = gpio_request(beagle_dvi_device.reset_gpio, "DVI reset"); + if (r < 0) { printk(KERN_ERR "Unable to get DVI reset GPIO\n"); + return; + } + + gpio_direction_output(beagle_dvi_device.reset_gpio, 0); } #include "sdram-micron-mt46h32m32lf-6.h" @@ -251,7 +276,7 @@ static struct gpio_led gpio_leds[]; static int beagle_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { - int r, usb_pwr_level; + int r; if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) { mmc[0].gpio_wp = -EINVAL; @@ -270,46 +295,66 @@ static int beagle_twl_gpio_setup(struct device *dev, beagle_vmmc1_supply.dev = mmc[0].dev; beagle_vsim_supply.dev = mmc[0].dev; + /* REVISIT: need ehci-omap hooks for external VBUS + * power switch and overcurrent detect + */ + if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM) { + r = gpio_request(gpio + 1, "EHCI_nOC"); + if (!r) { + r = gpio_direction_input(gpio + 1); + if (r) + gpio_free(gpio + 1); + } + if (r) + pr_err("%s: unable to configure EHCI_nOC\n", __func__); + } + /* * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active * high / others active low) - * DVI reset GPIO is different between beagle revisions */ - if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) { - usb_pwr_level = GPIOF_OUT_INIT_HIGH; + gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); + if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1); + else + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); + + /* DVI reset GPIO is different between beagle revisions */ + if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) beagle_dvi_device.reset_gpio = 129; - /* - * gpio + 1 on Xm controls the TFP410's enable line (active low) - * gpio + 2 control varies depending on the board rev as below: - * P7/P8 revisions(prototype): Camera EN - * A2+ revisions (production): LDO (DVI, serial, led blocks) - */ - r = gpio_request_one(gpio + 1, GPIOF_OUT_INIT_LOW, - "nDVI_PWR_EN"); + else + beagle_dvi_device.reset_gpio = 170; + + /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ + gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; + + /* + * gpio + 1 on Xm controls the TFP410's enable line (active low) + * gpio + 2 control varies depending on the board rev as follows: + * P7/P8 revisions(prototype): Camera EN + * A2+ revisions (production): LDO (supplies DVI, serial, led blocks) + */ + if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) { + r = gpio_request(gpio + 1, "nDVI_PWR_EN"); + if (!r) { + r = gpio_direction_output(gpio + 1, 0); + if (r) + gpio_free(gpio + 1); + } if (r) pr_err("%s: unable to configure nDVI_PWR_EN\n", __func__); - r = gpio_request_one(gpio + 2, GPIOF_OUT_INIT_HIGH, - "DVI_LDO_EN"); + r = gpio_request(gpio + 2, "DVI_LDO_EN"); + if (!r) { + r = gpio_direction_output(gpio + 2, 1); + if (r) + gpio_free(gpio + 2); + } if (r) pr_err("%s: unable to configure DVI_LDO_EN\n", __func__); - } else { - usb_pwr_level = GPIOF_OUT_INIT_LOW; - beagle_dvi_device.reset_gpio = 170; - /* - * REVISIT: need ehci-omap hooks for external VBUS - * power switch and overcurrent detect - */ - if (gpio_request_one(gpio + 1, GPIOF_IN, "EHCI_nOC")) - pr_err("%s: unable to configure EHCI_nOC\n", __func__); } - gpio_request_one(gpio + TWL4030_GPIO_MAX, usb_pwr_level, "nEN_USB_PWR"); - - /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ - gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; - return 0; } @@ -408,6 +453,15 @@ static struct twl4030_platform_data beagle_twldata = { .vpll2 = &beagle_vpll2, }; +static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &beagle_twldata, + }, +}; + static struct i2c_board_info __initdata beagle_i2c_eeprom[] = { { I2C_BOARD_INFO("eeprom", 0x50), @@ -416,7 +470,8 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = { static int __init omap3_beagle_i2c_init(void) { - omap3_pmic_init("twl4030", &beagle_twldata); + omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo, + ARRAY_SIZE(beagle_i2c_boardinfo)); /* Bus 3 is attached to the DVI port where devices like the pico DLP * projector don't work reliably with 400kHz */ omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom)); @@ -496,6 +551,39 @@ static struct platform_device *omap3_beagle_devices[] __initdata = { &keys_gpio, }; +static void __init omap3beagle_flash_init(void) +{ + u8 cs = 0; + u8 nandcs = GPMC_CS_NUM + 1; + + /* find out the chip-select on which NAND exists */ + while (cs < GPMC_CS_NUM) { + u32 ret = 0; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + if ((ret & 0xC00) == 0x800) { + printk(KERN_INFO "Found NAND on CS%d\n", cs); + if (nandcs > GPMC_CS_NUM) + nandcs = cs; + } + cs++; + } + + if (nandcs > GPMC_CS_NUM) { + printk(KERN_INFO "NAND: Unable to find configuration " + "in GPMC\n "); + return; + } + + if (nandcs < GPMC_CS_NUM) { + omap3beagle_nand_data.cs = nandcs; + + printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); + if (gpmc_nand_init(&omap3beagle_nand_data) < 0) + printk(KERN_ERR "Unable to register NAND device\n"); + } +} + static const struct usbhs_omap_board_data usbhs_bdata __initconst = { .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, @@ -514,6 +602,12 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + static void __init beagle_opp_init(void) { int r = 0; @@ -571,13 +665,13 @@ static void __init omap3_beagle_init(void) omap_serial_init(); omap_mux_init_gpio(170, OMAP_PIN_INPUT); + gpio_request(170, "DVI_nPD"); /* REVISIT leave DVI powered down until it's needed ... */ - gpio_request_one(170, GPIOF_OUT_INIT_HIGH, "DVI_nPD"); + gpio_direction_output(170, true); - usb_musb_init(NULL); + usb_musb_init(&musb_board_data); usbhs_init(&usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions, - ARRAY_SIZE(omap3beagle_nand_partitions)); + omap3beagle_flash_init(); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); diff --git a/trunk/arch/arm/mach-omap2/board-omap3evm.c b/trunk/arch/arm/mach-omap2/board-omap3evm.c index b4d43464a303..7f94cccdb076 100644 --- a/trunk/arch/arm/mach-omap2/board-omap3evm.c +++ b/trunk/arch/arm/mach-omap2/board-omap3evm.c @@ -50,7 +50,6 @@ #include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" -#include "common-board-devices.h" #define OMAP3_EVM_TS_GPIO 175 #define OMAP3_EVM_EHCI_VBUS 22 @@ -102,20 +101,49 @@ static void __init omap3_evm_get_revision(void) } #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) -#include +static struct resource omap3evm_smsc911x_resources[] = { + [0] = { + .start = OMAP3EVM_ETHR_START, + .end = (OMAP3EVM_ETHR_START + OMAP3EVM_ETHR_SIZE - 1), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = OMAP_GPIO_IRQ(OMAP3EVM_ETHR_GPIO_IRQ), + .end = OMAP_GPIO_IRQ(OMAP3EVM_ETHR_GPIO_IRQ), + .flags = (IORESOURCE_IRQ | IRQF_TRIGGER_LOW), + }, +}; -static struct omap_smsc911x_platform_data smsc911x_cfg = { - .cs = OMAP3EVM_SMSC911X_CS, - .gpio_irq = OMAP3EVM_ETHR_GPIO_IRQ, - .gpio_reset = -EINVAL, - .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS, +static struct smsc911x_platform_config smsc911x_config = { + .phy_interface = PHY_INTERFACE_MODE_MII, + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, + .flags = (SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS), +}; + +static struct platform_device omap3evm_smsc911x_device = { + .name = "smsc911x", + .id = -1, + .num_resources = ARRAY_SIZE(omap3evm_smsc911x_resources), + .resource = &omap3evm_smsc911x_resources[0], + .dev = { + .platform_data = &smsc911x_config, + }, }; static inline void __init omap3evm_init_smsc911x(void) { + int eth_cs, eth_rst; struct clk *l3ck; unsigned int rate; + if (get_omap3_evm_rev() == OMAP3EVM_BOARD_GEN_1) + eth_rst = OMAP3EVM_GEN1_ETHR_GPIO_RST; + else + eth_rst = OMAP3EVM_GEN2_ETHR_GPIO_RST; + + eth_cs = OMAP3EVM_SMSC911X_CS; + l3ck = clk_get(NULL, "l3_ck"); if (IS_ERR(l3ck)) rate = 100000000; @@ -124,13 +152,33 @@ static inline void __init omap3evm_init_smsc911x(void) /* Configure ethernet controller reset gpio */ if (cpu_is_omap3430()) { - if (get_omap3_evm_rev() == OMAP3EVM_BOARD_GEN_1) - smsc911x_cfg.gpio_reset = OMAP3EVM_GEN1_ETHR_GPIO_RST; - else - smsc911x_cfg.gpio_reset = OMAP3EVM_GEN2_ETHR_GPIO_RST; + if (gpio_request(eth_rst, "SMSC911x gpio") < 0) { + pr_err(KERN_ERR "Failed to request %d for smsc911x\n", + eth_rst); + return; + } + + if (gpio_direction_output(eth_rst, 1) < 0) { + pr_err(KERN_ERR "Failed to set direction of %d for" \ + " smsc911x\n", eth_rst); + return; + } + /* reset pulse to ethernet controller*/ + usleep_range(150, 220); + gpio_set_value(eth_rst, 0); + usleep_range(150, 220); + gpio_set_value(eth_rst, 1); + usleep_range(1, 2); + } + + if (gpio_request(OMAP3EVM_ETHR_GPIO_IRQ, "SMSC911x irq") < 0) { + printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n", + OMAP3EVM_ETHR_GPIO_IRQ); + return; } - gpmc_smsc911x_init(&smsc911x_cfg); + gpio_direction_input(OMAP3EVM_ETHR_GPIO_IRQ); + platform_device_register(&omap3evm_smsc911x_device); } #else @@ -149,15 +197,6 @@ static inline void __init omap3evm_init_smsc911x(void) { return; } #define OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO 210 #define OMAP3EVM_DVI_PANEL_EN_GPIO 199 -static struct gpio omap3_evm_dss_gpios[] __initdata = { - { OMAP3EVM_LCD_PANEL_RESB, GPIOF_OUT_INIT_HIGH, "lcd_panel_resb" }, - { OMAP3EVM_LCD_PANEL_INI, GPIOF_OUT_INIT_HIGH, "lcd_panel_ini" }, - { OMAP3EVM_LCD_PANEL_QVGA, GPIOF_OUT_INIT_LOW, "lcd_panel_qvga" }, - { OMAP3EVM_LCD_PANEL_LR, GPIOF_OUT_INIT_HIGH, "lcd_panel_lr" }, - { OMAP3EVM_LCD_PANEL_UD, GPIOF_OUT_INIT_HIGH, "lcd_panel_ud" }, - { OMAP3EVM_LCD_PANEL_ENVDD, GPIOF_OUT_INIT_LOW, "lcd_panel_envdd" }, -}; - static int lcd_enabled; static int dvi_enabled; @@ -165,10 +204,61 @@ static void __init omap3_evm_display_init(void) { int r; - r = gpio_request_array(omap3_evm_dss_gpios, - ARRAY_SIZE(omap3_evm_dss_gpios)); - if (r) - printk(KERN_ERR "failed to get lcd_panel_* gpios\n"); + r = gpio_request(OMAP3EVM_LCD_PANEL_RESB, "lcd_panel_resb"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_resb\n"); + return; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_RESB, 1); + + r = gpio_request(OMAP3EVM_LCD_PANEL_INI, "lcd_panel_ini"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_ini\n"); + goto err_1; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_INI, 1); + + r = gpio_request(OMAP3EVM_LCD_PANEL_QVGA, "lcd_panel_qvga"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_qvga\n"); + goto err_2; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_QVGA, 0); + + r = gpio_request(OMAP3EVM_LCD_PANEL_LR, "lcd_panel_lr"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_lr\n"); + goto err_3; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_LR, 1); + + r = gpio_request(OMAP3EVM_LCD_PANEL_UD, "lcd_panel_ud"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_ud\n"); + goto err_4; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_UD, 1); + + r = gpio_request(OMAP3EVM_LCD_PANEL_ENVDD, "lcd_panel_envdd"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_envdd\n"); + goto err_5; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_ENVDD, 0); + + return; + +err_5: + gpio_free(OMAP3EVM_LCD_PANEL_UD); +err_4: + gpio_free(OMAP3EVM_LCD_PANEL_LR); +err_3: + gpio_free(OMAP3EVM_LCD_PANEL_QVGA); +err_2: + gpio_free(OMAP3EVM_LCD_PANEL_INI); +err_1: + gpio_free(OMAP3EVM_LCD_PANEL_RESB); + } static int omap3_evm_enable_lcd(struct omap_dss_device *dssdev) @@ -358,7 +448,7 @@ static struct platform_device leds_gpio = { static int omap3evm_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { - int r, lcd_bl_en; + int r; /* gpio + 0 is "mmc0_cd" (input/IRQ) */ omap_mux_init_gpio(63, OMAP_PIN_INPUT); @@ -375,14 +465,16 @@ static int omap3evm_twl_gpio_setup(struct device *dev, */ /* TWL4030_GPIO_MAX + 0 == ledA, LCD Backlight control */ - lcd_bl_en = get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2 ? - GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - r = gpio_request_one(gpio + TWL4030_GPIO_MAX, lcd_bl_en, "EN_LCD_BKL"); + r = gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL"); + if (!r) + r = gpio_direction_output(gpio + TWL4030_GPIO_MAX, + (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) ? 1 : 0); if (r) printk(KERN_ERR "failed to get/set lcd_bkl gpio\n"); /* gpio + 7 == DVI Enable */ - gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "EN_DVI"); + gpio_request(gpio + 7, "EN_DVI"); + gpio_direction_output(gpio + 7, 0); /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; @@ -560,18 +652,78 @@ static struct twl4030_platform_data omap3evm_twldata = { .vdac = &omap3_evm_vdac, .vpll2 = &omap3_evm_vpll2, .vio = &omap3evm_vio, - .vmmc1 = &omap3evm_vmmc1, - .vsim = &omap3evm_vsim, +}; + +static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &omap3evm_twldata, + }, }; static int __init omap3_evm_i2c_init(void) { - omap3_pmic_init("twl4030", &omap3evm_twldata); + /* + * REVISIT: These entries can be set in omap3evm_twl_data + * after a merge with MFD tree + */ + omap3evm_twldata.vmmc1 = &omap3evm_vmmc1; + omap3evm_twldata.vsim = &omap3evm_vsim; + + omap_register_i2c_bus(1, 2600, omap3evm_i2c_boardinfo, + ARRAY_SIZE(omap3evm_i2c_boardinfo)); omap_register_i2c_bus(2, 400, NULL, 0); omap_register_i2c_bus(3, 400, NULL, 0); return 0; } +static void ads7846_dev_init(void) +{ + if (gpio_request(OMAP3_EVM_TS_GPIO, "ADS7846 pendown") < 0) + printk(KERN_ERR "can't get ads7846 pen down GPIO\n"); + + gpio_direction_input(OMAP3_EVM_TS_GPIO); + gpio_set_debounce(OMAP3_EVM_TS_GPIO, 310); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(OMAP3_EVM_TS_GPIO); +} + +static struct ads7846_platform_data ads7846_config = { + .x_max = 0x0fff, + .y_max = 0x0fff, + .x_plate_ohms = 180, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 3, + .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, + .settle_delay_usecs = 150, + .wakeup = true, +}; + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info omap3evm_spi_board_info[] = { + [0] = { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OMAP3_EVM_TS_GPIO), + .platform_data = &ads7846_config, + }, +}; + static struct omap_board_config_kernel omap3_evm_config[] __initdata = { }; @@ -673,11 +825,6 @@ static struct omap_musb_board_data musb_board_data = { .power = 100, }; -static struct gpio omap3_evm_ehci_gpios[] __initdata = { - { OMAP3_EVM_EHCI_VBUS, GPIOF_OUT_INIT_HIGH, "enable EHCI VBUS" }, - { OMAP3_EVM_EHCI_SELECT, GPIOF_OUT_INIT_LOW, "select EHCI port" }, -}; - static void __init omap3_evm_init(void) { omap3_evm_get_revision(); @@ -694,6 +841,9 @@ static void __init omap3_evm_init(void) omap_display_init(&omap3_evm_dss_data); + spi_register_board_info(omap3evm_spi_board_info, + ARRAY_SIZE(omap3evm_spi_board_info)); + omap_serial_init(); /* OMAP3EVM uses ISP1504 phy and so register nop transceiver */ @@ -701,12 +851,16 @@ static void __init omap3_evm_init(void) if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) { /* enable EHCI VBUS using GPIO22 */ - omap_mux_init_gpio(OMAP3_EVM_EHCI_VBUS, OMAP_PIN_INPUT_PULLUP); + omap_mux_init_gpio(22, OMAP_PIN_INPUT_PULLUP); + gpio_request(OMAP3_EVM_EHCI_VBUS, "enable EHCI VBUS"); + gpio_direction_output(OMAP3_EVM_EHCI_VBUS, 0); + gpio_set_value(OMAP3_EVM_EHCI_VBUS, 1); + /* Select EHCI port on main board */ - omap_mux_init_gpio(OMAP3_EVM_EHCI_SELECT, - OMAP_PIN_INPUT_PULLUP); - gpio_request_array(omap3_evm_ehci_gpios, - ARRAY_SIZE(omap3_evm_ehci_gpios)); + omap_mux_init_gpio(61, OMAP_PIN_INPUT_PULLUP); + gpio_request(OMAP3_EVM_EHCI_SELECT, "select EHCI port"); + gpio_direction_output(OMAP3_EVM_EHCI_SELECT, 0); + gpio_set_value(OMAP3_EVM_EHCI_SELECT, 0); /* setup EHCI phy reset config */ omap_mux_init_gpio(21, OMAP_PIN_INPUT_PULLUP); @@ -722,7 +876,7 @@ static void __init omap3_evm_init(void) } usb_musb_init(&musb_board_data); usbhs_init(&usbhs_bdata); - omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL); + ads7846_dev_init(); omap3evm_init_smsc911x(); omap3_evm_display_init(); diff --git a/trunk/arch/arm/mach-omap2/board-omap3logic.c b/trunk/arch/arm/mach-omap2/board-omap3logic.c index 60d9be49dbab..b726943d7c93 100644 --- a/trunk/arch/arm/mach-omap2/board-omap3logic.c +++ b/trunk/arch/arm/mach-omap2/board-omap3logic.c @@ -37,7 +37,6 @@ #include "hsmmc.h" #include "timer-gp.h" #include "control.h" -#include "common-board-devices.h" #include #include @@ -94,9 +93,19 @@ static struct twl4030_platform_data omap3logic_twldata = { .vmmc1 = &omap3logic_vmmc1, }; +static struct i2c_board_info __initdata omap3logic_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &omap3logic_twldata, + }, +}; + static int __init omap3logic_i2c_init(void) { - omap3_pmic_init("twl4030", &omap3logic_twldata); + omap_register_i2c_bus(1, 2600, omap3logic_i2c_boardinfo, + ARRAY_SIZE(omap3logic_i2c_boardinfo)); return 0; } @@ -138,6 +147,7 @@ static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = { .cs = OMAP3LOGIC_SMSC911X_CS, .gpio_irq = -EINVAL, .gpio_reset = -EINVAL, + .flags = IORESOURCE_IRQ_LOWLEVEL, }; /* TODO/FIXME (comment by Peter Barada, LogicPD): diff --git a/trunk/arch/arm/mach-omap2/board-omap3pandora.c b/trunk/arch/arm/mach-omap2/board-omap3pandora.c index 1d10736c6d3c..1db15492d82b 100644 --- a/trunk/arch/arm/mach-omap2/board-omap3pandora.c +++ b/trunk/arch/arm/mach-omap2/board-omap3pandora.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -51,7 +52,6 @@ #include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" -#include "common-board-devices.h" #define PANDORA_WIFI_IRQ_GPIO 21 #define PANDORA_WIFI_NRESET_GPIO 23 @@ -305,13 +305,24 @@ static int omap3pandora_twl_gpio_setup(struct device *dev, /* gpio + 13 drives 32kHz buffer for wifi module */ gpio_32khz = gpio + 13; - ret = gpio_request_one(gpio_32khz, GPIOF_OUT_INIT_HIGH, "wifi 32kHz"); + ret = gpio_request(gpio_32khz, "wifi 32kHz"); if (ret < 0) { pr_err("Cannot get GPIO line %d, ret=%d\n", gpio_32khz, ret); - return -ENODEV; + goto fail; + } + + ret = gpio_direction_output(gpio_32khz, 1); + if (ret < 0) { + pr_err("Cannot set GPIO line %d, ret=%d\n", gpio_32khz, ret); + goto fail_direction; } return 0; + +fail_direction: + gpio_free(gpio_32khz); +fail: + return -ENODEV; } static struct twl4030_gpio_platform_data omap3pandora_gpio_data = { @@ -533,6 +544,15 @@ static struct twl4030_platform_data omap3pandora_twldata = { .bci = &pandora_bci_data, }; +static struct i2c_board_info __initdata omap3pandora_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("tps65950", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &omap3pandora_twldata, + }, +}; + static struct i2c_board_info __initdata omap3pandora_i2c3_boardinfo[] = { { I2C_BOARD_INFO("bq27500", 0x55), @@ -542,15 +562,61 @@ static struct i2c_board_info __initdata omap3pandora_i2c3_boardinfo[] = { static int __init omap3pandora_i2c_init(void) { - omap3_pmic_init("tps65950", &omap3pandora_twldata); + omap_register_i2c_bus(1, 2600, omap3pandora_i2c_boardinfo, + ARRAY_SIZE(omap3pandora_i2c_boardinfo)); /* i2c2 pins are not connected */ omap_register_i2c_bus(3, 100, omap3pandora_i2c3_boardinfo, ARRAY_SIZE(omap3pandora_i2c3_boardinfo)); return 0; } +static void __init omap3pandora_ads7846_init(void) +{ + int gpio = OMAP3_PANDORA_TS_GPIO; + int ret; + + ret = gpio_request(gpio, "ads7846_pen_down"); + if (ret < 0) { + printk(KERN_ERR "Failed to request GPIO %d for " + "ads7846 pen down IRQ\n", gpio); + return; + } + + gpio_direction_input(gpio); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(OMAP3_PANDORA_TS_GPIO); +} + +static struct ads7846_platform_data ads7846_config = { + .x_max = 0x0fff, + .y_max = 0x0fff, + .x_plate_ohms = 180, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 3, + .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, +}; + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + static struct spi_board_info omap3pandora_spi_board_info[] __initdata = { { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OMAP3_PANDORA_TS_GPIO), + .platform_data = &ads7846_config, + }, { .modalias = "tpo_td043mtea1_panel_spi", .bus_num = 1, .chip_select = 1, @@ -573,10 +639,14 @@ static void __init pandora_wl1251_init(void) memset(&pandora_wl1251_pdata, 0, sizeof(pandora_wl1251_pdata)); - ret = gpio_request_one(PANDORA_WIFI_IRQ_GPIO, GPIOF_IN, "wl1251 irq"); + ret = gpio_request(PANDORA_WIFI_IRQ_GPIO, "wl1251 irq"); if (ret < 0) goto fail; + ret = gpio_direction_input(PANDORA_WIFI_IRQ_GPIO); + if (ret < 0) + goto fail_irq; + pandora_wl1251_pdata.irq = gpio_to_irq(PANDORA_WIFI_IRQ_GPIO); if (pandora_wl1251_pdata.irq < 0) goto fail_irq; @@ -618,6 +688,12 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + static void __init omap3pandora_init(void) { omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); @@ -629,9 +705,9 @@ static void __init omap3pandora_init(void) omap_serial_init(); spi_register_board_info(omap3pandora_spi_board_info, ARRAY_SIZE(omap3pandora_spi_board_info)); - omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL); + omap3pandora_ads7846_init(); usbhs_init(&usbhs_bdata); - usb_musb_init(NULL); + usb_musb_init(&musb_board_data); gpmc_nand_init(&pandora_nand_data); /* Ensure SDRC pins are mux'd for self-refresh */ diff --git a/trunk/arch/arm/mach-omap2/board-omap3stalker.c b/trunk/arch/arm/mach-omap2/board-omap3stalker.c index 0c108a212ea2..a72c90a08c8a 100644 --- a/trunk/arch/arm/mach-omap2/board-omap3stalker.c +++ b/trunk/arch/arm/mach-omap2/board-omap3stalker.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -53,28 +54,52 @@ #include "mux.h" #include "hsmmc.h" #include "timer-gp.h" -#include "common-board-devices.h" #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) -#include - #define OMAP3STALKER_ETHR_START 0x2c000000 #define OMAP3STALKER_ETHR_SIZE 1024 #define OMAP3STALKER_ETHR_GPIO_IRQ 19 #define OMAP3STALKER_SMC911X_CS 5 -static struct omap_smsc911x_platform_data smsc911x_cfg = { - .cs = OMAP3STALKER_SMC911X_CS, - .gpio_irq = OMAP3STALKER_ETHR_GPIO_IRQ, - .gpio_reset = -EINVAL, +static struct resource omap3stalker_smsc911x_resources[] = { + [0] = { + .start = OMAP3STALKER_ETHR_START, + .end = + (OMAP3STALKER_ETHR_START + OMAP3STALKER_ETHR_SIZE - 1), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = OMAP_GPIO_IRQ(OMAP3STALKER_ETHR_GPIO_IRQ), + .end = OMAP_GPIO_IRQ(OMAP3STALKER_ETHR_GPIO_IRQ), + .flags = (IORESOURCE_IRQ | IRQF_TRIGGER_LOW), + }, +}; + +static struct smsc911x_platform_config smsc911x_config = { + .phy_interface = PHY_INTERFACE_MODE_MII, + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, .flags = (SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS), }; +static struct platform_device omap3stalker_smsc911x_device = { + .name = "smsc911x", + .id = -1, + .num_resources = ARRAY_SIZE(omap3stalker_smsc911x_resources), + .resource = &omap3stalker_smsc911x_resources[0], + .dev = { + .platform_data = &smsc911x_config, + }, +}; + static inline void __init omap3stalker_init_eth(void) { + int eth_cs; struct clk *l3ck; unsigned int rate; + eth_cs = OMAP3STALKER_SMC911X_CS; + l3ck = clk_get(NULL, "l3_ck"); if (IS_ERR(l3ck)) rate = 100000000; @@ -82,7 +107,16 @@ static inline void __init omap3stalker_init_eth(void) rate = clk_get_rate(l3ck); omap_mux_init_gpio(19, OMAP_PIN_INPUT_PULLUP); - gpmc_smsc911x_init(&smsc911x_cfg); + if (gpio_request(OMAP3STALKER_ETHR_GPIO_IRQ, "SMC911x irq") < 0) { + printk(KERN_ERR + "Failed to request GPIO%d for smc911x IRQ\n", + OMAP3STALKER_ETHR_GPIO_IRQ); + return; + } + + gpio_direction_input(OMAP3STALKER_ETHR_GPIO_IRQ); + + platform_device_register(&omap3stalker_smsc911x_device); } #else @@ -331,11 +365,12 @@ omap3stalker_twl_gpio_setup(struct device *dev, */ /* TWL4030_GPIO_MAX + 0 == ledA, LCD Backlight control */ - gpio_request_one(gpio + TWL4030_GPIO_MAX, GPIOF_OUT_INIT_LOW, - "EN_LCD_BKL"); + gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL"); + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); /* gpio + 7 == DVI Enable */ - gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "EN_DVI"); + gpio_request(gpio + 7, "EN_DVI"); + gpio_direction_output(gpio + 7, 0); /* TWL4030_GPIO_MAX + 1 == ledB (out, mmc0) */ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; @@ -454,8 +489,15 @@ static struct twl4030_platform_data omap3stalker_twldata = { .codec = &omap3stalker_codec_data, .vdac = &omap3_stalker_vdac, .vpll2 = &omap3_stalker_vpll2, - .vmmc1 = &omap3stalker_vmmc1, - .vsim = &omap3stalker_vsim, +}; + +static struct i2c_board_info __initdata omap3stalker_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &omap3stalker_twldata, + }, }; static struct at24_platform_data fram_info = { @@ -474,7 +516,15 @@ static struct i2c_board_info __initdata omap3stalker_i2c_boardinfo3[] = { static int __init omap3_stalker_i2c_init(void) { - omap3_pmic_init("twl4030", &omap3stalker_twldata); + /* + * REVISIT: These entries can be set in omap3evm_twl_data + * after a merge with MFD tree + */ + omap3stalker_twldata.vmmc1 = &omap3stalker_vmmc1; + omap3stalker_twldata.vsim = &omap3stalker_vsim; + + omap_register_i2c_bus(1, 2600, omap3stalker_i2c_boardinfo, + ARRAY_SIZE(omap3stalker_i2c_boardinfo)); omap_register_i2c_bus(2, 400, NULL, 0); omap_register_i2c_bus(3, 400, omap3stalker_i2c_boardinfo3, ARRAY_SIZE(omap3stalker_i2c_boardinfo3)); @@ -482,6 +532,49 @@ static int __init omap3_stalker_i2c_init(void) } #define OMAP3_STALKER_TS_GPIO 175 +static void ads7846_dev_init(void) +{ + if (gpio_request(OMAP3_STALKER_TS_GPIO, "ADS7846 pendown") < 0) + printk(KERN_ERR "can't get ads7846 pen down GPIO\n"); + + gpio_direction_input(OMAP3_STALKER_TS_GPIO); + gpio_set_debounce(OMAP3_STALKER_TS_GPIO, 310); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(OMAP3_STALKER_TS_GPIO); +} + +static struct ads7846_platform_data ads7846_config = { + .x_max = 0x0fff, + .y_max = 0x0fff, + .x_plate_ohms = 180, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 3, + .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, + .settle_delay_usecs = 150, +}; + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info omap3stalker_spi_board_info[] = { + [0] = { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OMAP3_STALKER_TS_GPIO), + .platform_data = &ads7846_config, + }, +}; static struct omap_board_config_kernel omap3_stalker_config[] __initdata = { }; @@ -525,6 +618,12 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + static void __init omap3_stalker_init(void) { omap3_mux_init(board_mux, OMAP_PACKAGE_CUS); @@ -537,11 +636,13 @@ static void __init omap3_stalker_init(void) ARRAY_SIZE(omap3_stalker_devices)); omap_display_init(&omap3_stalker_dss_data); + spi_register_board_info(omap3stalker_spi_board_info, + ARRAY_SIZE(omap3stalker_spi_board_info)); omap_serial_init(); - usb_musb_init(NULL); + usb_musb_init(&musb_board_data); usbhs_init(&usbhs_bdata); - omap_ads7846_init(1, OMAP3_STALKER_TS_GPIO, 310, NULL); + ads7846_dev_init(); omap_mux_init_gpio(21, OMAP_PIN_OUTPUT); omap_mux_init_gpio(18, OMAP_PIN_INPUT_PULLUP); diff --git a/trunk/arch/arm/mach-omap2/board-omap3touchbook.c b/trunk/arch/arm/mach-omap2/board-omap3touchbook.c index 82872d7d313b..127cb1752bdd 100644 --- a/trunk/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/trunk/arch/arm/mach-omap2/board-omap3touchbook.c @@ -52,7 +52,6 @@ #include "mux.h" #include "hsmmc.h" #include "timer-gp.h" -#include "common-board-devices.h" #include @@ -96,6 +95,15 @@ static struct mtd_partition omap3touchbook_nand_partitions[] = { }, }; +static struct omap_nand_platform_data omap3touchbook_nand_data = { + .options = NAND_BUSWIDTH_16, + .parts = omap3touchbook_nand_partitions, + .nr_parts = ARRAY_SIZE(omap3touchbook_nand_partitions), + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ + .nand_setup = NULL, + .dev_ready = NULL, +}; + #include "sdram-micron-mt46h32m32lf-6.h" static struct omap2_hsmmc_info mmc[] = { @@ -146,11 +154,13 @@ static int touchbook_twl_gpio_setup(struct device *dev, /* REVISIT: need ehci-omap hooks for external VBUS * power switch and overcurrent detect */ - gpio_request_one(gpio + 1, GPIOF_IN, "EHCI_nOC"); + + gpio_request(gpio + 1, "EHCI_nOC"); + gpio_direction_input(gpio + 1); /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */ - gpio_request_one(gpio + TWL4030_GPIO_MAX, GPIOF_OUT_INIT_LOW, - "nEN_USB_PWR"); + gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; @@ -263,6 +273,15 @@ static struct twl4030_platform_data touchbook_twldata = { .vpll2 = &touchbook_vpll2, }; +static struct i2c_board_info __initdata touchbook_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &touchbook_twldata, + }, +}; + static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = { { I2C_BOARD_INFO("bq27200", 0x55), @@ -272,7 +291,8 @@ static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = { static int __init omap3_touchbook_i2c_init(void) { /* Standard TouchBook bus */ - omap3_pmic_init("twl4030", &touchbook_twldata); + omap_register_i2c_bus(1, 2600, touchbook_i2c_boardinfo, + ARRAY_SIZE(touchbook_i2c_boardinfo)); /* Additional TouchBook bus */ omap_register_i2c_bus(3, 100, touchBook_i2c_boardinfo, @@ -281,7 +301,19 @@ static int __init omap3_touchbook_i2c_init(void) return 0; } -static struct ads7846_platform_data ads7846_pdata = { +static void __init omap3_ads7846_init(void) +{ + if (gpio_request(OMAP3_TS_GPIO, "ads7846_pen_down")) { + printk(KERN_ERR "Failed to request GPIO %d for " + "ads7846 pen down IRQ\n", OMAP3_TS_GPIO); + return; + } + + gpio_direction_input(OMAP3_TS_GPIO); + gpio_set_debounce(OMAP3_TS_GPIO, 310); +} + +static struct ads7846_platform_data ads7846_config = { .x_min = 100, .y_min = 265, .x_max = 3950, @@ -295,6 +327,23 @@ static struct ads7846_platform_data ads7846_pdata = { .keep_vref_on = 1, }; +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info omap3_ads7846_spi_board_info[] __initdata = { + { + .modalias = "ads7846", + .bus_num = 4, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OMAP3_TS_GPIO), + .platform_data = &ads7846_config, + } +}; + static struct gpio_led gpio_leds[] = { { .name = "touchbook::usr0", @@ -385,6 +434,39 @@ static struct platform_device *omap3_touchbook_devices[] __initdata = { &keys_gpio, }; +static void __init omap3touchbook_flash_init(void) +{ + u8 cs = 0; + u8 nandcs = GPMC_CS_NUM + 1; + + /* find out the chip-select on which NAND exists */ + while (cs < GPMC_CS_NUM) { + u32 ret = 0; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + if ((ret & 0xC00) == 0x800) { + printk(KERN_INFO "Found NAND on CS%d\n", cs); + if (nandcs > GPMC_CS_NUM) + nandcs = cs; + } + cs++; + } + + if (nandcs > GPMC_CS_NUM) { + printk(KERN_INFO "NAND: Unable to find configuration " + "in GPMC\n "); + return; + } + + if (nandcs < GPMC_CS_NUM) { + omap3touchbook_nand_data.cs = nandcs; + + printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); + if (gpmc_nand_init(&omap3touchbook_nand_data) < 0) + printk(KERN_ERR "Unable to register NAND device\n"); + } +} + static const struct usbhs_omap_board_data usbhs_bdata __initconst = { .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, @@ -399,10 +481,15 @@ static const struct usbhs_omap_board_data usbhs_bdata __initconst = { static void omap3_touchbook_poweroff(void) { - int pwr_off = TB_KILL_POWER_GPIO; + int r; - if (gpio_request_one(pwr_off, GPIOF_OUT_INIT_LOW, "DVI reset") < 0) + r = gpio_request(TB_KILL_POWER_GPIO, "DVI reset"); + if (r < 0) { printk(KERN_ERR "Unable to get kill power GPIO\n"); + return; + } + + gpio_direction_output(TB_KILL_POWER_GPIO, 0); } static int __init early_touchbook_revision(char *p) @@ -414,6 +501,12 @@ static int __init early_touchbook_revision(char *p) } early_param("tbr", early_touchbook_revision); +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + static void __init omap3_touchbook_init(void) { omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); @@ -428,15 +521,17 @@ static void __init omap3_touchbook_init(void) omap_serial_init(); omap_mux_init_gpio(170, OMAP_PIN_INPUT); + gpio_request(176, "DVI_nPD"); /* REVISIT leave DVI powered down until it's needed ... */ - gpio_request_one(176, GPIOF_OUT_INIT_HIGH, "DVI_nPD"); + gpio_direction_output(176, true); /* Touchscreen and accelerometer */ - omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata); - usb_musb_init(NULL); + spi_register_board_info(omap3_ads7846_spi_board_info, + ARRAY_SIZE(omap3_ads7846_spi_board_info)); + omap3_ads7846_init(); + usb_musb_init(&musb_board_data); usbhs_init(&usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, omap3touchbook_nand_partitions, - ARRAY_SIZE(omap3touchbook_nand_partitions)); + omap3touchbook_flash_init(); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); diff --git a/trunk/arch/arm/mach-omap2/board-omap4panda.c b/trunk/arch/arm/mach-omap2/board-omap4panda.c index 90485fced973..e4973ac77cbc 100644 --- a/trunk/arch/arm/mach-omap2/board-omap4panda.c +++ b/trunk/arch/arm/mach-omap2/board-omap4panda.c @@ -46,7 +46,6 @@ #include "hsmmc.h" #include "control.h" #include "mux.h" -#include "common-board-devices.h" #define GPIO_HUB_POWER 1 #define GPIO_HUB_NRESET 62 @@ -112,11 +111,6 @@ static const struct usbhs_omap_board_data usbhs_bdata __initconst = { .reset_gpio_port[2] = -EINVAL }; -static struct gpio panda_ehci_gpios[] __initdata = { - { GPIO_HUB_POWER, GPIOF_OUT_INIT_LOW, "hub_power" }, - { GPIO_HUB_NRESET, GPIOF_OUT_INIT_LOW, "hub_nreset" }, -}; - static void __init omap4_ehci_init(void) { int ret; @@ -126,27 +120,44 @@ static void __init omap4_ehci_init(void) phy_ref_clk = clk_get(NULL, "auxclk3_ck"); if (IS_ERR(phy_ref_clk)) { pr_err("Cannot request auxclk3\n"); - return; + goto error1; } clk_set_rate(phy_ref_clk, 19200000); clk_enable(phy_ref_clk); - /* disable the power to the usb hub prior to init and reset phy+hub */ - ret = gpio_request_array(panda_ehci_gpios, - ARRAY_SIZE(panda_ehci_gpios)); + /* disable the power to the usb hub prior to init */ + ret = gpio_request(GPIO_HUB_POWER, "hub_power"); if (ret) { - pr_err("Unable to initialize EHCI power/reset\n"); - return; + pr_err("Cannot request GPIO %d\n", GPIO_HUB_POWER); + goto error1; } - gpio_export(GPIO_HUB_POWER, 0); + gpio_direction_output(GPIO_HUB_POWER, 0); + gpio_set_value(GPIO_HUB_POWER, 0); + + /* reset phy+hub */ + ret = gpio_request(GPIO_HUB_NRESET, "hub_nreset"); + if (ret) { + pr_err("Cannot request GPIO %d\n", GPIO_HUB_NRESET); + goto error2; + } gpio_export(GPIO_HUB_NRESET, 0); + gpio_direction_output(GPIO_HUB_NRESET, 0); + gpio_set_value(GPIO_HUB_NRESET, 0); gpio_set_value(GPIO_HUB_NRESET, 1); usbhs_init(&usbhs_bdata); /* enable power to hub */ gpio_set_value(GPIO_HUB_POWER, 1); + return; + +error2: + gpio_free(GPIO_HUB_POWER); +error1: + pr_err("Unable to initialize EHCI power/reset\n"); + return; + } static struct omap_musb_board_data musb_board_data = { @@ -397,6 +408,15 @@ static struct twl4030_platform_data omap4_panda_twldata = { .usb = &omap4_usbphy_data, }; +static struct i2c_board_info __initdata omap4_panda_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl6030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = OMAP44XX_IRQ_SYS_1N, + .platform_data = &omap4_panda_twldata, + }, +}; + /* * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM * is connected as I2C slave device, and can be accessed at address 0x50 @@ -409,7 +429,12 @@ static struct i2c_board_info __initdata panda_i2c_eeprom[] = { static int __init omap4_panda_i2c_init(void) { - omap4_pmic_init("twl6030", &omap4_panda_twldata); + /* + * Phoenix Audio IC needs I2C1 to + * start with 400 KHz or less + */ + omap_register_i2c_bus(1, 400, omap4_panda_i2c_boardinfo, + ARRAY_SIZE(omap4_panda_i2c_boardinfo)); omap_register_i2c_bus(2, 400, NULL, 0); /* * Bus 3 is attached to the DVI port where devices like the pico DLP @@ -626,19 +651,27 @@ static void omap4_panda_hdmi_mux_init(void) OMAP_PIN_INPUT_PULLUP); } -static struct gpio panda_hdmi_gpios[] = { - { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" }, - { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, -}; - static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev) { int status; - status = gpio_request_array(panda_hdmi_gpios, - ARRAY_SIZE(panda_hdmi_gpios)); - if (status) - pr_err("Cannot request HDMI GPIOs\n"); + status = gpio_request_one(HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, + "hdmi_gpio_hpd"); + if (status) { + pr_err("Cannot request GPIO %d\n", HDMI_GPIO_HPD); + return status; + } + status = gpio_request_one(HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, + "hdmi_gpio_ls_oe"); + if (status) { + pr_err("Cannot request GPIO %d\n", HDMI_GPIO_LS_OE); + goto error1; + } + + return 0; + +error1: + gpio_free(HDMI_GPIO_HPD); return status; } diff --git a/trunk/arch/arm/mach-omap2/board-overo.c b/trunk/arch/arm/mach-omap2/board-overo.c index 1555918e3ffa..9d192ff3b9ac 100644 --- a/trunk/arch/arm/mach-omap2/board-overo.c +++ b/trunk/arch/arm/mach-omap2/board-overo.c @@ -56,7 +56,6 @@ #include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" -#include "common-board-devices.h" #define OVERO_GPIO_BT_XGATE 15 #define OVERO_GPIO_W2W_NRESET 16 @@ -75,6 +74,30 @@ #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) +#include + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(OVERO_GPIO_PENDOWN); +} + +static struct ads7846_platform_data ads7846_config = { + .x_max = 0x0fff, + .y_max = 0x0fff, + .x_plate_ohms = 180, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 3, + .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, +}; + /* fixed regulator for ads7846 */ static struct regulator_consumer_supply ads7846_supply = REGULATOR_SUPPLY("vcc", "spi1.0"); @@ -105,7 +128,14 @@ static struct platform_device vads7846_device = { static void __init overo_ads7846_init(void) { - omap_ads7846_init(1, OVERO_GPIO_PENDOWN, 0, NULL); + if ((gpio_request(OVERO_GPIO_PENDOWN, "ADS7846_PENDOWN") == 0) && + (gpio_direction_input(OVERO_GPIO_PENDOWN) == 0)) { + gpio_export(OVERO_GPIO_PENDOWN, 0); + } else { + printk(KERN_ERR "could not obtain gpio for ADS7846_PENDOWN\n"); + return; + } + platform_device_register(&vads7846_device); } @@ -116,28 +146,106 @@ static inline void __init overo_ads7846_init(void) { return; } #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include -#include -static struct omap_smsc911x_platform_data smsc911x_cfg = { +static struct resource overo_smsc911x_resources[] = { + { + .name = "smsc911x-memory", + .flags = IORESOURCE_MEM, + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, +}; + +static struct resource overo_smsc911x2_resources[] = { + { + .name = "smsc911x2-memory", + .flags = IORESOURCE_MEM, + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, +}; + +static struct smsc911x_platform_config overo_smsc911x_config = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, + .flags = SMSC911X_USE_32BIT , + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct platform_device overo_smsc911x_device = { + .name = "smsc911x", .id = 0, - .cs = OVERO_SMSC911X_CS, - .gpio_irq = OVERO_SMSC911X_GPIO, - .gpio_reset = -EINVAL, - .flags = SMSC911X_USE_32BIT, + .num_resources = ARRAY_SIZE(overo_smsc911x_resources), + .resource = overo_smsc911x_resources, + .dev = { + .platform_data = &overo_smsc911x_config, + }, }; -static struct omap_smsc911x_platform_data smsc911x2_cfg = { +static struct platform_device overo_smsc911x2_device = { + .name = "smsc911x", .id = 1, - .cs = OVERO_SMSC911X2_CS, - .gpio_irq = OVERO_SMSC911X2_GPIO, - .gpio_reset = -EINVAL, - .flags = SMSC911X_USE_32BIT, + .num_resources = ARRAY_SIZE(overo_smsc911x2_resources), + .resource = overo_smsc911x2_resources, + .dev = { + .platform_data = &overo_smsc911x_config, + }, }; -static void __init overo_init_smsc911x(void) +static struct platform_device *smsc911x_devices[] = { + &overo_smsc911x_device, + &overo_smsc911x2_device, +}; + +static inline void __init overo_init_smsc911x(void) { - gpmc_smsc911x_init(&smsc911x_cfg); - gpmc_smsc911x_init(&smsc911x2_cfg); + unsigned long cs_mem_base, cs_mem_base2; + + /* set up first smsc911x chip */ + + if (gpmc_cs_request(OVERO_SMSC911X_CS, SZ_16M, &cs_mem_base) < 0) { + printk(KERN_ERR "Failed request for GPMC mem for smsc911x\n"); + return; + } + + overo_smsc911x_resources[0].start = cs_mem_base + 0x0; + overo_smsc911x_resources[0].end = cs_mem_base + 0xff; + + if ((gpio_request(OVERO_SMSC911X_GPIO, "SMSC911X IRQ") == 0) && + (gpio_direction_input(OVERO_SMSC911X_GPIO) == 0)) { + gpio_export(OVERO_SMSC911X_GPIO, 0); + } else { + printk(KERN_ERR "could not obtain gpio for SMSC911X IRQ\n"); + return; + } + + overo_smsc911x_resources[1].start = OMAP_GPIO_IRQ(OVERO_SMSC911X_GPIO); + overo_smsc911x_resources[1].end = 0; + + /* set up second smsc911x chip */ + + if (gpmc_cs_request(OVERO_SMSC911X2_CS, SZ_16M, &cs_mem_base2) < 0) { + printk(KERN_ERR "Failed request for GPMC mem for smsc911x2\n"); + return; + } + + overo_smsc911x2_resources[0].start = cs_mem_base2 + 0x0; + overo_smsc911x2_resources[0].end = cs_mem_base2 + 0xff; + + if ((gpio_request(OVERO_SMSC911X2_GPIO, "SMSC911X2 IRQ") == 0) && + (gpio_direction_input(OVERO_SMSC911X2_GPIO) == 0)) { + gpio_export(OVERO_SMSC911X2_GPIO, 0); + } else { + printk(KERN_ERR "could not obtain gpio for SMSC911X2 IRQ\n"); + return; + } + + overo_smsc911x2_resources[1].start = OMAP_GPIO_IRQ(OVERO_SMSC911X2_GPIO); + overo_smsc911x2_resources[1].end = 0; + + platform_add_devices(smsc911x_devices, ARRAY_SIZE(smsc911x_devices)); } #else @@ -151,20 +259,21 @@ static int dvi_enabled; #define OVERO_GPIO_LCD_EN 144 #define OVERO_GPIO_LCD_BL 145 -static struct gpio overo_dss_gpios[] __initdata = { - { OVERO_GPIO_LCD_EN, GPIOF_OUT_INIT_HIGH, "OVERO_GPIO_LCD_EN" }, - { OVERO_GPIO_LCD_BL, GPIOF_OUT_INIT_HIGH, "OVERO_GPIO_LCD_BL" }, -}; - static void __init overo_display_init(void) { - if (gpio_request_array(overo_dss_gpios, ARRAY_SIZE(overo_dss_gpios))) { - printk(KERN_ERR "could not obtain DSS control GPIOs\n"); - return; - } + if ((gpio_request(OVERO_GPIO_LCD_EN, "OVERO_GPIO_LCD_EN") == 0) && + (gpio_direction_output(OVERO_GPIO_LCD_EN, 1) == 0)) + gpio_export(OVERO_GPIO_LCD_EN, 0); + else + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_LCD_EN\n"); - gpio_export(OVERO_GPIO_LCD_EN, 0); - gpio_export(OVERO_GPIO_LCD_BL, 0); + if ((gpio_request(OVERO_GPIO_LCD_BL, "OVERO_GPIO_LCD_BL") == 0) && + (gpio_direction_output(OVERO_GPIO_LCD_BL, 1) == 0)) + gpio_export(OVERO_GPIO_LCD_BL, 0); + else + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_LCD_BL\n"); } static int overo_panel_enable_dvi(struct omap_dss_device *dssdev) @@ -303,6 +412,45 @@ static struct mtd_partition overo_nand_partitions[] = { }, }; +static struct omap_nand_platform_data overo_nand_data = { + .parts = overo_nand_partitions, + .nr_parts = ARRAY_SIZE(overo_nand_partitions), + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ +}; + +static void __init overo_flash_init(void) +{ + u8 cs = 0; + u8 nandcs = GPMC_CS_NUM + 1; + + /* find out the chip-select on which NAND exists */ + while (cs < GPMC_CS_NUM) { + u32 ret = 0; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + if ((ret & 0xC00) == 0x800) { + printk(KERN_INFO "Found NAND on CS%d\n", cs); + if (nandcs > GPMC_CS_NUM) + nandcs = cs; + } + cs++; + } + + if (nandcs > GPMC_CS_NUM) { + printk(KERN_INFO "NAND: Unable to find configuration " + "in GPMC\n "); + return; + } + + if (nandcs < GPMC_CS_NUM) { + overo_nand_data.cs = nandcs; + + printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); + if (gpmc_nand_init(&overo_nand_data) < 0) + printk(KERN_ERR "Unable to register NAND device\n"); + } +} + static struct omap2_hsmmc_info mmc[] = { { .mmc = 1, @@ -500,15 +648,37 @@ static struct twl4030_platform_data overo_twldata = { .vpll2 = &overo_vpll2, }; +static struct i2c_board_info __initdata overo_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("tps65950", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &overo_twldata, + }, +}; + static int __init overo_i2c_init(void) { - omap3_pmic_init("tps65950", &overo_twldata); + omap_register_i2c_bus(1, 2600, overo_i2c_boardinfo, + ARRAY_SIZE(overo_i2c_boardinfo)); /* i2c2 pins are used for gpio */ omap_register_i2c_bus(3, 400, NULL, 0); return 0; } static struct spi_board_info overo_spi_board_info[] __initdata = { +#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ + defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) + { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN), + .platform_data = &ads7846_config, + }, +#endif #if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \ defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE) { @@ -552,22 +722,20 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif -static struct gpio overo_bt_gpios[] __initdata = { - { OVERO_GPIO_BT_XGATE, GPIOF_OUT_INIT_LOW, "lcd enable" }, - { OVERO_GPIO_BT_NRESET, GPIOF_OUT_INIT_HIGH, "lcd bl enable" }, +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, }; static void __init overo_init(void) { - int ret; - omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); overo_i2c_init(); omap_display_init(&overo_dss_data); omap_serial_init(); - omap_nand_flash_init(0, overo_nand_partitions, - ARRAY_SIZE(overo_nand_partitions)); - usb_musb_init(NULL); + overo_flash_init(); + usb_musb_init(&musb_board_data); usbhs_init(&usbhs_bdata); overo_spi_init(); overo_ads7846_init(); @@ -580,9 +748,9 @@ static void __init overo_init(void) omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); - ret = gpio_request_one(OVERO_GPIO_W2W_NRESET, GPIOF_OUT_INIT_HIGH, - "OVERO_GPIO_W2W_NRESET"); - if (ret == 0) { + if ((gpio_request(OVERO_GPIO_W2W_NRESET, + "OVERO_GPIO_W2W_NRESET") == 0) && + (gpio_direction_output(OVERO_GPIO_W2W_NRESET, 1) == 0)) { gpio_export(OVERO_GPIO_W2W_NRESET, 0); gpio_set_value(OVERO_GPIO_W2W_NRESET, 0); udelay(10); @@ -592,20 +760,25 @@ static void __init overo_init(void) "OVERO_GPIO_W2W_NRESET\n"); } - ret = gpio_request_array(overo_bt_gpios, ARRAY_SIZE(overo_bt_gpios)); - if (ret) { - pr_err("%s: could not obtain BT gpios\n", __func__); - } else { + if ((gpio_request(OVERO_GPIO_BT_XGATE, "OVERO_GPIO_BT_XGATE") == 0) && + (gpio_direction_output(OVERO_GPIO_BT_XGATE, 0) == 0)) gpio_export(OVERO_GPIO_BT_XGATE, 0); + else + printk(KERN_ERR "could not obtain gpio for OVERO_GPIO_BT_XGATE\n"); + + if ((gpio_request(OVERO_GPIO_BT_NRESET, "OVERO_GPIO_BT_NRESET") == 0) && + (gpio_direction_output(OVERO_GPIO_BT_NRESET, 1) == 0)) { gpio_export(OVERO_GPIO_BT_NRESET, 0); gpio_set_value(OVERO_GPIO_BT_NRESET, 0); mdelay(6); gpio_set_value(OVERO_GPIO_BT_NRESET, 1); + } else { + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_BT_NRESET\n"); } - ret = gpio_request_one(OVERO_GPIO_USBH_CPEN, GPIOF_OUT_INIT_HIGH, - "OVERO_GPIO_USBH_CPEN"); - if (ret == 0) + if ((gpio_request(OVERO_GPIO_USBH_CPEN, "OVERO_GPIO_USBH_CPEN") == 0) && + (gpio_direction_output(OVERO_GPIO_USBH_CPEN, 1) == 0)) gpio_export(OVERO_GPIO_USBH_CPEN, 0); else printk(KERN_ERR "could not obtain gpio for " diff --git a/trunk/arch/arm/mach-omap2/board-rm680.c b/trunk/arch/arm/mach-omap2/board-rm680.c index 42d10b12da3c..2af8b05e786d 100644 --- a/trunk/arch/arm/mach-omap2/board-rm680.c +++ b/trunk/arch/arm/mach-omap2/board-rm680.c @@ -31,7 +31,6 @@ #include "mux.h" #include "hsmmc.h" #include "sdram-nokia.h" -#include "common-board-devices.h" static struct regulator_consumer_supply rm680_vemmc_consumers[] = { REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"), @@ -91,9 +90,19 @@ static struct twl4030_platform_data rm680_twl_data = { /* add rest of the children here */ }; +static struct i2c_board_info __initdata rm680_twl_i2c_board_info[] = { + { + I2C_BOARD_INFO("twl5031", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &rm680_twl_data, + }, +}; + static void __init rm680_i2c_init(void) { - omap_pmic_init(1, 2900, "twl5031", INT_34XX_SYS_NIRQ, &rm680_twl_data); + omap_register_i2c_bus(1, 2900, rm680_twl_i2c_board_info, + ARRAY_SIZE(rm680_twl_i2c_board_info)); omap_register_i2c_bus(2, 400, NULL, 0); omap_register_i2c_bus(3, 400, NULL, 0); } @@ -144,11 +153,17 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif +static struct omap_musb_board_data rm680_musb_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_PERIPHERAL, + .power = 100, +}; + static void __init rm680_init(void) { omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap_serial_init(); - usb_musb_init(NULL); + usb_musb_init(&rm680_musb_data); rm680_peripherals_init(); } diff --git a/trunk/arch/arm/mach-omap2/board-rx51-peripherals.c b/trunk/arch/arm/mach-omap2/board-rx51-peripherals.c index f6247e71a194..bbcb6775a6a3 100644 --- a/trunk/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/trunk/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -44,7 +43,6 @@ #include "mux.h" #include "hsmmc.h" -#include "common-board-devices.h" #define SYSTEM_REV_B_USES_VAUX3 0x1699 #define SYSTEM_REV_S_USES_VAUX3 0x8 @@ -54,8 +52,6 @@ #define RX51_FMTX_RESET_GPIO 163 #define RX51_FMTX_IRQ 53 -#define RX51_USB_TRANSCEIVER_RST_GPIO 67 - /* list all spi devices here */ enum { RX51_SPI_WL1251, @@ -114,30 +110,10 @@ static struct spi_board_info rx51_peripherals_spi_board_info[] __initdata = { }, }; -static void rx51_charger_set_power(bool on) -{ - gpio_set_value(RX51_USB_TRANSCEIVER_RST_GPIO, on); -} - -static struct isp1704_charger_data rx51_charger_data = { - .set_power = rx51_charger_set_power, -}; - static struct platform_device rx51_charger_device = { - .name = "isp1704_charger", - .dev = { - .platform_data = &rx51_charger_data, - }, + .name = "isp1704_charger", }; -static void __init rx51_charger_init(void) -{ - WARN_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO, - GPIOF_OUT_INIT_LOW, "isp1704_reset")); - - platform_device_register(&rx51_charger_device); -} - #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) #define RX51_GPIO_CAMERA_LENS_COVER 110 @@ -581,8 +557,10 @@ static __init void rx51_init_si4713(void) static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n) { /* FIXME this gpio setup is just a placeholder for now */ - gpio_request_one(gpio + 6, GPIOF_OUT_INIT_LOW, "backlight_pwm"); - gpio_request_one(gpio + 7, GPIOF_OUT_INIT_HIGH, "speaker_en"); + gpio_request(gpio + 6, "backlight_pwm"); + gpio_direction_output(gpio + 6, 0); + gpio_request(gpio + 7, "speaker_en"); + gpio_direction_output(gpio + 7, 1); return 0; } @@ -752,7 +730,7 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = { { .resource = RES_RESET, .devgroup = -1, .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 }, - { .resource = RES_MAIN_REF, .devgroup = -1, + { .resource = RES_Main_Ref, .devgroup = -1, .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 }, { 0, 0}, @@ -799,6 +777,15 @@ static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata_or_module = .power_gpio = 98, }; +static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_1[] = { + { + I2C_BOARD_INFO("twl5030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &rx51_twldata, + }, +}; + /* Audio setup data */ static struct aic3x_setup_data rx51_aic34_setup = { .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, @@ -846,7 +833,8 @@ static int __init rx51_i2c_init(void) rx51_twldata.vaux3 = &rx51_vaux3_cam; } rx51_twldata.vmmc2 = &rx51_vmmc2; - omap_pmic_init(1, 2200, "twl5030", INT_34XX_SYS_NIRQ, &rx51_twldata); + omap_register_i2c_bus(1, 2200, rx51_peripherals_i2c_board_info_1, + ARRAY_SIZE(rx51_peripherals_i2c_board_info_1)); omap_register_i2c_bus(2, 100, rx51_peripherals_i2c_board_info_2, ARRAY_SIZE(rx51_peripherals_i2c_board_info_2)); omap_register_i2c_bus(3, 400, NULL, 0); @@ -933,20 +921,26 @@ static void rx51_wl1251_set_power(bool enable) gpio_set_value(RX51_WL1251_POWER_GPIO, enable); } -static struct gpio rx51_wl1251_gpios[] __initdata = { - { RX51_WL1251_POWER_GPIO, GPIOF_OUT_INIT_LOW, "wl1251 power" }, - { RX51_WL1251_IRQ_GPIO, GPIOF_IN, "wl1251 irq" }, -}; - static void __init rx51_init_wl1251(void) { int irq, ret; - ret = gpio_request_array(rx51_wl1251_gpios, - ARRAY_SIZE(rx51_wl1251_gpios)); + ret = gpio_request(RX51_WL1251_POWER_GPIO, "wl1251 power"); if (ret < 0) goto error; + ret = gpio_direction_output(RX51_WL1251_POWER_GPIO, 0); + if (ret < 0) + goto err_power; + + ret = gpio_request(RX51_WL1251_IRQ_GPIO, "wl1251 irq"); + if (ret < 0) + goto err_power; + + ret = gpio_direction_input(RX51_WL1251_IRQ_GPIO); + if (ret < 0) + goto err_irq; + irq = gpio_to_irq(RX51_WL1251_IRQ_GPIO); if (irq < 0) goto err_irq; @@ -958,7 +952,10 @@ static void __init rx51_init_wl1251(void) err_irq: gpio_free(RX51_WL1251_IRQ_GPIO); + +err_power: gpio_free(RX51_WL1251_POWER_GPIO); + error: printk(KERN_ERR "wl1251 board initialisation failed\n"); wl1251_pdata.set_power = NULL; @@ -984,6 +981,6 @@ void __init rx51_peripherals_init(void) if (partition) omap2_hsmmc_init(mmc); - rx51_charger_init(); + platform_device_register(&rx51_charger_device); } diff --git a/trunk/arch/arm/mach-omap2/board-rx51-video.c b/trunk/arch/arm/mach-omap2/board-rx51-video.c index 2c1289bd5e6a..2df10b6a5940 100644 --- a/trunk/arch/arm/mach-omap2/board-rx51-video.c +++ b/trunk/arch/arm/mach-omap2/board-rx51-video.c @@ -76,12 +76,13 @@ static int __init rx51_video_init(void) return 0; } - if (gpio_request_one(RX51_LCD_RESET_GPIO, GPIOF_OUT_INIT_HIGH, - "LCD ACX565AKM reset")) { + if (gpio_request(RX51_LCD_RESET_GPIO, "LCD ACX565AKM reset")) { pr_err("%s failed to get LCD Reset GPIO\n", __func__); return 0; } + gpio_direction_output(RX51_LCD_RESET_GPIO, 1); + omap_display_init(&rx51_dss_board_info); return 0; } diff --git a/trunk/arch/arm/mach-omap2/board-rx51.c b/trunk/arch/arm/mach-omap2/board-rx51.c index fec4cac8fa0a..f8ba20a14e62 100644 --- a/trunk/arch/arm/mach-omap2/board-rx51.c +++ b/trunk/arch/arm/mach-omap2/board-rx51.c @@ -58,25 +58,21 @@ static struct platform_device leds_gpio = { }, }; -/* - * cpuidle C-states definition override from the default values. - * The 'exit_latency' field is the sum of sleep and wake-up latencies. - */ static struct cpuidle_params rx51_cpuidle_params[] = { /* C1 */ - {110 + 162, 5 , 1}, + {1, 110, 162, 5}, /* C2 */ - {106 + 180, 309, 1}, + {1, 106, 180, 309}, /* C3 */ - {107 + 410, 46057, 0}, + {0, 107, 410, 46057}, /* C4 */ - {121 + 3374, 46057, 0}, + {0, 121, 3374, 46057}, /* C5 */ - {855 + 1146, 46057, 1}, + {1, 855, 1146, 46057}, /* C6 */ - {7580 + 4134, 484329, 0}, + {0, 7580, 4134, 484329}, /* C7 */ - {7505 + 15274, 484329, 1}, + {1, 7505, 15274, 484329}, }; static struct omap_lcd_config rx51_lcd_config = { diff --git a/trunk/arch/arm/mach-omap2/board-zoom-debugboard.c b/trunk/arch/arm/mach-omap2/board-zoom-debugboard.c index 6402e781c458..007ebdc6c993 100644 --- a/trunk/arch/arm/mach-omap2/board-zoom-debugboard.c +++ b/trunk/arch/arm/mach-omap2/board-zoom-debugboard.c @@ -15,7 +15,6 @@ #include #include -#include #include @@ -27,16 +26,60 @@ #define DEBUG_BASE 0x08000000 #define ZOOM_ETHR_START DEBUG_BASE -static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = { - .cs = ZOOM_SMSC911X_CS, - .gpio_irq = ZOOM_SMSC911X_GPIO, - .gpio_reset = -EINVAL, +static struct resource zoom_smsc911x_resources[] = { + [0] = { + .start = ZOOM_ETHR_START, + .end = ZOOM_ETHR_START + SZ_4K, + .flags = IORESOURCE_MEM, + }, + [1] = { + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, +}; + +static struct smsc911x_platform_config zoom_smsc911x_config = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, .flags = SMSC911X_USE_32BIT, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct platform_device zoom_smsc911x_device = { + .name = "smsc911x", + .id = -1, + .num_resources = ARRAY_SIZE(zoom_smsc911x_resources), + .resource = zoom_smsc911x_resources, + .dev = { + .platform_data = &zoom_smsc911x_config, + }, }; static inline void __init zoom_init_smsc911x(void) { - gpmc_smsc911x_init(&zoom_smsc911x_cfg); + int eth_cs; + unsigned long cs_mem_base; + int eth_gpio = 0; + + eth_cs = ZOOM_SMSC911X_CS; + + if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) { + printk(KERN_ERR "Failed to request GPMC mem for smsc911x\n"); + return; + } + + zoom_smsc911x_resources[0].start = cs_mem_base + 0x0; + zoom_smsc911x_resources[0].end = cs_mem_base + 0xff; + + eth_gpio = ZOOM_SMSC911X_GPIO; + + zoom_smsc911x_resources[1].start = OMAP_GPIO_IRQ(eth_gpio); + + if (gpio_request(eth_gpio, "smsc911x irq") < 0) { + printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n", + eth_gpio); + return; + } + gpio_direction_input(eth_gpio); } static struct plat_serial8250_port serial_platform_data[] = { @@ -77,9 +120,12 @@ static inline void __init zoom_init_quaduart(void) quart_gpio = ZOOM_QUADUART_GPIO; - if (gpio_request_one(quart_gpio, GPIOF_IN, "TL16CP754C GPIO") < 0) + if (gpio_request(quart_gpio, "TL16CP754C GPIO") < 0) { printk(KERN_ERR "Failed to request GPIO%d for TL16CP754C\n", quart_gpio); + return; + } + gpio_direction_input(quart_gpio); } static inline int omap_zoom_debugboard_detect(void) @@ -89,12 +135,12 @@ static inline int omap_zoom_debugboard_detect(void) debug_board_detect = ZOOM_SMSC911X_GPIO; - if (gpio_request_one(debug_board_detect, GPIOF_IN, - "Zoom debug board detect") < 0) { + if (gpio_request(debug_board_detect, "Zoom debug board detect") < 0) { printk(KERN_ERR "Failed to request GPIO%d for Zoom debug" "board detect\n", debug_board_detect); return 0; } + gpio_direction_input(debug_board_detect); if (!gpio_get_value(debug_board_detect)) { ret = 0; @@ -104,6 +150,7 @@ static inline int omap_zoom_debugboard_detect(void) } static struct platform_device *zoom_devices[] __initdata = { + &zoom_smsc911x_device, &zoom_debugboard_serial_device, }; diff --git a/trunk/arch/arm/mach-omap2/board-zoom-display.c b/trunk/arch/arm/mach-omap2/board-zoom-display.c index c7c6beb1ec24..60e8645db59d 100644 --- a/trunk/arch/arm/mach-omap2/board-zoom-display.c +++ b/trunk/arch/arm/mach-omap2/board-zoom-display.c @@ -21,19 +21,34 @@ #define LCD_PANEL_RESET_GPIO_PILOT 55 #define LCD_PANEL_QVGA_GPIO 56 -static struct gpio zoom_lcd_gpios[] __initdata = { - { -EINVAL, GPIOF_OUT_INIT_HIGH, "lcd reset" }, - { LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "lcd qvga" }, -}; - static void zoom_lcd_panel_init(void) { - zoom_lcd_gpios[0].gpio = (omap_rev() > OMAP3430_REV_ES3_0) ? + int ret; + unsigned char lcd_panel_reset_gpio; + + lcd_panel_reset_gpio = (omap_rev() > OMAP3430_REV_ES3_0) ? LCD_PANEL_RESET_GPIO_PROD : LCD_PANEL_RESET_GPIO_PILOT; - if (gpio_request_array(zoom_lcd_gpios, ARRAY_SIZE(zoom_lcd_gpios))) - pr_err("%s: Failed to get LCD GPIOs.\n", __func__); + ret = gpio_request(lcd_panel_reset_gpio, "lcd reset"); + if (ret) { + pr_err("Failed to get LCD reset GPIO (gpio%d).\n", + lcd_panel_reset_gpio); + return; + } + gpio_direction_output(lcd_panel_reset_gpio, 1); + + ret = gpio_request(LCD_PANEL_QVGA_GPIO, "lcd qvga"); + if (ret) { + pr_err("Failed to get LCD_PANEL_QVGA_GPIO (gpio%d).\n", + LCD_PANEL_QVGA_GPIO); + goto err0; + } + gpio_direction_output(LCD_PANEL_QVGA_GPIO, 1); + + return; +err0: + gpio_free(lcd_panel_reset_gpio); } static int zoom_panel_enable_lcd(struct omap_dss_device *dssdev) diff --git a/trunk/arch/arm/mach-omap2/board-zoom-peripherals.c b/trunk/arch/arm/mach-omap2/board-zoom-peripherals.c index 118c6f53c5eb..8dee7549fbdf 100644 --- a/trunk/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/trunk/arch/arm/mach-omap2/board-zoom-peripherals.c @@ -31,7 +31,6 @@ #include "mux.h" #include "hsmmc.h" -#include "common-board-devices.h" #define OMAP_ZOOM_WLAN_PMENA_GPIO (101) #define OMAP_ZOOM_WLAN_IRQ_GPIO (162) @@ -277,11 +276,13 @@ static int zoom_twl_gpio_setup(struct device *dev, zoom_vsim_supply.dev = mmc[0].dev; zoom_vmmc2_supply.dev = mmc[1].dev; - ret = gpio_request_one(LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW, - "lcd enable"); - if (ret) + ret = gpio_request(LCD_PANEL_ENABLE_GPIO, "lcd enable"); + if (ret) { pr_err("Failed to get LCD_PANEL_ENABLE_GPIO (gpio%d).\n", LCD_PANEL_ENABLE_GPIO); + return ret; + } + gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0); return ret; } @@ -348,6 +349,15 @@ static struct twl4030_platform_data zoom_twldata = { .vdac = &zoom_vdac, }; +static struct i2c_board_info __initdata zoom_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl5030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &zoom_twldata, + }, +}; + static int __init omap_i2c_init(void) { if (machine_is_omap_zoom2()) { @@ -355,12 +365,19 @@ static int __init omap_i2c_init(void) zoom_audio_data.hs_extmute = 1; zoom_audio_data.set_hs_extmute = zoom2_set_hs_extmute; } - omap_pmic_init(1, 2400, "twl5030", INT_34XX_SYS_NIRQ, &zoom_twldata); + omap_register_i2c_bus(1, 2400, zoom_i2c_boardinfo, + ARRAY_SIZE(zoom_i2c_boardinfo)); omap_register_i2c_bus(2, 400, NULL, 0); omap_register_i2c_bus(3, 400, NULL, 0); return 0; } +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 100, +}; + static void enable_board_wakeup_source(void) { /* T2 interrupt line (keypad) */ @@ -375,7 +392,7 @@ void __init zoom_peripherals_init(void) omap_i2c_init(); platform_device_register(&omap_vwlan_device); - usb_musb_init(NULL); + usb_musb_init(&musb_board_data); enable_board_wakeup_source(); omap_serial_init(); } diff --git a/trunk/arch/arm/mach-omap2/common-board-devices.c b/trunk/arch/arm/mach-omap2/common-board-devices.c deleted file mode 100644 index e94903b2c65b..000000000000 --- a/trunk/arch/arm/mach-omap2/common-board-devices.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * common-board-devices.c - * - * Copyright (C) 2011 CompuLab, Ltd. - * Author: Mike Rapoport - * - * 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 in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include "common-board-devices.h" - -static struct i2c_board_info __initdata pmic_i2c_board_info = { - .addr = 0x48, - .flags = I2C_CLIENT_WAKE, -}; - -void __init omap_pmic_init(int bus, u32 clkrate, - const char *pmic_type, int pmic_irq, - struct twl4030_platform_data *pmic_data) -{ - strncpy(pmic_i2c_board_info.type, pmic_type, - sizeof(pmic_i2c_board_info.type)); - pmic_i2c_board_info.irq = pmic_irq; - pmic_i2c_board_info.platform_data = pmic_data; - - omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1); -} - -#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ - defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) -static struct omap2_mcspi_device_config ads7846_mcspi_config = { - .turbo_mode = 0, - .single_channel = 1, /* 0: slave, 1: master */ -}; - -static struct ads7846_platform_data ads7846_config = { - .x_max = 0x0fff, - .y_max = 0x0fff, - .x_plate_ohms = 180, - .pressure_max = 255, - .debounce_max = 10, - .debounce_tol = 3, - .debounce_rep = 1, - .gpio_pendown = -EINVAL, - .keep_vref_on = 1, -}; - -static struct spi_board_info ads7846_spi_board_info __initdata = { - .modalias = "ads7846", - .bus_num = -EINVAL, - .chip_select = 0, - .max_speed_hz = 1500000, - .controller_data = &ads7846_mcspi_config, - .irq = -EINVAL, - .platform_data = &ads7846_config, -}; - -void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, - struct ads7846_platform_data *board_pdata) -{ - struct spi_board_info *spi_bi = &ads7846_spi_board_info; - int err; - - err = gpio_request(gpio_pendown, "TS PenDown"); - if (err) { - pr_err("Could not obtain gpio for TS PenDown: %d\n", err); - return; - } - - gpio_direction_input(gpio_pendown); - gpio_export(gpio_pendown, 0); - - if (gpio_debounce) - gpio_set_debounce(gpio_pendown, gpio_debounce); - - ads7846_config.gpio_pendown = gpio_pendown; - - spi_bi->bus_num = bus_num; - spi_bi->irq = OMAP_GPIO_IRQ(gpio_pendown); - - if (board_pdata) - spi_bi->platform_data = board_pdata; - - spi_register_board_info(&ads7846_spi_board_info, 1); -} -#else -void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, - struct ads7846_platform_data *board_pdata) -{ -} -#endif - -#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) -static struct omap_nand_platform_data nand_data = { - .dma_channel = -1, /* disable DMA in OMAP NAND driver */ -}; - -void __init omap_nand_flash_init(int options, struct mtd_partition *parts, - int nr_parts) -{ - u8 cs = 0; - u8 nandcs = GPMC_CS_NUM + 1; - - /* find out the chip-select on which NAND exists */ - while (cs < GPMC_CS_NUM) { - u32 ret = 0; - ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); - - if ((ret & 0xC00) == 0x800) { - printk(KERN_INFO "Found NAND on CS%d\n", cs); - if (nandcs > GPMC_CS_NUM) - nandcs = cs; - } - cs++; - } - - if (nandcs > GPMC_CS_NUM) { - printk(KERN_INFO "NAND: Unable to find configuration " - "in GPMC\n "); - return; - } - - if (nandcs < GPMC_CS_NUM) { - nand_data.cs = nandcs; - nand_data.parts = parts; - nand_data.nr_parts = nr_parts; - nand_data.options = options; - - printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (gpmc_nand_init(&nand_data) < 0) - printk(KERN_ERR "Unable to register NAND device\n"); - } -} -#else -void __init omap_nand_flash_init(int options, struct mtd_partition *parts, - int nr_parts) -{ -} -#endif diff --git a/trunk/arch/arm/mach-omap2/common-board-devices.h b/trunk/arch/arm/mach-omap2/common-board-devices.h deleted file mode 100644 index eb80b3b0ef47..000000000000 --- a/trunk/arch/arm/mach-omap2/common-board-devices.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __OMAP_COMMON_BOARD_DEVICES__ -#define __OMAP_COMMON_BOARD_DEVICES__ - -struct twl4030_platform_data; -struct mtd_partition; - -void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq, - struct twl4030_platform_data *pmic_data); - -static inline void omap2_pmic_init(const char *pmic_type, - struct twl4030_platform_data *pmic_data) -{ - omap_pmic_init(2, 2600, pmic_type, INT_24XX_SYS_NIRQ, pmic_data); -} - -static inline void omap3_pmic_init(const char *pmic_type, - struct twl4030_platform_data *pmic_data) -{ - omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data); -} - -static inline void omap4_pmic_init(const char *pmic_type, - struct twl4030_platform_data *pmic_data) -{ - /* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */ - omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data); -} - -struct ads7846_platform_data; - -void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, - struct ads7846_platform_data *board_pdata); -void omap_nand_flash_init(int opts, struct mtd_partition *parts, int n_parts); - -#endif /* __OMAP_COMMON_BOARD_DEVICES__ */ diff --git a/trunk/arch/arm/mach-omap2/cpuidle34xx.c b/trunk/arch/arm/mach-omap2/cpuidle34xx.c index 4bf6e6e8b100..1c240eff3918 100644 --- a/trunk/arch/arm/mach-omap2/cpuidle34xx.c +++ b/trunk/arch/arm/mach-omap2/cpuidle34xx.c @@ -36,6 +36,36 @@ #ifdef CONFIG_CPU_IDLE +#define OMAP3_MAX_STATES 7 +#define OMAP3_STATE_C1 0 /* C1 - MPU WFI + Core active */ +#define OMAP3_STATE_C2 1 /* C2 - MPU WFI + Core inactive */ +#define OMAP3_STATE_C3 2 /* C3 - MPU CSWR + Core inactive */ +#define OMAP3_STATE_C4 3 /* C4 - MPU OFF + Core iactive */ +#define OMAP3_STATE_C5 4 /* C5 - MPU RET + Core RET */ +#define OMAP3_STATE_C6 5 /* C6 - MPU OFF + Core RET */ +#define OMAP3_STATE_C7 6 /* C7 - MPU OFF + Core OFF */ + +#define OMAP3_STATE_MAX OMAP3_STATE_C7 + +#define CPUIDLE_FLAG_CHECK_BM 0x10000 /* use omap3_enter_idle_bm() */ + +struct omap3_processor_cx { + u8 valid; + u8 type; + u32 sleep_latency; + u32 wakeup_latency; + u32 mpu_state; + u32 core_state; + u32 threshold; + u32 flags; + const char *desc; +}; + +struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES]; +struct omap3_processor_cx current_cx_state; +struct powerdomain *mpu_pd, *core_pd, *per_pd; +struct powerdomain *cam_pd; + /* * The latencies/thresholds for various C states have * to be configured from the respective board files. @@ -45,31 +75,27 @@ */ static struct cpuidle_params cpuidle_params_table[] = { /* C1 */ - {2 + 2, 5, 1}, + {1, 2, 2, 5}, /* C2 */ - {10 + 10, 30, 1}, + {1, 10, 10, 30}, /* C3 */ - {50 + 50, 300, 1}, + {1, 50, 50, 300}, /* C4 */ - {1500 + 1800, 4000, 1}, + {1, 1500, 1800, 4000}, /* C5 */ - {2500 + 7500, 12000, 1}, + {1, 2500, 7500, 12000}, /* C6 */ - {3000 + 8500, 15000, 1}, + {1, 3000, 8500, 15000}, /* C7 */ - {10000 + 30000, 300000, 1}, -}; -#define OMAP3_NUM_STATES ARRAY_SIZE(cpuidle_params_table) - -/* Mach specific information to be recorded in the C-state driver_data */ -struct omap3_idle_statedata { - u32 mpu_state; - u32 core_state; - u8 valid; + {1, 10000, 30000, 300000}, }; -struct omap3_idle_statedata omap3_idle_data[OMAP3_NUM_STATES]; -struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; +static int omap3_idle_bm_check(void) +{ + if (!omap3_can_sleep()) + return 1; + return 0; +} static int _cpuidle_allow_idle(struct powerdomain *pwrdm, struct clockdomain *clkdm) @@ -96,10 +122,12 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm, static int omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) { - struct omap3_idle_statedata *cx = cpuidle_get_statedata(state); + struct omap3_processor_cx *cx = cpuidle_get_statedata(state); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state = cx->mpu_state, core_state = cx->core_state; + current_cx_state = *cx; + /* Used to keep track of the total time in idle */ getnstimeofday(&ts_preidle); @@ -112,8 +140,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, if (omap_irq_pending() || need_resched()) goto return_sleep_time; - /* Deny idle for C1 */ - if (state == &dev->states[0]) { + if (cx->type == OMAP3_STATE_C1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); } @@ -121,8 +148,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, /* Execute ARM wfi */ omap_sram_idle(); - /* Re-allow idle for C1 */ - if (state == &dev->states[0]) { + if (cx->type == OMAP3_STATE_C1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); } @@ -138,53 +164,41 @@ static int omap3_enter_idle(struct cpuidle_device *dev, } /** - * next_valid_state - Find next valid C-state + * next_valid_state - Find next valid c-state * @dev: cpuidle device - * @state: Currently selected C-state + * @state: Currently selected c-state * * If the current state is valid, it is returned back to the caller. * Else, this function searches for a lower c-state which is still - * valid. - * - * A state is valid if the 'valid' field is enabled and - * if it satisfies the enable_off_mode condition. + * valid (as defined in omap3_power_states[]). */ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, - struct cpuidle_state *curr) + struct cpuidle_state *curr) { struct cpuidle_state *next = NULL; - struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); - u32 mpu_deepest_state = PWRDM_POWER_RET; - u32 core_deepest_state = PWRDM_POWER_RET; + struct omap3_processor_cx *cx; - if (enable_off_mode) { - mpu_deepest_state = PWRDM_POWER_OFF; - /* - * Erratum i583: valable for ES rev < Es1.2 on 3630. - * CORE OFF mode is not supported in a stable form, restrict - * instead the CORE state to RET. - */ - if (!IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) - core_deepest_state = PWRDM_POWER_OFF; - } + cx = (struct omap3_processor_cx *)cpuidle_get_statedata(curr); /* Check if current state is valid */ - if ((cx->valid) && - (cx->mpu_state >= mpu_deepest_state) && - (cx->core_state >= core_deepest_state)) { + if (cx->valid) { return curr; } else { - int idx = OMAP3_NUM_STATES - 1; + u8 idx = OMAP3_STATE_MAX; - /* Reach the current state starting at highest C-state */ - for (; idx >= 0; idx--) { + /* + * Reach the current state starting at highest C-state + */ + for (; idx >= OMAP3_STATE_C1; idx--) { if (&dev->states[idx] == curr) { next = &dev->states[idx]; break; } } - /* Should never hit this condition */ + /* + * Should never hit this condition. + */ WARN_ON(next == NULL); /* @@ -192,17 +206,17 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, * Start search from the next (lower) state. */ idx--; - for (; idx >= 0; idx--) { + for (; idx >= OMAP3_STATE_C1; idx--) { + struct omap3_processor_cx *cx; + cx = cpuidle_get_statedata(&dev->states[idx]); - if ((cx->valid) && - (cx->mpu_state >= mpu_deepest_state) && - (cx->core_state >= core_deepest_state)) { + if (cx->valid) { next = &dev->states[idx]; break; } } /* - * C1 is always valid. + * C1 and C2 are always valid. * So, no need to check for 'next==NULL' outside this loop. */ } @@ -215,22 +229,36 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, * @dev: cpuidle device * @state: The target state to be programmed * - * This function checks for any pending activity and then programs - * the device to the specified or a safer state. + * Used for C states with CPUIDLE_FLAG_CHECK_BM flag set. This + * function checks for any pending activity and then programs the + * device to the specified or a safer state. */ static int omap3_enter_idle_bm(struct cpuidle_device *dev, struct cpuidle_state *state) { - struct cpuidle_state *new_state; - u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; - struct omap3_idle_statedata *cx; + struct cpuidle_state *new_state = next_valid_state(dev, state); + u32 core_next_state, per_next_state = 0, per_saved_state = 0; + u32 cam_state; + struct omap3_processor_cx *cx; int ret; - if (!omap3_can_sleep()) { + if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) { + BUG_ON(!dev->safe_state); new_state = dev->safe_state; goto select_state; } + cx = cpuidle_get_statedata(state); + core_next_state = cx->core_state; + + /* + * FIXME: we currently manage device-specific idle states + * for PER and CORE in combination with CPU-specific + * idle states. This is wrong, and device-specific + * idle management needs to be separated out into + * its own code. + */ + /* * Prevent idle completely if CAM is active. * CAM does not have wakeup capability in OMAP3. @@ -241,20 +269,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, goto select_state; } - /* - * FIXME: we currently manage device-specific idle states - * for PER and CORE in combination with CPU-specific - * idle states. This is wrong, and device-specific - * idle management needs to be separated out into - * its own code. - */ - /* * Prevent PER off if CORE is not in retention or off as this * would disable PER wakeups completely. */ - cx = cpuidle_get_statedata(state); - core_next_state = cx->core_state; per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); if ((per_next_state == PWRDM_POWER_OFF) && (core_next_state > PWRDM_POWER_RET)) @@ -264,8 +282,6 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, if (per_next_state != per_saved_state) pwrdm_set_next_pwrst(per_pd, per_next_state); - new_state = next_valid_state(dev, state); - select_state: dev->last_state = new_state; ret = omap3_enter_idle(dev, new_state); @@ -279,6 +295,31 @@ 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 up to and including this for mpu domain + * @core_deepest_state: Enable states up to and including this for core domain + * + * This goes through the list of states available and enables and disables the + * validity of C states based on deepest state that can be achieved for the + * variable domain + */ +void omap3_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state) +{ + int i; + + for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { + struct omap3_processor_cx *cx = &omap3_power_states[i]; + + if ((cx->mpu_state >= mpu_deepest_state) && + (cx->core_state >= core_deepest_state)) { + cx->valid = 1; + } else { + cx->valid = 0; + } + } +} + void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params) { int i; @@ -286,109 +327,212 @@ void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params) if (!cpuidle_board_params) return; - for (i = 0; i < OMAP3_NUM_STATES; i++) { - cpuidle_params_table[i].valid = cpuidle_board_params[i].valid; - cpuidle_params_table[i].exit_latency = - cpuidle_board_params[i].exit_latency; - cpuidle_params_table[i].target_residency = - cpuidle_board_params[i].target_residency; + for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { + cpuidle_params_table[i].valid = + cpuidle_board_params[i].valid; + cpuidle_params_table[i].sleep_latency = + cpuidle_board_params[i].sleep_latency; + cpuidle_params_table[i].wake_latency = + cpuidle_board_params[i].wake_latency; + cpuidle_params_table[i].threshold = + cpuidle_board_params[i].threshold; } return; } +/* omap3_init_power_states - Initialises the OMAP3 specific C states. + * + * Below is the desciption of each C state. + * C1 . MPU WFI + Core active + * C2 . MPU WFI + Core inactive + * C3 . MPU CSWR + Core inactive + * C4 . MPU OFF + Core inactive + * C5 . MPU CSWR + Core CSWR + * C6 . MPU OFF + Core CSWR + * C7 . MPU OFF + Core OFF + */ +void omap_init_power_states(void) +{ + /* C1 . MPU WFI + Core active */ + omap3_power_states[OMAP3_STATE_C1].valid = + cpuidle_params_table[OMAP3_STATE_C1].valid; + omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1; + omap3_power_states[OMAP3_STATE_C1].sleep_latency = + cpuidle_params_table[OMAP3_STATE_C1].sleep_latency; + omap3_power_states[OMAP3_STATE_C1].wakeup_latency = + cpuidle_params_table[OMAP3_STATE_C1].wake_latency; + omap3_power_states[OMAP3_STATE_C1].threshold = + cpuidle_params_table[OMAP3_STATE_C1].threshold; + omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON; + omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON; + omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID; + omap3_power_states[OMAP3_STATE_C1].desc = "MPU ON + CORE ON"; + + /* C2 . MPU WFI + Core inactive */ + omap3_power_states[OMAP3_STATE_C2].valid = + cpuidle_params_table[OMAP3_STATE_C2].valid; + omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2; + omap3_power_states[OMAP3_STATE_C2].sleep_latency = + cpuidle_params_table[OMAP3_STATE_C2].sleep_latency; + omap3_power_states[OMAP3_STATE_C2].wakeup_latency = + cpuidle_params_table[OMAP3_STATE_C2].wake_latency; + omap3_power_states[OMAP3_STATE_C2].threshold = + cpuidle_params_table[OMAP3_STATE_C2].threshold; + omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON; + omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON; + omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_CHECK_BM; + omap3_power_states[OMAP3_STATE_C2].desc = "MPU ON + CORE ON"; + + /* C3 . MPU CSWR + Core inactive */ + omap3_power_states[OMAP3_STATE_C3].valid = + cpuidle_params_table[OMAP3_STATE_C3].valid; + omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3; + omap3_power_states[OMAP3_STATE_C3].sleep_latency = + cpuidle_params_table[OMAP3_STATE_C3].sleep_latency; + omap3_power_states[OMAP3_STATE_C3].wakeup_latency = + cpuidle_params_table[OMAP3_STATE_C3].wake_latency; + omap3_power_states[OMAP3_STATE_C3].threshold = + cpuidle_params_table[OMAP3_STATE_C3].threshold; + omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET; + omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON; + omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_CHECK_BM; + omap3_power_states[OMAP3_STATE_C3].desc = "MPU RET + CORE ON"; + + /* C4 . MPU OFF + Core inactive */ + omap3_power_states[OMAP3_STATE_C4].valid = + cpuidle_params_table[OMAP3_STATE_C4].valid; + omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4; + omap3_power_states[OMAP3_STATE_C4].sleep_latency = + cpuidle_params_table[OMAP3_STATE_C4].sleep_latency; + omap3_power_states[OMAP3_STATE_C4].wakeup_latency = + cpuidle_params_table[OMAP3_STATE_C4].wake_latency; + omap3_power_states[OMAP3_STATE_C4].threshold = + cpuidle_params_table[OMAP3_STATE_C4].threshold; + omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF; + omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON; + omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_CHECK_BM; + omap3_power_states[OMAP3_STATE_C4].desc = "MPU OFF + CORE ON"; + + /* C5 . MPU CSWR + Core CSWR*/ + omap3_power_states[OMAP3_STATE_C5].valid = + cpuidle_params_table[OMAP3_STATE_C5].valid; + omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5; + omap3_power_states[OMAP3_STATE_C5].sleep_latency = + cpuidle_params_table[OMAP3_STATE_C5].sleep_latency; + omap3_power_states[OMAP3_STATE_C5].wakeup_latency = + cpuidle_params_table[OMAP3_STATE_C5].wake_latency; + omap3_power_states[OMAP3_STATE_C5].threshold = + cpuidle_params_table[OMAP3_STATE_C5].threshold; + omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_RET; + omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET; + omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_CHECK_BM; + omap3_power_states[OMAP3_STATE_C5].desc = "MPU RET + CORE RET"; + + /* C6 . MPU OFF + Core CSWR */ + omap3_power_states[OMAP3_STATE_C6].valid = + cpuidle_params_table[OMAP3_STATE_C6].valid; + omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6; + omap3_power_states[OMAP3_STATE_C6].sleep_latency = + cpuidle_params_table[OMAP3_STATE_C6].sleep_latency; + omap3_power_states[OMAP3_STATE_C6].wakeup_latency = + cpuidle_params_table[OMAP3_STATE_C6].wake_latency; + omap3_power_states[OMAP3_STATE_C6].threshold = + cpuidle_params_table[OMAP3_STATE_C6].threshold; + omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF; + omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET; + omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_CHECK_BM; + omap3_power_states[OMAP3_STATE_C6].desc = "MPU OFF + CORE RET"; + + /* C7 . MPU OFF + Core OFF */ + omap3_power_states[OMAP3_STATE_C7].valid = + cpuidle_params_table[OMAP3_STATE_C7].valid; + omap3_power_states[OMAP3_STATE_C7].type = OMAP3_STATE_C7; + omap3_power_states[OMAP3_STATE_C7].sleep_latency = + cpuidle_params_table[OMAP3_STATE_C7].sleep_latency; + omap3_power_states[OMAP3_STATE_C7].wakeup_latency = + cpuidle_params_table[OMAP3_STATE_C7].wake_latency; + omap3_power_states[OMAP3_STATE_C7].threshold = + cpuidle_params_table[OMAP3_STATE_C7].threshold; + omap3_power_states[OMAP3_STATE_C7].mpu_state = PWRDM_POWER_OFF; + 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; + omap3_power_states[OMAP3_STATE_C7].desc = "MPU OFF + CORE OFF"; + + /* + * 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; + pr_warn("%s: core off state C7 disabled due to i583\n", + __func__); + } +} + struct cpuidle_driver omap3_idle_driver = { .name = "omap3_idle", .owner = THIS_MODULE, }; -/* Helper to fill the C-state common data and register the driver_data */ -static inline struct omap3_idle_statedata *_fill_cstate( - struct cpuidle_device *dev, - int idx, const char *descr) -{ - struct omap3_idle_statedata *cx = &omap3_idle_data[idx]; - struct cpuidle_state *state = &dev->states[idx]; - - state->exit_latency = cpuidle_params_table[idx].exit_latency; - state->target_residency = cpuidle_params_table[idx].target_residency; - state->flags = CPUIDLE_FLAG_TIME_VALID; - state->enter = omap3_enter_idle_bm; - cx->valid = cpuidle_params_table[idx].valid; - sprintf(state->name, "C%d", idx + 1); - strncpy(state->desc, descr, CPUIDLE_DESC_LEN); - cpuidle_set_statedata(state, cx); - - return cx; -} - /** * omap3_idle_init - Init routine for OMAP3 idle * - * Registers the OMAP3 specific cpuidle driver to the cpuidle + * Registers the OMAP3 specific cpuidle driver with the cpuidle * framework with the valid set of states. */ int __init omap3_idle_init(void) { + int i, count = 0; + struct omap3_processor_cx *cx; + struct cpuidle_state *state; struct cpuidle_device *dev; - struct omap3_idle_statedata *cx; mpu_pd = pwrdm_lookup("mpu_pwrdm"); core_pd = pwrdm_lookup("core_pwrdm"); per_pd = pwrdm_lookup("per_pwrdm"); cam_pd = pwrdm_lookup("cam_pwrdm"); + omap_init_power_states(); cpuidle_register_driver(&omap3_idle_driver); - dev = &per_cpu(omap3_idle_dev, smp_processor_id()); - - /* C1 . MPU WFI + Core active */ - cx = _fill_cstate(dev, 0, "MPU ON + CORE ON"); - (&dev->states[0])->enter = omap3_enter_idle; - dev->safe_state = &dev->states[0]; - cx->valid = 1; /* C1 is always valid */ - cx->mpu_state = PWRDM_POWER_ON; - cx->core_state = PWRDM_POWER_ON; - /* C2 . MPU WFI + Core inactive */ - cx = _fill_cstate(dev, 1, "MPU ON + CORE ON"); - cx->mpu_state = PWRDM_POWER_ON; - cx->core_state = PWRDM_POWER_ON; - - /* C3 . MPU CSWR + Core inactive */ - cx = _fill_cstate(dev, 2, "MPU RET + CORE ON"); - cx->mpu_state = PWRDM_POWER_RET; - cx->core_state = PWRDM_POWER_ON; - - /* C4 . MPU OFF + Core inactive */ - cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON"); - cx->mpu_state = PWRDM_POWER_OFF; - cx->core_state = PWRDM_POWER_ON; + dev = &per_cpu(omap3_idle_dev, smp_processor_id()); - /* C5 . MPU RET + Core RET */ - cx = _fill_cstate(dev, 4, "MPU RET + CORE RET"); - cx->mpu_state = PWRDM_POWER_RET; - cx->core_state = PWRDM_POWER_RET; + for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { + cx = &omap3_power_states[i]; + state = &dev->states[count]; + + if (!cx->valid) + continue; + cpuidle_set_statedata(state, cx); + state->exit_latency = cx->sleep_latency + cx->wakeup_latency; + state->target_residency = cx->threshold; + state->flags = cx->flags; + state->enter = (state->flags & CPUIDLE_FLAG_CHECK_BM) ? + omap3_enter_idle_bm : omap3_enter_idle; + if (cx->type == OMAP3_STATE_C1) + dev->safe_state = state; + sprintf(state->name, "C%d", count+1); + strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); + count++; + } - /* C6 . MPU OFF + Core RET */ - cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET"); - cx->mpu_state = PWRDM_POWER_OFF; - cx->core_state = PWRDM_POWER_RET; + if (!count) + return -EINVAL; + dev->state_count = count; - /* C7 . MPU OFF + Core OFF */ - cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF"); - /* - * 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)) { - cx->valid = 0; - pr_warn("%s: core off state C7 disabled due to i583\n", - __func__); - } - cx->mpu_state = PWRDM_POWER_OFF; - cx->core_state = PWRDM_POWER_OFF; + 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); - dev->state_count = OMAP3_NUM_STATES; if (cpuidle_register_device(dev)) { printk(KERN_ERR "%s: CPUidle register device failed\n", __func__); diff --git a/trunk/arch/arm/mach-omap2/gpmc-smc91x.c b/trunk/arch/arm/mach-omap2/gpmc-smc91x.c index ba10c24f3d8d..877c6f5807b7 100644 --- a/trunk/arch/arm/mach-omap2/gpmc-smc91x.c +++ b/trunk/arch/arm/mach-omap2/gpmc-smc91x.c @@ -147,24 +147,25 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data) goto free1; } - if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "SMC91X irq") < 0) + if (gpio_request(gpmc_cfg->gpio_irq, "SMC91X irq") < 0) goto free1; + gpio_direction_input(gpmc_cfg->gpio_irq); gpmc_smc91x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq); if (gpmc_cfg->gpio_pwrdwn) { - ret = gpio_request_one(gpmc_cfg->gpio_pwrdwn, - GPIOF_OUT_INIT_LOW, "SMC91X powerdown"); + ret = gpio_request(gpmc_cfg->gpio_pwrdwn, "SMC91X powerdown"); if (ret) goto free2; + gpio_direction_output(gpmc_cfg->gpio_pwrdwn, 0); } if (gpmc_cfg->gpio_reset) { - ret = gpio_request_one(gpmc_cfg->gpio_reset, - GPIOF_OUT_INIT_LOW, "SMC91X reset"); + ret = gpio_request(gpmc_cfg->gpio_reset, "SMC91X reset"); if (ret) goto free3; + gpio_direction_output(gpmc_cfg->gpio_reset, 0); gpio_set_value(gpmc_cfg->gpio_reset, 1); msleep(100); gpio_set_value(gpmc_cfg->gpio_reset, 0); diff --git a/trunk/arch/arm/mach-omap2/gpmc-smsc911x.c b/trunk/arch/arm/mach-omap2/gpmc-smsc911x.c index 997033129d26..703f150dd01d 100644 --- a/trunk/arch/arm/mach-omap2/gpmc-smsc911x.c +++ b/trunk/arch/arm/mach-omap2/gpmc-smsc911x.c @@ -10,7 +10,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#define pr_fmt(fmt) "%s: " fmt, __func__ #include #include @@ -31,7 +30,7 @@ static struct resource gpmc_smsc911x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + .flags = IORESOURCE_IRQ, }, }; @@ -42,6 +41,16 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = { .flags = SMSC911X_USE_16BIT, }; +static struct platform_device gpmc_smsc911x_device = { + .name = "smsc911x", + .id = -1, + .num_resources = ARRAY_SIZE(gpmc_smsc911x_resources), + .resource = gpmc_smsc911x_resources, + .dev = { + .platform_data = &gpmc_smsc911x_config, + }, +}; + /* * Initialize smsc911x device connected to the GPMC. Note that we * assume that pin multiplexing is done in the board-*.c file, @@ -49,49 +58,46 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = { */ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *board_data) { - struct platform_device *pdev; unsigned long cs_mem_base; int ret; gpmc_cfg = board_data; if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) { - pr_err("Failed to request GPMC mem region\n"); + printk(KERN_ERR "Failed to request GPMC mem for smsc911x\n"); return; } gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0; gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff; - if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "smsc911x irq")) { - pr_err("Failed to request IRQ GPIO%d\n", gpmc_cfg->gpio_irq); + if (gpio_request(gpmc_cfg->gpio_irq, "smsc911x irq") < 0) { + printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n", + gpmc_cfg->gpio_irq); goto free1; } + gpio_direction_input(gpmc_cfg->gpio_irq); gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq); + gpmc_smsc911x_resources[1].flags |= + (gpmc_cfg->flags & IRQF_TRIGGER_MASK); if (gpio_is_valid(gpmc_cfg->gpio_reset)) { - ret = gpio_request_one(gpmc_cfg->gpio_reset, - GPIOF_OUT_INIT_HIGH, "smsc911x reset"); + ret = gpio_request(gpmc_cfg->gpio_reset, "smsc911x reset"); if (ret) { - pr_err("Failed to request reset GPIO%d\n", - gpmc_cfg->gpio_reset); + printk(KERN_ERR "Failed to request GPIO%d for smsc911x reset\n", + gpmc_cfg->gpio_reset); goto free2; } + gpio_direction_output(gpmc_cfg->gpio_reset, 1); gpio_set_value(gpmc_cfg->gpio_reset, 0); msleep(100); gpio_set_value(gpmc_cfg->gpio_reset, 1); } - if (gpmc_cfg->flags) - gpmc_smsc911x_config.flags = gpmc_cfg->flags; - - pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id, - gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources), - &gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config)); - if (!pdev) { - pr_err("Unable to register platform device\n"); + if (platform_device_register(&gpmc_smsc911x_device) < 0) { + printk(KERN_ERR "Unable to register smsc911x device\n"); gpio_free(gpmc_cfg->gpio_reset); goto free2; } @@ -103,5 +109,5 @@ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *board_data) free1: gpmc_cs_free(gpmc_cfg->cs); - pr_err("Could not initialize smsc911x device\n"); + printk(KERN_ERR "Could not initialize smsc911x\n"); } diff --git a/trunk/arch/arm/mach-omap2/omap_l3_noc.c b/trunk/arch/arm/mach-omap2/omap_l3_noc.c index 7b9f1909ddb2..82632c24076f 100644 --- a/trunk/arch/arm/mach-omap2/omap_l3_noc.c +++ b/trunk/arch/arm/mach-omap2/omap_l3_noc.c @@ -63,7 +63,10 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3) char *source_name; /* Get the Type of interrupt */ - inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR; + if (irq == l3->app_irq) + inttype = L3_APPLICATION_ERROR; + else + inttype = L3_DEBUG_ERROR; for (i = 0; i < L3_MODULES; i++) { /* @@ -81,10 +84,10 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3) err_src = j; /* Read the stderrlog_main_source from clk domain */ - std_err_main_addr = base + *(l3_targ[i] + err_src); - std_err_main = readl(std_err_main_addr); + std_err_main_addr = base + (*(l3_targ[i] + err_src)); + std_err_main = readl(std_err_main_addr); - switch (std_err_main & CUSTOM_ERROR) { + switch ((std_err_main & CUSTOM_ERROR)) { case STANDARD_ERROR: source_name = l3_targ_stderrlog_main_name[i][err_src]; @@ -129,49 +132,49 @@ static int __init omap4_l3_probe(struct platform_device *pdev) l3 = kzalloc(sizeof(*l3), GFP_KERNEL); if (!l3) - return -ENOMEM; + ret = -ENOMEM; platform_set_drvdata(pdev, l3); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "couldn't find resource 0\n"); ret = -ENODEV; - goto err0; + goto err1; } l3->l3_base[0] = ioremap(res->start, resource_size(res)); - if (!l3->l3_base[0]) { + if (!(l3->l3_base[0])) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; - goto err0; + goto err2; } res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) { dev_err(&pdev->dev, "couldn't find resource 1\n"); ret = -ENODEV; - goto err1; + goto err3; } l3->l3_base[1] = ioremap(res->start, resource_size(res)); - if (!l3->l3_base[1]) { + if (!(l3->l3_base[1])) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; - goto err1; + goto err4; } res = platform_get_resource(pdev, IORESOURCE_MEM, 2); if (!res) { dev_err(&pdev->dev, "couldn't find resource 2\n"); ret = -ENODEV; - goto err2; + goto err5; } l3->l3_base[2] = ioremap(res->start, resource_size(res)); - if (!l3->l3_base[2]) { + if (!(l3->l3_base[2])) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; - goto err2; + goto err6; } /* @@ -184,7 +187,7 @@ static int __init omap4_l3_probe(struct platform_device *pdev) if (ret) { pr_crit("L3: request_irq failed to register for 0x%x\n", OMAP44XX_IRQ_L3_DBG); - goto err3; + goto err7; } l3->debug_irq = irq; @@ -195,22 +198,24 @@ static int __init omap4_l3_probe(struct platform_device *pdev) if (ret) { pr_crit("L3: request_irq failed to register for 0x%x\n", OMAP44XX_IRQ_L3_APP); - goto err4; + goto err8; } l3->app_irq = irq; - return 0; - + goto err0; +err8: +err7: + iounmap(l3->l3_base[2]); +err6: +err5: + iounmap(l3->l3_base[1]); err4: - free_irq(l3->debug_irq, l3); err3: - iounmap(l3->l3_base[2]); + iounmap(l3->l3_base[0]); err2: - iounmap(l3->l3_base[1]); err1: - iounmap(l3->l3_base[0]); -err0: kfree(l3); +err0: return ret; } diff --git a/trunk/arch/arm/mach-omap2/omap_l3_smx.c b/trunk/arch/arm/mach-omap2/omap_l3_smx.c index 873c0e33b512..4321e7938929 100644 --- a/trunk/arch/arm/mach-omap2/omap_l3_smx.c +++ b/trunk/arch/arm/mach-omap2/omap_l3_smx.c @@ -155,7 +155,7 @@ static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3, u8 multi = error & L3_ERROR_LOG_MULTI; u32 address = omap3_l3_decode_addr(error_addr); - WARN(true, "%s seen by %s %s at address %x\n", + WARN(true, "%s Error seen by %s %s at address %x\n", omap3_l3_code_string(code), omap3_l3_initiator_string(initid), multi ? "Multiple Errors" : "", @@ -167,15 +167,21 @@ static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3, static irqreturn_t omap3_l3_app_irq(int irq, void *_l3) { struct omap3_l3 *l3 = _l3; + u64 status, clear; u64 error; u64 error_addr; u64 err_source = 0; void __iomem *base; int int_type; + irqreturn_t ret = IRQ_NONE; - int_type = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR; + if (irq == l3->app_irq) + int_type = L3_APPLICATION_ERROR; + else + int_type = L3_DEBUG_ERROR; + if (!int_type) { status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_0); /* @@ -196,6 +202,7 @@ static irqreturn_t omap3_l3_app_irq(int irq, void *_l3) base = l3->rt + *(omap3_l3_bases[int_type] + err_source); error = omap3_l3_readll(base, L3_ERROR_LOG); + if (error) { error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR); @@ -203,8 +210,9 @@ static irqreturn_t omap3_l3_app_irq(int irq, void *_l3) } /* Clear the status register */ - clear = (L3_AGENT_STATUS_CLEAR_IA << int_type) | - L3_AGENT_STATUS_CLEAR_TA; + clear = ((L3_AGENT_STATUS_CLEAR_IA << int_type) | + (L3_AGENT_STATUS_CLEAR_TA)); + omap3_l3_writell(base, L3_AGENT_STATUS, clear); /* clear the error log register */ @@ -220,8 +228,10 @@ static int __init omap3_l3_probe(struct platform_device *pdev) int ret; l3 = kzalloc(sizeof(*l3), GFP_KERNEL); - if (!l3) - return -ENOMEM; + if (!l3) { + ret = -ENOMEM; + goto err0; + } platform_set_drvdata(pdev, l3); @@ -229,13 +239,13 @@ static int __init omap3_l3_probe(struct platform_device *pdev) if (!res) { dev_err(&pdev->dev, "couldn't find resource\n"); ret = -ENODEV; - goto err0; + goto err1; } l3->rt = ioremap(res->start, resource_size(res)); - if (!l3->rt) { + if (!(l3->rt)) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; - goto err0; + goto err2; } l3->debug_irq = platform_get_irq(pdev, 0); @@ -244,26 +254,28 @@ static int __init omap3_l3_probe(struct platform_device *pdev) "l3-debug-irq", l3); if (ret) { dev_err(&pdev->dev, "couldn't request debug irq\n"); - goto err1; + goto err3; } l3->app_irq = platform_get_irq(pdev, 1); ret = request_irq(l3->app_irq, omap3_l3_app_irq, IRQF_DISABLED | IRQF_TRIGGER_RISING, "l3-app-irq", l3); + if (ret) { dev_err(&pdev->dev, "couldn't request app irq\n"); - goto err2; + goto err4; } - return 0; + goto err0; +err4: +err3: + iounmap(l3->rt); err2: - free_irq(l3->debug_irq, l3); err1: - iounmap(l3->rt); -err0: kfree(l3); +err0: return ret; } diff --git a/trunk/arch/arm/mach-omap2/omap_phy_internal.c b/trunk/arch/arm/mach-omap2/omap_phy_internal.c index f47813edd951..05f6abc96b0d 100644 --- a/trunk/arch/arm/mach-omap2/omap_phy_internal.c +++ b/trunk/arch/arm/mach-omap2/omap_phy_internal.c @@ -50,16 +50,13 @@ int omap4430_phy_init(struct device *dev) { ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K); if (!ctrl_base) { - pr_err("control module ioremap failed\n"); + dev_err(dev, "control module ioremap failed\n"); return -ENOMEM; } /* Power down the phy */ __raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF); - - if (!dev) - return 0; - phyclk = clk_get(dev, "ocp2scp_usb_phy_ick"); + if (IS_ERR(phyclk)) { dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n"); iounmap(ctrl_base); @@ -231,7 +228,7 @@ void am35x_musb_clear_irq(void) regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); } -void am35x_set_mode(u8 musb_mode) +void am35x_musb_set_mode(u8 musb_mode) { u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); diff --git a/trunk/arch/arm/mach-omap2/pm.h b/trunk/arch/arm/mach-omap2/pm.h index 45bcfce77352..797bfd12b643 100644 --- a/trunk/arch/arm/mach-omap2/pm.h +++ b/trunk/arch/arm/mach-omap2/pm.h @@ -36,16 +36,11 @@ static inline int omap4_opp_init(void) } #endif -/* - * cpuidle mach specific parameters - * - * The board code can override the default C-states definition using - * omap3_pm_init_cpuidle - */ struct cpuidle_params { - u32 exit_latency; /* exit_latency = sleep + wake-up latencies */ - u32 target_residency; - u8 valid; /* validates the C-state */ + u8 valid; + u32 sleep_latency; + u32 wake_latency; + u32 threshold; }; #if defined(CONFIG_PM) && defined(CONFIG_CPU_IDLE) @@ -78,6 +73,10 @@ extern u32 sleep_while_idle; #define sleep_while_idle 0 #endif +#if defined(CONFIG_CPU_IDLE) +extern void omap3_cpuidle_update_states(u32, u32); +#endif + #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); extern int pm_dbg_regset_save(int reg_set); diff --git a/trunk/arch/arm/mach-omap2/pm34xx.c b/trunk/arch/arm/mach-omap2/pm34xx.c index c155c9d1c82c..0c5e3a46a3ad 100644 --- a/trunk/arch/arm/mach-omap2/pm34xx.c +++ b/trunk/arch/arm/mach-omap2/pm34xx.c @@ -779,6 +779,18 @@ void omap3_pm_off_mode_enable(int enable) else 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); +#endif + list_for_each_entry(pwrst, &pwrst_list, node) { if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) && pwrst->pwrdm == core_pwrdm && @@ -883,6 +895,8 @@ static int __init omap3_pm_init(void) pm_errata_configure(); + printk(KERN_ERR "Power Management for TI OMAP3.\n"); + /* XXX prcm_setup_regs needs to be before enabling hw * supervised mode for powerdomains */ prcm_setup_regs(); diff --git a/trunk/arch/arm/mach-omap2/pm44xx.c b/trunk/arch/arm/mach-omap2/pm44xx.c index 59a870be8390..76cfff2db514 100644 --- a/trunk/arch/arm/mach-omap2/pm44xx.c +++ b/trunk/arch/arm/mach-omap2/pm44xx.c @@ -105,11 +105,13 @@ static int __init omap4_pm_init(void) pr_err("Power Management for TI OMAP4.\n"); +#ifdef CONFIG_PM ret = pwrdm_for_each(pwrdms_setup, NULL); if (ret) { pr_err("Failed to setup powerdomains\n"); goto err2; } +#endif #ifdef CONFIG_SUSPEND suspend_set_ops(&omap_pm_ops); diff --git a/trunk/arch/arm/mach-omap2/smartreflex.c b/trunk/arch/arm/mach-omap2/smartreflex.c index fb7dc52394a8..13e24f913dd4 100644 --- a/trunk/arch/arm/mach-omap2/smartreflex.c +++ b/trunk/arch/arm/mach-omap2/smartreflex.c @@ -847,14 +847,6 @@ static int __init omap_sr_probe(struct platform_device *pdev) goto err_free_devinfo; } - mem = request_mem_region(mem->start, resource_size(mem), - dev_name(&pdev->dev)); - if (!mem) { - dev_err(&pdev->dev, "%s: no mem region\n", __func__); - ret = -EBUSY; - goto err_free_devinfo; - } - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); pm_runtime_enable(&pdev->dev); @@ -891,7 +883,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) ret = sr_late_init(sr_info); if (ret) { pr_warning("%s: Error in SR late init\n", __func__); - return ret; + goto err_release_region; } } @@ -904,7 +896,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm); if (!vdd_dbg_dir) { ret = -EINVAL; - goto err_iounmap; + goto err_release_region; } sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir); @@ -912,7 +904,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n", __func__); ret = PTR_ERR(sr_info->dbg_dir); - goto err_iounmap; + goto err_release_region; } (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, @@ -929,7 +921,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) dev_err(&pdev->dev, "%s: Unable to create debugfs directory" "for n-values\n", __func__); ret = PTR_ERR(nvalue_dir); - goto err_debugfs; + goto err_release_region; } omap_voltage_get_volttable(sr_info->voltdm, &volt_data); @@ -939,7 +931,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) "entries for n-values\n", __func__, sr_info->voltdm->name); ret = -ENODATA; - goto err_debugfs; + goto err_release_region; } for (i = 0; i < sr_info->nvalue_count; i++) { @@ -953,11 +945,6 @@ static int __init omap_sr_probe(struct platform_device *pdev) return ret; -err_debugfs: - debugfs_remove_recursive(sr_info->dbg_dir); -err_iounmap: - list_del(&sr_info->node); - iounmap(sr_info->base); err_release_region: release_mem_region(mem->start, resource_size(mem)); err_free_devinfo: diff --git a/trunk/arch/arm/mach-omap2/usb-musb.c b/trunk/arch/arm/mach-omap2/usb-musb.c index c7ed540d868d..35559f77e2de 100644 --- a/trunk/arch/arm/mach-omap2/usb-musb.c +++ b/trunk/arch/arm/mach-omap2/usb-musb.c @@ -108,13 +108,7 @@ static void usb_musb_mux_init(struct omap_musb_board_data *board_data) } } -static struct omap_musb_board_data musb_default_board_data = { - .interface_type = MUSB_INTERFACE_ULPI, - .mode = MUSB_OTG, - .power = 100, -}; - -void __init usb_musb_init(struct omap_musb_board_data *musb_board_data) +void __init usb_musb_init(struct omap_musb_board_data *board_data) { struct omap_hwmod *oh; struct omap_device *od; @@ -122,12 +116,11 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data) struct device *dev; int bus_id = -1; const char *oh_name, *name; - struct omap_musb_board_data *board_data; - if (musb_board_data) - board_data = musb_board_data; - else - board_data = &musb_default_board_data; + if (cpu_is_omap3517() || cpu_is_omap3505()) { + } else if (cpu_is_omap44xx()) { + usb_musb_mux_init(board_data); + } /* * REVISIT: This line can be removed once all the platforms using @@ -171,15 +164,10 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data) dev->dma_mask = &musb_dmamask; dev->coherent_dma_mask = musb_dmamask; put_device(dev); - - if (cpu_is_omap44xx()) - omap4430_phy_init(dev); } #else void __init usb_musb_init(struct omap_musb_board_data *board_data) { - if (cpu_is_omap44xx()) - omap4430_phy_init(NULL); } #endif /* CONFIG_USB_MUSB_SOC */ diff --git a/trunk/arch/arm/mach-omap2/usb-tusb6010.c b/trunk/arch/arm/mach-omap2/usb-tusb6010.c index 8dd26b765b7d..8a3c05f3c1d6 100644 --- a/trunk/arch/arm/mach-omap2/usb-tusb6010.c +++ b/trunk/arch/arm/mach-omap2/usb-tusb6010.c @@ -293,11 +293,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data, ); /* IRQ */ - status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq"); + status = gpio_request(irq, "TUSB6010 irq"); if (status < 0) { printk(error, 3, status); return status; } + gpio_direction_input(irq); tusb_resources[2].start = irq + IH_GPIO_BASE; /* set up memory timings ... can speed them up later */ diff --git a/trunk/arch/arm/mach-omap2/voltage.c b/trunk/arch/arm/mach-omap2/voltage.c index 9ef3789ded4b..0c1552d9d995 100644 --- a/trunk/arch/arm/mach-omap2/voltage.c +++ b/trunk/arch/arm/mach-omap2/voltage.c @@ -148,6 +148,7 @@ static int vp_volt_debug_get(void *data, u64 *val) } vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage); + pr_notice("curr_vsel = %x\n", vsel); if (!vdd->pmic_info->vsel_to_uv) { pr_warning("PMIC function to convert vsel to voltage" diff --git a/trunk/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h b/trunk/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h index ea6c9c88c725..872de0bf1e6b 100644 --- a/trunk/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h +++ b/trunk/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h @@ -14,14 +14,14 @@ #ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__ struct omap_smsc911x_platform_data { - int id; int cs; int gpio_irq; int gpio_reset; u32 flags; }; -#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) +#if defined(CONFIG_SMSC911X) || \ + defined(CONFIG_SMSC911X_MODULE) extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d); diff --git a/trunk/arch/arm/plat-omap/include/plat/uncompress.h b/trunk/arch/arm/plat-omap/include/plat/uncompress.h index ac4b60d9aa29..565d2664f5a7 100644 --- a/trunk/arch/arm/plat-omap/include/plat/uncompress.h +++ b/trunk/arch/arm/plat-omap/include/plat/uncompress.h @@ -129,6 +129,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) DEBUG_LL_OMAP1(3, sx1); /* omap2 based boards using UART1 */ + DEBUG_LL_OMAP2(1, omap2evm); DEBUG_LL_OMAP2(1, omap_2430sdp); DEBUG_LL_OMAP2(1, omap_apollon); DEBUG_LL_OMAP2(1, omap_h4); diff --git a/trunk/arch/arm/plat-omap/include/plat/usb.h b/trunk/arch/arm/plat-omap/include/plat/usb.h index 17d3c939775c..02b96c8f6a17 100644 --- a/trunk/arch/arm/plat-omap/include/plat/usb.h +++ b/trunk/arch/arm/plat-omap/include/plat/usb.h @@ -113,7 +113,7 @@ extern int omap4430_phy_suspend(struct device *dev, int suspend); extern void am35x_musb_reset(void); extern void am35x_musb_phy_power(u8 on); extern void am35x_musb_clear_irq(void); -extern void am35x_set_mode(u8 musb_mode); +extern void am35x_musb_set_mode(u8 musb_mode); /* * FIXME correct answer depends on hmc_mode, diff --git a/trunk/arch/avr32/include/asm/bitops.h b/trunk/arch/avr32/include/asm/bitops.h index b70c19bab63a..72444d97f80c 100644 --- a/trunk/arch/avr32/include/asm/bitops.h +++ b/trunk/arch/avr32/include/asm/bitops.h @@ -270,21 +270,14 @@ static inline int __fls(unsigned long word) unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size); -#define find_first_zero_bit find_first_zero_bit - unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset); -#define find_next_zero_bit find_next_zero_bit - unsigned long find_first_bit(const unsigned long *addr, unsigned long size); -#define find_first_bit find_first_bit - unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset); -#define find_next_bit find_next_bit /* * ffs: find first bit set. This is defined the same way as @@ -306,14 +299,6 @@ static inline int ffs(unsigned long word) #include #include -extern unsigned long find_next_zero_bit_le(const void *addr, - unsigned long size, unsigned long offset); -#define find_next_zero_bit_le find_next_zero_bit_le - -extern unsigned long find_next_bit_le(const void *addr, - unsigned long size, unsigned long offset); -#define find_next_bit_le find_next_bit_le - #include #include diff --git a/trunk/arch/blackfin/Kconfig b/trunk/arch/blackfin/Kconfig index d619b17c4413..a18180f2d007 100644 --- a/trunk/arch/blackfin/Kconfig +++ b/trunk/arch/blackfin/Kconfig @@ -47,6 +47,9 @@ config GENERIC_BUG config ZONE_DMA def_bool y +config GENERIC_FIND_NEXT_BIT + def_bool y + config GENERIC_GPIO def_bool y diff --git a/trunk/arch/blackfin/include/asm/kgdb.h b/trunk/arch/blackfin/include/asm/kgdb.h index aaf884591b07..3ac0c72e9fee 100644 --- a/trunk/arch/blackfin/include/asm/kgdb.h +++ b/trunk/arch/blackfin/include/asm/kgdb.h @@ -108,7 +108,6 @@ static inline void arch_kgdb_breakpoint(void) #else # define CACHE_FLUSH_IS_SAFE 1 #endif -#define GDB_ADJUSTS_BREAK_OFFSET #define HW_INST_WATCHPOINT_NUM 6 #define HW_WATCHPOINT_NUM 8 #define TYPE_INST_WATCHPOINT 0 diff --git a/trunk/arch/blackfin/include/asm/ptrace.h b/trunk/arch/blackfin/include/asm/ptrace.h index 7854d4367c15..1066d63e62b5 100644 --- a/trunk/arch/blackfin/include/asm/ptrace.h +++ b/trunk/arch/blackfin/include/asm/ptrace.h @@ -102,6 +102,9 @@ struct pt_regs { /* user_mode returns true if only one bit is set in IPEND, other than the master interrupt enable. */ #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1))) +#define instruction_pointer(regs) ((regs)->pc) +#define user_stack_pointer(regs) ((regs)->usp) +#define profile_pc(regs) instruction_pointer(regs) extern void show_regs(struct pt_regs *); #define arch_has_single_step() (1) @@ -125,8 +128,6 @@ extern int is_user_addr_valid(struct task_struct *child, ((unsigned long)task_stack_page(task) + \ (THREAD_SIZE - sizeof(struct pt_regs))) -#include - #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ diff --git a/trunk/arch/cris/Kconfig b/trunk/arch/cris/Kconfig index b6b94a27d276..a6d03069d0ff 100644 --- a/trunk/arch/cris/Kconfig +++ b/trunk/arch/cris/Kconfig @@ -31,6 +31,10 @@ config ARCH_HAS_ILOG2_U64 bool default n +config GENERIC_FIND_NEXT_BIT + bool + default y + config GENERIC_HWEIGHT bool default y diff --git a/trunk/arch/frv/Kconfig b/trunk/arch/frv/Kconfig index cb884e489425..064f62196745 100644 --- a/trunk/arch/frv/Kconfig +++ b/trunk/arch/frv/Kconfig @@ -19,6 +19,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config GENERIC_FIND_NEXT_BIT + bool + default y + +config GENERIC_FIND_BIT_LE + bool + default y + config GENERIC_HWEIGHT bool default y diff --git a/trunk/arch/h8300/Kconfig b/trunk/arch/h8300/Kconfig index 091ed6192ae8..e20322ffcaf8 100644 --- a/trunk/arch/h8300/Kconfig +++ b/trunk/arch/h8300/Kconfig @@ -41,6 +41,14 @@ config ARCH_HAS_ILOG2_U64 bool default n +config GENERIC_FIND_NEXT_BIT + bool + default y + +config GENERIC_FIND_BIT_LE + bool + default y + config GENERIC_HWEIGHT bool default y diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 38280ef4a2af..e5cc56ae6ce3 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -78,6 +78,10 @@ config HUGETLB_PAGE_SIZE_VARIABLE depends on HUGETLB_PAGE default y +config GENERIC_FIND_NEXT_BIT + bool + default y + config GENERIC_CALIBRATE_DELAY bool default y diff --git a/trunk/arch/ia64/kernel/time.c b/trunk/arch/ia64/kernel/time.c index 85118dfe9bb5..04440cc09b40 100644 --- a/trunk/arch/ia64/kernel/time.c +++ b/trunk/arch/ia64/kernel/time.c @@ -36,7 +36,7 @@ static cycle_t itc_get_cycles(struct clocksource *cs); struct fsyscall_gtod_data_t fsyscall_gtod_data = { - .lock = __SEQLOCK_UNLOCKED(fsyscall_gtod_data.lock), + .lock = SEQLOCK_UNLOCKED, }; struct itc_jitter_data_t itc_jitter_data; diff --git a/trunk/arch/m32r/Kconfig b/trunk/arch/m32r/Kconfig index 85b44e858225..736b808d2291 100644 --- a/trunk/arch/m32r/Kconfig +++ b/trunk/arch/m32r/Kconfig @@ -256,6 +256,14 @@ config ARCH_HAS_ILOG2_U64 bool default n +config GENERIC_FIND_NEXT_BIT + bool + default y + +config GENERIC_FIND_BIT_LE + bool + default y + config GENERIC_HWEIGHT bool default y diff --git a/trunk/arch/m32r/include/asm/smp.h b/trunk/arch/m32r/include/asm/smp.h index cf7829a61551..8accc1bb0263 100644 --- a/trunk/arch/m32r/include/asm/smp.h +++ b/trunk/arch/m32r/include/asm/smp.h @@ -81,11 +81,11 @@ static __inline__ int cpu_number_map(int cpu) static __inline__ unsigned int num_booting_cpus(void) { - return cpumask_weight(&cpu_callout_map); + return cpus_weight(cpu_callout_map); } extern void smp_send_timer(void); -extern unsigned long send_IPI_mask_phys(const cpumask_t*, int, int); +extern unsigned long send_IPI_mask_phys(cpumask_t, int, int); extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); diff --git a/trunk/arch/m32r/kernel/smp.c b/trunk/arch/m32r/kernel/smp.c index 092d40a6708e..fc10b39893d4 100644 --- a/trunk/arch/m32r/kernel/smp.c +++ b/trunk/arch/m32r/kernel/smp.c @@ -30,7 +30,6 @@ #include #include #include -#include /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ /* Data structures and variables */ @@ -62,22 +61,33 @@ extern spinlock_t ipi_lock[]; /* Function Prototypes */ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +void smp_send_reschedule(int); void smp_reschedule_interrupt(void); + +void smp_flush_cache_all(void); void smp_flush_cache_all_interrupt(void); +void smp_flush_tlb_all(void); static void flush_tlb_all_ipi(void *); + +void smp_flush_tlb_mm(struct mm_struct *); +void smp_flush_tlb_range(struct vm_area_struct *, unsigned long, \ + unsigned long); +void smp_flush_tlb_page(struct vm_area_struct *, unsigned long); static void flush_tlb_others(cpumask_t, struct mm_struct *, struct vm_area_struct *, unsigned long); - void smp_invalidate_interrupt(void); +void smp_send_stop(void); static void stop_this_cpu(void *); +void smp_send_timer(void); void smp_ipi_timer_interrupt(struct pt_regs *); void smp_local_timer_interrupt(void); static void send_IPI_allbutself(int, int); static void send_IPI_mask(const struct cpumask *, int, int); +unsigned long send_IPI_mask_phys(cpumask_t, int, int); /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ /* Rescheduling request Routines */ @@ -152,10 +162,10 @@ void smp_flush_cache_all(void) unsigned long *mask; preempt_disable(); - cpumask_copy(&cpumask, cpu_online_mask); - cpumask_clear_cpu(smp_processor_id(), &cpumask); + cpumask = cpu_online_map; + cpu_clear(smp_processor_id(), cpumask); spin_lock(&flushcache_lock); - mask=cpumask_bits(&cpumask); + mask=cpus_addr(cpumask); atomic_set_mask(*mask, (atomic_t *)&flushcache_cpumask); send_IPI_mask(&cpumask, INVALIDATE_CACHE_IPI, 0); _flush_cache_copyback_all(); @@ -253,8 +263,8 @@ void smp_flush_tlb_mm(struct mm_struct *mm) preempt_disable(); cpu_id = smp_processor_id(); mmc = &mm->context[cpu_id]; - cpumask_copy(&cpu_mask, mm_cpumask(mm)); - cpumask_clear_cpu(cpu_id, &cpu_mask); + cpu_mask = *mm_cpumask(mm); + cpu_clear(cpu_id, cpu_mask); if (*mmc != NO_CONTEXT) { local_irq_save(flags); @@ -265,7 +275,7 @@ void smp_flush_tlb_mm(struct mm_struct *mm) cpumask_clear_cpu(cpu_id, mm_cpumask(mm)); local_irq_restore(flags); } - if (!cpumask_empty(&cpu_mask)) + if (!cpus_empty(cpu_mask)) flush_tlb_others(cpu_mask, mm, NULL, FLUSH_ALL); preempt_enable(); @@ -323,8 +333,8 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va) preempt_disable(); cpu_id = smp_processor_id(); mmc = &mm->context[cpu_id]; - cpumask_copy(&cpu_mask, mm_cpumask(mm)); - cpumask_clear_cpu(cpu_id, &cpu_mask); + cpu_mask = *mm_cpumask(mm); + cpu_clear(cpu_id, cpu_mask); #ifdef DEBUG_SMP if (!mm) @@ -338,7 +348,7 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va) __flush_tlb_page(va); local_irq_restore(flags); } - if (!cpumask_empty(&cpu_mask)) + if (!cpus_empty(cpu_mask)) flush_tlb_others(cpu_mask, mm, vma, va); preempt_enable(); @@ -385,14 +395,14 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, * - current CPU must not be in mask * - mask must exist :) */ - BUG_ON(cpumask_empty(&cpumask)); + BUG_ON(cpus_empty(cpumask)); - BUG_ON(cpumask_test_cpu(smp_processor_id(), &cpumask)); + BUG_ON(cpu_isset(smp_processor_id(), cpumask)); BUG_ON(!mm); /* If a CPU which we ran on has gone down, OK. */ - cpumask_and(&cpumask, &cpumask, cpu_online_mask); - if (cpumask_empty(&cpumask)) + cpus_and(cpumask, cpumask, cpu_online_map); + if (cpus_empty(cpumask)) return; /* @@ -406,7 +416,7 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, flush_mm = mm; flush_vma = vma; flush_va = va; - mask=cpumask_bits(&cpumask); + mask=cpus_addr(cpumask); atomic_set_mask(*mask, (atomic_t *)&flush_cpumask); /* @@ -415,7 +425,7 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, */ send_IPI_mask(&cpumask, INVALIDATE_TLB_IPI, 0); - while (!cpumask_empty((cpumask_t*)&flush_cpumask)) { + while (!cpus_empty(flush_cpumask)) { /* nothing. lockup detection does not belong here */ mb(); } @@ -450,7 +460,7 @@ void smp_invalidate_interrupt(void) int cpu_id = smp_processor_id(); unsigned long *mmc = &flush_mm->context[cpu_id]; - if (!cpumask_test_cpu(cpu_id, &flush_cpumask)) + if (!cpu_isset(cpu_id, flush_cpumask)) return; if (flush_va == FLUSH_ALL) { @@ -468,7 +478,7 @@ void smp_invalidate_interrupt(void) __flush_tlb_page(va); } } - cpumask_clear_cpu(cpu_id, (cpumask_t*)&flush_cpumask); + cpu_clear(cpu_id, flush_cpumask); } /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ @@ -520,7 +530,7 @@ static void stop_this_cpu(void *dummy) /* * Remove this CPU: */ - set_cpu_online(cpu_id, false); + cpu_clear(cpu_id, cpu_online_map); /* * PSW IE = 1; @@ -715,8 +725,8 @@ static void send_IPI_allbutself(int ipi_num, int try) { cpumask_t cpumask; - cpumask_copy(&cpumask, cpu_online_mask); - cpumask_clear_cpu(smp_processor_id(), &cpumask); + cpumask = cpu_online_map; + cpu_clear(smp_processor_id(), cpumask); send_IPI_mask(&cpumask, ipi_num, try); } @@ -753,13 +763,13 @@ static void send_IPI_mask(const struct cpumask *cpumask, int ipi_num, int try) cpumask_and(&tmp, cpumask, cpu_online_mask); BUG_ON(!cpumask_equal(cpumask, &tmp)); - cpumask_clear(&physid_mask); + physid_mask = CPU_MASK_NONE; for_each_cpu(cpu_id, cpumask) { if ((phys_id = cpu_to_physid(cpu_id)) != -1) - cpumask_set_cpu(phys_id, &physid_mask); + cpu_set(phys_id, physid_mask); } - send_IPI_mask_phys(&physid_mask, ipi_num, try); + send_IPI_mask_phys(physid_mask, ipi_num, try); } /*==========================================================================* @@ -782,14 +792,14 @@ static void send_IPI_mask(const struct cpumask *cpumask, int ipi_num, int try) * ---------- --- -------------------------------------------------------- * *==========================================================================*/ -unsigned long send_IPI_mask_phys(const cpumask_t *physid_mask, int ipi_num, +unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num, int try) { spinlock_t *ipilock; volatile unsigned long *ipicr_addr; unsigned long ipicr_val; unsigned long my_physid_mask; - unsigned long mask = cpumask_bits(physid_mask)[0]; + unsigned long mask = cpus_addr(physid_mask)[0]; if (mask & ~physids_coerce(phys_cpu_present_map)) diff --git a/trunk/arch/m32r/kernel/smpboot.c b/trunk/arch/m32r/kernel/smpboot.c index cfdbe5d15002..e034844cfc0d 100644 --- a/trunk/arch/m32r/kernel/smpboot.c +++ b/trunk/arch/m32r/kernel/smpboot.c @@ -135,9 +135,9 @@ void __devinit smp_prepare_boot_cpu(void) { bsp_phys_id = hard_smp_processor_id(); physid_set(bsp_phys_id, phys_cpu_present_map); - set_cpu_online(0, true); /* BSP's cpu_id == 0 */ - cpumask_set_cpu(0, &cpu_callout_map); - cpumask_set_cpu(0, &cpu_callin_map); + cpu_set(0, cpu_online_map); /* BSP's cpu_id == 0 */ + cpu_set(0, cpu_callout_map); + cpu_set(0, cpu_callin_map); /* * Initialize the logical to physical CPU number mapping @@ -178,7 +178,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++) physid_set(phys_id, phys_cpu_present_map); #ifndef CONFIG_HOTPLUG_CPU - init_cpu_present(cpu_possible_mask); + init_cpu_present(&cpu_possible_map); #endif show_mp_info(nr_cpu); @@ -294,10 +294,10 @@ static void __init do_boot_cpu(int phys_id) send_status = 0; boot_status = 0; - cpumask_set_cpu(phys_id, &cpu_bootout_map); + cpu_set(phys_id, cpu_bootout_map); /* Send Startup IPI */ - send_IPI_mask_phys(cpumask_of(phys_id), CPU_BOOT_IPI, 0); + send_IPI_mask_phys(cpumask_of_cpu(phys_id), CPU_BOOT_IPI, 0); Dprintk("Waiting for send to finish...\n"); timeout = 0; @@ -306,7 +306,7 @@ static void __init do_boot_cpu(int phys_id) do { Dprintk("+"); udelay(1000); - send_status = !cpumask_test_cpu(phys_id, &cpu_bootin_map); + send_status = !cpu_isset(phys_id, cpu_bootin_map); } while (send_status && (timeout++ < 100)); Dprintk("After Startup.\n"); @@ -316,19 +316,19 @@ static void __init do_boot_cpu(int phys_id) * allow APs to start initializing. */ Dprintk("Before Callout %d.\n", cpu_id); - cpumask_set_cpu(cpu_id, &cpu_callout_map); + cpu_set(cpu_id, cpu_callout_map); Dprintk("After Callout %d.\n", cpu_id); /* * Wait 5s total for a response */ for (timeout = 0; timeout < 5000; timeout++) { - if (cpumask_test_cpu(cpu_id, &cpu_callin_map)) + if (cpu_isset(cpu_id, cpu_callin_map)) break; /* It has booted */ udelay(1000); } - if (cpumask_test_cpu(cpu_id, &cpu_callin_map)) { + if (cpu_isset(cpu_id, cpu_callin_map)) { /* number CPUs logically, starting from 1 (BSP is 0) */ Dprintk("OK.\n"); } else { @@ -340,9 +340,9 @@ static void __init do_boot_cpu(int phys_id) if (send_status || boot_status) { unmap_cpu_to_physid(cpu_id, phys_id); - cpumask_clear_cpu(cpu_id, &cpu_callout_map); - cpumask_clear_cpu(cpu_id, &cpu_callin_map); - cpumask_clear_cpu(cpu_id, &cpu_initialized); + cpu_clear(cpu_id, cpu_callout_map); + cpu_clear(cpu_id, cpu_callin_map); + cpu_clear(cpu_id, cpu_initialized); cpucount--; } } @@ -351,17 +351,17 @@ int __cpuinit __cpu_up(unsigned int cpu_id) { int timeout; - cpumask_set_cpu(cpu_id, &smp_commenced_mask); + cpu_set(cpu_id, smp_commenced_mask); /* * Wait 5s total for a response */ for (timeout = 0; timeout < 5000; timeout++) { - if (cpu_online(cpu_id)) + if (cpu_isset(cpu_id, cpu_online_map)) break; udelay(1000); } - if (!cpu_online(cpu_id)) + if (!cpu_isset(cpu_id, cpu_online_map)) BUG(); return 0; @@ -373,11 +373,11 @@ void __init smp_cpus_done(unsigned int max_cpus) unsigned long bogosum = 0; for (timeout = 0; timeout < 5000; timeout++) { - if (cpumask_equal(&cpu_callin_map, cpu_online_mask)) + if (cpus_equal(cpu_callin_map, cpu_online_map)) break; udelay(1000); } - if (!cpumask_equal(&cpu_callin_map, cpu_online_mask)) + if (!cpus_equal(cpu_callin_map, cpu_online_map)) BUG(); for (cpu_id = 0 ; cpu_id < num_online_cpus() ; cpu_id++) @@ -388,7 +388,7 @@ void __init smp_cpus_done(unsigned int max_cpus) */ Dprintk("Before bogomips.\n"); if (cpucount) { - for_each_cpu(cpu_id,cpu_online_mask) + for_each_cpu_mask(cpu_id, cpu_online_map) bogosum += cpu_data[cpu_id].loops_per_jiffy; printk(KERN_INFO "Total of %d processors activated " \ @@ -425,7 +425,7 @@ int __init start_secondary(void *unused) cpu_init(); preempt_disable(); smp_callin(); - while (!cpumask_test_cpu(smp_processor_id(), &smp_commenced_mask)) + while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) cpu_relax(); smp_online(); @@ -463,7 +463,7 @@ static void __init smp_callin(void) int cpu_id = smp_processor_id(); unsigned long timeout; - if (cpumask_test_cpu(cpu_id, &cpu_callin_map)) { + if (cpu_isset(cpu_id, cpu_callin_map)) { printk("huh, phys CPU#%d, CPU#%d already present??\n", phys_id, cpu_id); BUG(); @@ -474,7 +474,7 @@ static void __init smp_callin(void) timeout = jiffies + (2 * HZ); while (time_before(jiffies, timeout)) { /* Has the boot CPU finished it's STARTUP sequence ? */ - if (cpumask_test_cpu(cpu_id, &cpu_callout_map)) + if (cpu_isset(cpu_id, cpu_callout_map)) break; cpu_relax(); } @@ -486,7 +486,7 @@ static void __init smp_callin(void) } /* Allow the master to continue. */ - cpumask_set_cpu(cpu_id, &cpu_callin_map); + cpu_set(cpu_id, cpu_callin_map); } static void __init smp_online(void) @@ -503,7 +503,7 @@ static void __init smp_online(void) /* Save our processor parameters */ smp_store_cpu_info(cpu_id); - set_cpu_online(cpu_id, true); + cpu_set(cpu_id, cpu_online_map); } /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ diff --git a/trunk/arch/m68k/Kconfig.nommu b/trunk/arch/m68k/Kconfig.nommu index fc98f9b9d4d2..273bccab9517 100644 --- a/trunk/arch/m68k/Kconfig.nommu +++ b/trunk/arch/m68k/Kconfig.nommu @@ -2,6 +2,10 @@ config FPU bool default n +config GENERIC_FIND_NEXT_BIT + bool + default y + config GENERIC_GPIO bool default n diff --git a/trunk/arch/m68k/include/asm/bitops_mm.h b/trunk/arch/m68k/include/asm/bitops_mm.h index 89cf5b814a4d..e9020f88a748 100644 --- a/trunk/arch/m68k/include/asm/bitops_mm.h +++ b/trunk/arch/m68k/include/asm/bitops_mm.h @@ -200,7 +200,6 @@ static inline int find_first_zero_bit(const unsigned long *vaddr, res += ((long)p - (long)vaddr - 4) * 8; return res < size ? res : size; } -#define find_first_zero_bit find_first_zero_bit static inline int find_next_zero_bit(const unsigned long *vaddr, int size, int offset) @@ -230,7 +229,6 @@ static inline int find_next_zero_bit(const unsigned long *vaddr, int size, /* No zero yet, search remaining full bytes for a zero */ return offset + find_first_zero_bit(p, size - offset); } -#define find_next_zero_bit find_next_zero_bit static inline int find_first_bit(const unsigned long *vaddr, unsigned size) { @@ -255,7 +253,6 @@ static inline int find_first_bit(const unsigned long *vaddr, unsigned size) res += ((long)p - (long)vaddr - 4) * 8; return res < size ? res : size; } -#define find_first_bit find_first_bit static inline int find_next_bit(const unsigned long *vaddr, int size, int offset) @@ -285,7 +282,6 @@ static inline int find_next_bit(const unsigned long *vaddr, int size, /* No one yet, search remaining full bytes for a one */ return offset + find_first_bit(p, size - offset); } -#define find_next_bit find_next_bit /* * ffz = Find First Zero in word. Undefined if no zero exists, @@ -402,7 +398,6 @@ static inline int find_first_zero_bit_le(const void *vaddr, unsigned size) res += (p - addr) * 32; return res < size ? res : size; } -#define find_first_zero_bit_le find_first_zero_bit_le static inline unsigned long find_next_zero_bit_le(const void *addr, unsigned long size, unsigned long offset) @@ -432,7 +427,6 @@ static inline unsigned long find_next_zero_bit_le(const void *addr, /* No zero yet, search remaining full bytes for a zero */ return offset + find_first_zero_bit_le(p, size - offset); } -#define find_next_zero_bit_le find_next_zero_bit_le static inline int find_first_bit_le(const void *vaddr, unsigned size) { @@ -457,7 +451,6 @@ static inline int find_first_bit_le(const void *vaddr, unsigned size) res += (p - addr) * 32; return res < size ? res : size; } -#define find_first_bit_le find_first_bit_le static inline unsigned long find_next_bit_le(const void *addr, unsigned long size, unsigned long offset) @@ -487,7 +480,6 @@ static inline unsigned long find_next_bit_le(const void *addr, /* No set bit yet, search remaining full bytes for a set bit */ return offset + find_first_bit_le(p, size - offset); } -#define find_next_bit_le find_next_bit_le /* Bitmap functions for the ext2 filesystem. */ diff --git a/trunk/arch/m68k/include/asm/bitops_no.h b/trunk/arch/m68k/include/asm/bitops_no.h index 72e85acdd7bd..6b0e2d349f0e 100644 --- a/trunk/arch/m68k/include/asm/bitops_no.h +++ b/trunk/arch/m68k/include/asm/bitops_no.h @@ -319,10 +319,6 @@ static inline unsigned long find_next_zero_bit_le(void *addr, unsigned long size found_middle: return result + ffz(__swab32(tmp)); } -#define find_next_zero_bit_le find_next_zero_bit_le - -extern unsigned long find_next_bit_le(const void *addr, - unsigned long size, unsigned long offset); #endif /* __KERNEL__ */ diff --git a/trunk/arch/microblaze/Kconfig b/trunk/arch/microblaze/Kconfig index e446bab2427b..eccdefe70d4e 100644 --- a/trunk/arch/microblaze/Kconfig +++ b/trunk/arch/microblaze/Kconfig @@ -33,6 +33,12 @@ config ARCH_HAS_ILOG2_U32 config ARCH_HAS_ILOG2_U64 def_bool n +config GENERIC_FIND_NEXT_BIT + def_bool y + +config GENERIC_FIND_BIT_LE + def_bool y + config GENERIC_HWEIGHT def_bool y diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 653da62d0682..cef1a854487d 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -821,6 +821,14 @@ config ARCH_SUPPORTS_OPROFILE bool default y if !MIPS_MT_SMTC +config GENERIC_FIND_NEXT_BIT + bool + default y + +config GENERIC_FIND_BIT_LE + bool + default y + config GENERIC_HWEIGHT bool default y diff --git a/trunk/arch/mips/configs/bcm47xx_defconfig b/trunk/arch/mips/configs/bcm47xx_defconfig index ad15fb10322b..22fdf2f0cc23 100644 --- a/trunk/arch/mips/configs/bcm47xx_defconfig +++ b/trunk/arch/mips/configs/bcm47xx_defconfig @@ -16,6 +16,7 @@ CONFIG_TASK_IO_ACCOUNTING=y CONFIG_AUDIT=y CONFIG_TINY_RCU=y CONFIG_CGROUPS=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_CPUACCT=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y diff --git a/trunk/arch/mn10300/Kconfig b/trunk/arch/mn10300/Kconfig index 1f870340ebdd..feaf09cc8632 100644 --- a/trunk/arch/mn10300/Kconfig +++ b/trunk/arch/mn10300/Kconfig @@ -44,6 +44,9 @@ config GENERIC_CALIBRATE_DELAY config GENERIC_CMOS_UPDATE def_bool n +config GENERIC_FIND_NEXT_BIT + def_bool y + config GENERIC_HWEIGHT def_bool y diff --git a/trunk/arch/mn10300/configs/asb2364_defconfig b/trunk/arch/mn10300/configs/asb2364_defconfig index fbb96ae3122a..31d76261a3d5 100644 --- a/trunk/arch/mn10300/configs/asb2364_defconfig +++ b/trunk/arch/mn10300/configs/asb2364_defconfig @@ -8,6 +8,7 @@ CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_CGROUPS=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y diff --git a/trunk/arch/parisc/Kconfig b/trunk/arch/parisc/Kconfig index 65adc86a230e..69ff049c8571 100644 --- a/trunk/arch/parisc/Kconfig +++ b/trunk/arch/parisc/Kconfig @@ -47,6 +47,14 @@ config ARCH_HAS_ILOG2_U64 bool default n +config GENERIC_FIND_NEXT_BIT + bool + default y + +config GENERIC_FIND_BIT_LE + bool + default y + config GENERIC_BUG bool default y diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index 2729c6663d8a..423145a6f7ba 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -91,6 +91,14 @@ config GENERIC_HWEIGHT bool default y +config GENERIC_FIND_NEXT_BIT + bool + default y + +config GENERIC_FIND_BIT_LE + bool + default y + config GENERIC_GPIO bool help @@ -133,7 +141,6 @@ config PPC select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW_LEVEL select HAVE_RCU_TABLE_FREE if SMP - select HAVE_SYSCALL_TRACEPOINTS config EARLY_PRINTK bool diff --git a/trunk/arch/powerpc/boot/dts/canyonlands.dts b/trunk/arch/powerpc/boot/dts/canyonlands.dts index 22dd6ae84da0..2779f08313a5 100644 --- a/trunk/arch/powerpc/boot/dts/canyonlands.dts +++ b/trunk/arch/powerpc/boot/dts/canyonlands.dts @@ -530,23 +530,5 @@ 0x0 0x0 0x0 0x3 &UIC3 0x12 0x4 /* swizzled int C */ 0x0 0x0 0x0 0x4 &UIC3 0x13 0x4 /* swizzled int D */>; }; - - MSI: ppc4xx-msi@C10000000 { - compatible = "amcc,ppc4xx-msi", "ppc4xx-msi"; - reg = < 0xC 0x10000000 0x100>; - sdr-base = <0x36C>; - msi-data = <0x00000000>; - msi-mask = <0x44440000>; - interrupt-count = <3>; - interrupts = <0 1 2 3>; - interrupt-parent = <&UIC3>; - #interrupt-cells = <1>; - #address-cells = <0>; - #size-cells = <0>; - interrupt-map = <0 &UIC3 0x18 1 - 1 &UIC3 0x19 1 - 2 &UIC3 0x1A 1 - 3 &UIC3 0x1B 1>; - }; }; }; diff --git a/trunk/arch/powerpc/boot/dts/katmai.dts b/trunk/arch/powerpc/boot/dts/katmai.dts index f913dbe25d35..7c3be5e45748 100644 --- a/trunk/arch/powerpc/boot/dts/katmai.dts +++ b/trunk/arch/powerpc/boot/dts/katmai.dts @@ -442,24 +442,6 @@ 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>; }; - MSI: ppc4xx-msi@400300000 { - compatible = "amcc,ppc4xx-msi", "ppc4xx-msi"; - reg = < 0x4 0x00300000 0x100>; - sdr-base = <0x3B0>; - msi-data = <0x00000000>; - msi-mask = <0x44440000>; - interrupt-count = <3>; - interrupts =<0 1 2 3>; - interrupt-parent = <&UIC0>; - #interrupt-cells = <1>; - #address-cells = <0>; - #size-cells = <0>; - interrupt-map = <0 &UIC0 0xC 1 - 1 &UIC0 0x0D 1 - 2 &UIC0 0x0E 1 - 3 &UIC0 0x0F 1>; - }; - I2O: i2o@400100000 { compatible = "ibm,i2o-440spe"; reg = <0x00000004 0x00100000 0x100>; diff --git a/trunk/arch/powerpc/boot/dts/kilauea.dts b/trunk/arch/powerpc/boot/dts/kilauea.dts index 1613d6e4049e..89edb16649c3 100644 --- a/trunk/arch/powerpc/boot/dts/kilauea.dts +++ b/trunk/arch/powerpc/boot/dts/kilauea.dts @@ -403,33 +403,5 @@ 0x0 0x0 0x0 0x3 &UIC2 0xd 0x4 /* swizzled int C */ 0x0 0x0 0x0 0x4 &UIC2 0xe 0x4 /* swizzled int D */>; }; - - MSI: ppc4xx-msi@C10000000 { - compatible = "amcc,ppc4xx-msi", "ppc4xx-msi"; - reg = < 0x0 0xEF620000 0x100>; - sdr-base = <0x4B0>; - msi-data = <0x00000000>; - msi-mask = <0x44440000>; - interrupt-count = <12>; - interrupts = <0 1 2 3 4 5 6 7 8 9 0xA 0xB 0xC 0xD>; - interrupt-parent = <&UIC2>; - #interrupt-cells = <1>; - #address-cells = <0>; - #size-cells = <0>; - interrupt-map = <0 &UIC2 0x10 1 - 1 &UIC2 0x11 1 - 2 &UIC2 0x12 1 - 2 &UIC2 0x13 1 - 2 &UIC2 0x14 1 - 2 &UIC2 0x15 1 - 2 &UIC2 0x16 1 - 2 &UIC2 0x17 1 - 2 &UIC2 0x18 1 - 2 &UIC2 0x19 1 - 2 &UIC2 0x1A 1 - 2 &UIC2 0x1B 1 - 2 &UIC2 0x1C 1 - 3 &UIC2 0x1D 1>; - }; }; }; diff --git a/trunk/arch/powerpc/boot/dts/redwood.dts b/trunk/arch/powerpc/boot/dts/redwood.dts index d86a3a498118..81636c01d906 100644 --- a/trunk/arch/powerpc/boot/dts/redwood.dts +++ b/trunk/arch/powerpc/boot/dts/redwood.dts @@ -358,28 +358,8 @@ 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>; }; - MSI: ppc4xx-msi@400300000 { - compatible = "amcc,ppc4xx-msi", "ppc4xx-msi"; - reg = < 0x4 0x00300000 0x100 - 0x4 0x00300000 0x100>; - sdr-base = <0x3B0>; - msi-data = <0x00000000>; - msi-mask = <0x44440000>; - interrupt-count = <3>; - interrupts =<0 1 2 3>; - interrupt-parent = <&UIC0>; - #interrupt-cells = <1>; - #address-cells = <0>; - #size-cells = <0>; - interrupt-map = <0 &UIC0 0xC 1 - 1 &UIC0 0x0D 1 - 2 &UIC0 0x0E 1 - 3 &UIC0 0x0F 1>; - }; - }; - chosen { linux,stdout-path = "/plb/opb/serial@ef600200"; }; diff --git a/trunk/arch/powerpc/configs/ppc6xx_defconfig b/trunk/arch/powerpc/configs/ppc6xx_defconfig index 04360f9b0109..214208924a9c 100644 --- a/trunk/arch/powerpc/configs/ppc6xx_defconfig +++ b/trunk/arch/powerpc/configs/ppc6xx_defconfig @@ -10,6 +10,7 @@ CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_AUDIT=y CONFIG_CGROUPS=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y diff --git a/trunk/arch/powerpc/configs/pseries_defconfig b/trunk/arch/powerpc/configs/pseries_defconfig index c9f212b5f3de..7de13865508c 100644 --- a/trunk/arch/powerpc/configs/pseries_defconfig +++ b/trunk/arch/powerpc/configs/pseries_defconfig @@ -15,6 +15,7 @@ CONFIG_AUDITSYSCALL=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_CGROUPS=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y diff --git a/trunk/arch/powerpc/include/asm/fsl_lbc.h b/trunk/arch/powerpc/include/asm/fsl_lbc.h index 8a0b5ece8f76..5c1bf3466749 100644 --- a/trunk/arch/powerpc/include/asm/fsl_lbc.h +++ b/trunk/arch/powerpc/include/asm/fsl_lbc.h @@ -157,8 +157,6 @@ struct fsl_lbc_regs { #define LBCR_EPAR_SHIFT 16 #define LBCR_BMT 0x0000FF00 #define LBCR_BMT_SHIFT 8 -#define LBCR_BMTPS 0x0000000F -#define LBCR_BMTPS_SHIFT 0 #define LBCR_INIT 0x00040000 __be32 lcrr; /**< Clock Ratio Register */ #define LCRR_DBYP 0x80000000 diff --git a/trunk/arch/powerpc/include/asm/ftrace.h b/trunk/arch/powerpc/include/asm/ftrace.h index 169d039ed402..dde1296b8b41 100644 --- a/trunk/arch/powerpc/include/asm/ftrace.h +++ b/trunk/arch/powerpc/include/asm/ftrace.h @@ -60,18 +60,4 @@ struct dyn_arch_ftrace { #endif -#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64) && !defined(__ASSEMBLY__) -#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME -static inline bool arch_syscall_match_sym_name(const char *sym, const char *name) -{ - /* - * Compare the symbol name with the system call name. Skip the .sys or .SyS - * prefix from the symbol name and the sys prefix from the system call name and - * just match the rest. This is only needed on ppc64 since symbol names on - * 32bit do not start with a period so the generic function will work. - */ - return !strcmp(sym + 4, name + 3); -} -#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 && !__ASSEMBLY__ */ - #endif /* _ASM_POWERPC_FTRACE */ diff --git a/trunk/arch/powerpc/include/asm/hvcall.h b/trunk/arch/powerpc/include/asm/hvcall.h index fd8201dddd4b..852b8c1c09db 100644 --- a/trunk/arch/powerpc/include/asm/hvcall.h +++ b/trunk/arch/powerpc/include/asm/hvcall.h @@ -236,7 +236,7 @@ #define H_HOME_NODE_ASSOCIATIVITY 0x2EC #define H_BEST_ENERGY 0x2F4 #define H_GET_MPP_X 0x314 -#define MAX_HCALL_OPCODE H_GET_MPP_X +#define MAX_HCALL_OPCODE H_BEST_ENERGY #ifndef __ASSEMBLY__ diff --git a/trunk/arch/powerpc/include/asm/rio.h b/trunk/arch/powerpc/include/asm/rio.h index d902abd33995..0018bf80cb25 100644 --- a/trunk/arch/powerpc/include/asm/rio.h +++ b/trunk/arch/powerpc/include/asm/rio.h @@ -14,10 +14,5 @@ #define ASM_PPC_RIO_H extern void platform_rio_init(void); -#ifdef CONFIG_RAPIDIO -extern int fsl_rio_mcheck_exception(struct pt_regs *); -#else -static inline int fsl_rio_mcheck_exception(struct pt_regs *regs) {return 0; } -#endif #endif /* ASM_PPC_RIO_H */ diff --git a/trunk/arch/powerpc/include/asm/smp.h b/trunk/arch/powerpc/include/asm/smp.h index 11eb404b5606..880b8c1e6e53 100644 --- a/trunk/arch/powerpc/include/asm/smp.h +++ b/trunk/arch/powerpc/include/asm/smp.h @@ -191,6 +191,8 @@ extern unsigned long __secondary_hold_spinloop; extern unsigned long __secondary_hold_acknowledge; extern char __secondary_hold; +extern irqreturn_t debug_ipi_action(int irq, void *data); + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/trunk/arch/powerpc/include/asm/syscall.h b/trunk/arch/powerpc/include/asm/syscall.h index b54b2add07be..23913e902fc3 100644 --- a/trunk/arch/powerpc/include/asm/syscall.h +++ b/trunk/arch/powerpc/include/asm/syscall.h @@ -15,11 +15,6 @@ #include -/* ftrace syscalls requires exporting the sys_call_table */ -#ifdef CONFIG_FTRACE_SYSCALLS -extern const unsigned long *sys_call_table; -#endif /* CONFIG_FTRACE_SYSCALLS */ - static inline long syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { diff --git a/trunk/arch/powerpc/include/asm/thread_info.h b/trunk/arch/powerpc/include/asm/thread_info.h index 836f231ec1f0..37c353e8af7c 100644 --- a/trunk/arch/powerpc/include/asm/thread_info.h +++ b/trunk/arch/powerpc/include/asm/thread_info.h @@ -110,8 +110,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_NOERROR 12 /* Force successful syscall return */ #define TIF_NOTIFY_RESUME 13 /* callback before returning to user */ #define TIF_FREEZE 14 /* Freezing for suspend */ -#define TIF_SYSCALL_TRACEPOINT 15 /* syscall tracepoint instrumentation */ -#define TIF_RUNLATCH 16 /* Is the runlatch enabled? */ +#define TIF_RUNLATCH 15 /* Is the runlatch enabled? */ /* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1< #include #include -#include #ifdef CONFIG_DYNAMIC_FTRACE @@ -601,10 +600,3 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) } } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ - -#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64) -unsigned long __init arch_syscall_addr(int nr) -{ - return sys_call_table[nr*2]; -} -#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 */ diff --git a/trunk/arch/powerpc/kernel/irq.c b/trunk/arch/powerpc/kernel/irq.c index 5b428e308666..a24d37d4cf51 100644 --- a/trunk/arch/powerpc/kernel/irq.c +++ b/trunk/arch/powerpc/kernel/irq.c @@ -295,20 +295,17 @@ static inline void handle_one_irq(unsigned int irq) unsigned long saved_sp_limit; struct irq_desc *desc; - desc = irq_to_desc(irq); - if (!desc) - return; - /* Switch to the irq stack to handle this */ curtp = current_thread_info(); irqtp = hardirq_ctx[smp_processor_id()]; if (curtp == irqtp) { /* We're already on the irq stack, just handle it */ - desc->handle_irq(irq, desc); + generic_handle_irq(irq); return; } + desc = irq_to_desc(irq); saved_sp_limit = current->thread.ksp_limit; irqtp->task = curtp->task; @@ -560,8 +557,15 @@ struct irq_host *irq_alloc_host(struct device_node *of_node, if (revmap_type == IRQ_HOST_MAP_LEGACY) { if (irq_map[0].host != NULL) { raw_spin_unlock_irqrestore(&irq_big_lock, flags); - of_node_put(host->of_node); - kfree(host); + /* If we are early boot, we can't free the structure, + * too bad... + * this will be fixed once slab is made available early + * instead of the current cruft + */ + if (mem_init_done) { + of_node_put(host->of_node); + kfree(host); + } return NULL; } irq_map[0].host = host; @@ -723,7 +727,9 @@ unsigned int irq_create_mapping(struct irq_host *host, } pr_debug("irq: -> using host @%p\n", host); - /* Check if mapping already exists */ + /* Check if mapping already exist, if it does, call + * host->ops->map() to update the flags + */ virq = irq_find_mapping(host, hwirq); if (virq != NO_IRQ) { pr_debug("irq: -> existing mapping on virq %d\n", virq); @@ -893,13 +899,10 @@ unsigned int irq_radix_revmap_lookup(struct irq_host *host, return irq_find_mapping(host, hwirq); /* - * The ptr returned references the static global irq_map. - * but freeing an irq can delete nodes along the path to - * do the lookup via call_rcu. + * No rcu_read_lock(ing) needed, the ptr returned can't go under us + * as it's referencing an entry in the static irq_map table. */ - rcu_read_lock(); ptr = radix_tree_lookup(&host->revmap_data.tree, hwirq); - rcu_read_unlock(); /* * If found in radix tree, then fine. @@ -1007,23 +1010,14 @@ void irq_free_virt(unsigned int virq, unsigned int count) WARN_ON (virq < NUM_ISA_INTERRUPTS); WARN_ON (count == 0 || (virq + count) > irq_virq_count); - if (virq < NUM_ISA_INTERRUPTS) { - if (virq + count < NUM_ISA_INTERRUPTS) - return; - count =- NUM_ISA_INTERRUPTS - virq; - virq = NUM_ISA_INTERRUPTS; - } - - if (count > irq_virq_count || virq > irq_virq_count - count) { - if (virq > irq_virq_count) - return; - count = irq_virq_count - virq; - } - raw_spin_lock_irqsave(&irq_big_lock, flags); for (i = virq; i < (virq + count); i++) { struct irq_host *host; + if (i < NUM_ISA_INTERRUPTS || + (virq + count) > irq_virq_count) + continue; + host = irq_map[i].host; irq_map[i].hwirq = host->inval_irq; smp_wmb(); diff --git a/trunk/arch/powerpc/kernel/ptrace.c b/trunk/arch/powerpc/kernel/ptrace.c index cb22024f2b42..a6ae1cfad86c 100644 --- a/trunk/arch/powerpc/kernel/ptrace.c +++ b/trunk/arch/powerpc/kernel/ptrace.c @@ -29,7 +29,6 @@ #include #include #include -#include #ifdef CONFIG_PPC32 #include #endif @@ -41,9 +40,6 @@ #include #include -#define CREATE_TRACE_POINTS -#include - /* * The parameter save area on the stack is used to store arguments being passed * to callee function and is located at fixed offset from stack pointer. @@ -1714,9 +1710,6 @@ long do_syscall_trace_enter(struct pt_regs *regs) */ ret = -1L; - if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) - trace_sys_enter(regs, regs->gpr[0]); - if (unlikely(current->audit_context)) { #ifdef CONFIG_PPC64 if (!is_32bit_task()) @@ -1745,9 +1738,6 @@ void do_syscall_trace_leave(struct pt_regs *regs) audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, regs->result); - if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) - trace_sys_exit(regs, regs->result); - step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); diff --git a/trunk/arch/powerpc/kernel/smp.c b/trunk/arch/powerpc/kernel/smp.c index 8ebc6700b98d..4a6f2ec7e761 100644 --- a/trunk/arch/powerpc/kernel/smp.c +++ b/trunk/arch/powerpc/kernel/smp.c @@ -129,7 +129,7 @@ static irqreturn_t call_function_single_action(int irq, void *data) return IRQ_HANDLED; } -static irqreturn_t debug_ipi_action(int irq, void *data) +irqreturn_t debug_ipi_action(int irq, void *data) { if (crash_ipi_function_ptr) { crash_ipi_function_ptr(get_irq_regs()); diff --git a/trunk/arch/powerpc/kernel/traps.c b/trunk/arch/powerpc/kernel/traps.c index 0ff4ab98d50c..b13306b0d925 100644 --- a/trunk/arch/powerpc/kernel/traps.c +++ b/trunk/arch/powerpc/kernel/traps.c @@ -55,7 +55,6 @@ #endif #include #include -#include #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) int (*__debugger)(struct pt_regs *regs) __read_mostly; @@ -425,12 +424,6 @@ int machine_check_e500mc(struct pt_regs *regs) unsigned long reason = mcsr; int recoverable = 1; - if (reason & MCSR_BUS_RBERR) { - recoverable = fsl_rio_mcheck_exception(regs); - if (recoverable == 1) - goto silent_out; - } - printk("Machine check in kernel mode.\n"); printk("Caused by (from MCSR=%lx): ", reason); @@ -506,7 +499,6 @@ int machine_check_e500mc(struct pt_regs *regs) reason & MCSR_MEA ? "Effective" : "Physical", addr); } -silent_out: mtspr(SPRN_MCSR, mcsr); return mfspr(SPRN_MCSR) == 0 && recoverable; } @@ -515,11 +507,6 @@ int machine_check_e500(struct pt_regs *regs) { unsigned long reason = get_mc_reason(regs); - if (reason & MCSR_BUS_RBERR) { - if (fsl_rio_mcheck_exception(regs)) - return 1; - } - printk("Machine check in kernel mode.\n"); printk("Caused by (from MCSR=%lx): ", reason); diff --git a/trunk/arch/powerpc/oprofile/op_model_power4.c b/trunk/arch/powerpc/oprofile/op_model_power4.c index e6bec74be131..8ee51a252cf1 100644 --- a/trunk/arch/powerpc/oprofile/op_model_power4.c +++ b/trunk/arch/powerpc/oprofile/op_model_power4.c @@ -261,28 +261,6 @@ static int get_kernel(unsigned long pc, unsigned long mmcra) return is_kernel; } -static bool pmc_overflow(unsigned long val) -{ - if ((int)val < 0) - return true; - - /* - * Events on POWER7 can roll back if a speculative event doesn't - * eventually complete. Unfortunately in some rare cases they will - * raise a performance monitor exception. We need to catch this to - * ensure we reset the PMC. In all cases the PMC will be 256 or less - * cycles from overflow. - * - * We only do this if the first pass fails to find any overflowing - * PMCs because a user might set a period of less than 256 and we - * don't want to mistakenly reset them. - */ - if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256)) - return true; - - return false; -} - static void power4_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr) { @@ -303,7 +281,7 @@ static void power4_handle_interrupt(struct pt_regs *regs, for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { val = classic_ctr_read(i); - if (pmc_overflow(val)) { + if (val < 0) { if (oprofile_running && ctr[i].enabled) { oprofile_add_ext_sample(pc, regs, i, is_kernel); classic_ctr_write(i, reset_value[i]); diff --git a/trunk/arch/powerpc/platforms/40x/Kconfig b/trunk/arch/powerpc/platforms/40x/Kconfig index d733d7ca939c..b72176434ebe 100644 --- a/trunk/arch/powerpc/platforms/40x/Kconfig +++ b/trunk/arch/powerpc/platforms/40x/Kconfig @@ -57,8 +57,6 @@ config KILAUEA select 405EX select PPC40x_SIMPLE select PPC4xx_PCI_EXPRESS - select PCI_MSI - select PPC4xx_MSI help This option enables support for the AMCC PPC405EX evaluation board. diff --git a/trunk/arch/powerpc/platforms/44x/Kconfig b/trunk/arch/powerpc/platforms/44x/Kconfig index e958b6f48ec2..f485fc5f6d5e 100644 --- a/trunk/arch/powerpc/platforms/44x/Kconfig +++ b/trunk/arch/powerpc/platforms/44x/Kconfig @@ -74,8 +74,6 @@ config KATMAI select 440SPe select PCI select PPC4xx_PCI_EXPRESS - select PCI_MSI - select PCC4xx_MSI help This option enables support for the AMCC PPC440SPe evaluation board. @@ -120,8 +118,6 @@ config CANYONLANDS select 460EX select PCI select PPC4xx_PCI_EXPRESS - select PCI_MSI - select PPC4xx_MSI select IBM_NEW_EMAC_RGMII select IBM_NEW_EMAC_ZMII help @@ -148,8 +144,6 @@ config REDWOOD select 460SX select PCI select PPC4xx_PCI_EXPRESS - select PCI_MSI - select PPC4xx_MSI help This option enables support for the AMCC PPC460SX Redwood board. diff --git a/trunk/arch/powerpc/platforms/cell/interrupt.c b/trunk/arch/powerpc/platforms/cell/interrupt.c index 3e4eba603e6b..449c08c15862 100644 --- a/trunk/arch/powerpc/platforms/cell/interrupt.c +++ b/trunk/arch/powerpc/platforms/cell/interrupt.c @@ -176,14 +176,14 @@ EXPORT_SYMBOL_GPL(iic_get_target_id); #ifdef CONFIG_SMP /* Use the highest interrupt priorities for IPI */ -static inline int iic_msg_to_irq(int msg) +static inline int iic_ipi_to_irq(int ipi) { - return IIC_IRQ_TYPE_IPI + 0xf - msg; + return IIC_IRQ_TYPE_IPI + 0xf - ipi; } -void iic_message_pass(int cpu, int msg) +void iic_cause_IPI(int cpu, int mesg) { - out_be64(&per_cpu(cpu_iic, cpu).regs->generate, (0xf - msg) << 4); + out_be64(&per_cpu(cpu_iic, cpu).regs->generate, (0xf - mesg) << 4); } struct irq_host *iic_get_irq_host(int node) @@ -192,31 +192,50 @@ struct irq_host *iic_get_irq_host(int node) } EXPORT_SYMBOL_GPL(iic_get_irq_host); -static void iic_request_ipi(int msg) +static irqreturn_t iic_ipi_action(int irq, void *dev_id) +{ + int ipi = (int)(long)dev_id; + + switch(ipi) { + case PPC_MSG_CALL_FUNCTION: + generic_smp_call_function_interrupt(); + break; + case PPC_MSG_RESCHEDULE: + scheduler_ipi(); + break; + case PPC_MSG_CALL_FUNC_SINGLE: + generic_smp_call_function_single_interrupt(); + break; + case PPC_MSG_DEBUGGER_BREAK: + debug_ipi_action(0, NULL); + break; + } + return IRQ_HANDLED; +} +static void iic_request_ipi(int ipi, const char *name) { int virq; - virq = irq_create_mapping(iic_host, iic_msg_to_irq(msg)); + virq = irq_create_mapping(iic_host, iic_ipi_to_irq(ipi)); if (virq == NO_IRQ) { printk(KERN_ERR - "iic: failed to map IPI %s\n", smp_ipi_name[msg]); + "iic: failed to map IPI %s\n", name); return; } - - /* - * If smp_request_message_ipi encounters an error it will notify - * the error. If a message is not needed it will return non-zero. - */ - if (smp_request_message_ipi(virq, msg)) - irq_dispose_mapping(virq); + if (request_irq(virq, iic_ipi_action, IRQF_DISABLED, name, + (void *)(long)ipi)) + printk(KERN_ERR + "iic: failed to request IPI %s\n", name); } void iic_request_IPIs(void) { - iic_request_ipi(PPC_MSG_CALL_FUNCTION); - iic_request_ipi(PPC_MSG_RESCHEDULE); - iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE); - iic_request_ipi(PPC_MSG_DEBUGGER_BREAK); + iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call"); + iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched"); + iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE, "IPI-call-single"); +#ifdef CONFIG_DEBUGGER + iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); +#endif /* CONFIG_DEBUGGER */ } #endif /* CONFIG_SMP */ diff --git a/trunk/arch/powerpc/platforms/cell/interrupt.h b/trunk/arch/powerpc/platforms/cell/interrupt.h index 4f60ae6ca358..942dc39d6045 100644 --- a/trunk/arch/powerpc/platforms/cell/interrupt.h +++ b/trunk/arch/powerpc/platforms/cell/interrupt.h @@ -75,7 +75,7 @@ enum { }; extern void iic_init_IRQ(void); -extern void iic_message_pass(int cpu, int msg); +extern void iic_cause_IPI(int cpu, int mesg); extern void iic_request_IPIs(void); extern void iic_setup_cpu(void); diff --git a/trunk/arch/powerpc/platforms/cell/smp.c b/trunk/arch/powerpc/platforms/cell/smp.c index dbb641ea90dd..d176e6148e3f 100644 --- a/trunk/arch/powerpc/platforms/cell/smp.c +++ b/trunk/arch/powerpc/platforms/cell/smp.c @@ -152,7 +152,7 @@ static int smp_cell_cpu_bootable(unsigned int nr) return 1; } static struct smp_ops_t bpa_iic_smp_ops = { - .message_pass = iic_message_pass, + .message_pass = iic_cause_IPI, .probe = smp_iic_probe, .kick_cpu = smp_cell_kick_cpu, .setup_cpu = smp_cell_setup_cpu, diff --git a/trunk/arch/powerpc/sysdev/Kconfig b/trunk/arch/powerpc/sysdev/Kconfig index 7b4df37ac381..d775fd148d13 100644 --- a/trunk/arch/powerpc/sysdev/Kconfig +++ b/trunk/arch/powerpc/sysdev/Kconfig @@ -7,18 +7,11 @@ config PPC4xx_PCI_EXPRESS depends on PCI && 4xx default n -config PPC4xx_MSI - bool - depends on PCI_MSI - depends on PCI && 4xx - default n - config PPC_MSI_BITMAP bool depends on PCI_MSI default y if MPIC default y if FSL_PCI - default y if PPC4xx_MSI source "arch/powerpc/sysdev/xics/Kconfig" diff --git a/trunk/arch/powerpc/sysdev/Makefile b/trunk/arch/powerpc/sysdev/Makefile index 0efa990e3344..6076e0074a87 100644 --- a/trunk/arch/powerpc/sysdev/Makefile +++ b/trunk/arch/powerpc/sysdev/Makefile @@ -41,7 +41,6 @@ obj-$(CONFIG_OF_RTC) += of_rtc.o ifeq ($(CONFIG_PCI),y) obj-$(CONFIG_4xx) += ppc4xx_pci.o endif -obj-$(CONFIG_PPC4xx_MSI) += ppc4xx_msi.o obj-$(CONFIG_PPC4xx_CPM) += ppc4xx_cpm.o obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o diff --git a/trunk/arch/powerpc/sysdev/fsl_lbc.c b/trunk/arch/powerpc/sysdev/fsl_lbc.c index 0608b1657da4..4fcb5a4e60dd 100644 --- a/trunk/arch/powerpc/sysdev/fsl_lbc.c +++ b/trunk/arch/powerpc/sysdev/fsl_lbc.c @@ -184,8 +184,7 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) } EXPORT_SYMBOL(fsl_upm_run_pattern); -static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl, - struct device_node *node) +static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl) { struct fsl_lbc_regs __iomem *lbc = ctrl->regs; @@ -199,10 +198,6 @@ static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl, /* Enable interrupts for any detected events */ out_be32(&lbc->lteir, LTEIR_ENABLE); - /* Set the monitor timeout value to the maximum for erratum A001 */ - if (of_device_is_compatible(node, "fsl,elbc")) - clrsetbits_be32(&lbc->lbcr, LBCR_BMT, LBCR_BMTPS); - return 0; } @@ -309,7 +304,7 @@ static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev) fsl_lbc_ctrl_dev->dev = &dev->dev; - ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev, dev->dev.of_node); + ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev); if (ret < 0) goto err; diff --git a/trunk/arch/powerpc/sysdev/fsl_rio.c b/trunk/arch/powerpc/sysdev/fsl_rio.c index 5b206a2fe17c..49798532b477 100644 --- a/trunk/arch/powerpc/sysdev/fsl_rio.c +++ b/trunk/arch/powerpc/sysdev/fsl_rio.c @@ -10,7 +10,7 @@ * - Added Port-Write message handling * - Added Machine Check exception handling * - * Copyright (C) 2007, 2008, 2010 Freescale Semiconductor, Inc. + * Copyright (C) 2007, 2008 Freescale Semiconductor, Inc. * Zhang Wei * * Copyright 2005 MontaVista Software, Inc. @@ -47,33 +47,15 @@ #define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq) #define IRQ_RIO_PW(m) (((struct rio_priv *)(m->priv))->pwirq) -#define IPWSR_CLEAR 0x98 -#define OMSR_CLEAR 0x1cb3 -#define IMSR_CLEAR 0x491 -#define IDSR_CLEAR 0x91 -#define ODSR_CLEAR 0x1c00 -#define LTLEECSR_ENABLE_ALL 0xFFC000FC -#define ESCSR_CLEAR 0x07120204 - -#define RIO_PORT1_EDCSR 0x0640 -#define RIO_PORT2_EDCSR 0x0680 -#define RIO_PORT1_IECSR 0x10130 -#define RIO_PORT2_IECSR 0x101B0 -#define RIO_IM0SR 0x13064 -#define RIO_IM1SR 0x13164 -#define RIO_OM0SR 0x13004 -#define RIO_OM1SR 0x13104 - #define RIO_ATMU_REGS_OFFSET 0x10c00 #define RIO_P_MSG_REGS_OFFSET 0x11000 #define RIO_S_MSG_REGS_OFFSET 0x13000 #define RIO_GCCSR 0x13c #define RIO_ESCSR 0x158 -#define RIO_PORT2_ESCSR 0x178 #define RIO_CCSR 0x15c #define RIO_LTLEDCSR 0x0608 -#define RIO_LTLEDCSR_IER 0x80000000 -#define RIO_LTLEDCSR_PRT 0x01000000 +#define RIO_LTLEDCSR_IER 0x80000000 +#define RIO_LTLEDCSR_PRT 0x01000000 #define RIO_LTLEECSR 0x060c #define RIO_EPWISR 0x10010 #define RIO_ISR_AACR 0x10120 @@ -106,10 +88,7 @@ #define RIO_IPWSR_PWD 0x00000008 #define RIO_IPWSR_PWB 0x00000004 -/* EPWISR Error match value */ -#define RIO_EPWISR_PINT1 0x80000000 -#define RIO_EPWISR_PINT2 0x40000000 -#define RIO_EPWISR_MU 0x00000002 +#define RIO_EPWISR_PINT 0x80000000 #define RIO_EPWISR_PW 0x00000001 #define RIO_MSG_DESC_SIZE 32 @@ -281,7 +260,9 @@ struct rio_priv { static void __iomem *rio_regs_win; #ifdef CONFIG_E500 -int fsl_rio_mcheck_exception(struct pt_regs *regs) +static int (*saved_mcheck_exception)(struct pt_regs *regs); + +static int fsl_rio_mcheck_exception(struct pt_regs *regs) { const struct exception_table_entry *entry = NULL; unsigned long reason = mfspr(SPRN_MCSR); @@ -303,9 +284,11 @@ int fsl_rio_mcheck_exception(struct pt_regs *regs) } } - return 0; + if (saved_mcheck_exception) + return saved_mcheck_exception(regs); + else + return cur_cpu_spec->machine_check(regs); } -EXPORT_SYMBOL_GPL(fsl_rio_mcheck_exception); #endif /** @@ -1081,40 +1064,6 @@ static int fsl_rio_doorbell_init(struct rio_mport *mport) return rc; } -static void port_error_handler(struct rio_mport *port, int offset) -{ - /*XXX: Error recovery is not implemented, we just clear errors */ - out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); - - if (offset == 0) { - out_be32((u32 *)(rio_regs_win + RIO_PORT1_EDCSR), 0); - out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), 0); - out_be32((u32 *)(rio_regs_win + RIO_ESCSR), ESCSR_CLEAR); - } else { - out_be32((u32 *)(rio_regs_win + RIO_PORT2_EDCSR), 0); - out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), 0); - out_be32((u32 *)(rio_regs_win + RIO_PORT2_ESCSR), ESCSR_CLEAR); - } -} - -static void msg_unit_error_handler(struct rio_mport *port) -{ - struct rio_priv *priv = port->priv; - - /*XXX: Error recovery is not implemented, we just clear errors */ - out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); - - out_be32((u32 *)(rio_regs_win + RIO_IM0SR), IMSR_CLEAR); - out_be32((u32 *)(rio_regs_win + RIO_IM1SR), IMSR_CLEAR); - out_be32((u32 *)(rio_regs_win + RIO_OM0SR), OMSR_CLEAR); - out_be32((u32 *)(rio_regs_win + RIO_OM1SR), OMSR_CLEAR); - - out_be32(&priv->msg_regs->odsr, ODSR_CLEAR); - out_be32(&priv->msg_regs->dsr, IDSR_CLEAR); - - out_be32(&priv->msg_regs->pwsr, IPWSR_CLEAR); -} - /** * fsl_rio_port_write_handler - MPC85xx port write interrupt handler * @irq: Linux interrupt number @@ -1195,22 +1144,10 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) } pw_done: - if (epwisr & RIO_EPWISR_PINT1) { - tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); - pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); - port_error_handler(port, 0); - } - - if (epwisr & RIO_EPWISR_PINT2) { + if (epwisr & RIO_EPWISR_PINT) { tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); - port_error_handler(port, 1); - } - - if (epwisr & RIO_EPWISR_MU) { - tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); - pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); - msg_unit_error_handler(port); + out_be32(priv->regs_win + RIO_LTLEDCSR, 0); } return IRQ_HANDLED; @@ -1321,14 +1258,12 @@ static int fsl_rio_port_write_init(struct rio_mport *mport) /* Hook up port-write handler */ - rc = request_irq(IRQ_RIO_PW(mport), fsl_rio_port_write_handler, - IRQF_SHARED, "port-write", (void *)mport); + rc = request_irq(IRQ_RIO_PW(mport), fsl_rio_port_write_handler, 0, + "port-write", (void *)mport); if (rc < 0) { pr_err("MPC85xx RIO: unable to request inbound doorbell irq"); goto err_out; } - /* Enable Error Interrupt */ - out_be32((u32 *)(rio_regs_win + RIO_LTLEECSR), LTLEECSR_ENABLE_ALL); INIT_WORK(&priv->pw_work, fsl_pw_dpc); spin_lock_init(&priv->pw_fifo_lock); @@ -1603,6 +1538,11 @@ int fsl_rio_setup(struct platform_device *dev) fsl_rio_doorbell_init(port); fsl_rio_port_write_init(port); +#ifdef CONFIG_E500 + saved_mcheck_exception = ppc_md.machine_check_exception; + ppc_md.machine_check_exception = fsl_rio_mcheck_exception; +#endif + return 0; err: iounmap(priv->regs_win); diff --git a/trunk/arch/powerpc/sysdev/ppc4xx_msi.c b/trunk/arch/powerpc/sysdev/ppc4xx_msi.c deleted file mode 100644 index 367af0241851..000000000000 --- a/trunk/arch/powerpc/sysdev/ppc4xx_msi.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Adding PCI-E MSI support for PPC4XX SoCs. - * - * Copyright (c) 2010, Applied Micro Circuits Corporation - * Authors: Tirumala R Marri - * Feng Kan - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PEIH_TERMADH 0x00 -#define PEIH_TERMADL 0x08 -#define PEIH_MSIED 0x10 -#define PEIH_MSIMK 0x18 -#define PEIH_MSIASS 0x20 -#define PEIH_FLUSH0 0x30 -#define PEIH_FLUSH1 0x38 -#define PEIH_CNTRST 0x48 -#define NR_MSI_IRQS 4 - -struct ppc4xx_msi { - u32 msi_addr_lo; - u32 msi_addr_hi; - void __iomem *msi_regs; - int msi_virqs[NR_MSI_IRQS]; - struct msi_bitmap bitmap; - struct device_node *msi_dev; -}; - -static struct ppc4xx_msi ppc4xx_msi; - -static int ppc4xx_msi_init_allocator(struct platform_device *dev, - struct ppc4xx_msi *msi_data) -{ - int err; - - err = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, - dev->dev.of_node); - if (err) - return err; - - err = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap); - if (err < 0) { - msi_bitmap_free(&msi_data->bitmap); - return err; - } - - return 0; -} - -static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) -{ - int int_no = -ENOMEM; - unsigned int virq; - struct msi_msg msg; - struct msi_desc *entry; - struct ppc4xx_msi *msi_data = &ppc4xx_msi; - - list_for_each_entry(entry, &dev->msi_list, list) { - int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); - if (int_no >= 0) - break; - if (int_no < 0) { - pr_debug("%s: fail allocating msi interrupt\n", - __func__); - } - virq = irq_of_parse_and_map(msi_data->msi_dev, int_no); - if (virq == NO_IRQ) { - dev_err(&dev->dev, "%s: fail mapping irq\n", __func__); - msi_bitmap_free_hwirqs(&msi_data->bitmap, int_no, 1); - return -ENOSPC; - } - dev_dbg(&dev->dev, "%s: virq = %d\n", __func__, virq); - - /* Setup msi address space */ - msg.address_hi = msi_data->msi_addr_hi; - msg.address_lo = msi_data->msi_addr_lo; - - irq_set_msi_desc(virq, entry); - msg.data = int_no; - write_msi_msg(virq, &msg); - } - return 0; -} - -void ppc4xx_teardown_msi_irqs(struct pci_dev *dev) -{ - struct msi_desc *entry; - struct ppc4xx_msi *msi_data = &ppc4xx_msi; - - dev_dbg(&dev->dev, "PCIE-MSI: tearing down msi irqs\n"); - - list_for_each_entry(entry, &dev->msi_list, list) { - if (entry->irq == NO_IRQ) - continue; - irq_set_msi_desc(entry->irq, NULL); - msi_bitmap_free_hwirqs(&msi_data->bitmap, - virq_to_hw(entry->irq), 1); - irq_dispose_mapping(entry->irq); - } -} - -static int ppc4xx_msi_check_device(struct pci_dev *pdev, int nvec, int type) -{ - dev_dbg(&pdev->dev, "PCIE-MSI:%s called. vec %x type %d\n", - __func__, nvec, type); - if (type == PCI_CAP_ID_MSIX) - pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n"); - - return 0; -} - -static int ppc4xx_setup_pcieh_hw(struct platform_device *dev, - struct resource res, struct ppc4xx_msi *msi) -{ - const u32 *msi_data; - const u32 *msi_mask; - const u32 *sdr_addr; - dma_addr_t msi_phys; - void *msi_virt; - - sdr_addr = of_get_property(dev->dev.of_node, "sdr-base", NULL); - if (!sdr_addr) - return -1; - - SDR0_WRITE(sdr_addr, (u64)res.start >> 32); /*HIGH addr */ - SDR0_WRITE(sdr_addr + 1, res.start & 0xFFFFFFFF); /* Low addr */ - - - msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi"); - if (msi->msi_dev) - return -ENODEV; - - msi->msi_regs = of_iomap(msi->msi_dev, 0); - if (!msi->msi_regs) { - dev_err(&dev->dev, "of_iomap problem failed\n"); - return -ENOMEM; - } - dev_dbg(&dev->dev, "PCIE-MSI: msi register mapped 0x%x 0x%x\n", - (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs)); - - msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL); - msi->msi_addr_hi = 0x0; - msi->msi_addr_lo = (u32) msi_phys; - dev_dbg(&dev->dev, "PCIE-MSI: msi address 0x%x\n", msi->msi_addr_lo); - - /* Progam the Interrupt handler Termination addr registers */ - out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi); - out_be32(msi->msi_regs + PEIH_TERMADL, msi->msi_addr_lo); - - msi_data = of_get_property(dev->dev.of_node, "msi-data", NULL); - if (!msi_data) - return -1; - msi_mask = of_get_property(dev->dev.of_node, "msi-mask", NULL); - if (!msi_mask) - return -1; - /* Program MSI Expected data and Mask bits */ - out_be32(msi->msi_regs + PEIH_MSIED, *msi_data); - out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask); - - return 0; -} - -static int ppc4xx_of_msi_remove(struct platform_device *dev) -{ - struct ppc4xx_msi *msi = dev->dev.platform_data; - int i; - int virq; - - for (i = 0; i < NR_MSI_IRQS; i++) { - virq = msi->msi_virqs[i]; - if (virq != NO_IRQ) - irq_dispose_mapping(virq); - } - - if (msi->bitmap.bitmap) - msi_bitmap_free(&msi->bitmap); - iounmap(msi->msi_regs); - of_node_put(msi->msi_dev); - kfree(msi); - - return 0; -} - -static int __devinit ppc4xx_msi_probe(struct platform_device *dev) -{ - struct ppc4xx_msi *msi; - struct resource res; - int err = 0; - - msi = &ppc4xx_msi;/*keep the msi data for further use*/ - - dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n"); - - msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL); - if (!msi) { - dev_err(&dev->dev, "No memory for MSI structure\n"); - return -ENOMEM; - } - dev->dev.platform_data = msi; - - /* Get MSI ranges */ - err = of_address_to_resource(dev->dev.of_node, 0, &res); - if (err) { - dev_err(&dev->dev, "%s resource error!\n", - dev->dev.of_node->full_name); - goto error_out; - } - - if (ppc4xx_setup_pcieh_hw(dev, res, msi)) - goto error_out; - - err = ppc4xx_msi_init_allocator(dev, msi); - if (err) { - dev_err(&dev->dev, "Error allocating MSI bitmap\n"); - goto error_out; - } - - ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs; - ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs; - ppc_md.msi_check_device = ppc4xx_msi_check_device; - return err; - -error_out: - ppc4xx_of_msi_remove(dev); - return err; -} -static const struct of_device_id ppc4xx_msi_ids[] = { - { - .compatible = "amcc,ppc4xx-msi", - }, - {} -}; -static struct platform_driver ppc4xx_msi_driver = { - .probe = ppc4xx_msi_probe, - .remove = ppc4xx_of_msi_remove, - .driver = { - .name = "ppc4xx-msi", - .owner = THIS_MODULE, - .of_match_table = ppc4xx_msi_ids, - }, - -}; - -static __init int ppc4xx_msi_init(void) -{ - return platform_driver_register(&ppc4xx_msi_driver); -} - -subsys_initcall(ppc4xx_msi_init); diff --git a/trunk/arch/s390/include/asm/bitops.h b/trunk/arch/s390/include/asm/bitops.h index 667c6e9f6a34..e1c8f3a49884 100644 --- a/trunk/arch/s390/include/asm/bitops.h +++ b/trunk/arch/s390/include/asm/bitops.h @@ -621,7 +621,6 @@ static inline unsigned long find_first_zero_bit(const unsigned long *addr, bits = __ffz_word(bytes*8, __load_ulong_be(addr, bytes)); return (bits < size) ? bits : size; } -#define find_first_zero_bit find_first_zero_bit /** * find_first_bit - find the first set bit in a memory region @@ -642,7 +641,6 @@ static inline unsigned long find_first_bit(const unsigned long * addr, bits = __ffs_word(bytes*8, __load_ulong_be(addr, bytes)); return (bits < size) ? bits : size; } -#define find_first_bit find_first_bit /** * find_next_zero_bit - find the first zero bit in a memory region @@ -679,7 +677,6 @@ static inline int find_next_zero_bit (const unsigned long * addr, } return offset + find_first_zero_bit(p, size); } -#define find_next_zero_bit find_next_zero_bit /** * find_next_bit - find the first set bit in a memory region @@ -716,7 +713,6 @@ static inline int find_next_bit (const unsigned long * addr, } return offset + find_first_bit(p, size); } -#define find_next_bit find_next_bit /* * Every architecture must define this function. It's the fastest @@ -746,6 +742,41 @@ static inline int sched_find_first_bit(unsigned long *b) * 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 */ +static inline void __set_bit_le(unsigned long nr, void *addr) +{ + __set_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr); +} + +static inline void __clear_bit_le(unsigned long nr, void *addr) +{ + __clear_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr); +} + +static inline int __test_and_set_bit_le(unsigned long nr, void *addr) +{ + return __test_and_set_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr); +} + +static inline int test_and_set_bit_le(unsigned long nr, void *addr) +{ + return test_and_set_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr); +} + +static inline int __test_and_clear_bit_le(unsigned long nr, void *addr) +{ + return __test_and_clear_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr); +} + +static inline int test_and_clear_bit_le(unsigned long nr, void *addr) +{ + return test_and_clear_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr); +} + +static inline int test_bit_le(unsigned long nr, const void *addr) +{ + return test_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr); +} + static inline int find_first_zero_bit_le(void *vaddr, unsigned int size) { unsigned long bytes, bits; @@ -756,7 +787,6 @@ static inline int find_first_zero_bit_le(void *vaddr, unsigned int size) bits = __ffz_word(bytes*8, __load_ulong_le(vaddr, bytes)); return (bits < size) ? bits : size; } -#define find_first_zero_bit_le find_first_zero_bit_le static inline int find_next_zero_bit_le(void *vaddr, unsigned long size, unsigned long offset) @@ -786,7 +816,6 @@ static inline int find_next_zero_bit_le(void *vaddr, unsigned long size, } return offset + find_first_zero_bit_le(p, size); } -#define find_next_zero_bit_le find_next_zero_bit_le static inline unsigned long find_first_bit_le(void *vaddr, unsigned long size) { @@ -798,7 +827,6 @@ static inline unsigned long find_first_bit_le(void *vaddr, unsigned long size) bits = __ffs_word(bytes*8, __load_ulong_le(vaddr, bytes)); return (bits < size) ? bits : size; } -#define find_first_bit_le find_first_bit_le static inline int find_next_bit_le(void *vaddr, unsigned long size, unsigned long offset) @@ -828,9 +856,6 @@ static inline int find_next_bit_le(void *vaddr, unsigned long size, } return offset + find_first_bit_le(p, size); } -#define find_next_bit_le find_next_bit_le - -#include #define ext2_set_bit_atomic(lock, nr, addr) \ test_and_set_bit_le(nr, addr) diff --git a/trunk/arch/s390/mm/fault.c b/trunk/arch/s390/mm/fault.c index a0f9e730f26a..e46ba2927424 100644 --- a/trunk/arch/s390/mm/fault.c +++ b/trunk/arch/s390/mm/fault.c @@ -485,7 +485,6 @@ int pfault_init(void) "2:\n" EX_TABLE(0b,1b) : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc"); - __ctl_set_bit(0, 9); return rc; } @@ -500,7 +499,6 @@ void pfault_fini(void) if (!MACHINE_IS_VM || pfault_disable) return; - __ctl_clear_bit(0,9); asm volatile( " diag %0,0,0x258\n" "0:\n" @@ -615,6 +613,7 @@ static int __init pfault_irq_init(void) rc = pfault_init() == 0 ? 0 : -EOPNOTSUPP; if (rc) goto out_pfault; + ctl_set_bit(0, 9); hotcpu_notifier(pfault_cpu_notify, 0); return 0; diff --git a/trunk/arch/score/Kconfig b/trunk/arch/score/Kconfig index 288add8d168f..e73bc781cc14 100644 --- a/trunk/arch/score/Kconfig +++ b/trunk/arch/score/Kconfig @@ -43,6 +43,9 @@ config NO_DMA config RWSEM_GENERIC_SPINLOCK def_bool y +config GENERIC_FIND_NEXT_BIT + def_bool y + config GENERIC_HWEIGHT def_bool y diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index 74495a5ea027..b44e37753b9a 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -71,6 +71,12 @@ config GENERIC_CSUM def_bool y depends on SUPERH64 +config GENERIC_FIND_NEXT_BIT + def_bool y + +config GENERIC_FIND_BIT_LE + def_bool y + config GENERIC_HWEIGHT def_bool y diff --git a/trunk/arch/sh/configs/apsh4ad0a_defconfig b/trunk/arch/sh/configs/apsh4ad0a_defconfig index e7583484cc07..77ec0e7b8ddf 100644 --- a/trunk/arch/sh/configs/apsh4ad0a_defconfig +++ b/trunk/arch/sh/configs/apsh4ad0a_defconfig @@ -7,6 +7,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_CGROUPS=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y diff --git a/trunk/arch/sh/configs/sdk7786_defconfig b/trunk/arch/sh/configs/sdk7786_defconfig index 8a7dd7b59c5c..c41650572d79 100644 --- a/trunk/arch/sh/configs/sdk7786_defconfig +++ b/trunk/arch/sh/configs/sdk7786_defconfig @@ -12,6 +12,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_CGROUPS=y CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y diff --git a/trunk/arch/sh/configs/se7206_defconfig b/trunk/arch/sh/configs/se7206_defconfig index 72c3fad7383f..a468ff227fc6 100644 --- a/trunk/arch/sh/configs/se7206_defconfig +++ b/trunk/arch/sh/configs/se7206_defconfig @@ -8,6 +8,7 @@ CONFIG_RCU_TRACE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_CGROUPS=y CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y diff --git a/trunk/arch/sh/configs/shx3_defconfig b/trunk/arch/sh/configs/shx3_defconfig index 6bb413036892..3f92d37c6374 100644 --- a/trunk/arch/sh/configs/shx3_defconfig +++ b/trunk/arch/sh/configs/shx3_defconfig @@ -9,6 +9,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_CGROUPS=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y diff --git a/trunk/arch/sh/configs/urquell_defconfig b/trunk/arch/sh/configs/urquell_defconfig index 8bfa4d056d7a..7b3daec6fefe 100644 --- a/trunk/arch/sh/configs/urquell_defconfig +++ b/trunk/arch/sh/configs/urquell_defconfig @@ -9,6 +9,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_CGROUPS=y CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y diff --git a/trunk/arch/sh/include/asm/kgdb.h b/trunk/arch/sh/include/asm/kgdb.h index f3613952d1ae..4235e228d921 100644 --- a/trunk/arch/sh/include/asm/kgdb.h +++ b/trunk/arch/sh/include/asm/kgdb.h @@ -34,6 +34,5 @@ static inline void arch_kgdb_breakpoint(void) #define CACHE_FLUSH_IS_SAFE 1 #define BREAK_INSTR_SIZE 2 -#define GDB_ADJUSTS_BREAK_OFFSET #endif /* __ASM_SH_KGDB_H */ diff --git a/trunk/arch/sh/include/asm/ptrace.h b/trunk/arch/sh/include/asm/ptrace.h index 40725b4a8018..de167d3a1a80 100644 --- a/trunk/arch/sh/include/asm/ptrace.h +++ b/trunk/arch/sh/include/asm/ptrace.h @@ -40,8 +40,9 @@ #include #define user_mode(regs) (((regs)->sr & 0x40000000)==0) +#define user_stack_pointer(_regs) ((unsigned long)(_regs)->regs[15]) #define kernel_stack_pointer(_regs) ((unsigned long)(_regs)->regs[15]) -#define GET_USP(regs) ((regs)->regs[15]) +#define instruction_pointer(regs) ((unsigned long)(regs)->pc) extern void show_regs(struct pt_regs *); @@ -138,9 +139,6 @@ static inline unsigned long profile_pc(struct pt_regs *regs) return pc; } -#define profile_pc profile_pc - -#include #endif /* __KERNEL__ */ #endif /* __ASM_SH_PTRACE_H */ diff --git a/trunk/arch/sparc/Kconfig b/trunk/arch/sparc/Kconfig index af32e17fa170..63a027c9ada5 100644 --- a/trunk/arch/sparc/Kconfig +++ b/trunk/arch/sparc/Kconfig @@ -190,6 +190,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y if SPARC64 +config GENERIC_FIND_NEXT_BIT + bool + default y + +config GENERIC_FIND_BIT_LE + bool + default y + config GENERIC_HWEIGHT bool default y if !ULTRA_HAS_POPULATION_COUNT diff --git a/trunk/arch/tile/Kconfig b/trunk/arch/tile/Kconfig index e1e50101b3bb..635e1bfb1c5d 100644 --- a/trunk/arch/tile/Kconfig +++ b/trunk/arch/tile/Kconfig @@ -5,6 +5,7 @@ config TILE def_bool y select HAVE_KVM if !TILEGX select GENERIC_FIND_FIRST_BIT + select GENERIC_FIND_NEXT_BIT select USE_GENERIC_SMP_HELPERS select CC_OPTIMIZE_FOR_SIZE select HAVE_GENERIC_HARDIRQS diff --git a/trunk/arch/um/Kconfig.x86 b/trunk/arch/um/Kconfig.x86 index 8aae429a56e2..795ea8e869f4 100644 --- a/trunk/arch/um/Kconfig.x86 +++ b/trunk/arch/um/Kconfig.x86 @@ -15,6 +15,7 @@ endmenu config UML_X86 def_bool y select GENERIC_FIND_FIRST_BIT + select GENERIC_FIND_NEXT_BIT config 64BIT bool diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index da349723d411..483775f42d2a 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -64,6 +64,7 @@ config X86 select HAVE_GENERIC_HARDIRQS select HAVE_SPARSE_IRQ select GENERIC_FIND_FIRST_BIT + select GENERIC_FIND_NEXT_BIT select GENERIC_IRQ_PROBE select GENERIC_PENDING_IRQ if SMP select GENERIC_IRQ_SHOW diff --git a/trunk/arch/x86/configs/i386_defconfig b/trunk/arch/x86/configs/i386_defconfig index 2bf18059fbea..6f9872658dd2 100644 --- a/trunk/arch/x86/configs/i386_defconfig +++ b/trunk/arch/x86/configs/i386_defconfig @@ -10,6 +10,7 @@ CONFIG_TASK_IO_ACCOUNTING=y CONFIG_AUDIT=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_CGROUPS=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y diff --git a/trunk/arch/x86/configs/x86_64_defconfig b/trunk/arch/x86/configs/x86_64_defconfig index 22a0dc8e51dd..ee01a9d5d4f0 100644 --- a/trunk/arch/x86/configs/x86_64_defconfig +++ b/trunk/arch/x86/configs/x86_64_defconfig @@ -11,6 +11,7 @@ CONFIG_TASK_IO_ACCOUNTING=y CONFIG_AUDIT=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_CGROUPS=y +CONFIG_CGROUP_NS=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y diff --git a/trunk/arch/x86/include/asm/kgdb.h b/trunk/arch/x86/include/asm/kgdb.h index 77e95f54570a..396f5b5fc4d7 100644 --- a/trunk/arch/x86/include/asm/kgdb.h +++ b/trunk/arch/x86/include/asm/kgdb.h @@ -77,7 +77,6 @@ static inline void arch_kgdb_breakpoint(void) } #define BREAK_INSTR_SIZE 1 #define CACHE_FLUSH_IS_SAFE 1 -#define GDB_ADJUSTS_BREAK_OFFSET extern int kgdb_ll_trap(int cmd, const char *str, struct pt_regs *regs, long err, int trap, int sig); diff --git a/trunk/arch/x86/include/asm/ptrace.h b/trunk/arch/x86/include/asm/ptrace.h index 94e7618fcac8..1babf8adecdf 100644 --- a/trunk/arch/x86/include/asm/ptrace.h +++ b/trunk/arch/x86/include/asm/ptrace.h @@ -136,7 +136,6 @@ struct cpuinfo_x86; struct task_struct; extern unsigned long profile_pc(struct pt_regs *regs); -#define profile_pc profile_pc extern unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs); @@ -203,11 +202,20 @@ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) #endif } -#define GET_IP(regs) ((regs)->ip) -#define GET_FP(regs) ((regs)->bp) -#define GET_USP(regs) ((regs)->sp) +static inline unsigned long instruction_pointer(struct pt_regs *regs) +{ + return regs->ip; +} + +static inline unsigned long frame_pointer(struct pt_regs *regs) +{ + return regs->bp; +} -#include +static inline unsigned long user_stack_pointer(struct pt_regs *regs) +{ + return regs->sp; +} /* Query offset/name of register from its name/offset */ extern int regs_query_register_offset(const char *name); diff --git a/trunk/arch/x86/include/asm/tsc.h b/trunk/arch/x86/include/asm/tsc.h index 9db5583b6d38..83e2efd181e2 100644 --- a/trunk/arch/x86/include/asm/tsc.h +++ b/trunk/arch/x86/include/asm/tsc.h @@ -51,10 +51,6 @@ extern int unsynchronized_tsc(void); extern int check_tsc_unstable(void); extern unsigned long native_calibrate_tsc(void); -#ifdef CONFIG_X86_64 -extern cycles_t vread_tsc(void); -#endif - /* * Boot-time check whether the TSCs are synchronized across * all CPUs/cores: diff --git a/trunk/arch/x86/include/asm/vdso.h b/trunk/arch/x86/include/asm/vdso.h index bb0522850b74..9064052b73de 100644 --- a/trunk/arch/x86/include/asm/vdso.h +++ b/trunk/arch/x86/include/asm/vdso.h @@ -1,6 +1,20 @@ #ifndef _ASM_X86_VDSO_H #define _ASM_X86_VDSO_H +#ifdef CONFIG_X86_64 +extern const char VDSO64_PRELINK[]; + +/* + * Given a pointer to the vDSO image, find the pointer to VDSO64_name + * as that symbol is defined in the vDSO sources or linker script. + */ +#define VDSO64_SYMBOL(base, name) \ +({ \ + extern const char VDSO64_##name[]; \ + (void *)(VDSO64_##name - VDSO64_PRELINK + (unsigned long)(base)); \ +}) +#endif + #if defined CONFIG_X86_32 || defined CONFIG_COMPAT extern const char VDSO32_PRELINK[]; diff --git a/trunk/arch/x86/include/asm/vgtod.h b/trunk/arch/x86/include/asm/vgtod.h index 646b4c1ca695..3d61e204826f 100644 --- a/trunk/arch/x86/include/asm/vgtod.h +++ b/trunk/arch/x86/include/asm/vgtod.h @@ -23,6 +23,8 @@ struct vsyscall_gtod_data { struct timespec wall_to_monotonic; struct timespec wall_time_coarse; }; +extern struct vsyscall_gtod_data __vsyscall_gtod_data +__section_vsyscall_gtod_data; extern struct vsyscall_gtod_data vsyscall_gtod_data; #endif /* _ASM_X86_VGTOD_H */ diff --git a/trunk/arch/x86/include/asm/vsyscall.h b/trunk/arch/x86/include/asm/vsyscall.h index d55597351f6a..d0983d255fbd 100644 --- a/trunk/arch/x86/include/asm/vsyscall.h +++ b/trunk/arch/x86/include/asm/vsyscall.h @@ -16,19 +16,27 @@ enum vsyscall_num { #ifdef __KERNEL__ #include +#define __section_vgetcpu_mode __attribute__ ((unused, __section__ (".vgetcpu_mode"), aligned(16))) +#define __section_jiffies __attribute__ ((unused, __section__ (".jiffies"), aligned(16))) + /* Definitions for CONFIG_GENERIC_TIME definitions */ +#define __section_vsyscall_gtod_data __attribute__ \ + ((unused, __section__ (".vsyscall_gtod_data"),aligned(16))) +#define __section_vsyscall_clock __attribute__ \ + ((unused, __section__ (".vsyscall_clock"),aligned(16))) #define __vsyscall_fn \ __attribute__ ((unused, __section__(".vsyscall_fn"))) notrace #define VGETCPU_RDTSCP 1 #define VGETCPU_LSL 2 +extern int __vgetcpu_mode; +extern volatile unsigned long __jiffies; + /* kernel space (writeable) */ extern int vgetcpu_mode; extern struct timezone sys_tz; -#include - extern void map_vsyscall(void); #endif /* __KERNEL__ */ diff --git a/trunk/arch/x86/include/asm/vvar.h b/trunk/arch/x86/include/asm/vvar.h deleted file mode 100644 index 341b3559452b..000000000000 --- a/trunk/arch/x86/include/asm/vvar.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * vvar.h: Shared vDSO/kernel variable declarations - * Copyright (c) 2011 Andy Lutomirski - * Subject to the GNU General Public License, version 2 - * - * A handful of variables are accessible (read-only) from userspace - * code in the vsyscall page and the vdso. They are declared here. - * Some other file must define them with DEFINE_VVAR. - * - * In normal kernel code, they are used like any other variable. - * In user code, they are accessed through the VVAR macro. - * - * Each of these variables lives in the vsyscall page, and each - * one needs a unique offset within the little piece of the page - * reserved for vvars. Specify that offset in DECLARE_VVAR. - * (There are 896 bytes available. If you mess up, the linker will - * catch it.) - */ - -/* Offset of vars within vsyscall page */ -#define VSYSCALL_VARS_OFFSET (3072 + 128) - -#if defined(__VVAR_KERNEL_LDS) - -/* The kernel linker script defines its own magic to put vvars in the - * right place. - */ -#define DECLARE_VVAR(offset, type, name) \ - EMIT_VVAR(name, VSYSCALL_VARS_OFFSET + offset) - -#else - -#define DECLARE_VVAR(offset, type, name) \ - static type const * const vvaraddr_ ## name = \ - (void *)(VSYSCALL_START + VSYSCALL_VARS_OFFSET + (offset)); - -#define DEFINE_VVAR(type, name) \ - type __vvar_ ## name \ - __attribute__((section(".vsyscall_var_" #name), aligned(16))) - -#define VVAR(name) (*vvaraddr_ ## name) - -#endif - -/* DECLARE_VVAR(offset, type, name) */ - -DECLARE_VVAR(0, volatile unsigned long, jiffies) -DECLARE_VVAR(8, int, vgetcpu_mode) -DECLARE_VVAR(128, struct vsyscall_gtod_data, vsyscall_gtod_data) - -#undef DECLARE_VVAR -#undef VSYSCALL_VARS_OFFSET diff --git a/trunk/arch/x86/include/asm/xen/hypercall.h b/trunk/arch/x86/include/asm/xen/hypercall.h index d240ea950519..8508bfe52296 100644 --- a/trunk/arch/x86/include/asm/xen/hypercall.h +++ b/trunk/arch/x86/include/asm/xen/hypercall.h @@ -447,13 +447,6 @@ HYPERVISOR_hvm_op(int op, void *arg) return _hypercall2(unsigned long, hvm_op, op, arg); } -static inline int -HYPERVISOR_tmem_op( - struct tmem_op *op) -{ - return _hypercall1(int, tmem_op, op); -} - static inline void MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set) { diff --git a/trunk/arch/x86/kernel/Makefile b/trunk/arch/x86/kernel/Makefile index f5abe3a245b8..250806472a7e 100644 --- a/trunk/arch/x86/kernel/Makefile +++ b/trunk/arch/x86/kernel/Makefile @@ -8,6 +8,7 @@ CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE) ifdef CONFIG_FUNCTION_TRACER # Do not profile debug and lowlevel utilities +CFLAGS_REMOVE_tsc.o = -pg CFLAGS_REMOVE_rtc.o = -pg CFLAGS_REMOVE_paravirt-spinlocks.o = -pg CFLAGS_REMOVE_pvclock.o = -pg @@ -23,16 +24,13 @@ endif nostackp := $(call cc-option, -fno-stack-protector) CFLAGS_vsyscall_64.o := $(PROFILING) -g0 $(nostackp) CFLAGS_hpet.o := $(nostackp) -CFLAGS_vread_tsc_64.o := $(nostackp) +CFLAGS_tsc.o := $(nostackp) CFLAGS_paravirt.o := $(nostackp) GCOV_PROFILE_vsyscall_64.o := n GCOV_PROFILE_hpet.o := n GCOV_PROFILE_tsc.o := n GCOV_PROFILE_paravirt.o := n -# vread_tsc_64 is hot and should be fully optimized: -CFLAGS_REMOVE_vread_tsc_64.o = -pg -fno-optimize-sibling-calls - obj-y := process_$(BITS).o signal.o entry_$(BITS).o obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o obj-y += time.o ioport.o ldt.o dumpstack.o @@ -41,7 +39,7 @@ obj-$(CONFIG_IRQ_WORK) += irq_work.o obj-y += probe_roms.o obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o -obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o vread_tsc_64.o +obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o obj-y += bootflag.o e820.o obj-y += pci-dma.o quirks.o topology.o kdebugfs.o obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o diff --git a/trunk/arch/x86/kernel/time.c b/trunk/arch/x86/kernel/time.c index 00cbb272627f..25a28a245937 100644 --- a/trunk/arch/x86/kernel/time.c +++ b/trunk/arch/x86/kernel/time.c @@ -23,7 +23,7 @@ #include #ifdef CONFIG_X86_64 -DEFINE_VVAR(volatile unsigned long, jiffies) = INITIAL_JIFFIES; +volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; #endif unsigned long profile_pc(struct pt_regs *regs) diff --git a/trunk/arch/x86/kernel/tsc.c b/trunk/arch/x86/kernel/tsc.c index 6cc6922262af..9335bf7dd2e7 100644 --- a/trunk/arch/x86/kernel/tsc.c +++ b/trunk/arch/x86/kernel/tsc.c @@ -763,6 +763,25 @@ static cycle_t read_tsc(struct clocksource *cs) ret : clocksource_tsc.cycle_last; } +#ifdef CONFIG_X86_64 +static cycle_t __vsyscall_fn vread_tsc(void) +{ + cycle_t ret; + + /* + * Surround the RDTSC by barriers, to make sure it's not + * speculated to outside the seqlock critical section and + * does not cause time warps: + */ + rdtsc_barrier(); + ret = (cycle_t)vget_cycles(); + rdtsc_barrier(); + + return ret >= __vsyscall_gtod_data.clock.cycle_last ? + ret : __vsyscall_gtod_data.clock.cycle_last; +} +#endif + static void resume_tsc(struct clocksource *cs) { clocksource_tsc.cycle_last = 0; diff --git a/trunk/arch/x86/kernel/vmlinux.lds.S b/trunk/arch/x86/kernel/vmlinux.lds.S index 89aed99aafce..61682f0ac264 100644 --- a/trunk/arch/x86/kernel/vmlinux.lds.S +++ b/trunk/arch/x86/kernel/vmlinux.lds.S @@ -161,12 +161,6 @@ SECTIONS #define VVIRT_OFFSET (VSYSCALL_ADDR - __vsyscall_0) #define VVIRT(x) (ADDR(x) - VVIRT_OFFSET) -#define EMIT_VVAR(x, offset) .vsyscall_var_ ## x \ - ADDR(.vsyscall_0) + offset \ - : AT(VLOAD(.vsyscall_var_ ## x)) { \ - *(.vsyscall_var_ ## x) \ - } \ - x = VVIRT(.vsyscall_var_ ## x); . = ALIGN(4096); __vsyscall_0 = .; @@ -181,6 +175,18 @@ SECTIONS *(.vsyscall_fn) } + . = ALIGN(L1_CACHE_BYTES); + .vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data)) { + *(.vsyscall_gtod_data) + } + + vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data); + .vsyscall_clock : AT(VLOAD(.vsyscall_clock)) { + *(.vsyscall_clock) + } + vsyscall_clock = VVIRT(.vsyscall_clock); + + .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) { *(.vsyscall_1) } @@ -188,14 +194,21 @@ SECTIONS *(.vsyscall_2) } + .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { + *(.vgetcpu_mode) + } + vgetcpu_mode = VVIRT(.vgetcpu_mode); + + . = ALIGN(L1_CACHE_BYTES); + .jiffies : AT(VLOAD(.jiffies)) { + *(.jiffies) + } + jiffies = VVIRT(.jiffies); + .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) { *(.vsyscall_3) } -#define __VVAR_KERNEL_LDS -#include -#undef __VVAR_KERNEL_LDS - . = __vsyscall_0 + PAGE_SIZE; #undef VSYSCALL_ADDR @@ -203,7 +216,6 @@ SECTIONS #undef VLOAD #undef VVIRT_OFFSET #undef VVIRT -#undef EMIT_VVAR #endif /* CONFIG_X86_64 */ diff --git a/trunk/arch/x86/kernel/vread_tsc_64.c b/trunk/arch/x86/kernel/vread_tsc_64.c deleted file mode 100644 index a81aa9e9894c..000000000000 --- a/trunk/arch/x86/kernel/vread_tsc_64.c +++ /dev/null @@ -1,36 +0,0 @@ -/* This code runs in userspace. */ - -#define DISABLE_BRANCH_PROFILING -#include - -notrace cycle_t __vsyscall_fn vread_tsc(void) -{ - cycle_t ret; - u64 last; - - /* - * Empirically, a fence (of type that depends on the CPU) - * before rdtsc is enough to ensure that rdtsc is ordered - * with respect to loads. The various CPU manuals are unclear - * as to whether rdtsc can be reordered with later loads, - * but no one has ever seen it happen. - */ - rdtsc_barrier(); - ret = (cycle_t)vget_cycles(); - - last = VVAR(vsyscall_gtod_data).clock.cycle_last; - - if (likely(ret >= last)) - return ret; - - /* - * GCC likes to generate cmov here, but this branch is extremely - * predictable (it's just a funciton of time and the likely is - * very likely) and there's a data dependence, so force GCC - * to generate a branch instead. I don't barrier() because - * we don't actually need a barrier, and if this function - * ever gets inlined it will generate worse code. - */ - asm volatile (""); - return last; -} diff --git a/trunk/arch/x86/kernel/vsyscall_64.c b/trunk/arch/x86/kernel/vsyscall_64.c index 3e682184d76c..dcbb28c4b694 100644 --- a/trunk/arch/x86/kernel/vsyscall_64.c +++ b/trunk/arch/x86/kernel/vsyscall_64.c @@ -49,10 +49,17 @@ __attribute__ ((unused, __section__(".vsyscall_" #nr))) notrace #define __syscall_clobber "r11","cx","memory" -DEFINE_VVAR(int, vgetcpu_mode); -DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) = +/* + * vsyscall_gtod_data contains data that is : + * - readonly from vsyscalls + * - written by timer interrupt or systcl (/proc/sys/kernel/vsyscall64) + * Try to keep this structure as small as possible to avoid cache line ping pongs + */ +int __vgetcpu_mode __section_vgetcpu_mode; + +struct vsyscall_gtod_data __vsyscall_gtod_data __section_vsyscall_gtod_data = { - .lock = __SEQLOCK_UNLOCKED(__vsyscall_gtod_data.lock), + .lock = SEQLOCK_UNLOCKED, .sysctl_enabled = 1, }; @@ -90,7 +97,7 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm, */ static __always_inline void do_get_tz(struct timezone * tz) { - *tz = VVAR(vsyscall_gtod_data).sys_tz; + *tz = __vsyscall_gtod_data.sys_tz; } static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz) @@ -119,24 +126,23 @@ static __always_inline void do_vgettimeofday(struct timeval * tv) unsigned long mult, shift, nsec; cycle_t (*vread)(void); do { - seq = read_seqbegin(&VVAR(vsyscall_gtod_data).lock); + seq = read_seqbegin(&__vsyscall_gtod_data.lock); - vread = VVAR(vsyscall_gtod_data).clock.vread; - if (unlikely(!VVAR(vsyscall_gtod_data).sysctl_enabled || - !vread)) { + vread = __vsyscall_gtod_data.clock.vread; + if (unlikely(!__vsyscall_gtod_data.sysctl_enabled || !vread)) { gettimeofday(tv,NULL); return; } now = vread(); - base = VVAR(vsyscall_gtod_data).clock.cycle_last; - mask = VVAR(vsyscall_gtod_data).clock.mask; - mult = VVAR(vsyscall_gtod_data).clock.mult; - shift = VVAR(vsyscall_gtod_data).clock.shift; + base = __vsyscall_gtod_data.clock.cycle_last; + mask = __vsyscall_gtod_data.clock.mask; + mult = __vsyscall_gtod_data.clock.mult; + shift = __vsyscall_gtod_data.clock.shift; - tv->tv_sec = VVAR(vsyscall_gtod_data).wall_time_sec; - nsec = VVAR(vsyscall_gtod_data).wall_time_nsec; - } while (read_seqretry(&VVAR(vsyscall_gtod_data).lock, seq)); + tv->tv_sec = __vsyscall_gtod_data.wall_time_sec; + nsec = __vsyscall_gtod_data.wall_time_nsec; + } while (read_seqretry(&__vsyscall_gtod_data.lock, seq)); /* calculate interval: */ cycle_delta = (now - base) & mask; @@ -165,15 +171,15 @@ time_t __vsyscall(1) vtime(time_t *t) { unsigned seq; time_t result; - if (unlikely(!VVAR(vsyscall_gtod_data).sysctl_enabled)) + if (unlikely(!__vsyscall_gtod_data.sysctl_enabled)) return time_syscall(t); do { - seq = read_seqbegin(&VVAR(vsyscall_gtod_data).lock); + seq = read_seqbegin(&__vsyscall_gtod_data.lock); - result = VVAR(vsyscall_gtod_data).wall_time_sec; + result = __vsyscall_gtod_data.wall_time_sec; - } while (read_seqretry(&VVAR(vsyscall_gtod_data).lock, seq)); + } while (read_seqretry(&__vsyscall_gtod_data.lock, seq)); if (t) *t = result; @@ -202,9 +208,9 @@ vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache) We do this here because otherwise user space would do it on its own in a likely inferior way (no access to jiffies). If you don't like it pass NULL. */ - if (tcache && tcache->blob[0] == (j = VVAR(jiffies))) { + if (tcache && tcache->blob[0] == (j = __jiffies)) { p = tcache->blob[1]; - } else if (VVAR(vgetcpu_mode) == VGETCPU_RDTSCP) { + } else if (__vgetcpu_mode == VGETCPU_RDTSCP) { /* Load per CPU data from RDTSCP */ native_read_tscp(&p); } else { diff --git a/trunk/arch/x86/vdso/Makefile b/trunk/arch/x86/vdso/Makefile index bef0bc962400..b6552b189bcd 100644 --- a/trunk/arch/x86/vdso/Makefile +++ b/trunk/arch/x86/vdso/Makefile @@ -11,7 +11,7 @@ vdso-install-$(VDSO32-y) += $(vdso32-images) # files to link into the vdso -vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o +vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o vvar.o # files to link into kernel obj-$(VDSO64-y) += vma.o vdso.o @@ -37,24 +37,11 @@ $(obj)/%.so: OBJCOPYFLAGS := -S $(obj)/%.so: $(obj)/%.so.dbg FORCE $(call if_changed,objcopy) -# -# Don't omit frame pointers for ease of userspace debugging, but do -# optimize sibling calls. -# CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \ - $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \ - -fno-omit-frame-pointer -foptimize-sibling-calls + $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) $(vobjs): KBUILD_CFLAGS += $(CFL) -# -# vDSO code runs in userspace and -pg doesn't help with profiling anyway. -# -CFLAGS_REMOVE_vdso-note.o = -pg -CFLAGS_REMOVE_vclock_gettime.o = -pg -CFLAGS_REMOVE_vgetcpu.o = -pg -CFLAGS_REMOVE_vvar.o = -pg - targets += vdso-syms.lds obj-$(VDSO64-y) += vdso-syms.lds diff --git a/trunk/arch/x86/vdso/vclock_gettime.c b/trunk/arch/x86/vdso/vclock_gettime.c index a724905fdae7..ee55754cc3c5 100644 --- a/trunk/arch/x86/vdso/vclock_gettime.c +++ b/trunk/arch/x86/vdso/vclock_gettime.c @@ -2,7 +2,7 @@ * Copyright 2006 Andi Kleen, SUSE Labs. * Subject to the GNU Public License, v.2 * - * Fast user context implementation of clock_gettime, gettimeofday, and time. + * Fast user context implementation of clock_gettime and gettimeofday. * * The code should have no internal unresolved relocations. * Check with readelf after changing. @@ -22,8 +22,9 @@ #include #include #include +#include "vextern.h" -#define gtod (&VVAR(vsyscall_gtod_data)) +#define gtod vdso_vsyscall_gtod_data notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) { @@ -55,6 +56,22 @@ notrace static noinline int do_realtime(struct timespec *ts) return 0; } +/* Copy of the version in kernel/time.c which we cannot directly access */ +notrace static void +vset_normalized_timespec(struct timespec *ts, long sec, long nsec) +{ + while (nsec >= NSEC_PER_SEC) { + nsec -= NSEC_PER_SEC; + ++sec; + } + while (nsec < 0) { + nsec += NSEC_PER_SEC; + --sec; + } + ts->tv_sec = sec; + ts->tv_nsec = nsec; +} + notrace static noinline int do_monotonic(struct timespec *ts) { unsigned long seq, ns, secs; @@ -65,17 +82,7 @@ notrace static noinline int do_monotonic(struct timespec *ts) secs += gtod->wall_to_monotonic.tv_sec; ns += gtod->wall_to_monotonic.tv_nsec; } while (unlikely(read_seqretry(>od->lock, seq))); - - /* wall_time_nsec, vgetns(), and wall_to_monotonic.tv_nsec - * are all guaranteed to be nonnegative. - */ - while (ns >= NSEC_PER_SEC) { - ns -= NSEC_PER_SEC; - ++secs; - } - ts->tv_sec = secs; - ts->tv_nsec = ns; - + vset_normalized_timespec(ts, secs, ns); return 0; } @@ -100,17 +107,7 @@ notrace static noinline int do_monotonic_coarse(struct timespec *ts) secs += gtod->wall_to_monotonic.tv_sec; ns += gtod->wall_to_monotonic.tv_nsec; } while (unlikely(read_seqretry(>od->lock, seq))); - - /* wall_time_nsec and wall_to_monotonic.tv_nsec are - * guaranteed to be between 0 and NSEC_PER_SEC. - */ - if (ns >= NSEC_PER_SEC) { - ns -= NSEC_PER_SEC; - ++secs; - } - ts->tv_sec = secs; - ts->tv_nsec = ns; - + vset_normalized_timespec(ts, secs, ns); return 0; } @@ -160,32 +157,3 @@ notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) } int gettimeofday(struct timeval *, struct timezone *) __attribute__((weak, alias("__vdso_gettimeofday"))); - -/* This will break when the xtime seconds get inaccurate, but that is - * unlikely */ - -static __always_inline long time_syscall(long *t) -{ - long secs; - asm volatile("syscall" - : "=a" (secs) - : "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory"); - return secs; -} - -notrace time_t __vdso_time(time_t *t) -{ - time_t result; - - if (unlikely(!VVAR(vsyscall_gtod_data).sysctl_enabled)) - return time_syscall(t); - - /* This is atomic on x86_64 so we don't need any locks. */ - result = ACCESS_ONCE(VVAR(vsyscall_gtod_data).wall_time_sec); - - if (t) - *t = result; - return result; -} -int time(time_t *t) - __attribute__((weak, alias("__vdso_time"))); diff --git a/trunk/arch/x86/vdso/vdso.lds.S b/trunk/arch/x86/vdso/vdso.lds.S index b96b2677cad8..4e5dd3b4de7f 100644 --- a/trunk/arch/x86/vdso/vdso.lds.S +++ b/trunk/arch/x86/vdso/vdso.lds.S @@ -23,10 +23,15 @@ VERSION { __vdso_gettimeofday; getcpu; __vdso_getcpu; - time; - __vdso_time; local: *; }; } VDSO64_PRELINK = VDSO_PRELINK; + +/* + * Define VDSO64_x for each VEXTERN(x), for use via VDSO64_SYMBOL. + */ +#define VEXTERN(x) VDSO64_ ## x = vdso_ ## x; +#include "vextern.h" +#undef VEXTERN diff --git a/trunk/arch/x86/vdso/vextern.h b/trunk/arch/x86/vdso/vextern.h new file mode 100644 index 000000000000..1683ba2ae3e8 --- /dev/null +++ b/trunk/arch/x86/vdso/vextern.h @@ -0,0 +1,16 @@ +#ifndef VEXTERN +#include +#define VEXTERN(x) \ + extern typeof(x) *vdso_ ## x __attribute__((visibility("hidden"))); +#endif + +#define VMAGIC 0xfeedbabeabcdefabUL + +/* Any kernel variables used in the vDSO must be exported in the main + kernel's vmlinux.lds.S/vsyscall.h/proper __section and + put into vextern.h and be referenced as a pointer with vdso prefix. + The main kernel later fills in the values. */ + +VEXTERN(jiffies) +VEXTERN(vgetcpu_mode) +VEXTERN(vsyscall_gtod_data) diff --git a/trunk/arch/x86/vdso/vgetcpu.c b/trunk/arch/x86/vdso/vgetcpu.c index 5463ad558573..9fbc6b20026b 100644 --- a/trunk/arch/x86/vdso/vgetcpu.c +++ b/trunk/arch/x86/vdso/vgetcpu.c @@ -11,13 +11,14 @@ #include #include #include +#include "vextern.h" notrace long __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused) { unsigned int p; - if (VVAR(vgetcpu_mode) == VGETCPU_RDTSCP) { + if (*vdso_vgetcpu_mode == VGETCPU_RDTSCP) { /* Load per CPU data from RDTSCP */ native_read_tscp(&p); } else { diff --git a/trunk/arch/x86/vdso/vma.c b/trunk/arch/x86/vdso/vma.c index 7abd2be0f9b9..4b5d26f108bb 100644 --- a/trunk/arch/x86/vdso/vma.c +++ b/trunk/arch/x86/vdso/vma.c @@ -15,6 +15,9 @@ #include #include +#include "vextern.h" /* Just for VMAGIC. */ +#undef VEXTERN + unsigned int __read_mostly vdso_enabled = 1; extern char vdso_start[], vdso_end[]; @@ -23,10 +26,20 @@ extern unsigned short vdso_sync_cpuid; static struct page **vdso_pages; static unsigned vdso_size; +static inline void *var_ref(void *p, char *name) +{ + if (*(void **)p != (void *)VMAGIC) { + printk("VDSO: variable %s broken\n", name); + vdso_enabled = 0; + } + return p; +} + static int __init init_vdso_vars(void) { int npages = (vdso_end - vdso_start + PAGE_SIZE - 1) / PAGE_SIZE; int i; + char *vbase; vdso_size = npages << PAGE_SHIFT; vdso_pages = kmalloc(sizeof(struct page *) * npages, GFP_KERNEL); @@ -41,6 +54,20 @@ static int __init init_vdso_vars(void) copy_page(page_address(p), vdso_start + i*PAGE_SIZE); } + vbase = vmap(vdso_pages, npages, 0, PAGE_KERNEL); + if (!vbase) + goto oom; + + if (memcmp(vbase, "\177ELF", 4)) { + printk("VDSO: I'm broken; not ELF\n"); + vdso_enabled = 0; + } + +#define VEXTERN(x) \ + *(typeof(__ ## x) **) var_ref(VDSO64_SYMBOL(vbase, x), #x) = &__ ## x; +#include "vextern.h" +#undef VEXTERN + vunmap(vbase); return 0; oom: diff --git a/trunk/arch/x86/vdso/vvar.c b/trunk/arch/x86/vdso/vvar.c new file mode 100644 index 000000000000..1b7e703684f9 --- /dev/null +++ b/trunk/arch/x86/vdso/vvar.c @@ -0,0 +1,12 @@ +/* Define pointer to external vDSO variables. + These are part of the vDSO. The kernel fills in the real addresses + at boot time. This is done because when the vdso is linked the + kernel isn't yet and we don't know the final addresses. */ +#include +#include +#include +#include +#include + +#define VEXTERN(x) typeof (__ ## x) *const vdso_ ## x = (void *)VMAGIC; +#include "vextern.h" diff --git a/trunk/arch/x86/xen/mmu.c b/trunk/arch/x86/xen/mmu.c index dc708dcc62f1..02d752460371 100644 --- a/trunk/arch/x86/xen/mmu.c +++ b/trunk/arch/x86/xen/mmu.c @@ -75,12 +75,67 @@ #include "mmu.h" #include "debugfs.h" +#define MMU_UPDATE_HISTO 30 + /* * Protects atomic reservation decrease/increase against concurrent increases. * Also protects non-atomic updates of current_pages and balloon lists. */ DEFINE_SPINLOCK(xen_reservation_lock); +#ifdef CONFIG_XEN_DEBUG_FS + +static struct { + u32 pgd_update; + u32 pgd_update_pinned; + u32 pgd_update_batched; + + u32 pud_update; + u32 pud_update_pinned; + u32 pud_update_batched; + + u32 pmd_update; + u32 pmd_update_pinned; + u32 pmd_update_batched; + + u32 pte_update; + u32 pte_update_pinned; + u32 pte_update_batched; + + u32 mmu_update; + u32 mmu_update_extended; + u32 mmu_update_histo[MMU_UPDATE_HISTO]; + + u32 prot_commit; + u32 prot_commit_batched; + + u32 set_pte_at; + u32 set_pte_at_batched; + u32 set_pte_at_pinned; + u32 set_pte_at_current; + u32 set_pte_at_kernel; +} mmu_stats; + +static u8 zero_stats; + +static inline void check_zero(void) +{ + if (unlikely(zero_stats)) { + memset(&mmu_stats, 0, sizeof(mmu_stats)); + zero_stats = 0; + } +} + +#define ADD_STATS(elem, val) \ + do { check_zero(); mmu_stats.elem += (val); } while(0) + +#else /* !CONFIG_XEN_DEBUG_FS */ + +#define ADD_STATS(elem, val) do { (void)(val); } while(0) + +#endif /* CONFIG_XEN_DEBUG_FS */ + + /* * Identity map, in addition to plain kernel map. This needs to be * large enough to allocate page table pages to allocate the rest. @@ -188,6 +243,11 @@ static bool xen_page_pinned(void *ptr) return PagePinned(page); } +static bool xen_iomap_pte(pte_t pte) +{ + return pte_flags(pte) & _PAGE_IOMAP; +} + void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid) { struct multicall_space mcs; @@ -197,7 +257,7 @@ void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid) u = mcs.args; /* ptep might be kmapped when using 32-bit HIGHPTE */ - u->ptr = virt_to_machine(ptep).maddr; + u->ptr = arbitrary_virt_to_machine(ptep).maddr; u->val = pte_val_ma(pteval); MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, domid); @@ -206,6 +266,11 @@ void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid) } EXPORT_SYMBOL_GPL(xen_set_domain_pte); +static void xen_set_iomap_pte(pte_t *ptep, pte_t pteval) +{ + xen_set_domain_pte(ptep, pteval, DOMID_IO); +} + static void xen_extend_mmu_update(const struct mmu_update *update) { struct multicall_space mcs; @@ -214,17 +279,27 @@ static void xen_extend_mmu_update(const struct mmu_update *update) mcs = xen_mc_extend_args(__HYPERVISOR_mmu_update, sizeof(*u)); if (mcs.mc != NULL) { + ADD_STATS(mmu_update_extended, 1); + ADD_STATS(mmu_update_histo[mcs.mc->args[1]], -1); + mcs.mc->args[1]++; + + if (mcs.mc->args[1] < MMU_UPDATE_HISTO) + ADD_STATS(mmu_update_histo[mcs.mc->args[1]], 1); + else + ADD_STATS(mmu_update_histo[0], 1); } else { + ADD_STATS(mmu_update, 1); mcs = __xen_mc_entry(sizeof(*u)); MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, DOMID_SELF); + ADD_STATS(mmu_update_histo[1], 1); } u = mcs.args; *u = *update; } -static void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val) +void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val) { struct mmu_update u; @@ -237,13 +312,17 @@ static void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val) u.val = pmd_val_ma(val); xen_extend_mmu_update(&u); + ADD_STATS(pmd_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); + xen_mc_issue(PARAVIRT_LAZY_MMU); preempt_enable(); } -static void xen_set_pmd(pmd_t *ptr, pmd_t val) +void xen_set_pmd(pmd_t *ptr, pmd_t val) { + ADD_STATS(pmd_update, 1); + /* If page is not pinned, we can just update the entry directly */ if (!xen_page_pinned(ptr)) { @@ -251,6 +330,8 @@ static void xen_set_pmd(pmd_t *ptr, pmd_t val) return; } + ADD_STATS(pmd_update_pinned, 1); + xen_set_pmd_hyper(ptr, val); } @@ -263,34 +344,35 @@ void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags) set_pte_vaddr(vaddr, mfn_pte(mfn, flags)); } -static bool xen_batched_set_pte(pte_t *ptep, pte_t pteval) +void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pteval) { - struct mmu_update u; - - if (paravirt_get_lazy_mode() != PARAVIRT_LAZY_MMU) - return false; - - xen_mc_batch(); - - u.ptr = virt_to_machine(ptep).maddr | MMU_NORMAL_PT_UPDATE; - u.val = pte_val_ma(pteval); - xen_extend_mmu_update(&u); - - xen_mc_issue(PARAVIRT_LAZY_MMU); + if (xen_iomap_pte(pteval)) { + xen_set_iomap_pte(ptep, pteval); + goto out; + } - return true; -} + ADD_STATS(set_pte_at, 1); +// ADD_STATS(set_pte_at_pinned, xen_page_pinned(ptep)); + ADD_STATS(set_pte_at_current, mm == current->mm); + ADD_STATS(set_pte_at_kernel, mm == &init_mm); -static void xen_set_pte(pte_t *ptep, pte_t pteval) -{ - if (!xen_batched_set_pte(ptep, pteval)) - native_set_pte(ptep, pteval); -} + if (mm == current->mm || mm == &init_mm) { + if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) { + struct multicall_space mcs; + mcs = xen_mc_entry(0); -static void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pteval) -{ + MULTI_update_va_mapping(mcs.mc, addr, pteval, 0); + ADD_STATS(set_pte_at_batched, 1); + xen_mc_issue(PARAVIRT_LAZY_MMU); + goto out; + } else + if (HYPERVISOR_update_va_mapping(addr, pteval, 0) == 0) + goto out; + } xen_set_pte(ptep, pteval); + +out: return; } pte_t xen_ptep_modify_prot_start(struct mm_struct *mm, @@ -307,10 +389,13 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr, xen_mc_batch(); - u.ptr = virt_to_machine(ptep).maddr | MMU_PT_UPDATE_PRESERVE_AD; + u.ptr = arbitrary_virt_to_machine(ptep).maddr | MMU_PT_UPDATE_PRESERVE_AD; u.val = pte_val_ma(pte); xen_extend_mmu_update(&u); + ADD_STATS(prot_commit, 1); + ADD_STATS(prot_commit_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); + xen_mc_issue(PARAVIRT_LAZY_MMU); } @@ -378,7 +463,7 @@ static pteval_t iomap_pte(pteval_t val) return val; } -static pteval_t xen_pte_val(pte_t pte) +pteval_t xen_pte_val(pte_t pte) { pteval_t pteval = pte.pte; @@ -395,7 +480,7 @@ static pteval_t xen_pte_val(pte_t pte) } PV_CALLEE_SAVE_REGS_THUNK(xen_pte_val); -static pgdval_t xen_pgd_val(pgd_t pgd) +pgdval_t xen_pgd_val(pgd_t pgd) { return pte_mfn_to_pfn(pgd.pgd); } @@ -426,7 +511,7 @@ void xen_set_pat(u64 pat) WARN_ON(pat != 0x0007010600070106ull); } -static pte_t xen_make_pte(pteval_t pte) +pte_t xen_make_pte(pteval_t pte) { phys_addr_t addr = (pte & PTE_PFN_MASK); @@ -496,20 +581,20 @@ pte_t xen_make_pte_debug(pteval_t pte) PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_debug); #endif -static pgd_t xen_make_pgd(pgdval_t pgd) +pgd_t xen_make_pgd(pgdval_t pgd) { pgd = pte_pfn_to_mfn(pgd); return native_make_pgd(pgd); } PV_CALLEE_SAVE_REGS_THUNK(xen_make_pgd); -static pmdval_t xen_pmd_val(pmd_t pmd) +pmdval_t xen_pmd_val(pmd_t pmd) { return pte_mfn_to_pfn(pmd.pmd); } PV_CALLEE_SAVE_REGS_THUNK(xen_pmd_val); -static void xen_set_pud_hyper(pud_t *ptr, pud_t val) +void xen_set_pud_hyper(pud_t *ptr, pud_t val) { struct mmu_update u; @@ -522,13 +607,17 @@ static void xen_set_pud_hyper(pud_t *ptr, pud_t val) u.val = pud_val_ma(val); xen_extend_mmu_update(&u); + ADD_STATS(pud_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); + xen_mc_issue(PARAVIRT_LAZY_MMU); preempt_enable(); } -static void xen_set_pud(pud_t *ptr, pud_t val) +void xen_set_pud(pud_t *ptr, pud_t val) { + ADD_STATS(pud_update, 1); + /* If page is not pinned, we can just update the entry directly */ if (!xen_page_pinned(ptr)) { @@ -536,28 +625,56 @@ static void xen_set_pud(pud_t *ptr, pud_t val) return; } + ADD_STATS(pud_update_pinned, 1); + xen_set_pud_hyper(ptr, val); } +void xen_set_pte(pte_t *ptep, pte_t pte) +{ + if (xen_iomap_pte(pte)) { + xen_set_iomap_pte(ptep, pte); + return; + } + + ADD_STATS(pte_update, 1); +// ADD_STATS(pte_update_pinned, xen_page_pinned(ptep)); + ADD_STATS(pte_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); + #ifdef CONFIG_X86_PAE -static void xen_set_pte_atomic(pte_t *ptep, pte_t pte) + ptep->pte_high = pte.pte_high; + smp_wmb(); + ptep->pte_low = pte.pte_low; +#else + *ptep = pte; +#endif +} + +#ifdef CONFIG_X86_PAE +void xen_set_pte_atomic(pte_t *ptep, pte_t pte) { + if (xen_iomap_pte(pte)) { + xen_set_iomap_pte(ptep, pte); + return; + } + set_64bit((u64 *)ptep, native_pte_val(pte)); } -static void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - if (!xen_batched_set_pte(ptep, native_make_pte(0))) - native_pte_clear(mm, addr, ptep); + ptep->pte_low = 0; + smp_wmb(); /* make sure low gets written first */ + ptep->pte_high = 0; } -static void xen_pmd_clear(pmd_t *pmdp) +void xen_pmd_clear(pmd_t *pmdp) { set_pmd(pmdp, __pmd(0)); } #endif /* CONFIG_X86_PAE */ -static pmd_t xen_make_pmd(pmdval_t pmd) +pmd_t xen_make_pmd(pmdval_t pmd) { pmd = pte_pfn_to_mfn(pmd); return native_make_pmd(pmd); @@ -565,13 +682,13 @@ static pmd_t xen_make_pmd(pmdval_t pmd) PV_CALLEE_SAVE_REGS_THUNK(xen_make_pmd); #if PAGETABLE_LEVELS == 4 -static pudval_t xen_pud_val(pud_t pud) +pudval_t xen_pud_val(pud_t pud) { return pte_mfn_to_pfn(pud.pud); } PV_CALLEE_SAVE_REGS_THUNK(xen_pud_val); -static pud_t xen_make_pud(pudval_t pud) +pud_t xen_make_pud(pudval_t pud) { pud = pte_pfn_to_mfn(pud); @@ -579,7 +696,7 @@ static pud_t xen_make_pud(pudval_t pud) } PV_CALLEE_SAVE_REGS_THUNK(xen_make_pud); -static pgd_t *xen_get_user_pgd(pgd_t *pgd) +pgd_t *xen_get_user_pgd(pgd_t *pgd) { pgd_t *pgd_page = (pgd_t *)(((unsigned long)pgd) & PAGE_MASK); unsigned offset = pgd - pgd_page; @@ -611,7 +728,7 @@ static void __xen_set_pgd_hyper(pgd_t *ptr, pgd_t val) * 2. It is always pinned * 3. It has no user pagetable attached to it */ -static void __init xen_set_pgd_hyper(pgd_t *ptr, pgd_t val) +void __init xen_set_pgd_hyper(pgd_t *ptr, pgd_t val) { preempt_disable(); @@ -624,10 +741,12 @@ static void __init xen_set_pgd_hyper(pgd_t *ptr, pgd_t val) preempt_enable(); } -static void xen_set_pgd(pgd_t *ptr, pgd_t val) +void xen_set_pgd(pgd_t *ptr, pgd_t val) { pgd_t *user_ptr = xen_get_user_pgd(ptr); + ADD_STATS(pgd_update, 1); + /* If page is not pinned, we can just update the entry directly */ if (!xen_page_pinned(ptr)) { @@ -639,6 +758,9 @@ static void xen_set_pgd(pgd_t *ptr, pgd_t val) return; } + ADD_STATS(pgd_update_pinned, 1); + ADD_STATS(pgd_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); + /* If it's pinned, then we can at least batch the kernel and user updates together. */ xen_mc_batch(); @@ -1040,14 +1162,14 @@ void xen_mm_unpin_all(void) spin_unlock(&pgd_lock); } -static void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) +void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) { spin_lock(&next->page_table_lock); xen_pgd_pin(next); spin_unlock(&next->page_table_lock); } -static void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) +void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) { spin_lock(&mm->page_table_lock); xen_pgd_pin(mm); @@ -1134,7 +1256,7 @@ static void xen_drop_mm_ref(struct mm_struct *mm) * pagetable because of lazy tlb flushing. This means we need need to * switch all CPUs off this pagetable before we can unpin it. */ -static void xen_exit_mmap(struct mm_struct *mm) +void xen_exit_mmap(struct mm_struct *mm) { get_cpu(); /* make sure we don't move around */ xen_drop_mm_ref(mm); @@ -2249,7 +2371,7 @@ static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token, struct remap_data *rmd = data; pte_t pte = pte_mkspecial(pfn_pte(rmd->mfn++, rmd->prot)); - rmd->mmu_update->ptr = virt_to_machine(ptep).maddr; + rmd->mmu_update->ptr = arbitrary_virt_to_machine(ptep).maddr; rmd->mmu_update->val = pte_val_ma(pte); rmd->mmu_update++; @@ -2303,6 +2425,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); #ifdef CONFIG_XEN_DEBUG_FS + static int p2m_dump_open(struct inode *inode, struct file *filp) { return single_open(filp, p2m_dump_show, NULL); @@ -2314,4 +2437,65 @@ static const struct file_operations p2m_dump_fops = { .llseek = seq_lseek, .release = single_release, }; -#endif /* CONFIG_XEN_DEBUG_FS */ + +static struct dentry *d_mmu_debug; + +static int __init xen_mmu_debugfs(void) +{ + struct dentry *d_xen = xen_init_debugfs(); + + if (d_xen == NULL) + return -ENOMEM; + + d_mmu_debug = debugfs_create_dir("mmu", d_xen); + + debugfs_create_u8("zero_stats", 0644, d_mmu_debug, &zero_stats); + + debugfs_create_u32("pgd_update", 0444, d_mmu_debug, &mmu_stats.pgd_update); + debugfs_create_u32("pgd_update_pinned", 0444, d_mmu_debug, + &mmu_stats.pgd_update_pinned); + debugfs_create_u32("pgd_update_batched", 0444, d_mmu_debug, + &mmu_stats.pgd_update_pinned); + + debugfs_create_u32("pud_update", 0444, d_mmu_debug, &mmu_stats.pud_update); + debugfs_create_u32("pud_update_pinned", 0444, d_mmu_debug, + &mmu_stats.pud_update_pinned); + debugfs_create_u32("pud_update_batched", 0444, d_mmu_debug, + &mmu_stats.pud_update_pinned); + + debugfs_create_u32("pmd_update", 0444, d_mmu_debug, &mmu_stats.pmd_update); + debugfs_create_u32("pmd_update_pinned", 0444, d_mmu_debug, + &mmu_stats.pmd_update_pinned); + debugfs_create_u32("pmd_update_batched", 0444, d_mmu_debug, + &mmu_stats.pmd_update_pinned); + + debugfs_create_u32("pte_update", 0444, d_mmu_debug, &mmu_stats.pte_update); +// debugfs_create_u32("pte_update_pinned", 0444, d_mmu_debug, +// &mmu_stats.pte_update_pinned); + debugfs_create_u32("pte_update_batched", 0444, d_mmu_debug, + &mmu_stats.pte_update_pinned); + + debugfs_create_u32("mmu_update", 0444, d_mmu_debug, &mmu_stats.mmu_update); + debugfs_create_u32("mmu_update_extended", 0444, d_mmu_debug, + &mmu_stats.mmu_update_extended); + xen_debugfs_create_u32_array("mmu_update_histo", 0444, d_mmu_debug, + mmu_stats.mmu_update_histo, 20); + + debugfs_create_u32("set_pte_at", 0444, d_mmu_debug, &mmu_stats.set_pte_at); + debugfs_create_u32("set_pte_at_batched", 0444, d_mmu_debug, + &mmu_stats.set_pte_at_batched); + debugfs_create_u32("set_pte_at_current", 0444, d_mmu_debug, + &mmu_stats.set_pte_at_current); + debugfs_create_u32("set_pte_at_kernel", 0444, d_mmu_debug, + &mmu_stats.set_pte_at_kernel); + + debugfs_create_u32("prot_commit", 0444, d_mmu_debug, &mmu_stats.prot_commit); + debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug, + &mmu_stats.prot_commit_batched); + + debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops); + return 0; +} +fs_initcall(xen_mmu_debugfs); + +#endif /* CONFIG_XEN_DEBUG_FS */ diff --git a/trunk/arch/x86/xen/mmu.h b/trunk/arch/x86/xen/mmu.h index 73809bb951b4..537bb9aab777 100644 --- a/trunk/arch/x86/xen/mmu.h +++ b/trunk/arch/x86/xen/mmu.h @@ -15,6 +15,43 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); + +void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next); +void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm); +void xen_exit_mmap(struct mm_struct *mm); + +pteval_t xen_pte_val(pte_t); +pmdval_t xen_pmd_val(pmd_t); +pgdval_t xen_pgd_val(pgd_t); + +pte_t xen_make_pte(pteval_t); +pmd_t xen_make_pmd(pmdval_t); +pgd_t xen_make_pgd(pgdval_t); + +void xen_set_pte(pte_t *ptep, pte_t pteval); +void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pteval); + +#ifdef CONFIG_X86_PAE +void xen_set_pte_atomic(pte_t *ptep, pte_t pte); +void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); +void xen_pmd_clear(pmd_t *pmdp); +#endif /* CONFIG_X86_PAE */ + +void xen_set_pmd(pmd_t *pmdp, pmd_t pmdval); +void xen_set_pud(pud_t *ptr, pud_t val); +void xen_set_pmd_hyper(pmd_t *pmdp, pmd_t pmdval); +void xen_set_pud_hyper(pud_t *ptr, pud_t val); + +#if PAGETABLE_LEVELS == 4 +pudval_t xen_pud_val(pud_t pud); +pud_t xen_make_pud(pudval_t pudval); +void xen_set_pgd(pgd_t *pgdp, pgd_t pgd); +void xen_set_pgd_hyper(pgd_t *pgdp, pgd_t pgd); +#endif + +pgd_t *xen_get_user_pgd(pgd_t *pgd); + pte_t xen_ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr, pte_t *ptep); void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte); diff --git a/trunk/arch/xtensa/Kconfig b/trunk/arch/xtensa/Kconfig index 5d43c1f8ada8..7c275f5d0df0 100644 --- a/trunk/arch/xtensa/Kconfig +++ b/trunk/arch/xtensa/Kconfig @@ -20,6 +20,12 @@ config XTENSA config RWSEM_XCHGADD_ALGORITHM def_bool y +config GENERIC_FIND_NEXT_BIT + def_bool y + +config GENERIC_FIND_BIT_LE + def_bool y + config GENERIC_HWEIGHT def_bool y diff --git a/trunk/block/blk-cgroup.c b/trunk/block/blk-cgroup.c index bcaf16ee6ad1..07371cfdfae6 100644 --- a/trunk/block/blk-cgroup.c +++ b/trunk/block/blk-cgroup.c @@ -30,8 +30,10 @@ EXPORT_SYMBOL_GPL(blkio_root_cgroup); static struct cgroup_subsys_state *blkiocg_create(struct cgroup_subsys *, struct cgroup *); -static int blkiocg_can_attach_task(struct cgroup *, struct task_struct *); -static void blkiocg_attach_task(struct cgroup *, struct task_struct *); +static int blkiocg_can_attach(struct cgroup_subsys *, struct cgroup *, + struct task_struct *, bool); +static void blkiocg_attach(struct cgroup_subsys *, struct cgroup *, + struct cgroup *, struct task_struct *, bool); static void blkiocg_destroy(struct cgroup_subsys *, struct cgroup *); static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *); @@ -44,8 +46,8 @@ static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *); struct cgroup_subsys blkio_subsys = { .name = "blkio", .create = blkiocg_create, - .can_attach_task = blkiocg_can_attach_task, - .attach_task = blkiocg_attach_task, + .can_attach = blkiocg_can_attach, + .attach = blkiocg_attach, .destroy = blkiocg_destroy, .populate = blkiocg_populate, #ifdef CONFIG_BLK_CGROUP @@ -1614,7 +1616,9 @@ blkiocg_create(struct cgroup_subsys *subsys, struct cgroup *cgroup) * of the main cic data structures. For now we allow a task to change * its cgroup only if it's the only owner of its ioc. */ -static int blkiocg_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk) +static int blkiocg_can_attach(struct cgroup_subsys *subsys, + struct cgroup *cgroup, struct task_struct *tsk, + bool threadgroup) { struct io_context *ioc; int ret = 0; @@ -1629,7 +1633,9 @@ static int blkiocg_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk) return ret; } -static void blkiocg_attach_task(struct cgroup *cgrp, struct task_struct *tsk) +static void blkiocg_attach(struct cgroup_subsys *subsys, struct cgroup *cgroup, + struct cgroup *prev, struct task_struct *tsk, + bool threadgroup) { struct io_context *ioc; diff --git a/trunk/drivers/bcma/host_pci.c b/trunk/drivers/bcma/host_pci.c index 471a04013fe0..ffd8797faf4f 100644 --- a/trunk/drivers/bcma/host_pci.c +++ b/trunk/drivers/bcma/host_pci.c @@ -6,7 +6,6 @@ */ #include "bcma_private.h" -#include #include #include diff --git a/trunk/drivers/char/ipmi/ipmi_msghandler.c b/trunk/drivers/char/ipmi/ipmi_msghandler.c index 58c0e6387cf7..38223e93aa98 100644 --- a/trunk/drivers/char/ipmi/ipmi_msghandler.c +++ b/trunk/drivers/char/ipmi/ipmi_msghandler.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -1897,128 +1896,102 @@ int ipmi_request_supply_msgs(ipmi_user_t user, EXPORT_SYMBOL(ipmi_request_supply_msgs); #ifdef CONFIG_PROC_FS -static int smi_ipmb_proc_show(struct seq_file *m, void *v) +static int ipmb_file_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { - ipmi_smi_t intf = m->private; + char *out = (char *) page; + ipmi_smi_t intf = data; int i; + int rv = 0; - seq_printf(m, "%x", intf->channels[0].address); - for (i = 1; i < IPMI_MAX_CHANNELS; i++) - seq_printf(m, " %x", intf->channels[i].address); - return seq_putc(m, '\n'); + for (i = 0; i < IPMI_MAX_CHANNELS; i++) + rv += sprintf(out+rv, "%x ", intf->channels[i].address); + out[rv-1] = '\n'; /* Replace the final space with a newline */ + out[rv] = '\0'; + rv++; + return rv; } -static int smi_ipmb_proc_open(struct inode *inode, struct file *file) +static int version_file_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { - return single_open(file, smi_ipmb_proc_show, PDE(inode)->data); -} + char *out = (char *) page; + ipmi_smi_t intf = data; -static const struct file_operations smi_ipmb_proc_ops = { - .open = smi_ipmb_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int smi_version_proc_show(struct seq_file *m, void *v) -{ - ipmi_smi_t intf = m->private; - - return seq_printf(m, "%u.%u\n", + return sprintf(out, "%u.%u\n", ipmi_version_major(&intf->bmc->id), ipmi_version_minor(&intf->bmc->id)); } -static int smi_version_proc_open(struct inode *inode, struct file *file) +static int stat_file_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { - return single_open(file, smi_version_proc_show, PDE(inode)->data); -} - -static const struct file_operations smi_version_proc_ops = { - .open = smi_version_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; + char *out = (char *) page; + ipmi_smi_t intf = data; -static int smi_stats_proc_show(struct seq_file *m, void *v) -{ - ipmi_smi_t intf = m->private; - - seq_printf(m, "sent_invalid_commands: %u\n", + out += sprintf(out, "sent_invalid_commands: %u\n", ipmi_get_stat(intf, sent_invalid_commands)); - seq_printf(m, "sent_local_commands: %u\n", + out += sprintf(out, "sent_local_commands: %u\n", ipmi_get_stat(intf, sent_local_commands)); - seq_printf(m, "handled_local_responses: %u\n", + out += sprintf(out, "handled_local_responses: %u\n", ipmi_get_stat(intf, handled_local_responses)); - seq_printf(m, "unhandled_local_responses: %u\n", + out += sprintf(out, "unhandled_local_responses: %u\n", ipmi_get_stat(intf, unhandled_local_responses)); - seq_printf(m, "sent_ipmb_commands: %u\n", + out += sprintf(out, "sent_ipmb_commands: %u\n", ipmi_get_stat(intf, sent_ipmb_commands)); - seq_printf(m, "sent_ipmb_command_errs: %u\n", + out += sprintf(out, "sent_ipmb_command_errs: %u\n", ipmi_get_stat(intf, sent_ipmb_command_errs)); - seq_printf(m, "retransmitted_ipmb_commands: %u\n", + out += sprintf(out, "retransmitted_ipmb_commands: %u\n", ipmi_get_stat(intf, retransmitted_ipmb_commands)); - seq_printf(m, "timed_out_ipmb_commands: %u\n", + out += sprintf(out, "timed_out_ipmb_commands: %u\n", ipmi_get_stat(intf, timed_out_ipmb_commands)); - seq_printf(m, "timed_out_ipmb_broadcasts: %u\n", + out += sprintf(out, "timed_out_ipmb_broadcasts: %u\n", ipmi_get_stat(intf, timed_out_ipmb_broadcasts)); - seq_printf(m, "sent_ipmb_responses: %u\n", + out += sprintf(out, "sent_ipmb_responses: %u\n", ipmi_get_stat(intf, sent_ipmb_responses)); - seq_printf(m, "handled_ipmb_responses: %u\n", + out += sprintf(out, "handled_ipmb_responses: %u\n", ipmi_get_stat(intf, handled_ipmb_responses)); - seq_printf(m, "invalid_ipmb_responses: %u\n", + out += sprintf(out, "invalid_ipmb_responses: %u\n", ipmi_get_stat(intf, invalid_ipmb_responses)); - seq_printf(m, "unhandled_ipmb_responses: %u\n", + out += sprintf(out, "unhandled_ipmb_responses: %u\n", ipmi_get_stat(intf, unhandled_ipmb_responses)); - seq_printf(m, "sent_lan_commands: %u\n", + out += sprintf(out, "sent_lan_commands: %u\n", ipmi_get_stat(intf, sent_lan_commands)); - seq_printf(m, "sent_lan_command_errs: %u\n", + out += sprintf(out, "sent_lan_command_errs: %u\n", ipmi_get_stat(intf, sent_lan_command_errs)); - seq_printf(m, "retransmitted_lan_commands: %u\n", + out += sprintf(out, "retransmitted_lan_commands: %u\n", ipmi_get_stat(intf, retransmitted_lan_commands)); - seq_printf(m, "timed_out_lan_commands: %u\n", + out += sprintf(out, "timed_out_lan_commands: %u\n", ipmi_get_stat(intf, timed_out_lan_commands)); - seq_printf(m, "sent_lan_responses: %u\n", + out += sprintf(out, "sent_lan_responses: %u\n", ipmi_get_stat(intf, sent_lan_responses)); - seq_printf(m, "handled_lan_responses: %u\n", + out += sprintf(out, "handled_lan_responses: %u\n", ipmi_get_stat(intf, handled_lan_responses)); - seq_printf(m, "invalid_lan_responses: %u\n", + out += sprintf(out, "invalid_lan_responses: %u\n", ipmi_get_stat(intf, invalid_lan_responses)); - seq_printf(m, "unhandled_lan_responses: %u\n", + out += sprintf(out, "unhandled_lan_responses: %u\n", ipmi_get_stat(intf, unhandled_lan_responses)); - seq_printf(m, "handled_commands: %u\n", + out += sprintf(out, "handled_commands: %u\n", ipmi_get_stat(intf, handled_commands)); - seq_printf(m, "invalid_commands: %u\n", + out += sprintf(out, "invalid_commands: %u\n", ipmi_get_stat(intf, invalid_commands)); - seq_printf(m, "unhandled_commands: %u\n", + out += sprintf(out, "unhandled_commands: %u\n", ipmi_get_stat(intf, unhandled_commands)); - seq_printf(m, "invalid_events: %u\n", + out += sprintf(out, "invalid_events: %u\n", ipmi_get_stat(intf, invalid_events)); - seq_printf(m, "events: %u\n", + out += sprintf(out, "events: %u\n", ipmi_get_stat(intf, events)); - seq_printf(m, "failed rexmit LAN msgs: %u\n", + out += sprintf(out, "failed rexmit LAN msgs: %u\n", ipmi_get_stat(intf, dropped_rexmit_lan_commands)); - seq_printf(m, "failed rexmit IPMB msgs: %u\n", + out += sprintf(out, "failed rexmit IPMB msgs: %u\n", ipmi_get_stat(intf, dropped_rexmit_ipmb_commands)); - return 0; -} -static int smi_stats_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, smi_stats_proc_show, PDE(inode)->data); + return (out - ((char *) page)); } - -static const struct file_operations smi_stats_proc_ops = { - .open = smi_stats_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; #endif /* CONFIG_PROC_FS */ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, - const struct file_operations *proc_ops, + read_proc_t *read_proc, void *data) { int rv = 0; @@ -2037,12 +2010,15 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, } strcpy(entry->name, name); - file = proc_create_data(name, 0, smi->proc_dir, proc_ops, data); + file = create_proc_entry(name, 0, smi->proc_dir); if (!file) { kfree(entry->name); kfree(entry); rv = -ENOMEM; } else { + file->data = data; + file->read_proc = read_proc; + mutex_lock(&smi->proc_entry_lock); /* Stick it on the list. */ entry->next = smi->proc_entries; @@ -2067,17 +2043,17 @@ static int add_proc_entries(ipmi_smi_t smi, int num) if (rv == 0) rv = ipmi_smi_add_proc_entry(smi, "stats", - &smi_stats_proc_ops, + stat_file_read_proc, smi); if (rv == 0) rv = ipmi_smi_add_proc_entry(smi, "ipmb", - &smi_ipmb_proc_ops, + ipmb_file_read_proc, smi); if (rv == 0) rv = ipmi_smi_add_proc_entry(smi, "version", - &smi_version_proc_ops, + version_file_read_proc, smi); #endif /* CONFIG_PROC_FS */ diff --git a/trunk/drivers/char/ipmi/ipmi_si_intf.c b/trunk/drivers/char/ipmi/ipmi_si_intf.c index 9397ab49b72e..64c6b8530615 100644 --- a/trunk/drivers/char/ipmi/ipmi_si_intf.c +++ b/trunk/drivers/char/ipmi/ipmi_si_intf.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -2806,73 +2805,54 @@ static int try_enable_event_buffer(struct smi_info *smi_info) return rv; } -static int smi_type_proc_show(struct seq_file *m, void *v) +static int type_file_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { - struct smi_info *smi = m->private; + struct smi_info *smi = data; - return seq_printf(m, "%s\n", si_to_str[smi->si_type]); + return sprintf(page, "%s\n", si_to_str[smi->si_type]); } -static int smi_type_proc_open(struct inode *inode, struct file *file) +static int stat_file_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { - return single_open(file, smi_type_proc_show, PDE(inode)->data); -} - -static const struct file_operations smi_type_proc_ops = { - .open = smi_type_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int smi_si_stats_proc_show(struct seq_file *m, void *v) -{ - struct smi_info *smi = m->private; + char *out = (char *) page; + struct smi_info *smi = data; - seq_printf(m, "interrupts_enabled: %d\n", + out += sprintf(out, "interrupts_enabled: %d\n", smi->irq && !smi->interrupt_disabled); - seq_printf(m, "short_timeouts: %u\n", + out += sprintf(out, "short_timeouts: %u\n", smi_get_stat(smi, short_timeouts)); - seq_printf(m, "long_timeouts: %u\n", + out += sprintf(out, "long_timeouts: %u\n", smi_get_stat(smi, long_timeouts)); - seq_printf(m, "idles: %u\n", + out += sprintf(out, "idles: %u\n", smi_get_stat(smi, idles)); - seq_printf(m, "interrupts: %u\n", + out += sprintf(out, "interrupts: %u\n", smi_get_stat(smi, interrupts)); - seq_printf(m, "attentions: %u\n", + out += sprintf(out, "attentions: %u\n", smi_get_stat(smi, attentions)); - seq_printf(m, "flag_fetches: %u\n", + out += sprintf(out, "flag_fetches: %u\n", smi_get_stat(smi, flag_fetches)); - seq_printf(m, "hosed_count: %u\n", + out += sprintf(out, "hosed_count: %u\n", smi_get_stat(smi, hosed_count)); - seq_printf(m, "complete_transactions: %u\n", + out += sprintf(out, "complete_transactions: %u\n", smi_get_stat(smi, complete_transactions)); - seq_printf(m, "events: %u\n", + out += sprintf(out, "events: %u\n", smi_get_stat(smi, events)); - seq_printf(m, "watchdog_pretimeouts: %u\n", + out += sprintf(out, "watchdog_pretimeouts: %u\n", smi_get_stat(smi, watchdog_pretimeouts)); - seq_printf(m, "incoming_messages: %u\n", + out += sprintf(out, "incoming_messages: %u\n", smi_get_stat(smi, incoming_messages)); - return 0; -} -static int smi_si_stats_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, smi_si_stats_proc_show, PDE(inode)->data); + return out - page; } -static const struct file_operations smi_si_stats_proc_ops = { - .open = smi_si_stats_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int smi_params_proc_show(struct seq_file *m, void *v) +static int param_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { - struct smi_info *smi = m->private; + struct smi_info *smi = data; - return seq_printf(m, + return sprintf(page, "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n", si_to_str[smi->si_type], addr_space_to_str[smi->io.addr_type], @@ -2884,18 +2864,6 @@ static int smi_params_proc_show(struct seq_file *m, void *v) smi->slave_addr); } -static int smi_params_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, smi_params_proc_show, PDE(inode)->data); -} - -static const struct file_operations smi_params_proc_ops = { - .open = smi_params_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - /* * oem_data_avail_to_receive_msg_avail * @info - smi_info structure with msg_flags set @@ -3289,7 +3257,7 @@ static int try_smi_init(struct smi_info *new_smi) } rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", - &smi_type_proc_ops, + type_file_read_proc, new_smi); if (rv) { dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); @@ -3297,7 +3265,7 @@ static int try_smi_init(struct smi_info *new_smi) } rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", - &smi_si_stats_proc_ops, + stat_file_read_proc, new_smi); if (rv) { dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); @@ -3305,7 +3273,7 @@ static int try_smi_init(struct smi_info *new_smi) } rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", - &smi_params_proc_ops, + param_read_proc, new_smi); if (rv) { dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); diff --git a/trunk/drivers/char/mspec.c b/trunk/drivers/char/mspec.c index 25d139c9dbed..966a95bc974b 100644 --- a/trunk/drivers/char/mspec.c +++ b/trunk/drivers/char/mspec.c @@ -271,13 +271,14 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; vdata_size = sizeof(struct vma_data) + pages * sizeof(long); if (vdata_size <= PAGE_SIZE) - vdata = kzalloc(vdata_size, GFP_KERNEL); + vdata = kmalloc(vdata_size, GFP_KERNEL); else { - vdata = vzalloc(vdata_size); + vdata = vmalloc(vdata_size); flags = VMD_VMALLOCED; } if (!vdata) return -ENOMEM; + memset(vdata, 0, vdata_size); vdata->vm_start = vma->vm_start; vdata->vm_end = vma->vm_end; diff --git a/trunk/drivers/char/ppdev.c b/trunk/drivers/char/ppdev.c index 3fcf80ff12f2..f176dbaeb15a 100644 --- a/trunk/drivers/char/ppdev.c +++ b/trunk/drivers/char/ppdev.c @@ -457,7 +457,6 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -ENODEV; modes = port->modes; - parport_put_port(port); if (copy_to_user (argp, &modes, sizeof (modes))) { return -EFAULT; } diff --git a/trunk/drivers/dma/timb_dma.c b/trunk/drivers/dma/timb_dma.c index f69f90a61873..d2c75feff7df 100644 --- a/trunk/drivers/dma/timb_dma.c +++ b/trunk/drivers/dma/timb_dma.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -684,7 +685,7 @@ static irqreturn_t td_irq(int irq, void *devid) static int __devinit td_probe(struct platform_device *pdev) { - struct timb_dma_platform_data *pdata = pdev->dev.platform_data; + struct timb_dma_platform_data *pdata = mfd_get_data(pdev); struct timb_dma *td; struct resource *iomem; int irq; diff --git a/trunk/drivers/edac/amd76x_edac.c b/trunk/drivers/edac/amd76x_edac.c index e47e73bbbcc5..cace0a7b707a 100644 --- a/trunk/drivers/edac/amd76x_edac.c +++ b/trunk/drivers/edac/amd76x_edac.c @@ -19,7 +19,7 @@ #include #include "edac_core.h" -#define AMD76X_REVISION " Ver: 2.0.2" +#define AMD76X_REVISION " Ver: 2.0.2 " __DATE__ #define EDAC_MOD_STR "amd76x_edac" #define amd76x_printk(level, fmt, arg...) \ diff --git a/trunk/drivers/edac/amd8111_edac.c b/trunk/drivers/edac/amd8111_edac.c index ddd890052ce2..35b78d04bbfa 100644 --- a/trunk/drivers/edac/amd8111_edac.c +++ b/trunk/drivers/edac/amd8111_edac.c @@ -33,7 +33,7 @@ #include "edac_module.h" #include "amd8111_edac.h" -#define AMD8111_EDAC_REVISION " Ver: 1.0.0" +#define AMD8111_EDAC_REVISION " Ver: 1.0.0 " __DATE__ #define AMD8111_EDAC_MOD_STR "amd8111_edac" #define PCI_DEVICE_ID_AMD_8111_PCI 0x7460 diff --git a/trunk/drivers/edac/amd8131_edac.c b/trunk/drivers/edac/amd8131_edac.c index a5c680561c73..b432d60c622a 100644 --- a/trunk/drivers/edac/amd8131_edac.c +++ b/trunk/drivers/edac/amd8131_edac.c @@ -33,7 +33,7 @@ #include "edac_module.h" #include "amd8131_edac.h" -#define AMD8131_EDAC_REVISION " Ver: 1.0.0" +#define AMD8131_EDAC_REVISION " Ver: 1.0.0 " __DATE__ #define AMD8131_EDAC_MOD_STR "amd8131_edac" /* Wrapper functions for accessing PCI configuration space */ diff --git a/trunk/drivers/edac/cpc925_edac.c b/trunk/drivers/edac/cpc925_edac.c index a687a0d16962..837ad8f85b48 100644 --- a/trunk/drivers/edac/cpc925_edac.c +++ b/trunk/drivers/edac/cpc925_edac.c @@ -30,7 +30,7 @@ #include "edac_core.h" #include "edac_module.h" -#define CPC925_EDAC_REVISION " Ver: 1.0.0" +#define CPC925_EDAC_REVISION " Ver: 1.0.0 " __DATE__ #define CPC925_EDAC_MOD_STR "cpc925_edac" #define cpc925_printk(level, fmt, arg...) \ diff --git a/trunk/drivers/edac/e752x_edac.c b/trunk/drivers/edac/e752x_edac.c index 1af531a11d21..ec302d426589 100644 --- a/trunk/drivers/edac/e752x_edac.c +++ b/trunk/drivers/edac/e752x_edac.c @@ -24,7 +24,7 @@ #include #include "edac_core.h" -#define E752X_REVISION " Ver: 2.0.2" +#define E752X_REVISION " Ver: 2.0.2 " __DATE__ #define EDAC_MOD_STR "e752x_edac" static int report_non_memory_errors; diff --git a/trunk/drivers/edac/e7xxx_edac.c b/trunk/drivers/edac/e7xxx_edac.c index 6ffb6d23281f..1731d7245816 100644 --- a/trunk/drivers/edac/e7xxx_edac.c +++ b/trunk/drivers/edac/e7xxx_edac.c @@ -29,7 +29,7 @@ #include #include "edac_core.h" -#define E7XXX_REVISION " Ver: 2.0.2" +#define E7XXX_REVISION " Ver: 2.0.2 " __DATE__ #define EDAC_MOD_STR "e7xxx_edac" #define e7xxx_printk(level, fmt, arg...) \ diff --git a/trunk/drivers/edac/edac_core.h b/trunk/drivers/edac/edac_core.h index 55b8278bb172..eefa3501916b 100644 --- a/trunk/drivers/edac/edac_core.h +++ b/trunk/drivers/edac/edac_core.h @@ -421,6 +421,10 @@ struct mem_ctl_info { u32 ce_count; /* Total Correctable Errors for this MC */ unsigned long start_time; /* mci load start time (in jiffies) */ + /* this stuff is for safe removal of mc devices from global list while + * NMI handlers may be traversing list + */ + struct rcu_head rcu; struct completion complete; /* edac sysfs device control */ @@ -616,6 +620,10 @@ struct edac_device_ctl_info { unsigned long start_time; /* edac_device load start time (jiffies) */ + /* these are for safe removal of mc devices from global list while + * NMI handlers may be traversing list + */ + struct rcu_head rcu; struct completion removal_complete; /* sysfs top name under 'edac' directory @@ -714,6 +722,10 @@ struct edac_pci_ctl_info { unsigned long start_time; /* edac_pci load start time (jiffies) */ + /* these are for safe removal of devices from global list while + * NMI handlers may be traversing list + */ + struct rcu_head rcu; struct completion complete; /* sysfs top name under 'edac' directory diff --git a/trunk/drivers/edac/edac_device.c b/trunk/drivers/edac/edac_device.c index c3f67437afb6..a7408cf86f37 100644 --- a/trunk/drivers/edac/edac_device.c +++ b/trunk/drivers/edac/edac_device.c @@ -345,19 +345,31 @@ static int add_edac_dev_to_global_list(struct edac_device_ctl_info *edac_dev) return 1; } +/* + * complete_edac_device_list_del + * + * callback function when reference count is zero + */ +static void complete_edac_device_list_del(struct rcu_head *head) +{ + struct edac_device_ctl_info *edac_dev; + + edac_dev = container_of(head, struct edac_device_ctl_info, rcu); + INIT_LIST_HEAD(&edac_dev->link); +} + /* * del_edac_device_from_global_list + * + * remove the RCU, setup for a callback call, + * then wait for the callback to occur */ static void del_edac_device_from_global_list(struct edac_device_ctl_info *edac_device) { list_del_rcu(&edac_device->link); - - /* these are for safe removal of devices from global list while - * NMI handlers may be traversing list - */ - synchronize_rcu(); - INIT_LIST_HEAD(&edac_device->link); + call_rcu(&edac_device->rcu, complete_edac_device_list_del); + rcu_barrier(); } /* diff --git a/trunk/drivers/edac/edac_mc.c b/trunk/drivers/edac/edac_mc.c index d69144a09043..1d8056049072 100644 --- a/trunk/drivers/edac/edac_mc.c +++ b/trunk/drivers/edac/edac_mc.c @@ -447,16 +447,20 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci) return 1; } +static void complete_mc_list_del(struct rcu_head *head) +{ + struct mem_ctl_info *mci; + + mci = container_of(head, struct mem_ctl_info, rcu); + INIT_LIST_HEAD(&mci->link); +} + static void del_mc_from_global_list(struct mem_ctl_info *mci) { atomic_dec(&edac_handlers); list_del_rcu(&mci->link); - - /* these are for safe removal of devices from global list while - * NMI handlers may be traversing list - */ - synchronize_rcu(); - INIT_LIST_HEAD(&mci->link); + call_rcu(&mci->rcu, complete_mc_list_del); + rcu_barrier(); } /** diff --git a/trunk/drivers/edac/edac_module.c b/trunk/drivers/edac/edac_module.c index 5ddaa86d6a6e..be4b075c3098 100644 --- a/trunk/drivers/edac/edac_module.c +++ b/trunk/drivers/edac/edac_module.c @@ -15,7 +15,7 @@ #include "edac_core.h" #include "edac_module.h" -#define EDAC_VERSION "Ver: 2.1.0" +#define EDAC_VERSION "Ver: 2.1.0 " __DATE__ #ifdef CONFIG_EDAC_DEBUG /* Values of 0 to 4 will generate output */ diff --git a/trunk/drivers/edac/edac_pci.c b/trunk/drivers/edac/edac_pci.c index 2b378207d571..efb5d5650783 100644 --- a/trunk/drivers/edac/edac_pci.c +++ b/trunk/drivers/edac/edac_pci.c @@ -163,6 +163,19 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci) return 1; } +/* + * complete_edac_pci_list_del + * + * RCU completion callback to indicate item is deleted + */ +static void complete_edac_pci_list_del(struct rcu_head *head) +{ + struct edac_pci_ctl_info *pci; + + pci = container_of(head, struct edac_pci_ctl_info, rcu); + INIT_LIST_HEAD(&pci->link); +} + /* * del_edac_pci_from_global_list * @@ -171,12 +184,8 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci) static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci) { list_del_rcu(&pci->link); - - /* these are for safe removal of devices from global list while - * NMI handlers may be traversing list - */ - synchronize_rcu(); - INIT_LIST_HEAD(&pci->link); + call_rcu(&pci->rcu, complete_edac_pci_list_del); + rcu_barrier(); } #if 0 diff --git a/trunk/drivers/edac/i5000_edac.c b/trunk/drivers/edac/i5000_edac.c index 4dc3ac25a422..87f427c2ce5c 100644 --- a/trunk/drivers/edac/i5000_edac.c +++ b/trunk/drivers/edac/i5000_edac.c @@ -27,7 +27,7 @@ /* * Alter this version for the I5000 module when modifications are made */ -#define I5000_REVISION " Ver: 2.0.12" +#define I5000_REVISION " Ver: 2.0.12 " __DATE__ #define EDAC_MOD_STR "i5000_edac" #define i5000_printk(level, fmt, arg...) \ diff --git a/trunk/drivers/edac/i5400_edac.c b/trunk/drivers/edac/i5400_edac.c index 74d6ec342afb..80a465efbae8 100644 --- a/trunk/drivers/edac/i5400_edac.c +++ b/trunk/drivers/edac/i5400_edac.c @@ -33,7 +33,7 @@ /* * Alter this version for the I5400 module when modifications are made */ -#define I5400_REVISION " Ver: 1.0.0" +#define I5400_REVISION " Ver: 1.0.0 " __DATE__ #define EDAC_MOD_STR "i5400_edac" diff --git a/trunk/drivers/edac/i7300_edac.c b/trunk/drivers/edac/i7300_edac.c index a76fe8366b68..363cc1602944 100644 --- a/trunk/drivers/edac/i7300_edac.c +++ b/trunk/drivers/edac/i7300_edac.c @@ -31,7 +31,7 @@ /* * Alter this version for the I7300 module when modifications are made */ -#define I7300_REVISION " Ver: 1.0.0" +#define I7300_REVISION " Ver: 1.0.0 " __DATE__ #define EDAC_MOD_STR "i7300_edac" diff --git a/trunk/drivers/edac/i7core_edac.c b/trunk/drivers/edac/i7core_edac.c index 04f1e7ce02b1..465cbc25149f 100644 --- a/trunk/drivers/edac/i7core_edac.c +++ b/trunk/drivers/edac/i7core_edac.c @@ -59,7 +59,7 @@ MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices"); /* * Alter this version for the module when modifications are made */ -#define I7CORE_REVISION " Ver: 1.0.0" +#define I7CORE_REVISION " Ver: 1.0.0 " __DATE__ #define EDAC_MOD_STR "i7core_edac" /* diff --git a/trunk/drivers/edac/i82860_edac.c b/trunk/drivers/edac/i82860_edac.c index 931a05775049..b8a95cf50718 100644 --- a/trunk/drivers/edac/i82860_edac.c +++ b/trunk/drivers/edac/i82860_edac.c @@ -16,7 +16,7 @@ #include #include "edac_core.h" -#define I82860_REVISION " Ver: 2.0.2" +#define I82860_REVISION " Ver: 2.0.2 " __DATE__ #define EDAC_MOD_STR "i82860_edac" #define i82860_printk(level, fmt, arg...) \ diff --git a/trunk/drivers/edac/i82875p_edac.c b/trunk/drivers/edac/i82875p_edac.c index 33864c63c684..b2fd1e899142 100644 --- a/trunk/drivers/edac/i82875p_edac.c +++ b/trunk/drivers/edac/i82875p_edac.c @@ -20,7 +20,7 @@ #include #include "edac_core.h" -#define I82875P_REVISION " Ver: 2.0.2" +#define I82875P_REVISION " Ver: 2.0.2 " __DATE__ #define EDAC_MOD_STR "i82875p_edac" #define i82875p_printk(level, fmt, arg...) \ diff --git a/trunk/drivers/edac/i82975x_edac.c b/trunk/drivers/edac/i82975x_edac.c index a5da732fe5b2..92e65e7038e9 100644 --- a/trunk/drivers/edac/i82975x_edac.c +++ b/trunk/drivers/edac/i82975x_edac.c @@ -16,7 +16,7 @@ #include #include "edac_core.h" -#define I82975X_REVISION " Ver: 1.0.0" +#define I82975X_REVISION " Ver: 1.0.0 " __DATE__ #define EDAC_MOD_STR "i82975x_edac" #define i82975x_printk(level, fmt, arg...) \ diff --git a/trunk/drivers/edac/mpc85xx_edac.h b/trunk/drivers/edac/mpc85xx_edac.h index 932016f2cf06..cb24df839460 100644 --- a/trunk/drivers/edac/mpc85xx_edac.h +++ b/trunk/drivers/edac/mpc85xx_edac.h @@ -11,7 +11,7 @@ #ifndef _MPC85XX_EDAC_H_ #define _MPC85XX_EDAC_H_ -#define MPC85XX_REVISION " Ver: 2.0.0" +#define MPC85XX_REVISION " Ver: 2.0.0 " __DATE__ #define EDAC_MOD_STR "MPC85xx_edac" #define mpc85xx_printk(level, fmt, arg...) \ diff --git a/trunk/drivers/edac/mv64x60_edac.h b/trunk/drivers/edac/mv64x60_edac.h index c7f209c92a1a..e042e2daa8f4 100644 --- a/trunk/drivers/edac/mv64x60_edac.h +++ b/trunk/drivers/edac/mv64x60_edac.h @@ -12,7 +12,7 @@ #ifndef _MV64X60_EDAC_H_ #define _MV64X60_EDAC_H_ -#define MV64x60_REVISION " Ver: 2.0.0" +#define MV64x60_REVISION " Ver: 2.0.0 " __DATE__ #define EDAC_MOD_STR "MV64x60_edac" #define mv64x60_printk(level, fmt, arg...) \ diff --git a/trunk/drivers/edac/ppc4xx_edac.c b/trunk/drivers/edac/ppc4xx_edac.c index 0de7d8770891..af8e7b1aa290 100644 --- a/trunk/drivers/edac/ppc4xx_edac.c +++ b/trunk/drivers/edac/ppc4xx_edac.c @@ -113,7 +113,7 @@ #define EDAC_OPSTATE_UNKNOWN_STR "unknown" #define PPC4XX_EDAC_MODULE_NAME "ppc4xx_edac" -#define PPC4XX_EDAC_MODULE_REVISION "v1.0.0" +#define PPC4XX_EDAC_MODULE_REVISION "v1.0.0 " __DATE__ #define PPC4XX_EDAC_MESSAGE_SIZE 256 diff --git a/trunk/drivers/edac/r82600_edac.c b/trunk/drivers/edac/r82600_edac.c index b153674431f1..678513738c33 100644 --- a/trunk/drivers/edac/r82600_edac.c +++ b/trunk/drivers/edac/r82600_edac.c @@ -22,7 +22,7 @@ #include #include "edac_core.h" -#define R82600_REVISION " Ver: 2.0.2" +#define R82600_REVISION " Ver: 2.0.2 " __DATE__ #define EDAC_MOD_STR "r82600_edac" #define r82600_printk(level, fmt, arg...) \ diff --git a/trunk/drivers/gpio/Kconfig b/trunk/drivers/gpio/Kconfig index d21364603755..d3b295305542 100644 --- a/trunk/drivers/gpio/Kconfig +++ b/trunk/drivers/gpio/Kconfig @@ -1,5 +1,5 @@ # -# GPIO infrastructure and drivers +# platform-neutral GPIO infrastructure and expanders # config ARCH_WANT_OPTIONAL_GPIOLIB @@ -31,7 +31,7 @@ menuconfig GPIOLIB help This enables GPIO support through the generic GPIO library. You only need to enable this, if you also want to enable - one or more of the GPIO drivers below. + one or more of the GPIO expansion card drivers below. If unsure, say N. @@ -63,26 +63,21 @@ config GPIO_SYSFS Kernel drivers may also request that a particular GPIO be exported to userspace; this can be useful when debugging. -# put drivers in the right section, in alphabetical order +# put expanders in the right section, in alphabetical order config GPIO_MAX730X tristate -comment "Memory mapped GPIO drivers:" - -config GPIO_BASIC_MMIO_CORE - tristate - help - Provides core functionality for basic memory-mapped GPIO controllers. +comment "Memory mapped GPIO expanders:" config GPIO_BASIC_MMIO tristate "Basic memory-mapped GPIO controllers support" - select GPIO_BASIC_MMIO_CORE help Say yes here to support basic memory-mapped GPIO controllers. config GPIO_IT8761E tristate "IT8761E GPIO support" + depends on GPIOLIB help Say yes here to support GPIO functionality of IT8761E super I/O chip. @@ -106,7 +101,7 @@ config GPIO_VR41XX config GPIO_SCH tristate "Intel SCH/TunnelCreek GPIO" - depends on PCI && X86 + depends on GPIOLIB && PCI && X86 select MFD_CORE select LPC_SCH help @@ -126,7 +121,7 @@ config GPIO_SCH config GPIO_VX855 tristate "VIA VX855/VX875 GPIO" - depends on MFD_SUPPORT && PCI + depends on GPIOLIB && MFD_SUPPORT && PCI select MFD_CORE select MFD_VX855 help @@ -352,13 +347,13 @@ config GPIO_ML_IOH config GPIO_TIMBERDALE bool "Support for timberdale GPIO IP" - depends on MFD_TIMBERDALE && HAS_IOMEM + depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM ---help--- Add support for the GPIO IP in the timberdale FPGA. config GPIO_RDC321X tristate "RDC R-321x GPIO support" - depends on PCI + depends on PCI && GPIOLIB select MFD_SUPPORT select MFD_CORE select MFD_RDC321X @@ -424,11 +419,4 @@ config AB8500_GPIO depends on AB8500_CORE && BROKEN help Select this to enable the AB8500 IC GPIO driver - -config GPIO_TPS65910 - bool "TPS65910 GPIO" - depends on MFD_TPS65910 - help - Select this option to enable GPIO driver for the TPS65910 - chip family. endif diff --git a/trunk/drivers/gpio/Makefile b/trunk/drivers/gpio/Makefile index 6a3387acc0e5..becef5954356 100644 --- a/trunk/drivers/gpio/Makefile +++ b/trunk/drivers/gpio/Makefile @@ -1,4 +1,8 @@ -# generic gpio support: platform drivers, dedicated expander chips, etc +# generic gpio support: dedicated expander chips, etc +# +# NOTE: platform-specific GPIO drivers don't belong in the +# drivers/gpio directory; put them with other platform setup +# code, IRQ controllers, board init, etc. ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG @@ -6,7 +10,6 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o -obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o obj-$(CONFIG_GPIO_MAX730X) += max730x.o @@ -40,4 +43,3 @@ obj-$(CONFIG_GPIO_SX150X) += sx150x.o obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o -obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o diff --git a/trunk/drivers/gpio/basic_mmio_gpio.c b/trunk/drivers/gpio/basic_mmio_gpio.c index 8152e9f516b0..3addea65894e 100644 --- a/trunk/drivers/gpio/basic_mmio_gpio.c +++ b/trunk/drivers/gpio/basic_mmio_gpio.c @@ -45,7 +45,6 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` */ #include -#include #include #include #include @@ -62,101 +61,102 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` #include #include -static void bgpio_write8(void __iomem *reg, unsigned long data) -{ - writeb(data, reg); -} - -static unsigned long bgpio_read8(void __iomem *reg) -{ - return readb(reg); -} - -static void bgpio_write16(void __iomem *reg, unsigned long data) -{ - writew(data, reg); -} - -static unsigned long bgpio_read16(void __iomem *reg) -{ - return readw(reg); -} +struct bgpio_chip { + struct gpio_chip gc; + void __iomem *reg_dat; + void __iomem *reg_set; + void __iomem *reg_clr; + + /* Number of bits (GPIOs): * 8. */ + int bits; + + /* + * Some GPIO controllers work with the big-endian bits notation, + * e.g. in a 8-bits register, GPIO7 is the least significant bit. + */ + int big_endian_bits; + + /* + * Used to lock bgpio_chip->data. Also, this is needed to keep + * shadowed and real data registers writes together. + */ + spinlock_t lock; + + /* Shadowed data register to clear/set bits safely. */ + unsigned long data; +}; -static void bgpio_write32(void __iomem *reg, unsigned long data) +static struct bgpio_chip *to_bgpio_chip(struct gpio_chip *gc) { - writel(data, reg); + return container_of(gc, struct bgpio_chip, gc); } -static unsigned long bgpio_read32(void __iomem *reg) +static unsigned long bgpio_in(struct bgpio_chip *bgc) { - return readl(reg); -} - + switch (bgc->bits) { + case 8: + return __raw_readb(bgc->reg_dat); + case 16: + return __raw_readw(bgc->reg_dat); + case 32: + return __raw_readl(bgc->reg_dat); #if BITS_PER_LONG >= 64 -static void bgpio_write64(void __iomem *reg, unsigned long data) -{ - writeq(data, reg); + case 64: + return __raw_readq(bgc->reg_dat); +#endif + } + return -EINVAL; } -static unsigned long bgpio_read64(void __iomem *reg) +static void bgpio_out(struct bgpio_chip *bgc, void __iomem *reg, + unsigned long data) { - return readq(reg); + switch (bgc->bits) { + case 8: + __raw_writeb(data, reg); + return; + case 16: + __raw_writew(data, reg); + return; + case 32: + __raw_writel(data, reg); + return; +#if BITS_PER_LONG >= 64 + case 64: + __raw_writeq(data, reg); + return; +#endif + } } -#endif /* BITS_PER_LONG >= 64 */ static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin) { - return 1 << pin; -} - -static unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc, - unsigned int pin) -{ - return 1 << (bgc->bits - 1 - pin); + if (bgc->big_endian_bits) + return 1 << (bgc->bits - 1 - pin); + else + return 1 << pin; } static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) { struct bgpio_chip *bgc = to_bgpio_chip(gc); - return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio); + return bgpio_in(bgc) & bgpio_pin2mask(bgc, gpio); } static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long mask = bgc->pin2mask(bgc, gpio); + unsigned long mask = bgpio_pin2mask(bgc, gpio); unsigned long flags; - spin_lock_irqsave(&bgc->lock, flags); - - if (val) - bgc->data |= mask; - else - bgc->data &= ~mask; - - bgc->write_reg(bgc->reg_dat, bgc->data); - - spin_unlock_irqrestore(&bgc->lock, flags); -} - -static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, - int val) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long mask = bgc->pin2mask(bgc, gpio); - - if (val) - bgc->write_reg(bgc->reg_set, mask); - else - bgc->write_reg(bgc->reg_clr, mask); -} - -static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long mask = bgc->pin2mask(bgc, gpio); - unsigned long flags; + if (bgc->reg_set) { + if (val) + bgpio_out(bgc, bgc->reg_set, mask); + else + bgpio_out(bgc, bgc->reg_clr, mask); + return; + } spin_lock_irqsave(&bgc->lock, flags); @@ -165,352 +165,103 @@ static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) else bgc->data &= ~mask; - bgc->write_reg(bgc->reg_set, bgc->data); + bgpio_out(bgc, bgc->reg_dat, bgc->data); spin_unlock_irqrestore(&bgc->lock, flags); } -static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) -{ - return 0; -} - -static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio, - int val) -{ - gc->set(gc, gpio, val); - - return 0; -} - static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long flags; - - spin_lock_irqsave(&bgc->lock, flags); - - bgc->dir &= ~bgc->pin2mask(bgc, gpio); - bgc->write_reg(bgc->reg_dir, bgc->dir); - - spin_unlock_irqrestore(&bgc->lock, flags); - return 0; } static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long flags; - - gc->set(gc, gpio, val); - - spin_lock_irqsave(&bgc->lock, flags); - - bgc->dir |= bgc->pin2mask(bgc, gpio); - bgc->write_reg(bgc->reg_dir, bgc->dir); - - spin_unlock_irqrestore(&bgc->lock, flags); - - return 0; -} - -static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long flags; - - spin_lock_irqsave(&bgc->lock, flags); - - bgc->dir |= bgc->pin2mask(bgc, gpio); - bgc->write_reg(bgc->reg_dir, bgc->dir); - - spin_unlock_irqrestore(&bgc->lock, flags); - + bgpio_set(gc, gpio, val); return 0; } -static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - unsigned long flags; - - gc->set(gc, gpio, val); - - spin_lock_irqsave(&bgc->lock, flags); - - bgc->dir &= ~bgc->pin2mask(bgc, gpio); - bgc->write_reg(bgc->reg_dir, bgc->dir); - - spin_unlock_irqrestore(&bgc->lock, flags); - - return 0; -} - -static int bgpio_setup_accessors(struct device *dev, - struct bgpio_chip *bgc, - bool be) +static int __devinit bgpio_probe(struct platform_device *pdev) { + const struct platform_device_id *platid = platform_get_device_id(pdev); + struct device *dev = &pdev->dev; + struct bgpio_pdata *pdata = dev_get_platdata(dev); + struct bgpio_chip *bgc; + struct resource *res_dat; + struct resource *res_set; + struct resource *res_clr; + resource_size_t dat_sz; + int bits; + int ret; - switch (bgc->bits) { - case 8: - bgc->read_reg = bgpio_read8; - bgc->write_reg = bgpio_write8; - break; - case 16: - bgc->read_reg = bgpio_read16; - bgc->write_reg = bgpio_write16; - break; - case 32: - bgc->read_reg = bgpio_read32; - bgc->write_reg = bgpio_write32; - break; -#if BITS_PER_LONG >= 64 - case 64: - bgc->read_reg = bgpio_read64; - bgc->write_reg = bgpio_write64; - break; -#endif /* BITS_PER_LONG >= 64 */ - default: - dev_err(dev, "unsupported data width %u bits\n", bgc->bits); + res_dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); + if (!res_dat) return -EINVAL; - } - - bgc->pin2mask = be ? bgpio_pin2mask_be : bgpio_pin2mask; - - return 0; -} - -/* - * Create the device and allocate the resources. For setting GPIO's there are - * three supported configurations: - * - * - single input/output register resource (named "dat"). - * - set/clear pair (named "set" and "clr"). - * - single output register resource and single input resource ("set" and - * dat"). - * - * For the single output register, this drives a 1 by setting a bit and a zero - * by clearing a bit. For the set clr pair, this drives a 1 by setting a bit - * in the set register and clears it by setting a bit in the clear register. - * The configuration is detected by which resources are present. - * - * For setting the GPIO direction, there are three supported configurations: - * - * - simple bidirection GPIO that requires no configuration. - * - an output direction register (named "dirout") where a 1 bit - * indicates the GPIO is an output. - * - an input direction register (named "dirin") where a 1 bit indicates - * the GPIO is an input. - */ -static int bgpio_setup_io(struct bgpio_chip *bgc, - void __iomem *dat, - void __iomem *set, - void __iomem *clr) -{ - bgc->reg_dat = dat; - if (!bgc->reg_dat) + dat_sz = resource_size(res_dat); + if (!is_power_of_2(dat_sz)) return -EINVAL; - if (set && clr) { - bgc->reg_set = set; - bgc->reg_clr = clr; - bgc->gc.set = bgpio_set_with_clear; - } else if (set && !clr) { - bgc->reg_set = set; - bgc->gc.set = bgpio_set_set; - } else { - bgc->gc.set = bgpio_set; - } + bits = dat_sz * 8; + if (bits > BITS_PER_LONG) + return -EINVAL; - bgc->gc.get = bgpio_get; + bgc = devm_kzalloc(dev, sizeof(*bgc), GFP_KERNEL); + if (!bgc) + return -ENOMEM; - return 0; -} + bgc->reg_dat = devm_ioremap(dev, res_dat->start, dat_sz); + if (!bgc->reg_dat) + return -ENOMEM; -static int bgpio_setup_direction(struct bgpio_chip *bgc, - void __iomem *dirout, - void __iomem *dirin) -{ - if (dirout && dirin) { + res_set = platform_get_resource_byname(pdev, IORESOURCE_MEM, "set"); + res_clr = platform_get_resource_byname(pdev, IORESOURCE_MEM, "clr"); + if (res_set && res_clr) { + if (resource_size(res_set) != resource_size(res_clr) || + resource_size(res_set) != dat_sz) + return -EINVAL; + + bgc->reg_set = devm_ioremap(dev, res_set->start, dat_sz); + bgc->reg_clr = devm_ioremap(dev, res_clr->start, dat_sz); + if (!bgc->reg_set || !bgc->reg_clr) + return -ENOMEM; + } else if (res_set || res_clr) { return -EINVAL; - } else if (dirout) { - bgc->reg_dir = dirout; - bgc->gc.direction_output = bgpio_dir_out; - bgc->gc.direction_input = bgpio_dir_in; - } else if (dirin) { - bgc->reg_dir = dirin; - bgc->gc.direction_output = bgpio_dir_out_inv; - bgc->gc.direction_input = bgpio_dir_in_inv; - } else { - bgc->gc.direction_output = bgpio_simple_dir_out; - bgc->gc.direction_input = bgpio_simple_dir_in; } - return 0; -} - -int __devexit bgpio_remove(struct bgpio_chip *bgc) -{ - int err = gpiochip_remove(&bgc->gc); - - kfree(bgc); - - return err; -} -EXPORT_SYMBOL_GPL(bgpio_remove); - -int __devinit bgpio_init(struct bgpio_chip *bgc, - struct device *dev, - unsigned long sz, - void __iomem *dat, - void __iomem *set, - void __iomem *clr, - void __iomem *dirout, - void __iomem *dirin, - bool big_endian) -{ - int ret; - - if (!is_power_of_2(sz)) - return -EINVAL; + spin_lock_init(&bgc->lock); - bgc->bits = sz * 8; - if (bgc->bits > BITS_PER_LONG) - return -EINVAL; + bgc->bits = bits; + bgc->big_endian_bits = !strcmp(platid->name, "basic-mmio-gpio-be"); + bgc->data = bgpio_in(bgc); - spin_lock_init(&bgc->lock); + bgc->gc.ngpio = bits; + bgc->gc.direction_input = bgpio_dir_in; + bgc->gc.direction_output = bgpio_dir_out; + bgc->gc.get = bgpio_get; + bgc->gc.set = bgpio_set; bgc->gc.dev = dev; bgc->gc.label = dev_name(dev); - bgc->gc.base = -1; - bgc->gc.ngpio = bgc->bits; - ret = bgpio_setup_io(bgc, dat, set, clr); - if (ret) - return ret; + if (pdata) + bgc->gc.base = pdata->base; + else + bgc->gc.base = -1; - ret = bgpio_setup_accessors(dev, bgc, big_endian); - if (ret) - return ret; + dev_set_drvdata(dev, bgc); - ret = bgpio_setup_direction(bgc, dirout, dirin); + ret = gpiochip_add(&bgc->gc); if (ret) - return ret; - - bgc->data = bgc->read_reg(bgc->reg_dat); + dev_err(dev, "gpiochip_add() failed: %d\n", ret); return ret; } -EXPORT_SYMBOL_GPL(bgpio_init); - -#ifdef CONFIG_GPIO_BASIC_MMIO -static void __iomem *bgpio_map(struct platform_device *pdev, - const char *name, - resource_size_t sane_sz, - int *err) +static int __devexit bgpio_remove(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - struct resource *r; - resource_size_t start; - resource_size_t sz; - void __iomem *ret; - - *err = 0; - - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - if (!r) - return NULL; + struct bgpio_chip *bgc = dev_get_drvdata(&pdev->dev); - sz = resource_size(r); - if (sz != sane_sz) { - *err = -EINVAL; - return NULL; - } - - start = r->start; - if (!devm_request_mem_region(dev, start, sz, r->name)) { - *err = -EBUSY; - return NULL; - } - - ret = devm_ioremap(dev, start, sz); - if (!ret) { - *err = -ENOMEM; - return NULL; - } - - return ret; -} - -static int __devinit bgpio_pdev_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct resource *r; - void __iomem *dat; - void __iomem *set; - void __iomem *clr; - void __iomem *dirout; - void __iomem *dirin; - unsigned long sz; - bool be; - int err; - struct bgpio_chip *bgc; - struct bgpio_pdata *pdata = dev_get_platdata(dev); - - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); - if (!r) - return -EINVAL; - - sz = resource_size(r); - - dat = bgpio_map(pdev, "dat", sz, &err); - if (!dat) - return err ? err : -EINVAL; - - set = bgpio_map(pdev, "set", sz, &err); - if (err) - return err; - - clr = bgpio_map(pdev, "clr", sz, &err); - if (err) - return err; - - dirout = bgpio_map(pdev, "dirout", sz, &err); - if (err) - return err; - - dirin = bgpio_map(pdev, "dirin", sz, &err); - if (err) - return err; - - be = !strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be"); - - bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL); - if (!bgc) - return -ENOMEM; - - err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, be); - if (err) - return err; - - if (pdata) { - bgc->gc.base = pdata->base; - if (pdata->ngpio > 0) - bgc->gc.ngpio = pdata->ngpio; - } - - platform_set_drvdata(pdev, bgc); - - return gpiochip_add(&bgc->gc); -} - -static int __devexit bgpio_pdev_remove(struct platform_device *pdev) -{ - struct bgpio_chip *bgc = platform_get_drvdata(pdev); - - return bgpio_remove(bgc); + return gpiochip_remove(&bgc->gc); } static const struct platform_device_id bgpio_id_table[] = { @@ -525,23 +276,21 @@ static struct platform_driver bgpio_driver = { .name = "basic-mmio-gpio", }, .id_table = bgpio_id_table, - .probe = bgpio_pdev_probe, - .remove = __devexit_p(bgpio_pdev_remove), + .probe = bgpio_probe, + .remove = __devexit_p(bgpio_remove), }; -static int __init bgpio_platform_init(void) +static int __init bgpio_init(void) { return platform_driver_register(&bgpio_driver); } -module_init(bgpio_platform_init); +module_init(bgpio_init); -static void __exit bgpio_platform_exit(void) +static void __exit bgpio_exit(void) { platform_driver_unregister(&bgpio_driver); } -module_exit(bgpio_platform_exit); - -#endif /* CONFIG_GPIO_BASIC_MMIO */ +module_exit(bgpio_exit); MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers"); MODULE_AUTHOR("Anton Vorontsov "); diff --git a/trunk/drivers/gpio/gpiolib.c b/trunk/drivers/gpio/gpiolib.c index 137a8ca67822..36a2974815b7 100644 --- a/trunk/drivers/gpio/gpiolib.c +++ b/trunk/drivers/gpio/gpiolib.c @@ -12,8 +12,6 @@ #include #include -#define CREATE_TRACE_POINTS -#include /* Optional implementation infrastructure for GPIO interfaces. * @@ -1167,7 +1165,6 @@ struct gpio_chip *gpiochip_find(void *data, return chip; } -EXPORT_SYMBOL_GPL(gpiochip_find); /* These "optional" allocation calls help prevent drivers from stomping * on each other, and help provide better diagnostics in debugfs. @@ -1407,8 +1404,6 @@ int gpio_direction_input(unsigned gpio) status = chip->direction_input(chip, gpio); if (status == 0) clear_bit(FLAG_IS_OUT, &desc->flags); - - trace_gpio_direction(chip->base + gpio, 1, status); lose: return status; fail: @@ -1462,8 +1457,6 @@ int gpio_direction_output(unsigned gpio, int value) status = chip->direction_output(chip, gpio, value); if (status == 0) set_bit(FLAG_IS_OUT, &desc->flags); - trace_gpio_value(chip->base + gpio, 0, value); - trace_gpio_direction(chip->base + gpio, 0, status); lose: return status; fail: @@ -1553,13 +1546,10 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce); int __gpio_get_value(unsigned gpio) { struct gpio_chip *chip; - int value; chip = gpio_to_chip(gpio); WARN_ON(chip->can_sleep); - value = chip->get ? chip->get(chip, gpio - chip->base) : 0; - trace_gpio_value(gpio, 1, value); - return value; + return chip->get ? chip->get(chip, gpio - chip->base) : 0; } EXPORT_SYMBOL_GPL(__gpio_get_value); @@ -1578,7 +1568,6 @@ void __gpio_set_value(unsigned gpio, int value) chip = gpio_to_chip(gpio); WARN_ON(chip->can_sleep); - trace_gpio_value(gpio, 0, value); chip->set(chip, gpio - chip->base, value); } EXPORT_SYMBOL_GPL(__gpio_set_value); @@ -1629,13 +1618,10 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq); int gpio_get_value_cansleep(unsigned gpio) { struct gpio_chip *chip; - int value; might_sleep_if(extra_checks); chip = gpio_to_chip(gpio); - value = chip->get ? chip->get(chip, gpio - chip->base) : 0; - trace_gpio_value(gpio, 1, value); - return value; + return chip->get ? chip->get(chip, gpio - chip->base) : 0; } EXPORT_SYMBOL_GPL(gpio_get_value_cansleep); @@ -1645,7 +1631,6 @@ void gpio_set_value_cansleep(unsigned gpio, int value) might_sleep_if(extra_checks); chip = gpio_to_chip(gpio); - trace_gpio_value(gpio, 0, value); chip->set(chip, gpio - chip->base, value); } EXPORT_SYMBOL_GPL(gpio_set_value_cansleep); diff --git a/trunk/drivers/gpio/janz-ttl.c b/trunk/drivers/gpio/janz-ttl.c index 813ac077e5d7..2514fb075f4a 100644 --- a/trunk/drivers/gpio/janz-ttl.c +++ b/trunk/drivers/gpio/janz-ttl.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -149,7 +150,7 @@ static int __devinit ttl_probe(struct platform_device *pdev) struct resource *res; int ret; - pdata = pdev->dev.platform_data; + pdata = mfd_get_data(pdev); if (!pdata) { dev_err(dev, "no platform data\n"); ret = -ENXIO; diff --git a/trunk/drivers/gpio/pca953x.c b/trunk/drivers/gpio/pca953x.c index 78a843947d82..7630ab7b9bec 100644 --- a/trunk/drivers/gpio/pca953x.c +++ b/trunk/drivers/gpio/pca953x.c @@ -397,7 +397,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, irq_set_chip_data(irq, chip); irq_set_chip_and_handler(irq, &pca953x_irq_chip, - handle_simple_irq); + handle_edge_irq); #ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID); #else diff --git a/trunk/drivers/gpio/rdc321x-gpio.c b/trunk/drivers/gpio/rdc321x-gpio.c index 2762698e0204..a9bda881935a 100644 --- a/trunk/drivers/gpio/rdc321x-gpio.c +++ b/trunk/drivers/gpio/rdc321x-gpio.c @@ -27,6 +27,7 @@ #include #include #include +#include #include struct rdc321x_gpio { @@ -135,7 +136,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) struct rdc321x_gpio *rdc321x_gpio_dev; struct rdc321x_gpio_pdata *pdata; - pdata = pdev->dev.platform_data; + pdata = mfd_get_data(pdev); if (!pdata) { dev_err(&pdev->dev, "no platform data supplied\n"); return -ENODEV; diff --git a/trunk/drivers/gpio/timbgpio.c b/trunk/drivers/gpio/timbgpio.c index 0265872e57d1..edbe1eae531f 100644 --- a/trunk/drivers/gpio/timbgpio.c +++ b/trunk/drivers/gpio/timbgpio.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -228,7 +229,7 @@ static int __devinit timbgpio_probe(struct platform_device *pdev) struct gpio_chip *gc; struct timbgpio *tgpio; struct resource *iomem; - struct timbgpio_platform_data *pdata = pdev->dev.platform_data; + struct timbgpio_platform_data *pdata = mfd_get_data(pdev); int irq = platform_get_irq(pdev, 0); if (!pdata || pdata->nr_pins > 32) { @@ -319,14 +320,13 @@ static int __devinit timbgpio_probe(struct platform_device *pdev) static int __devexit timbgpio_remove(struct platform_device *pdev) { int err; - struct timbgpio_platform_data *pdata = pdev->dev.platform_data; struct timbgpio *tgpio = platform_get_drvdata(pdev); struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); int irq = platform_get_irq(pdev, 0); if (irq >= 0 && tgpio->irq_base > 0) { int i; - for (i = 0; i < pdata->nr_pins; i++) { + for (i = 0; i < tgpio->gpio.ngpio; i++) { irq_set_chip(tgpio->irq_base + i, NULL); irq_set_chip_data(tgpio->irq_base + i, NULL); } diff --git a/trunk/drivers/gpio/tps65910-gpio.c b/trunk/drivers/gpio/tps65910-gpio.c deleted file mode 100644 index 8d1ddfdd63eb..000000000000 --- a/trunk/drivers/gpio/tps65910-gpio.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * tps65910-gpio.c -- TI TPS6591x - * - * Copyright 2010 Texas Instruments Inc. - * - * Author: Graeme Gregory - * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include - -static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); - uint8_t val; - - tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val); - - if (val & GPIO_STS_MASK) - return 1; - - return 0; -} - -static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); - - if (value) - tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset, - GPIO_SET_MASK); - else - tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset, - GPIO_SET_MASK); -} - -static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); - - /* Set the initial value */ - tps65910_gpio_set(gc, 0, value); - - return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset, - GPIO_CFG_MASK); -} - -static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset) -{ - struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); - - return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset, - GPIO_CFG_MASK); -} - -void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) -{ - int ret; - - if (!gpio_base) - return; - - tps65910->gpio.owner = THIS_MODULE; - tps65910->gpio.label = tps65910->i2c_client->name; - tps65910->gpio.dev = tps65910->dev; - tps65910->gpio.base = gpio_base; - - switch(tps65910_chip_id(tps65910)) { - case TPS65910: - tps65910->gpio.ngpio = 6; - case TPS65911: - tps65910->gpio.ngpio = 9; - default: - return; - } - tps65910->gpio.can_sleep = 1; - - tps65910->gpio.direction_input = tps65910_gpio_input; - tps65910->gpio.direction_output = tps65910_gpio_output; - tps65910->gpio.set = tps65910_gpio_set; - tps65910->gpio.get = tps65910_gpio_get; - - ret = gpiochip_add(&tps65910->gpio); - - if (ret) - dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret); -} diff --git a/trunk/drivers/hwmon/coretemp.c b/trunk/drivers/hwmon/coretemp.c index de3d2465fe24..9577c432e77f 100644 --- a/trunk/drivers/hwmon/coretemp.c +++ b/trunk/drivers/hwmon/coretemp.c @@ -350,7 +350,6 @@ static int get_pkg_tjmax(unsigned int cpu, struct device *dev) static int create_name_attr(struct platform_data *pdata, struct device *dev) { - sysfs_attr_init(&pdata->name_attr.attr); pdata->name_attr.attr.name = "name"; pdata->name_attr.attr.mode = S_IRUGO; pdata->name_attr.show = show_name; @@ -373,7 +372,6 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, for (i = 0; i < MAX_ATTRS; i++) { snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], attr_no); - sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; @@ -424,7 +422,7 @@ static void update_ttarget(__u8 cpu_model, struct temp_data *tdata, } } -static int __devinit chk_ucode_version(struct platform_device *pdev) +static int chk_ucode_version(struct platform_device *pdev) { struct cpuinfo_x86 *c = &cpu_data(pdev->id); int err; @@ -511,8 +509,8 @@ static int create_core_data(struct platform_data *pdata, /* * Provide a single set of attributes for all HT siblings of a core * to avoid duplicate sensors (the processor ID and core ID of all - * HT siblings of a core are the same). - * Skip if a HT sibling of this core is already registered. + * HT siblings of a core is the same). + * Skip if a HT sibling of this core is already online. * This is not an error. */ if (pdata->core_data[attr_no] != NULL) @@ -772,10 +770,10 @@ static void __cpuinit put_core_offline(unsigned int cpu) coretemp_remove_core(pdata, &pdev->dev, indx); /* - * If a HT sibling of a core is taken offline, but another HT sibling - * of the same core is still online, register the alternate sibling. - * This ensures that exactly one set of attributes is provided as long - * as at least one HT sibling of a core is online. + * If a core is taken offline, but a HT sibling of the same core is + * still online, register the alternate sibling. This ensures that + * exactly one set of attributes is provided as long as at least one + * HT sibling of a core is online. */ for_each_sibling(i, cpu) { if (i != cpu) { diff --git a/trunk/drivers/hwmon/pmbus_core.c b/trunk/drivers/hwmon/pmbus_core.c index 354770ed3186..98799bab69ce 100644 --- a/trunk/drivers/hwmon/pmbus_core.c +++ b/trunk/drivers/hwmon/pmbus_core.c @@ -707,7 +707,6 @@ do { \ struct sensor_device_attribute *a \ = &data->_type##s[data->num_##_type##s].attribute; \ BUG_ON(data->num_attributes >= data->max_attributes); \ - sysfs_attr_init(&a->dev_attr.attr); \ a->dev_attr.attr.name = _name; \ a->dev_attr.attr.mode = _mode; \ a->dev_attr.show = _show; \ diff --git a/trunk/drivers/i2c/busses/i2c-ocores.c b/trunk/drivers/i2c/busses/i2c-ocores.c index 1b46a9d9f907..fee1a2613861 100644 --- a/trunk/drivers/i2c/busses/i2c-ocores.c +++ b/trunk/drivers/i2c/busses/i2c-ocores.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -305,7 +306,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) return -EIO; } - pdata = pdev->dev.platform_data; + pdata = mfd_get_data(pdev); if (pdata) { i2c->regstep = pdata->regstep; i2c->clock_khz = pdata->clock_khz; diff --git a/trunk/drivers/i2c/busses/i2c-xiic.c b/trunk/drivers/i2c/busses/i2c-xiic.c index 4bb68f35caf2..e9d5ff4d1496 100644 --- a/trunk/drivers/i2c/busses/i2c-xiic.c +++ b/trunk/drivers/i2c/busses/i2c-xiic.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -704,7 +705,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) if (irq < 0) goto resource_missing; - pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data; + pdata = mfd_get_data(pdev); if (!pdata) return -EINVAL; diff --git a/trunk/drivers/infiniband/Kconfig b/trunk/drivers/infiniband/Kconfig index 0f9a84c1046a..6e35eccc9caa 100644 --- a/trunk/drivers/infiniband/Kconfig +++ b/trunk/drivers/infiniband/Kconfig @@ -2,7 +2,6 @@ menuconfig INFINIBAND tristate "InfiniBand support" depends on PCI || BROKEN depends on HAS_IOMEM - depends on NET ---help--- Core support for InfiniBand (IB). Make sure to also select any protocols you wish to use as well as drivers for your diff --git a/trunk/drivers/infiniband/core/Makefile b/trunk/drivers/infiniband/core/Makefile index c8bbaef1becb..cb1ab3ea4998 100644 --- a/trunk/drivers/infiniband/core/Makefile +++ b/trunk/drivers/infiniband/core/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \ $(user_access-y) ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ - device.o fmr_pool.o cache.o netlink.o + device.o fmr_pool.o cache.o ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o ib_mad-y := mad.o smi.o agent.o mad_rmpp.o diff --git a/trunk/drivers/infiniband/core/cm.c b/trunk/drivers/infiniband/core/cm.c index f62f52fb9ece..f804e28e1ebb 100644 --- a/trunk/drivers/infiniband/core/cm.c +++ b/trunk/drivers/infiniband/core/cm.c @@ -3639,16 +3639,8 @@ static struct kobj_type cm_port_obj_type = { .release = cm_release_port_obj }; -static char *cm_devnode(struct device *dev, mode_t *mode) -{ - *mode = 0666; - return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev)); -} - struct class cm_class = { - .owner = THIS_MODULE, .name = "infiniband_cm", - .devnode = cm_devnode, }; EXPORT_SYMBOL(cm_class); diff --git a/trunk/drivers/infiniband/core/cma.c b/trunk/drivers/infiniband/core/cma.c index b6a33b3c516d..99dde874fbbd 100644 --- a/trunk/drivers/infiniband/core/cma.c +++ b/trunk/drivers/infiniband/core/cma.c @@ -47,7 +47,6 @@ #include #include -#include #include #include #include @@ -90,6 +89,20 @@ struct cma_device { struct list_head id_list; }; +enum cma_state { + CMA_IDLE, + CMA_ADDR_QUERY, + CMA_ADDR_RESOLVED, + CMA_ROUTE_QUERY, + CMA_ROUTE_RESOLVED, + CMA_CONNECT, + CMA_DISCONNECT, + CMA_ADDR_BOUND, + CMA_LISTEN, + CMA_DEVICE_REMOVAL, + CMA_DESTROYING +}; + struct rdma_bind_list { struct idr *ps; struct hlist_head owners; @@ -113,7 +126,7 @@ struct rdma_id_private { struct list_head mc_list; int internal_id; - enum rdma_cm_state state; + enum cma_state state; spinlock_t lock; struct mutex qp_mutex; @@ -133,7 +146,6 @@ struct rdma_id_private { u32 seq_num; u32 qkey; u32 qp_num; - pid_t owner; u8 srq; u8 tos; u8 reuseaddr; @@ -153,8 +165,8 @@ struct cma_multicast { struct cma_work { struct work_struct work; struct rdma_id_private *id; - enum rdma_cm_state old_state; - enum rdma_cm_state new_state; + enum cma_state old_state; + enum cma_state new_state; struct rdma_cm_event event; }; @@ -205,7 +217,7 @@ struct sdp_hah { #define CMA_VERSION 0x00 #define SDP_MAJ_VERSION 0x2 -static int cma_comp(struct rdma_id_private *id_priv, enum rdma_cm_state comp) +static int cma_comp(struct rdma_id_private *id_priv, enum cma_state comp) { unsigned long flags; int ret; @@ -217,7 +229,7 @@ static int cma_comp(struct rdma_id_private *id_priv, enum rdma_cm_state comp) } static int cma_comp_exch(struct rdma_id_private *id_priv, - enum rdma_cm_state comp, enum rdma_cm_state exch) + enum cma_state comp, enum cma_state exch) { unsigned long flags; int ret; @@ -229,11 +241,11 @@ static int cma_comp_exch(struct rdma_id_private *id_priv, return ret; } -static enum rdma_cm_state cma_exch(struct rdma_id_private *id_priv, - enum rdma_cm_state exch) +static enum cma_state cma_exch(struct rdma_id_private *id_priv, + enum cma_state exch) { unsigned long flags; - enum rdma_cm_state old; + enum cma_state old; spin_lock_irqsave(&id_priv->lock, flags); old = id_priv->state; @@ -267,6 +279,11 @@ static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver) hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF); } +static inline int cma_is_ud_ps(enum rdma_port_space ps) +{ + return (ps == RDMA_PS_UDP || ps == RDMA_PS_IPOIB); +} + static void cma_attach_to_dev(struct rdma_id_private *id_priv, struct cma_device *cma_dev) { @@ -396,7 +413,7 @@ static void cma_deref_id(struct rdma_id_private *id_priv) } static int cma_disable_callback(struct rdma_id_private *id_priv, - enum rdma_cm_state state) + enum cma_state state) { mutex_lock(&id_priv->handler_mutex); if (id_priv->state != state) { @@ -412,8 +429,7 @@ static int cma_has_cm_dev(struct rdma_id_private *id_priv) } struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler, - void *context, enum rdma_port_space ps, - enum ib_qp_type qp_type) + void *context, enum rdma_port_space ps) { struct rdma_id_private *id_priv; @@ -421,12 +437,10 @@ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler, if (!id_priv) return ERR_PTR(-ENOMEM); - id_priv->owner = task_pid_nr(current); - id_priv->state = RDMA_CM_IDLE; + id_priv->state = CMA_IDLE; id_priv->id.context = context; id_priv->id.event_handler = event_handler; id_priv->id.ps = ps; - id_priv->id.qp_type = qp_type; spin_lock_init(&id_priv->lock); mutex_init(&id_priv->qp_mutex); init_completion(&id_priv->comp); @@ -494,7 +508,7 @@ int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd, if (IS_ERR(qp)) return PTR_ERR(qp); - if (id->qp_type == IB_QPT_UD) + if (cma_is_ud_ps(id_priv->id.ps)) ret = cma_init_ud_qp(id_priv, qp); else ret = cma_init_conn_qp(id_priv, qp); @@ -622,7 +636,7 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv, qp_attr->port_num = id_priv->id.port_num; *qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT; - if (id_priv->id.qp_type == IB_QPT_UD) { + if (cma_is_ud_ps(id_priv->id.ps)) { ret = cma_set_qkey(id_priv); if (ret) return ret; @@ -645,7 +659,7 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr, id_priv = container_of(id, struct rdma_id_private, id); switch (rdma_node_get_transport(id_priv->id.device->node_type)) { case RDMA_TRANSPORT_IB: - if (!id_priv->cm_id.ib || (id_priv->id.qp_type == IB_QPT_UD)) + if (!id_priv->cm_id.ib || cma_is_ud_ps(id_priv->id.ps)) ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask); else ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr, @@ -844,16 +858,16 @@ static void cma_cancel_listens(struct rdma_id_private *id_priv) } static void cma_cancel_operation(struct rdma_id_private *id_priv, - enum rdma_cm_state state) + enum cma_state state) { switch (state) { - case RDMA_CM_ADDR_QUERY: + case CMA_ADDR_QUERY: rdma_addr_cancel(&id_priv->id.route.addr.dev_addr); break; - case RDMA_CM_ROUTE_QUERY: + case CMA_ROUTE_QUERY: cma_cancel_route(id_priv); break; - case RDMA_CM_LISTEN: + case CMA_LISTEN: if (cma_any_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr) && !id_priv->cma_dev) cma_cancel_listens(id_priv); @@ -904,10 +918,10 @@ static void cma_leave_mc_groups(struct rdma_id_private *id_priv) void rdma_destroy_id(struct rdma_cm_id *id) { struct rdma_id_private *id_priv; - enum rdma_cm_state state; + enum cma_state state; id_priv = container_of(id, struct rdma_id_private, id); - state = cma_exch(id_priv, RDMA_CM_DESTROYING); + state = cma_exch(id_priv, CMA_DESTROYING); cma_cancel_operation(id_priv, state); /* @@ -1001,9 +1015,9 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) int ret = 0; if ((ib_event->event != IB_CM_TIMEWAIT_EXIT && - cma_disable_callback(id_priv, RDMA_CM_CONNECT)) || + cma_disable_callback(id_priv, CMA_CONNECT)) || (ib_event->event == IB_CM_TIMEWAIT_EXIT && - cma_disable_callback(id_priv, RDMA_CM_DISCONNECT))) + cma_disable_callback(id_priv, CMA_DISCONNECT))) return 0; memset(&event, 0, sizeof event); @@ -1034,8 +1048,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) event.status = -ETIMEDOUT; /* fall through */ case IB_CM_DREQ_RECEIVED: case IB_CM_DREP_RECEIVED: - if (!cma_comp_exch(id_priv, RDMA_CM_CONNECT, - RDMA_CM_DISCONNECT)) + if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT)) goto out; event.event = RDMA_CM_EVENT_DISCONNECTED; break; @@ -1062,7 +1075,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) if (ret) { /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.ib = NULL; - cma_exch(id_priv, RDMA_CM_DESTROYING); + cma_exch(id_priv, CMA_DESTROYING); mutex_unlock(&id_priv->handler_mutex); rdma_destroy_id(&id_priv->id); return ret; @@ -1088,7 +1101,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, goto err; id = rdma_create_id(listen_id->event_handler, listen_id->context, - listen_id->ps, ib_event->param.req_rcvd.qp_type); + listen_id->ps); if (IS_ERR(id)) goto err; @@ -1119,7 +1132,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); id_priv = container_of(id, struct rdma_id_private, id); - id_priv->state = RDMA_CM_CONNECT; + id_priv->state = CMA_CONNECT; return id_priv; destroy_id: @@ -1139,7 +1152,7 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, int ret; id = rdma_create_id(listen_id->event_handler, listen_id->context, - listen_id->ps, IB_QPT_UD); + listen_id->ps); if (IS_ERR(id)) return NULL; @@ -1159,7 +1172,7 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, } id_priv = container_of(id, struct rdma_id_private, id); - id_priv->state = RDMA_CM_CONNECT; + id_priv->state = CMA_CONNECT; return id_priv; err: rdma_destroy_id(id); @@ -1188,13 +1201,13 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) int offset, ret; listen_id = cm_id->context; - if (cma_disable_callback(listen_id, RDMA_CM_LISTEN)) + if (cma_disable_callback(listen_id, CMA_LISTEN)) return -ECONNABORTED; memset(&event, 0, sizeof event); offset = cma_user_data_offset(listen_id->id.ps); event.event = RDMA_CM_EVENT_CONNECT_REQUEST; - if (listen_id->id.qp_type == IB_QPT_UD) { + if (cma_is_ud_ps(listen_id->id.ps)) { conn_id = cma_new_udp_id(&listen_id->id, ib_event); event.param.ud.private_data = ib_event->private_data + offset; event.param.ud.private_data_len = @@ -1230,7 +1243,8 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) * while we're accessing the cm_id. */ mutex_lock(&lock); - if (cma_comp(conn_id, RDMA_CM_CONNECT) && (conn_id->id.qp_type != IB_QPT_UD)) + if (cma_comp(conn_id, CMA_CONNECT) && + !cma_is_ud_ps(conn_id->id.ps)) ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0); mutex_unlock(&lock); mutex_unlock(&conn_id->handler_mutex); @@ -1243,7 +1257,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) conn_id->cm_id.ib = NULL; release_conn_id: - cma_exch(conn_id, RDMA_CM_DESTROYING); + cma_exch(conn_id, CMA_DESTROYING); mutex_unlock(&conn_id->handler_mutex); rdma_destroy_id(&conn_id->id); @@ -1314,7 +1328,7 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) struct sockaddr_in *sin; int ret = 0; - if (cma_disable_callback(id_priv, RDMA_CM_CONNECT)) + if (cma_disable_callback(id_priv, CMA_CONNECT)) return 0; memset(&event, 0, sizeof event); @@ -1357,7 +1371,7 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) if (ret) { /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.iw = NULL; - cma_exch(id_priv, RDMA_CM_DESTROYING); + cma_exch(id_priv, CMA_DESTROYING); mutex_unlock(&id_priv->handler_mutex); rdma_destroy_id(&id_priv->id); return ret; @@ -1379,20 +1393,20 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, struct ib_device_attr attr; listen_id = cm_id->context; - if (cma_disable_callback(listen_id, RDMA_CM_LISTEN)) + if (cma_disable_callback(listen_id, CMA_LISTEN)) return -ECONNABORTED; /* Create a new RDMA id for the new IW CM ID */ new_cm_id = rdma_create_id(listen_id->id.event_handler, listen_id->id.context, - RDMA_PS_TCP, IB_QPT_RC); + RDMA_PS_TCP); if (IS_ERR(new_cm_id)) { ret = -ENOMEM; goto out; } conn_id = container_of(new_cm_id, struct rdma_id_private, id); mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING); - conn_id->state = RDMA_CM_CONNECT; + conn_id->state = CMA_CONNECT; dev = ip_dev_find(&init_net, iw_event->local_addr.sin_addr.s_addr); if (!dev) { @@ -1447,7 +1461,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, if (ret) { /* User wants to destroy the CM ID */ conn_id->cm_id.iw = NULL; - cma_exch(conn_id, RDMA_CM_DESTROYING); + cma_exch(conn_id, CMA_DESTROYING); mutex_unlock(&conn_id->handler_mutex); cma_deref_id(conn_id); rdma_destroy_id(&conn_id->id); @@ -1534,14 +1548,13 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv, struct rdma_cm_id *id; int ret; - id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps, - id_priv->id.qp_type); + id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps); if (IS_ERR(id)) return; dev_id_priv = container_of(id, struct rdma_id_private, id); - dev_id_priv->state = RDMA_CM_ADDR_BOUND; + dev_id_priv->state = CMA_ADDR_BOUND; memcpy(&id->route.addr.src_addr, &id_priv->id.route.addr.src_addr, ip_addr_size((struct sockaddr *) &id_priv->id.route.addr.src_addr)); @@ -1588,8 +1601,8 @@ static void cma_query_handler(int status, struct ib_sa_path_rec *path_rec, route->num_paths = 1; *route->path_rec = *path_rec; } else { - work->old_state = RDMA_CM_ROUTE_QUERY; - work->new_state = RDMA_CM_ADDR_RESOLVED; + work->old_state = CMA_ROUTE_QUERY; + work->new_state = CMA_ADDR_RESOLVED; work->event.event = RDMA_CM_EVENT_ROUTE_ERROR; work->event.status = status; } @@ -1647,7 +1660,7 @@ static void cma_work_handler(struct work_struct *_work) goto out; if (id_priv->id.event_handler(&id_priv->id, &work->event)) { - cma_exch(id_priv, RDMA_CM_DESTROYING); + cma_exch(id_priv, CMA_DESTROYING); destroy = 1; } out: @@ -1665,12 +1678,12 @@ static void cma_ndev_work_handler(struct work_struct *_work) int destroy = 0; mutex_lock(&id_priv->handler_mutex); - if (id_priv->state == RDMA_CM_DESTROYING || - id_priv->state == RDMA_CM_DEVICE_REMOVAL) + if (id_priv->state == CMA_DESTROYING || + id_priv->state == CMA_DEVICE_REMOVAL) goto out; if (id_priv->id.event_handler(&id_priv->id, &work->event)) { - cma_exch(id_priv, RDMA_CM_DESTROYING); + cma_exch(id_priv, CMA_DESTROYING); destroy = 1; } @@ -1694,8 +1707,8 @@ static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms) work->id = id_priv; INIT_WORK(&work->work, cma_work_handler); - work->old_state = RDMA_CM_ROUTE_QUERY; - work->new_state = RDMA_CM_ROUTE_RESOLVED; + work->old_state = CMA_ROUTE_QUERY; + work->new_state = CMA_ROUTE_RESOLVED; work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL); @@ -1724,8 +1737,7 @@ int rdma_set_ib_paths(struct rdma_cm_id *id, int ret; id_priv = container_of(id, struct rdma_id_private, id); - if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_RESOLVED, - RDMA_CM_ROUTE_RESOLVED)) + if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_RESOLVED)) return -EINVAL; id->route.path_rec = kmemdup(path_rec, sizeof *path_rec * num_paths, @@ -1738,7 +1750,7 @@ int rdma_set_ib_paths(struct rdma_cm_id *id, id->route.num_paths = num_paths; return 0; err: - cma_comp_exch(id_priv, RDMA_CM_ROUTE_RESOLVED, RDMA_CM_ADDR_RESOLVED); + cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_ADDR_RESOLVED); return ret; } EXPORT_SYMBOL(rdma_set_ib_paths); @@ -1753,8 +1765,8 @@ static int cma_resolve_iw_route(struct rdma_id_private *id_priv, int timeout_ms) work->id = id_priv; INIT_WORK(&work->work, cma_work_handler); - work->old_state = RDMA_CM_ROUTE_QUERY; - work->new_state = RDMA_CM_ROUTE_RESOLVED; + work->old_state = CMA_ROUTE_QUERY; + work->new_state = CMA_ROUTE_RESOLVED; work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; queue_work(cma_wq, &work->work); return 0; @@ -1818,8 +1830,8 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv) goto err2; } - work->old_state = RDMA_CM_ROUTE_QUERY; - work->new_state = RDMA_CM_ROUTE_RESOLVED; + work->old_state = CMA_ROUTE_QUERY; + work->new_state = CMA_ROUTE_RESOLVED; work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; work->event.status = 0; @@ -1841,7 +1853,7 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms) int ret; id_priv = container_of(id, struct rdma_id_private, id); - if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_RESOLVED, RDMA_CM_ROUTE_QUERY)) + if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_QUERY)) return -EINVAL; atomic_inc(&id_priv->refcount); @@ -1870,7 +1882,7 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms) return 0; err: - cma_comp_exch(id_priv, RDMA_CM_ROUTE_QUERY, RDMA_CM_ADDR_RESOLVED); + cma_comp_exch(id_priv, CMA_ROUTE_QUERY, CMA_ADDR_RESOLVED); cma_deref_id(id_priv); return ret; } @@ -1929,16 +1941,14 @@ static void addr_handler(int status, struct sockaddr *src_addr, memset(&event, 0, sizeof event); mutex_lock(&id_priv->handler_mutex); - if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY, - RDMA_CM_ADDR_RESOLVED)) + if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) goto out; if (!status && !id_priv->cma_dev) status = cma_acquire_dev(id_priv); if (status) { - if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_RESOLVED, - RDMA_CM_ADDR_BOUND)) + if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND)) goto out; event.event = RDMA_CM_EVENT_ADDR_ERROR; event.status = status; @@ -1949,7 +1959,7 @@ static void addr_handler(int status, struct sockaddr *src_addr, } if (id_priv->id.event_handler(&id_priv->id, &event)) { - cma_exch(id_priv, RDMA_CM_DESTROYING); + cma_exch(id_priv, CMA_DESTROYING); mutex_unlock(&id_priv->handler_mutex); cma_deref_id(id_priv); rdma_destroy_id(&id_priv->id); @@ -1994,8 +2004,8 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) work->id = id_priv; INIT_WORK(&work->work, cma_work_handler); - work->old_state = RDMA_CM_ADDR_QUERY; - work->new_state = RDMA_CM_ADDR_RESOLVED; + work->old_state = CMA_ADDR_QUERY; + work->new_state = CMA_ADDR_RESOLVED; work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED; queue_work(cma_wq, &work->work); return 0; @@ -2024,13 +2034,13 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, int ret; id_priv = container_of(id, struct rdma_id_private, id); - if (id_priv->state == RDMA_CM_IDLE) { + if (id_priv->state == CMA_IDLE) { ret = cma_bind_addr(id, src_addr, dst_addr); if (ret) return ret; } - if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) + if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_ADDR_QUERY)) return -EINVAL; atomic_inc(&id_priv->refcount); @@ -2046,7 +2056,7 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, return 0; err: - cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY, RDMA_CM_ADDR_BOUND); + cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND); cma_deref_id(id_priv); return ret; } @@ -2060,7 +2070,7 @@ int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse) id_priv = container_of(id, struct rdma_id_private, id); spin_lock_irqsave(&id_priv->lock, flags); - if (id_priv->state == RDMA_CM_IDLE) { + if (id_priv->state == CMA_IDLE) { id_priv->reuseaddr = reuse; ret = 0; } else { @@ -2167,7 +2177,7 @@ static int cma_check_port(struct rdma_bind_list *bind_list, if (id_priv == cur_id) continue; - if ((cur_id->state == RDMA_CM_LISTEN) || + if ((cur_id->state == CMA_LISTEN) || !reuseaddr || !cur_id->reuseaddr) { cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr; if (cma_any_addr(cur_addr)) @@ -2270,14 +2280,14 @@ int rdma_listen(struct rdma_cm_id *id, int backlog) int ret; id_priv = container_of(id, struct rdma_id_private, id); - if (id_priv->state == RDMA_CM_IDLE) { + if (id_priv->state == CMA_IDLE) { ((struct sockaddr *) &id->route.addr.src_addr)->sa_family = AF_INET; ret = rdma_bind_addr(id, (struct sockaddr *) &id->route.addr.src_addr); if (ret) return ret; } - if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_LISTEN)) + if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN)) return -EINVAL; if (id_priv->reuseaddr) { @@ -2309,7 +2319,7 @@ int rdma_listen(struct rdma_cm_id *id, int backlog) return 0; err: id_priv->backlog = 0; - cma_comp_exch(id_priv, RDMA_CM_LISTEN, RDMA_CM_ADDR_BOUND); + cma_comp_exch(id_priv, CMA_LISTEN, CMA_ADDR_BOUND); return ret; } EXPORT_SYMBOL(rdma_listen); @@ -2323,7 +2333,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) return -EAFNOSUPPORT; id_priv = container_of(id, struct rdma_id_private, id); - if (!cma_comp_exch(id_priv, RDMA_CM_IDLE, RDMA_CM_ADDR_BOUND)) + if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND)) return -EINVAL; ret = cma_check_linklocal(&id->route.addr.dev_addr, addr); @@ -2350,7 +2360,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) if (id_priv->cma_dev) cma_release_dev(id_priv); err1: - cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_IDLE); + cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE); return ret; } EXPORT_SYMBOL(rdma_bind_addr); @@ -2423,7 +2433,7 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd; int ret = 0; - if (cma_disable_callback(id_priv, RDMA_CM_CONNECT)) + if (cma_disable_callback(id_priv, CMA_CONNECT)) return 0; memset(&event, 0, sizeof event); @@ -2469,7 +2479,7 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, if (ret) { /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.ib = NULL; - cma_exch(id_priv, RDMA_CM_DESTROYING); + cma_exch(id_priv, CMA_DESTROYING); mutex_unlock(&id_priv->handler_mutex); rdma_destroy_id(&id_priv->id); return ret; @@ -2635,7 +2645,7 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) int ret; id_priv = container_of(id, struct rdma_id_private, id); - if (!cma_comp_exch(id_priv, RDMA_CM_ROUTE_RESOLVED, RDMA_CM_CONNECT)) + if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT)) return -EINVAL; if (!id->qp) { @@ -2645,7 +2655,7 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) switch (rdma_node_get_transport(id->device->node_type)) { case RDMA_TRANSPORT_IB: - if (id->qp_type == IB_QPT_UD) + if (cma_is_ud_ps(id->ps)) ret = cma_resolve_ib_udp(id_priv, conn_param); else ret = cma_connect_ib(id_priv, conn_param); @@ -2662,7 +2672,7 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) return 0; err: - cma_comp_exch(id_priv, RDMA_CM_CONNECT, RDMA_CM_ROUTE_RESOLVED); + cma_comp_exch(id_priv, CMA_CONNECT, CMA_ROUTE_RESOLVED); return ret; } EXPORT_SYMBOL(rdma_connect); @@ -2748,10 +2758,7 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) int ret; id_priv = container_of(id, struct rdma_id_private, id); - - id_priv->owner = task_pid_nr(current); - - if (!cma_comp(id_priv, RDMA_CM_CONNECT)) + if (!cma_comp(id_priv, CMA_CONNECT)) return -EINVAL; if (!id->qp && conn_param) { @@ -2761,7 +2768,7 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) switch (rdma_node_get_transport(id->device->node_type)) { case RDMA_TRANSPORT_IB: - if (id->qp_type == IB_QPT_UD) + if (cma_is_ud_ps(id->ps)) ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS, conn_param->private_data, conn_param->private_data_len); @@ -2822,7 +2829,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data, switch (rdma_node_get_transport(id->device->node_type)) { case RDMA_TRANSPORT_IB: - if (id->qp_type == IB_QPT_UD) + if (cma_is_ud_ps(id->ps)) ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT, private_data, private_data_len); else @@ -2880,8 +2887,8 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) int ret; id_priv = mc->id_priv; - if (cma_disable_callback(id_priv, RDMA_CM_ADDR_BOUND) && - cma_disable_callback(id_priv, RDMA_CM_ADDR_RESOLVED)) + if (cma_disable_callback(id_priv, CMA_ADDR_BOUND) && + cma_disable_callback(id_priv, CMA_ADDR_RESOLVED)) return 0; mutex_lock(&id_priv->qp_mutex); @@ -2905,7 +2912,7 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) ret = id_priv->id.event_handler(&id_priv->id, &event); if (ret) { - cma_exch(id_priv, RDMA_CM_DESTROYING); + cma_exch(id_priv, CMA_DESTROYING); mutex_unlock(&id_priv->handler_mutex); rdma_destroy_id(&id_priv->id); return 0; @@ -3088,8 +3095,8 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr, int ret; id_priv = container_of(id, struct rdma_id_private, id); - if (!cma_comp(id_priv, RDMA_CM_ADDR_BOUND) && - !cma_comp(id_priv, RDMA_CM_ADDR_RESOLVED)) + if (!cma_comp(id_priv, CMA_ADDR_BOUND) && + !cma_comp(id_priv, CMA_ADDR_RESOLVED)) return -EINVAL; mc = kmalloc(sizeof *mc, GFP_KERNEL); @@ -3254,19 +3261,19 @@ static void cma_add_one(struct ib_device *device) static int cma_remove_id_dev(struct rdma_id_private *id_priv) { struct rdma_cm_event event; - enum rdma_cm_state state; + enum cma_state state; int ret = 0; /* Record that we want to remove the device */ - state = cma_exch(id_priv, RDMA_CM_DEVICE_REMOVAL); - if (state == RDMA_CM_DESTROYING) + state = cma_exch(id_priv, CMA_DEVICE_REMOVAL); + if (state == CMA_DESTROYING) return 0; cma_cancel_operation(id_priv, state); mutex_lock(&id_priv->handler_mutex); /* Check for destruction from another callback. */ - if (!cma_comp(id_priv, RDMA_CM_DEVICE_REMOVAL)) + if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL)) goto out; memset(&event, 0, sizeof event); @@ -3321,100 +3328,6 @@ static void cma_remove_one(struct ib_device *device) kfree(cma_dev); } -static int cma_get_id_stats(struct sk_buff *skb, struct netlink_callback *cb) -{ - struct nlmsghdr *nlh; - struct rdma_cm_id_stats *id_stats; - struct rdma_id_private *id_priv; - struct rdma_cm_id *id = NULL; - struct cma_device *cma_dev; - int i_dev = 0, i_id = 0; - - /* - * We export all of the IDs as a sequence of messages. Each - * ID gets its own netlink message. - */ - mutex_lock(&lock); - - list_for_each_entry(cma_dev, &dev_list, list) { - if (i_dev < cb->args[0]) { - i_dev++; - continue; - } - - i_id = 0; - list_for_each_entry(id_priv, &cma_dev->id_list, list) { - if (i_id < cb->args[1]) { - i_id++; - continue; - } - - id_stats = ibnl_put_msg(skb, &nlh, cb->nlh->nlmsg_seq, - sizeof *id_stats, RDMA_NL_RDMA_CM, - RDMA_NL_RDMA_CM_ID_STATS); - if (!id_stats) - goto out; - - memset(id_stats, 0, sizeof *id_stats); - id = &id_priv->id; - id_stats->node_type = id->route.addr.dev_addr.dev_type; - id_stats->port_num = id->port_num; - id_stats->bound_dev_if = - id->route.addr.dev_addr.bound_dev_if; - - if (id->route.addr.src_addr.ss_family == AF_INET) { - if (ibnl_put_attr(skb, nlh, - sizeof(struct sockaddr_in), - &id->route.addr.src_addr, - RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) { - goto out; - } - if (ibnl_put_attr(skb, nlh, - sizeof(struct sockaddr_in), - &id->route.addr.dst_addr, - RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) { - goto out; - } - } else if (id->route.addr.src_addr.ss_family == AF_INET6) { - if (ibnl_put_attr(skb, nlh, - sizeof(struct sockaddr_in6), - &id->route.addr.src_addr, - RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) { - goto out; - } - if (ibnl_put_attr(skb, nlh, - sizeof(struct sockaddr_in6), - &id->route.addr.dst_addr, - RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) { - goto out; - } - } - - id_stats->pid = id_priv->owner; - id_stats->port_space = id->ps; - id_stats->cm_state = id_priv->state; - id_stats->qp_num = id_priv->qp_num; - id_stats->qp_type = id->qp_type; - - i_id++; - } - - cb->args[1] = 0; - i_dev++; - } - -out: - mutex_unlock(&lock); - cb->args[0] = i_dev; - cb->args[1] = i_id; - - return skb->len; -} - -static const struct ibnl_client_cbs cma_cb_table[] = { - [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats }, -}; - static int __init cma_init(void) { int ret; @@ -3430,10 +3343,6 @@ static int __init cma_init(void) ret = ib_register_client(&cma_client); if (ret) goto err; - - if (ibnl_add_client(RDMA_NL_RDMA_CM, RDMA_NL_RDMA_CM_NUM_OPS, cma_cb_table)) - printk(KERN_WARNING "RDMA CMA: failed to add netlink callback\n"); - return 0; err: @@ -3446,7 +3355,6 @@ static int __init cma_init(void) static void __exit cma_cleanup(void) { - ibnl_remove_client(RDMA_NL_RDMA_CM); ib_unregister_client(&cma_client); unregister_netdevice_notifier(&cma_nb); rdma_addr_unregister_client(&addr_client); diff --git a/trunk/drivers/infiniband/core/device.c b/trunk/drivers/infiniband/core/device.c index 4007f721d25d..f793bf2f5da7 100644 --- a/trunk/drivers/infiniband/core/device.c +++ b/trunk/drivers/infiniband/core/device.c @@ -38,7 +38,6 @@ #include #include #include -#include #include "core_priv.h" @@ -726,40 +725,22 @@ static int __init ib_core_init(void) return -ENOMEM; ret = ib_sysfs_setup(); - if (ret) { + if (ret) printk(KERN_WARNING "Couldn't create InfiniBand device class\n"); - goto err; - } - - ret = ibnl_init(); - if (ret) { - printk(KERN_WARNING "Couldn't init IB netlink interface\n"); - goto err_sysfs; - } ret = ib_cache_setup(); if (ret) { printk(KERN_WARNING "Couldn't set up InfiniBand P_Key/GID cache\n"); - goto err_nl; + ib_sysfs_cleanup(); + destroy_workqueue(ib_wq); } - return 0; - -err_nl: - ibnl_cleanup(); - -err_sysfs: - ib_sysfs_cleanup(); - -err: - destroy_workqueue(ib_wq); return ret; } static void __exit ib_core_cleanup(void) { ib_cache_cleanup(); - ibnl_cleanup(); ib_sysfs_cleanup(); /* Make sure that any pending umem accounting work is done. */ destroy_workqueue(ib_wq); diff --git a/trunk/drivers/infiniband/core/mad.c b/trunk/drivers/infiniband/core/mad.c index b4d8672a3e4e..822cfdcd9f78 100644 --- a/trunk/drivers/infiniband/core/mad.c +++ b/trunk/drivers/infiniband/core/mad.c @@ -276,13 +276,6 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, goto error1; } - /* Verify the QP requested is supported. For example, Ethernet devices - * will not have QP0 */ - if (!port_priv->qp_info[qpn].qp) { - ret = ERR_PTR(-EPROTONOSUPPORT); - goto error1; - } - /* Allocate structures */ mad_agent_priv = kzalloc(sizeof *mad_agent_priv, GFP_KERNEL); if (!mad_agent_priv) { diff --git a/trunk/drivers/infiniband/core/netlink.c b/trunk/drivers/infiniband/core/netlink.c deleted file mode 100644 index 4a5abaf0a25c..000000000000 --- a/trunk/drivers/infiniband/core/netlink.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2010 Voltaire Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ - -#include -#include -#include -#include - -struct ibnl_client { - struct list_head list; - int index; - int nops; - const struct ibnl_client_cbs *cb_table; -}; - -static DEFINE_MUTEX(ibnl_mutex); -static struct sock *nls; -static LIST_HEAD(client_list); - -int ibnl_add_client(int index, int nops, - const struct ibnl_client_cbs cb_table[]) -{ - struct ibnl_client *cur; - struct ibnl_client *nl_client; - - nl_client = kmalloc(sizeof *nl_client, GFP_KERNEL); - if (!nl_client) - return -ENOMEM; - - nl_client->index = index; - nl_client->nops = nops; - nl_client->cb_table = cb_table; - - mutex_lock(&ibnl_mutex); - - list_for_each_entry(cur, &client_list, list) { - if (cur->index == index) { - pr_warn("Client for %d already exists\n", index); - mutex_unlock(&ibnl_mutex); - kfree(nl_client); - return -EINVAL; - } - } - - list_add_tail(&nl_client->list, &client_list); - - mutex_unlock(&ibnl_mutex); - - return 0; -} -EXPORT_SYMBOL(ibnl_add_client); - -int ibnl_remove_client(int index) -{ - struct ibnl_client *cur, *next; - - mutex_lock(&ibnl_mutex); - list_for_each_entry_safe(cur, next, &client_list, list) { - if (cur->index == index) { - list_del(&(cur->list)); - mutex_unlock(&ibnl_mutex); - kfree(cur); - return 0; - } - } - pr_warn("Can't remove callback for client idx %d. Not found\n", index); - mutex_unlock(&ibnl_mutex); - - return -EINVAL; -} -EXPORT_SYMBOL(ibnl_remove_client); - -void *ibnl_put_msg(struct sk_buff *skb, struct nlmsghdr **nlh, int seq, - int len, int client, int op) -{ - unsigned char *prev_tail; - - prev_tail = skb_tail_pointer(skb); - *nlh = NLMSG_NEW(skb, 0, seq, RDMA_NL_GET_TYPE(client, op), - len, NLM_F_MULTI); - (*nlh)->nlmsg_len = skb_tail_pointer(skb) - prev_tail; - return NLMSG_DATA(*nlh); - -nlmsg_failure: - nlmsg_trim(skb, prev_tail); - return NULL; -} -EXPORT_SYMBOL(ibnl_put_msg); - -int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh, - int len, void *data, int type) -{ - unsigned char *prev_tail; - - prev_tail = skb_tail_pointer(skb); - NLA_PUT(skb, type, len, data); - nlh->nlmsg_len += skb_tail_pointer(skb) - prev_tail; - return 0; - -nla_put_failure: - nlmsg_trim(skb, prev_tail - nlh->nlmsg_len); - return -EMSGSIZE; -} -EXPORT_SYMBOL(ibnl_put_attr); - -static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) -{ - struct ibnl_client *client; - int type = nlh->nlmsg_type; - int index = RDMA_NL_GET_CLIENT(type); - int op = RDMA_NL_GET_OP(type); - - list_for_each_entry(client, &client_list, list) { - if (client->index == index) { - if (op < 0 || op >= client->nops || - !client->cb_table[RDMA_NL_GET_OP(op)].dump) - return -EINVAL; - return netlink_dump_start(nls, skb, nlh, - client->cb_table[op].dump, - NULL); - } - } - - pr_info("Index %d wasn't found in client list\n", index); - return -EINVAL; -} - -static void ibnl_rcv(struct sk_buff *skb) -{ - mutex_lock(&ibnl_mutex); - netlink_rcv_skb(skb, &ibnl_rcv_msg); - mutex_unlock(&ibnl_mutex); -} - -int __init ibnl_init(void) -{ - nls = netlink_kernel_create(&init_net, NETLINK_RDMA, 0, ibnl_rcv, - NULL, THIS_MODULE); - if (!nls) { - pr_warn("Failed to create netlink socket\n"); - return -ENOMEM; - } - - return 0; -} - -void ibnl_cleanup(void) -{ - struct ibnl_client *cur, *next; - - mutex_lock(&ibnl_mutex); - list_for_each_entry_safe(cur, next, &client_list, list) { - list_del(&(cur->list)); - kfree(cur); - } - mutex_unlock(&ibnl_mutex); - - netlink_kernel_release(nls); -} diff --git a/trunk/drivers/infiniband/core/ucma.c b/trunk/drivers/infiniband/core/ucma.c index 71be5eebd683..b3fa798525b2 100644 --- a/trunk/drivers/infiniband/core/ucma.c +++ b/trunk/drivers/infiniband/core/ucma.c @@ -367,28 +367,13 @@ static ssize_t ucma_get_event(struct ucma_file *file, const char __user *inbuf, return ret; } -static int ucma_get_qp_type(struct rdma_ucm_create_id *cmd, enum ib_qp_type *qp_type) -{ - switch (cmd->ps) { - case RDMA_PS_TCP: - *qp_type = IB_QPT_RC; - return 0; - case RDMA_PS_UDP: - case RDMA_PS_IPOIB: - *qp_type = IB_QPT_UD; - return 0; - default: - return -EINVAL; - } -} - -static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf, - int in_len, int out_len) +static ssize_t ucma_create_id(struct ucma_file *file, + const char __user *inbuf, + int in_len, int out_len) { struct rdma_ucm_create_id cmd; struct rdma_ucm_create_id_resp resp; struct ucma_context *ctx; - enum ib_qp_type qp_type; int ret; if (out_len < sizeof(resp)) @@ -397,10 +382,6 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf, if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; - ret = ucma_get_qp_type(&cmd, &qp_type); - if (ret) - return ret; - mutex_lock(&file->mut); ctx = ucma_alloc_ctx(file); mutex_unlock(&file->mut); @@ -408,7 +389,7 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf, return -ENOMEM; ctx->uid = cmd.uid; - ctx->cm_id = rdma_create_id(ucma_event_handler, ctx, cmd.ps, qp_type); + ctx->cm_id = rdma_create_id(ucma_event_handler, ctx, cmd.ps); if (IS_ERR(ctx->cm_id)) { ret = PTR_ERR(ctx->cm_id); goto err1; @@ -1357,11 +1338,9 @@ static const struct file_operations ucma_fops = { }; static struct miscdevice ucma_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = "rdma_cm", - .nodename = "infiniband/rdma_cm", - .mode = 0666, - .fops = &ucma_fops, + .minor = MISC_DYNAMIC_MINOR, + .name = "rdma_cm", + .fops = &ucma_fops, }; static ssize_t show_abi_version(struct device *dev, diff --git a/trunk/drivers/infiniband/core/user_mad.c b/trunk/drivers/infiniband/core/user_mad.c index 8d261b6ea5fe..cd1996d0ad08 100644 --- a/trunk/drivers/infiniband/core/user_mad.c +++ b/trunk/drivers/infiniband/core/user_mad.c @@ -1176,11 +1176,6 @@ static void ib_umad_remove_one(struct ib_device *device) kref_put(&umad_dev->ref, ib_umad_release_dev); } -static char *umad_devnode(struct device *dev, mode_t *mode) -{ - return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev)); -} - static int __init ib_umad_init(void) { int ret; @@ -1199,8 +1194,6 @@ static int __init ib_umad_init(void) goto out_chrdev; } - umad_class->devnode = umad_devnode; - ret = class_create_file(umad_class, &class_attr_abi_version.attr); if (ret) { printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n"); diff --git a/trunk/drivers/infiniband/core/uverbs_main.c b/trunk/drivers/infiniband/core/uverbs_main.c index e49a85f8a44d..ec83e9fe387b 100644 --- a/trunk/drivers/infiniband/core/uverbs_main.c +++ b/trunk/drivers/infiniband/core/uverbs_main.c @@ -824,12 +824,6 @@ static void ib_uverbs_remove_one(struct ib_device *device) kfree(uverbs_dev); } -static char *uverbs_devnode(struct device *dev, mode_t *mode) -{ - *mode = 0666; - return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev)); -} - static int __init ib_uverbs_init(void) { int ret; @@ -848,8 +842,6 @@ static int __init ib_uverbs_init(void) goto out_chrdev; } - uverbs_class->devnode = uverbs_devnode; - ret = class_create_file(uverbs_class, &class_attr_abi_version.attr); if (ret) { printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n"); diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c b/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c index 0a5008fbebac..239184138994 100644 --- a/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -914,7 +914,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb) goto err; if (peer2peer && iwch_rqes_posted(ep->com.qp) == 0) { - iwch_post_zb_read(ep); + iwch_post_zb_read(ep->com.qp); } goto out; @@ -1078,8 +1078,6 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) struct iwch_ep *ep = ctx; struct cpl_wr_ack *hdr = cplhdr(skb); unsigned int credits = ntohs(hdr->credits); - unsigned long flags; - int post_zb = 0; PDBG("%s ep %p credits %u\n", __func__, ep, credits); @@ -1089,34 +1087,28 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) return CPL_RET_BUF_DONE; } - spin_lock_irqsave(&ep->com.lock, flags); BUG_ON(credits != 1); dst_confirm(ep->dst); if (!ep->mpa_skb) { PDBG("%s rdma_init wr_ack ep %p state %u\n", - __func__, ep, ep->com.state); + __func__, ep, state_read(&ep->com)); if (ep->mpa_attr.initiator) { PDBG("%s initiator ep %p state %u\n", - __func__, ep, ep->com.state); - if (peer2peer && ep->com.state == FPDU_MODE) - post_zb = 1; + __func__, ep, state_read(&ep->com)); + if (peer2peer) + iwch_post_zb_read(ep->com.qp); } else { PDBG("%s responder ep %p state %u\n", - __func__, ep, ep->com.state); - if (ep->com.state == MPA_REQ_RCVD) { - ep->com.rpl_done = 1; - wake_up(&ep->com.waitq); - } + __func__, ep, state_read(&ep->com)); + ep->com.rpl_done = 1; + wake_up(&ep->com.waitq); } } else { PDBG("%s lsm ack ep %p state %u freeing skb\n", - __func__, ep, ep->com.state); + __func__, ep, state_read(&ep->com)); kfree_skb(ep->mpa_skb); ep->mpa_skb = NULL; } - spin_unlock_irqrestore(&ep->com.lock, flags); - if (post_zb) - iwch_post_zb_read(ep); return CPL_RET_BUF_DONE; } diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h index 9a342c9b220d..c5406da3f4cd 100644 --- a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h +++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h @@ -332,7 +332,7 @@ int iwch_bind_mw(struct ib_qp *qp, struct ib_mw_bind *mw_bind); int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg); -int iwch_post_zb_read(struct iwch_ep *ep); +int iwch_post_zb_read(struct iwch_qp *qhp); int iwch_register_device(struct iwch_dev *dev); void iwch_unregister_device(struct iwch_dev *dev); void stop_read_rep_timer(struct iwch_qp *qhp); diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_qp.c b/trunk/drivers/infiniband/hw/cxgb3/iwch_qp.c index ecd313f359a4..1b4cd09f74dc 100644 --- a/trunk/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_qp.c @@ -738,7 +738,7 @@ static inline void build_term_codes(struct respQ_msg_t *rsp_msg, } } -int iwch_post_zb_read(struct iwch_ep *ep) +int iwch_post_zb_read(struct iwch_qp *qhp) { union t3_wr *wqe; struct sk_buff *skb; @@ -761,10 +761,10 @@ int iwch_post_zb_read(struct iwch_ep *ep) wqe->read.local_len = cpu_to_be32(0); wqe->read.local_to = cpu_to_be64(1); wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_READ)); - wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(ep->hwtid)| + wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)| V_FW_RIWR_LEN(flit_cnt)); skb->priority = CPL_PRIORITY_DATA; - return iwch_cxgb3_ofld_send(ep->com.qp->rhp->rdev.t3cdev_p, skb); + return iwch_cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb); } /* diff --git a/trunk/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/trunk/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 4f045375c8e2..35d2a5dd9bb4 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/trunk/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -131,21 +131,28 @@ static inline int c4iw_num_stags(struct c4iw_rdev *rdev) #define C4IW_WR_TO (10*HZ) +enum { + REPLY_READY = 0, +}; + struct c4iw_wr_wait { - struct completion completion; + wait_queue_head_t wait; + unsigned long status; int ret; }; static inline void c4iw_init_wr_wait(struct c4iw_wr_wait *wr_waitp) { wr_waitp->ret = 0; - init_completion(&wr_waitp->completion); + wr_waitp->status = 0; + init_waitqueue_head(&wr_waitp->wait); } static inline void c4iw_wake_up(struct c4iw_wr_wait *wr_waitp, int ret) { wr_waitp->ret = ret; - complete(&wr_waitp->completion); + set_bit(REPLY_READY, &wr_waitp->status); + wake_up(&wr_waitp->wait); } static inline int c4iw_wait_for_reply(struct c4iw_rdev *rdev, @@ -157,7 +164,8 @@ static inline int c4iw_wait_for_reply(struct c4iw_rdev *rdev, int ret; do { - ret = wait_for_completion_timeout(&wr_waitp->completion, to); + ret = wait_event_timeout(wr_waitp->wait, + test_and_clear_bit(REPLY_READY, &wr_waitp->status), to); if (!ret) { printk(KERN_ERR MOD "%s - Device %s not responding - " "tid %u qpid %u\n", func, diff --git a/trunk/drivers/infiniband/hw/nes/nes.c b/trunk/drivers/infiniband/hw/nes/nes.c index 2d668c69f6d9..13de1192927c 100644 --- a/trunk/drivers/infiniband/hw/nes/nes.c +++ b/trunk/drivers/infiniband/hw/nes/nes.c @@ -1138,9 +1138,7 @@ static ssize_t nes_store_wqm_quanta(struct device_driver *ddp, u32 i = 0; struct nes_device *nesdev; - if (kstrtoul(buf, 0, &wqm_quanta_value) < 0) - return -EINVAL; - + strict_strtoul(buf, 0, &wqm_quanta_value); list_for_each_entry(nesdev, &nes_dev_list, list) { if (i == ee_flsh_adapter) { nesdev->nesadapter->wqm_quanta = wqm_quanta_value; diff --git a/trunk/drivers/infiniband/hw/qib/Kconfig b/trunk/drivers/infiniband/hw/qib/Kconfig index 8349f9c5064c..7c03a70c55a2 100644 --- a/trunk/drivers/infiniband/hw/qib/Kconfig +++ b/trunk/drivers/infiniband/hw/qib/Kconfig @@ -1,6 +1,6 @@ config INFINIBAND_QIB tristate "QLogic PCIe HCA support" - depends on 64BIT + depends on 64BIT && NET ---help--- This is a low-level driver for QLogic PCIe QLE InfiniBand host channel adapters. This driver does not support the QLogic diff --git a/trunk/drivers/infiniband/ulp/iser/iser_verbs.c b/trunk/drivers/infiniband/ulp/iser/iser_verbs.c index ede1475bee09..9876865732f7 100644 --- a/trunk/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/trunk/drivers/infiniband/ulp/iser/iser_verbs.c @@ -548,7 +548,7 @@ int iser_connect(struct iser_conn *ib_conn, iser_conn_get(ib_conn); /* ref ib conn's cma id */ ib_conn->cma_id = rdma_create_id(iser_cma_handler, (void *)ib_conn, - RDMA_PS_TCP, IB_QPT_RC); + RDMA_PS_TCP); if (IS_ERR(ib_conn->cma_id)) { err = PTR_ERR(ib_conn->cma_id); iser_err("rdma_create_id failed: %d\n", err); diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c index ee165fdcb596..376d640487d2 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c @@ -1147,7 +1147,7 @@ static void srp_process_aer_req(struct srp_target_port *target, static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) { struct ib_device *dev = target->srp_host->srp_dev->dev; - struct srp_iu *iu = (struct srp_iu *) (uintptr_t) wc->wr_id; + struct srp_iu *iu = (struct srp_iu *) wc->wr_id; int res; u8 opcode; @@ -1231,7 +1231,7 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr) break; } - iu = (struct srp_iu *) (uintptr_t) wc.wr_id; + iu = (struct srp_iu *) wc.wr_id; list_add(&iu->list, &target->free_tx); } } diff --git a/trunk/drivers/input/keyboard/Kconfig b/trunk/drivers/input/keyboard/Kconfig index b4dee9d5a055..69badb4e06aa 100644 --- a/trunk/drivers/input/keyboard/Kconfig +++ b/trunk/drivers/input/keyboard/Kconfig @@ -412,17 +412,6 @@ config KEYBOARD_PXA930_ROTARY To compile this driver as a module, choose M here: the module will be called pxa930_rotary. -config KEYBOARD_PMIC8XXX - tristate "Qualcomm PMIC8XXX keypad support" - depends on MFD_PM8XXX - help - Say Y here if you want to enable the driver for the PMIC8XXX - keypad provided as a reference design from Qualcomm. This is intended - to support upto 18x8 matrix based keypad design. - - To compile this driver as a module, choose M here: the module will - be called pmic8xxx-keypad. - config KEYBOARD_SAMSUNG tristate "Samsung keypad support" depends on SAMSUNG_DEV_KEYPAD diff --git a/trunk/drivers/input/keyboard/Makefile b/trunk/drivers/input/keyboard/Makefile index ddde0fd476f7..c49cf8e04cd7 100644 --- a/trunk/drivers/input/keyboard/Makefile +++ b/trunk/drivers/input/keyboard/Makefile @@ -34,7 +34,6 @@ obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o -obj-$(CONFIG_KEYBOARD_PMIC8XXX) += pmic8xxx-keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o diff --git a/trunk/drivers/input/keyboard/pmic8xxx-keypad.c b/trunk/drivers/input/keyboard/pmic8xxx-keypad.c deleted file mode 100644 index 40b02ae96f86..000000000000 --- a/trunk/drivers/input/keyboard/pmic8xxx-keypad.c +++ /dev/null @@ -1,799 +0,0 @@ -/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define PM8XXX_MAX_ROWS 18 -#define PM8XXX_MAX_COLS 8 -#define PM8XXX_ROW_SHIFT 3 -#define PM8XXX_MATRIX_MAX_SIZE (PM8XXX_MAX_ROWS * PM8XXX_MAX_COLS) - -#define PM8XXX_MIN_ROWS 5 -#define PM8XXX_MIN_COLS 5 - -#define MAX_SCAN_DELAY 128 -#define MIN_SCAN_DELAY 1 - -/* in nanoseconds */ -#define MAX_ROW_HOLD_DELAY 122000 -#define MIN_ROW_HOLD_DELAY 30500 - -#define MAX_DEBOUNCE_TIME 20 -#define MIN_DEBOUNCE_TIME 5 - -#define KEYP_CTRL 0x148 - -#define KEYP_CTRL_EVNTS BIT(0) -#define KEYP_CTRL_EVNTS_MASK 0x3 - -#define KEYP_CTRL_SCAN_COLS_SHIFT 5 -#define KEYP_CTRL_SCAN_COLS_MIN 5 -#define KEYP_CTRL_SCAN_COLS_BITS 0x3 - -#define KEYP_CTRL_SCAN_ROWS_SHIFT 2 -#define KEYP_CTRL_SCAN_ROWS_MIN 5 -#define KEYP_CTRL_SCAN_ROWS_BITS 0x7 - -#define KEYP_CTRL_KEYP_EN BIT(7) - -#define KEYP_SCAN 0x149 - -#define KEYP_SCAN_READ_STATE BIT(0) -#define KEYP_SCAN_DBOUNCE_SHIFT 1 -#define KEYP_SCAN_PAUSE_SHIFT 3 -#define KEYP_SCAN_ROW_HOLD_SHIFT 6 - -#define KEYP_TEST 0x14A - -#define KEYP_TEST_CLEAR_RECENT_SCAN BIT(6) -#define KEYP_TEST_CLEAR_OLD_SCAN BIT(5) -#define KEYP_TEST_READ_RESET BIT(4) -#define KEYP_TEST_DTEST_EN BIT(3) -#define KEYP_TEST_ABORT_READ BIT(0) - -#define KEYP_TEST_DBG_SELECT_SHIFT 1 - -/* bits of these registers represent - * '0' for key press - * '1' for key release - */ -#define KEYP_RECENT_DATA 0x14B -#define KEYP_OLD_DATA 0x14C - -#define KEYP_CLOCK_FREQ 32768 - -/** - * struct pmic8xxx_kp - internal keypad data structure - * @pdata - keypad platform data pointer - * @input - input device pointer for keypad - * @key_sense_irq - key press/release irq number - * @key_stuck_irq - key stuck notification irq number - * @keycodes - array to hold the key codes - * @dev - parent device pointer - * @keystate - present key press/release state - * @stuckstate - present state when key stuck irq - * @ctrl_reg - control register value - */ -struct pmic8xxx_kp { - const struct pm8xxx_keypad_platform_data *pdata; - struct input_dev *input; - int key_sense_irq; - int key_stuck_irq; - - unsigned short keycodes[PM8XXX_MATRIX_MAX_SIZE]; - - struct device *dev; - u16 keystate[PM8XXX_MAX_ROWS]; - u16 stuckstate[PM8XXX_MAX_ROWS]; - - u8 ctrl_reg; -}; - -static int pmic8xxx_kp_write_u8(struct pmic8xxx_kp *kp, - u8 data, u16 reg) -{ - int rc; - - rc = pm8xxx_writeb(kp->dev->parent, reg, data); - return rc; -} - -static int pmic8xxx_kp_read(struct pmic8xxx_kp *kp, - u8 *data, u16 reg, unsigned num_bytes) -{ - int rc; - - rc = pm8xxx_read_buf(kp->dev->parent, reg, data, num_bytes); - return rc; -} - -static int pmic8xxx_kp_read_u8(struct pmic8xxx_kp *kp, - u8 *data, u16 reg) -{ - int rc; - - rc = pmic8xxx_kp_read(kp, data, reg, 1); - return rc; -} - -static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) -{ - /* all keys pressed on that particular row? */ - if (col == 0x00) - return 1 << kp->pdata->num_cols; - else - return col & ((1 << kp->pdata->num_cols) - 1); -} - -/* - * Synchronous read protocol for RevB0 onwards: - * - * 1. Write '1' to ReadState bit in KEYP_SCAN register - * 2. Wait 2*32KHz clocks, so that HW can successfully enter read mode - * synchronously - * 3. Read rows in old array first if events are more than one - * 4. Read rows in recent array - * 5. Wait 4*32KHz clocks - * 6. Write '0' to ReadState bit of KEYP_SCAN register so that hw can - * synchronously exit read mode. - */ -static int pmic8xxx_chk_sync_read(struct pmic8xxx_kp *kp) -{ - int rc; - u8 scan_val; - - rc = pmic8xxx_kp_read_u8(kp, &scan_val, KEYP_SCAN); - if (rc < 0) { - dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); - return rc; - } - - scan_val |= 0x1; - - rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); - if (rc < 0) { - dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); - return rc; - } - - /* 2 * 32KHz clocks */ - udelay((2 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); - - return rc; -} - -static int pmic8xxx_kp_read_data(struct pmic8xxx_kp *kp, u16 *state, - u16 data_reg, int read_rows) -{ - int rc, row; - u8 new_data[PM8XXX_MAX_ROWS]; - - rc = pmic8xxx_kp_read(kp, new_data, data_reg, read_rows); - if (rc) - return rc; - - for (row = 0; row < kp->pdata->num_rows; row++) { - dev_dbg(kp->dev, "new_data[%d] = %d\n", row, - new_data[row]); - state[row] = pmic8xxx_col_state(kp, new_data[row]); - } - - return rc; -} - -static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, - u16 *old_state) -{ - int rc, read_rows; - u8 scan_val; - - if (kp->pdata->num_rows < PM8XXX_MIN_ROWS) - read_rows = PM8XXX_MIN_ROWS; - else - read_rows = kp->pdata->num_rows; - - pmic8xxx_chk_sync_read(kp); - - if (old_state) { - rc = pmic8xxx_kp_read_data(kp, old_state, KEYP_OLD_DATA, - read_rows); - if (rc < 0) { - dev_err(kp->dev, - "Error reading KEYP_OLD_DATA, rc=%d\n", rc); - return rc; - } - } - - rc = pmic8xxx_kp_read_data(kp, new_state, KEYP_RECENT_DATA, - read_rows); - if (rc < 0) { - dev_err(kp->dev, - "Error reading KEYP_RECENT_DATA, rc=%d\n", rc); - return rc; - } - - /* 4 * 32KHz clocks */ - udelay((4 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); - - rc = pmic8xxx_kp_read_u8(kp, &scan_val, KEYP_SCAN); - if (rc < 0) { - dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); - return rc; - } - - scan_val &= 0xFE; - rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); - if (rc < 0) - dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); - - return rc; -} - -static void __pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, u16 *new_state, - u16 *old_state) -{ - int row, col, code; - - for (row = 0; row < kp->pdata->num_rows; row++) { - int bits_changed = new_state[row] ^ old_state[row]; - - if (!bits_changed) - continue; - - for (col = 0; col < kp->pdata->num_cols; col++) { - if (!(bits_changed & (1 << col))) - continue; - - dev_dbg(kp->dev, "key [%d:%d] %s\n", row, col, - !(new_state[row] & (1 << col)) ? - "pressed" : "released"); - - code = MATRIX_SCAN_CODE(row, col, PM8XXX_ROW_SHIFT); - - input_event(kp->input, EV_MSC, MSC_SCAN, code); - input_report_key(kp->input, - kp->keycodes[code], - !(new_state[row] & (1 << col))); - - input_sync(kp->input); - } - } -} - -static bool pmic8xxx_detect_ghost_keys(struct pmic8xxx_kp *kp, u16 *new_state) -{ - int row, found_first = -1; - u16 check, row_state; - - check = 0; - for (row = 0; row < kp->pdata->num_rows; row++) { - row_state = (~new_state[row]) & - ((1 << kp->pdata->num_cols) - 1); - - if (hweight16(row_state) > 1) { - if (found_first == -1) - found_first = row; - if (check & row_state) { - dev_dbg(kp->dev, "detected ghost key on row[%d]" - " and row[%d]\n", found_first, row); - return true; - } - } - check |= row_state; - } - return false; -} - -static int pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, unsigned int events) -{ - u16 new_state[PM8XXX_MAX_ROWS]; - u16 old_state[PM8XXX_MAX_ROWS]; - int rc; - - switch (events) { - case 0x1: - rc = pmic8xxx_kp_read_matrix(kp, new_state, NULL); - if (rc < 0) - return rc; - - /* detecting ghost key is not an error */ - if (pmic8xxx_detect_ghost_keys(kp, new_state)) - return 0; - __pmic8xxx_kp_scan_matrix(kp, new_state, kp->keystate); - memcpy(kp->keystate, new_state, sizeof(new_state)); - break; - case 0x3: /* two events - eventcounter is gray-coded */ - rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); - if (rc < 0) - return rc; - - __pmic8xxx_kp_scan_matrix(kp, old_state, kp->keystate); - __pmic8xxx_kp_scan_matrix(kp, new_state, old_state); - memcpy(kp->keystate, new_state, sizeof(new_state)); - break; - case 0x2: - dev_dbg(kp->dev, "Some key events were lost\n"); - rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); - if (rc < 0) - return rc; - __pmic8xxx_kp_scan_matrix(kp, old_state, kp->keystate); - __pmic8xxx_kp_scan_matrix(kp, new_state, old_state); - memcpy(kp->keystate, new_state, sizeof(new_state)); - break; - default: - rc = -EINVAL; - } - return rc; -} - -/* - * NOTE: We are reading recent and old data registers blindly - * whenever key-stuck interrupt happens, because events counter doesn't - * get updated when this interrupt happens due to key stuck doesn't get - * considered as key state change. - * - * We are not using old data register contents after they are being read - * because it might report the key which was pressed before the key being stuck - * as stuck key because it's pressed status is stored in the old data - * register. - */ -static irqreturn_t pmic8xxx_kp_stuck_irq(int irq, void *data) -{ - u16 new_state[PM8XXX_MAX_ROWS]; - u16 old_state[PM8XXX_MAX_ROWS]; - int rc; - struct pmic8xxx_kp *kp = data; - - rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); - if (rc < 0) { - dev_err(kp->dev, "failed to read keypad matrix\n"); - return IRQ_HANDLED; - } - - __pmic8xxx_kp_scan_matrix(kp, new_state, kp->stuckstate); - - return IRQ_HANDLED; -} - -static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) -{ - struct pmic8xxx_kp *kp = data; - u8 ctrl_val, events; - int rc; - - rc = pmic8xxx_kp_read(kp, &ctrl_val, KEYP_CTRL, 1); - if (rc < 0) { - dev_err(kp->dev, "failed to read keyp_ctrl register\n"); - return IRQ_HANDLED; - } - - events = ctrl_val & KEYP_CTRL_EVNTS_MASK; - - rc = pmic8xxx_kp_scan_matrix(kp, events); - if (rc < 0) - dev_err(kp->dev, "failed to scan matrix\n"); - - return IRQ_HANDLED; -} - -static int __devinit pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) -{ - int bits, rc, cycles; - u8 scan_val = 0, ctrl_val = 0; - static const u8 row_bits[] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, - }; - - /* Find column bits */ - if (kp->pdata->num_cols < KEYP_CTRL_SCAN_COLS_MIN) - bits = 0; - else - bits = kp->pdata->num_cols - KEYP_CTRL_SCAN_COLS_MIN; - ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) << - KEYP_CTRL_SCAN_COLS_SHIFT; - - /* Find row bits */ - if (kp->pdata->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) - bits = 0; - else - bits = row_bits[kp->pdata->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; - - ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT); - - rc = pmic8xxx_kp_write_u8(kp, ctrl_val, KEYP_CTRL); - if (rc < 0) { - dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); - return rc; - } - - bits = (kp->pdata->debounce_ms / 5) - 1; - - scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT); - - bits = fls(kp->pdata->scan_delay_ms) - 1; - scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT); - - /* Row hold time is a multiple of 32KHz cycles. */ - cycles = (kp->pdata->row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; - - scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT); - - rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); - if (rc) - dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); - - return rc; - -} - -static int __devinit pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios, - struct pmic8xxx_kp *kp, struct pm_gpio *gpio_config) -{ - int rc, i; - - if (gpio_start < 0 || num_gpios < 0) - return -EINVAL; - - for (i = 0; i < num_gpios; i++) { - rc = pm8xxx_gpio_config(gpio_start + i, gpio_config); - if (rc) { - dev_err(kp->dev, "%s: FAIL pm8xxx_gpio_config():" - "for PM GPIO [%d] rc=%d.\n", - __func__, gpio_start + i, rc); - return rc; - } - } - - return 0; -} - -static int pmic8xxx_kp_enable(struct pmic8xxx_kp *kp) -{ - int rc; - - kp->ctrl_reg |= KEYP_CTRL_KEYP_EN; - - rc = pmic8xxx_kp_write_u8(kp, kp->ctrl_reg, KEYP_CTRL); - if (rc < 0) - dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); - - return rc; -} - -static int pmic8xxx_kp_disable(struct pmic8xxx_kp *kp) -{ - int rc; - - kp->ctrl_reg &= ~KEYP_CTRL_KEYP_EN; - - rc = pmic8xxx_kp_write_u8(kp, kp->ctrl_reg, KEYP_CTRL); - if (rc < 0) - return rc; - - return rc; -} - -static int pmic8xxx_kp_open(struct input_dev *dev) -{ - struct pmic8xxx_kp *kp = input_get_drvdata(dev); - - return pmic8xxx_kp_enable(kp); -} - -static void pmic8xxx_kp_close(struct input_dev *dev) -{ - struct pmic8xxx_kp *kp = input_get_drvdata(dev); - - pmic8xxx_kp_disable(kp); -} - -/* - * keypad controller should be initialized in the following sequence - * only, otherwise it might get into FSM stuck state. - * - * - Initialize keypad control parameters, like no. of rows, columns, - * timing values etc., - * - configure rows and column gpios pull up/down. - * - set irq edge type. - * - enable the keypad controller. - */ -static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) -{ - const struct pm8xxx_keypad_platform_data *pdata = mfd_get_data(pdev); - const struct matrix_keymap_data *keymap_data; - struct pmic8xxx_kp *kp; - int rc; - u8 ctrl_val; - - struct pm_gpio kypd_drv = { - .direction = PM_GPIO_DIR_OUT, - .output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN, - .output_value = 0, - .pull = PM_GPIO_PULL_NO, - .vin_sel = PM_GPIO_VIN_S3, - .out_strength = PM_GPIO_STRENGTH_LOW, - .function = PM_GPIO_FUNC_1, - .inv_int_pol = 1, - }; - - struct pm_gpio kypd_sns = { - .direction = PM_GPIO_DIR_IN, - .pull = PM_GPIO_PULL_UP_31P5, - .vin_sel = PM_GPIO_VIN_S3, - .out_strength = PM_GPIO_STRENGTH_NO, - .function = PM_GPIO_FUNC_NORMAL, - .inv_int_pol = 1, - }; - - - if (!pdata || !pdata->num_cols || !pdata->num_rows || - pdata->num_cols > PM8XXX_MAX_COLS || - pdata->num_rows > PM8XXX_MAX_ROWS || - pdata->num_cols < PM8XXX_MIN_COLS) { - dev_err(&pdev->dev, "invalid platform data\n"); - return -EINVAL; - } - - if (!pdata->scan_delay_ms || - pdata->scan_delay_ms > MAX_SCAN_DELAY || - pdata->scan_delay_ms < MIN_SCAN_DELAY || - !is_power_of_2(pdata->scan_delay_ms)) { - dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); - return -EINVAL; - } - - if (!pdata->row_hold_ns || - pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || - pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || - ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { - dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); - return -EINVAL; - } - - if (!pdata->debounce_ms || - ((pdata->debounce_ms % 5) != 0) || - pdata->debounce_ms > MAX_DEBOUNCE_TIME || - pdata->debounce_ms < MIN_DEBOUNCE_TIME) { - dev_err(&pdev->dev, "invalid debounce time supplied\n"); - return -EINVAL; - } - - keymap_data = pdata->keymap_data; - if (!keymap_data) { - dev_err(&pdev->dev, "no keymap data supplied\n"); - return -EINVAL; - } - - kp = kzalloc(sizeof(*kp), GFP_KERNEL); - if (!kp) - return -ENOMEM; - - platform_set_drvdata(pdev, kp); - - kp->pdata = pdata; - kp->dev = &pdev->dev; - - kp->input = input_allocate_device(); - if (!kp->input) { - dev_err(&pdev->dev, "unable to allocate input device\n"); - rc = -ENOMEM; - goto err_alloc_device; - } - - kp->key_sense_irq = platform_get_irq(pdev, 0); - if (kp->key_sense_irq < 0) { - dev_err(&pdev->dev, "unable to get keypad sense irq\n"); - rc = -ENXIO; - goto err_get_irq; - } - - kp->key_stuck_irq = platform_get_irq(pdev, 1); - if (kp->key_stuck_irq < 0) { - dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); - rc = -ENXIO; - goto err_get_irq; - } - - kp->input->name = pdata->input_name ? : "PMIC8XXX keypad"; - kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0"; - - kp->input->dev.parent = &pdev->dev; - - kp->input->id.bustype = BUS_I2C; - kp->input->id.version = 0x0001; - kp->input->id.product = 0x0001; - kp->input->id.vendor = 0x0001; - - kp->input->evbit[0] = BIT_MASK(EV_KEY); - - if (pdata->rep) - __set_bit(EV_REP, kp->input->evbit); - - kp->input->keycode = kp->keycodes; - kp->input->keycodemax = PM8XXX_MATRIX_MAX_SIZE; - kp->input->keycodesize = sizeof(kp->keycodes); - kp->input->open = pmic8xxx_kp_open; - kp->input->close = pmic8xxx_kp_close; - - matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT, - kp->input->keycode, kp->input->keybit); - - input_set_capability(kp->input, EV_MSC, MSC_SCAN); - input_set_drvdata(kp->input, kp); - - /* initialize keypad state */ - memset(kp->keystate, 0xff, sizeof(kp->keystate)); - memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); - - rc = pmic8xxx_kpd_init(kp); - if (rc < 0) { - dev_err(&pdev->dev, "unable to initialize keypad controller\n"); - goto err_get_irq; - } - - rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start, - pdata->num_cols, kp, &kypd_sns); - if (rc < 0) { - dev_err(&pdev->dev, "unable to configure keypad sense lines\n"); - goto err_gpio_config; - } - - rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start, - pdata->num_rows, kp, &kypd_drv); - if (rc < 0) { - dev_err(&pdev->dev, "unable to configure keypad drive lines\n"); - goto err_gpio_config; - } - - rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq, - IRQF_TRIGGER_RISING, "pmic-keypad", kp); - if (rc < 0) { - dev_err(&pdev->dev, "failed to request keypad sense irq\n"); - goto err_get_irq; - } - - rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq, - IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp); - if (rc < 0) { - dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); - goto err_req_stuck_irq; - } - - rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL); - if (rc < 0) { - dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); - goto err_pmic_reg_read; - } - - kp->ctrl_reg = ctrl_val; - - rc = input_register_device(kp->input); - if (rc < 0) { - dev_err(&pdev->dev, "unable to register keypad input device\n"); - goto err_pmic_reg_read; - } - - device_init_wakeup(&pdev->dev, pdata->wakeup); - - return 0; - -err_pmic_reg_read: - free_irq(kp->key_stuck_irq, NULL); -err_req_stuck_irq: - free_irq(kp->key_sense_irq, NULL); -err_gpio_config: -err_get_irq: - input_free_device(kp->input); -err_alloc_device: - platform_set_drvdata(pdev, NULL); - kfree(kp); - return rc; -} - -static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev) -{ - struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); - - device_init_wakeup(&pdev->dev, 0); - free_irq(kp->key_stuck_irq, NULL); - free_irq(kp->key_sense_irq, NULL); - input_unregister_device(kp->input); - kfree(kp); - - platform_set_drvdata(pdev, NULL); - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int pmic8xxx_kp_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); - struct input_dev *input_dev = kp->input; - - if (device_may_wakeup(dev)) { - enable_irq_wake(kp->key_sense_irq); - } else { - mutex_lock(&input_dev->mutex); - - if (input_dev->users) - pmic8xxx_kp_disable(kp); - - mutex_unlock(&input_dev->mutex); - } - - return 0; -} - -static int pmic8xxx_kp_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); - struct input_dev *input_dev = kp->input; - - if (device_may_wakeup(dev)) { - disable_irq_wake(kp->key_sense_irq); - } else { - mutex_lock(&input_dev->mutex); - - if (input_dev->users) - pmic8xxx_kp_enable(kp); - - mutex_unlock(&input_dev->mutex); - } - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, - pmic8xxx_kp_suspend, pmic8xxx_kp_resume); - -static struct platform_driver pmic8xxx_kp_driver = { - .probe = pmic8xxx_kp_probe, - .remove = __devexit_p(pmic8xxx_kp_remove), - .driver = { - .name = PM8XXX_KEYPAD_DEV_NAME, - .owner = THIS_MODULE, - .pm = &pm8xxx_kp_pm_ops, - }, -}; - -static int __init pmic8xxx_kp_init(void) -{ - return platform_driver_register(&pmic8xxx_kp_driver); -} -module_init(pmic8xxx_kp_init); - -static void __exit pmic8xxx_kp_exit(void) -{ - platform_driver_unregister(&pmic8xxx_kp_driver); -} -module_exit(pmic8xxx_kp_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("PMIC8XXX keypad driver"); -MODULE_VERSION("1.0"); -MODULE_ALIAS("platform:pmic8xxx_keypad"); -MODULE_AUTHOR("Trilok Soni "); diff --git a/trunk/drivers/input/misc/Kconfig b/trunk/drivers/input/misc/Kconfig index 45dc6aa62ba4..f9cf0881b0e3 100644 --- a/trunk/drivers/input/misc/Kconfig +++ b/trunk/drivers/input/misc/Kconfig @@ -330,17 +330,6 @@ config INPUT_PWM_BEEPER To compile this driver as a module, choose M here: the module will be called pwm-beeper. -config INPUT_PMIC8XXX_PWRKEY - tristate "PMIC8XXX power key support" - depends on MFD_PM8XXX - help - Say Y here if you want support for the PMIC8XXX power key. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called pmic8xxx-pwrkey. - config INPUT_GPIO_ROTARY_ENCODER tristate "Rotary encoders connected to GPIO pins" depends on GPIOLIB && GENERIC_GPIO diff --git a/trunk/drivers/input/misc/Makefile b/trunk/drivers/input/misc/Makefile index 38efb2cb182b..e3f7984e6274 100644 --- a/trunk/drivers/input/misc/Makefile +++ b/trunk/drivers/input/misc/Makefile @@ -33,7 +33,6 @@ obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o obj-$(CONFIG_INPUT_POWERMATE) += powermate.o obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o -obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o diff --git a/trunk/drivers/input/misc/pmic8xxx-pwrkey.c b/trunk/drivers/input/misc/pmic8xxx-pwrkey.c deleted file mode 100644 index 97e07e786e41..000000000000 --- a/trunk/drivers/input/misc/pmic8xxx-pwrkey.c +++ /dev/null @@ -1,231 +0,0 @@ -/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define PON_CNTL_1 0x1C -#define PON_CNTL_PULL_UP BIT(7) -#define PON_CNTL_TRIG_DELAY_MASK (0x7) - -/** - * struct pmic8xxx_pwrkey - pmic8xxx pwrkey information - * @key_press_irq: key press irq number - */ -struct pmic8xxx_pwrkey { - struct input_dev *pwr; - int key_press_irq; -}; - -static irqreturn_t pwrkey_press_irq(int irq, void *_pwrkey) -{ - struct pmic8xxx_pwrkey *pwrkey = _pwrkey; - - input_report_key(pwrkey->pwr, KEY_POWER, 1); - input_sync(pwrkey->pwr); - - return IRQ_HANDLED; -} - -static irqreturn_t pwrkey_release_irq(int irq, void *_pwrkey) -{ - struct pmic8xxx_pwrkey *pwrkey = _pwrkey; - - input_report_key(pwrkey->pwr, KEY_POWER, 0); - input_sync(pwrkey->pwr); - - return IRQ_HANDLED; -} - -#ifdef CONFIG_PM_SLEEP -static int pmic8xxx_pwrkey_suspend(struct device *dev) -{ - struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev); - - if (device_may_wakeup(dev)) - enable_irq_wake(pwrkey->key_press_irq); - - return 0; -} - -static int pmic8xxx_pwrkey_resume(struct device *dev) -{ - struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev); - - if (device_may_wakeup(dev)) - disable_irq_wake(pwrkey->key_press_irq); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops, - pmic8xxx_pwrkey_suspend, pmic8xxx_pwrkey_resume); - -static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev) -{ - struct input_dev *pwr; - int key_release_irq = platform_get_irq(pdev, 0); - int key_press_irq = platform_get_irq(pdev, 1); - int err; - unsigned int delay; - u8 pon_cntl; - struct pmic8xxx_pwrkey *pwrkey; - const struct pm8xxx_pwrkey_platform_data *pdata = mfd_get_data(pdev); - - if (!pdata) { - dev_err(&pdev->dev, "power key platform data not supplied\n"); - return -EINVAL; - } - - if (pdata->kpd_trigger_delay_us > 62500) { - dev_err(&pdev->dev, "invalid power key trigger delay\n"); - return -EINVAL; - } - - pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); - if (!pwrkey) - return -ENOMEM; - - pwr = input_allocate_device(); - if (!pwr) { - dev_dbg(&pdev->dev, "Can't allocate power button\n"); - err = -ENOMEM; - goto free_pwrkey; - } - - input_set_capability(pwr, EV_KEY, KEY_POWER); - - pwr->name = "pmic8xxx_pwrkey"; - pwr->phys = "pmic8xxx_pwrkey/input0"; - pwr->dev.parent = &pdev->dev; - - delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC; - delay = 1 + ilog2(delay); - - err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl); - if (err < 0) { - dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err); - goto free_input_dev; - } - - pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; - pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); - if (pdata->pull_up) - pon_cntl |= PON_CNTL_PULL_UP; - else - pon_cntl &= ~PON_CNTL_PULL_UP; - - err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl); - if (err < 0) { - dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err); - goto free_input_dev; - } - - err = input_register_device(pwr); - if (err) { - dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); - goto free_input_dev; - } - - pwrkey->key_press_irq = key_press_irq; - pwrkey->pwr = pwr; - - platform_set_drvdata(pdev, pwrkey); - - err = request_irq(key_press_irq, pwrkey_press_irq, - IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey); - if (err < 0) { - dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", - key_press_irq, err); - goto unreg_input_dev; - } - - err = request_irq(key_release_irq, pwrkey_release_irq, - IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey); - if (err < 0) { - dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", - key_release_irq, err); - - goto free_press_irq; - } - - device_init_wakeup(&pdev->dev, pdata->wakeup); - - return 0; - -free_press_irq: - free_irq(key_press_irq, NULL); -unreg_input_dev: - platform_set_drvdata(pdev, NULL); - input_unregister_device(pwr); - pwr = NULL; -free_input_dev: - input_free_device(pwr); -free_pwrkey: - kfree(pwrkey); - return err; -} - -static int __devexit pmic8xxx_pwrkey_remove(struct platform_device *pdev) -{ - struct pmic8xxx_pwrkey *pwrkey = platform_get_drvdata(pdev); - int key_release_irq = platform_get_irq(pdev, 0); - int key_press_irq = platform_get_irq(pdev, 1); - - device_init_wakeup(&pdev->dev, 0); - - free_irq(key_press_irq, pwrkey); - free_irq(key_release_irq, pwrkey); - input_unregister_device(pwrkey->pwr); - platform_set_drvdata(pdev, NULL); - kfree(pwrkey); - - return 0; -} - -static struct platform_driver pmic8xxx_pwrkey_driver = { - .probe = pmic8xxx_pwrkey_probe, - .remove = __devexit_p(pmic8xxx_pwrkey_remove), - .driver = { - .name = PM8XXX_PWRKEY_DEV_NAME, - .owner = THIS_MODULE, - .pm = &pm8xxx_pwr_key_pm_ops, - }, -}; - -static int __init pmic8xxx_pwrkey_init(void) -{ - return platform_driver_register(&pmic8xxx_pwrkey_driver); -} -module_init(pmic8xxx_pwrkey_init); - -static void __exit pmic8xxx_pwrkey_exit(void) -{ - platform_driver_unregister(&pmic8xxx_pwrkey_driver); -} -module_exit(pmic8xxx_pwrkey_exit); - -MODULE_ALIAS("platform:pmic8xxx_pwrkey"); -MODULE_DESCRIPTION("PMIC8XXX Power Key driver"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Trilok Soni "); diff --git a/trunk/drivers/input/misc/twl4030-vibra.c b/trunk/drivers/input/misc/twl4030-vibra.c index 014dd4ad0d4f..6a11694e3fc7 100644 --- a/trunk/drivers/input/misc/twl4030-vibra.c +++ b/trunk/drivers/input/misc/twl4030-vibra.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -196,7 +197,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, static int __devinit twl4030_vibra_probe(struct platform_device *pdev) { - struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; + struct twl4030_codec_vibra_data *pdata = mfd_get_data(pdev); struct vibra_info *info; int ret; diff --git a/trunk/drivers/isdn/hardware/eicon/divasfunc.c b/trunk/drivers/isdn/hardware/eicon/divasfunc.c index 0bbee7824d78..d36a4c09e25d 100644 --- a/trunk/drivers/isdn/hardware/eicon/divasfunc.c +++ b/trunk/drivers/isdn/hardware/eicon/divasfunc.c @@ -113,8 +113,9 @@ void diva_xdi_didd_remove_adapter(int card) static void start_dbg(void) { DbgRegister("DIVAS", DRIVERRELEASE_DIVAS, (debugmask) ? debugmask : DBG_DEFAULT); - DBG_LOG(("DIVA ISDNXDI BUILD (%s[%s])", - DIVA_BUILD, diva_xdi_common_code_build)) + DBG_LOG(("DIVA ISDNXDI BUILD (%s[%s]-%s-%s)", + DIVA_BUILD, diva_xdi_common_code_build, __DATE__, + __TIME__)) } /* diff --git a/trunk/drivers/leds/Kconfig b/trunk/drivers/leds/Kconfig index 23f0d5e99f35..1d027b475b22 100644 --- a/trunk/drivers/leds/Kconfig +++ b/trunk/drivers/leds/Kconfig @@ -389,16 +389,6 @@ config LEDS_NETXBIG and 5Big Network v2 boards. The LEDs are wired to a CPLD and are controlled through a GPIO extension bus. -config LEDS_ASIC3 - bool "LED support for the HTC ASIC3" - depends on MFD_ASIC3 - default y - help - This option enables support for the LEDs on the HTC ASIC3. The HTC - ASIC3 LED GPIOs are inputs, not outputs, thus the leds-gpio driver - cannot be used. This driver supports hardware blinking with an on+off - period from 62ms to 125s. Say Y to enable LEDs on the HP iPAQ hx4700. - config LEDS_TRIGGERS bool "LED Trigger support" depends on LEDS_CLASS diff --git a/trunk/drivers/leds/Makefile b/trunk/drivers/leds/Makefile index bbfd2e367dc0..bccb96c9bb45 100644 --- a/trunk/drivers/leds/Makefile +++ b/trunk/drivers/leds/Makefile @@ -42,7 +42,6 @@ obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o obj-$(CONFIG_LEDS_NS2) += leds-ns2.o obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o -obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/trunk/drivers/leds/leds-88pm860x.c b/trunk/drivers/leds/leds-88pm860x.c index 0d4c16678ace..416def84d045 100644 --- a/trunk/drivers/leds/leds-88pm860x.c +++ b/trunk/drivers/leds/leds-88pm860x.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #define LED_PWM_SHIFT (3) @@ -170,6 +171,7 @@ static int pm860x_led_probe(struct platform_device *pdev) struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); struct pm860x_led_pdata *pdata; struct pm860x_led *data; + struct mfd_cell *cell; struct resource *res; int ret; @@ -179,7 +181,10 @@ static int pm860x_led_probe(struct platform_device *pdev) return -EINVAL; } - pdata = pdev->dev.platform_data; + cell = pdev->dev.platform_data; + if (cell == NULL) + return -ENODEV; + pdata = cell->mfd_data; if (pdata == NULL) { dev_err(&pdev->dev, "No platform data!\n"); return -EINVAL; diff --git a/trunk/drivers/leds/leds-asic3.c b/trunk/drivers/leds/leds-asic3.c deleted file mode 100644 index 22f847c890c9..000000000000 --- a/trunk/drivers/leds/leds-asic3.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2011 Paul Parsons - * - * 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 - -/* - * The HTC ASIC3 LED GPIOs are inputs, not outputs. - * Hence we turn the LEDs on/off via the TimeBase register. - */ - -/* - * When TimeBase is 4 the clock resolution is about 32Hz. - * This driver supports hardware blinking with an on+off - * period from 62ms (2 clocks) to 125s (4000 clocks). - */ -#define MS_TO_CLK(ms) DIV_ROUND_CLOSEST(((ms)*1024), 32000) -#define CLK_TO_MS(clk) (((clk)*32000)/1024) -#define MAX_CLK 4000 /* Fits into 12-bit Time registers */ -#define MAX_MS CLK_TO_MS(MAX_CLK) - -static const unsigned int led_n_base[ASIC3_NUM_LEDS] = { - [0] = ASIC3_LED_0_Base, - [1] = ASIC3_LED_1_Base, - [2] = ASIC3_LED_2_Base, -}; - -static void brightness_set(struct led_classdev *cdev, - enum led_brightness value) -{ - struct platform_device *pdev = to_platform_device(cdev->dev->parent); - const struct mfd_cell *cell = mfd_get_cell(pdev); - struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); - u32 timebase; - unsigned int base; - - timebase = (value == LED_OFF) ? 0 : (LED_EN|0x4); - - base = led_n_base[cell->id]; - asic3_write_register(asic, (base + ASIC3_LED_PeriodTime), 32); - asic3_write_register(asic, (base + ASIC3_LED_DutyTime), 32); - asic3_write_register(asic, (base + ASIC3_LED_AutoStopCount), 0); - asic3_write_register(asic, (base + ASIC3_LED_TimeBase), timebase); -} - -static int blink_set(struct led_classdev *cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - struct platform_device *pdev = to_platform_device(cdev->dev->parent); - const struct mfd_cell *cell = mfd_get_cell(pdev); - struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); - u32 on; - u32 off; - unsigned int base; - - if (*delay_on > MAX_MS || *delay_off > MAX_MS) - return -EINVAL; - - if (*delay_on == 0 && *delay_off == 0) { - /* If both are zero then a sensible default should be chosen */ - on = MS_TO_CLK(500); - off = MS_TO_CLK(500); - } else { - on = MS_TO_CLK(*delay_on); - off = MS_TO_CLK(*delay_off); - if ((on + off) > MAX_CLK) - return -EINVAL; - } - - base = led_n_base[cell->id]; - asic3_write_register(asic, (base + ASIC3_LED_PeriodTime), (on + off)); - asic3_write_register(asic, (base + ASIC3_LED_DutyTime), on); - asic3_write_register(asic, (base + ASIC3_LED_AutoStopCount), 0); - asic3_write_register(asic, (base + ASIC3_LED_TimeBase), (LED_EN|0x4)); - - *delay_on = CLK_TO_MS(on); - *delay_off = CLK_TO_MS(off); - - return 0; -} - -static int __devinit asic3_led_probe(struct platform_device *pdev) -{ - struct asic3_led *led = pdev->dev.platform_data; - int ret; - - ret = mfd_cell_enable(pdev); - if (ret < 0) - goto ret0; - - led->cdev = kzalloc(sizeof(struct led_classdev), GFP_KERNEL); - if (!led->cdev) { - ret = -ENOMEM; - goto ret1; - } - - led->cdev->name = led->name; - led->cdev->default_trigger = led->default_trigger; - led->cdev->brightness_set = brightness_set; - led->cdev->blink_set = blink_set; - - ret = led_classdev_register(&pdev->dev, led->cdev); - if (ret < 0) - goto ret2; - - return 0; - -ret2: - kfree(led->cdev); -ret1: - (void) mfd_cell_disable(pdev); -ret0: - return ret; -} - -static int __devexit asic3_led_remove(struct platform_device *pdev) -{ - struct asic3_led *led = pdev->dev.platform_data; - - led_classdev_unregister(led->cdev); - - kfree(led->cdev); - - return mfd_cell_disable(pdev); -} - -static struct platform_driver asic3_led_driver = { - .probe = asic3_led_probe, - .remove = __devexit_p(asic3_led_remove), - .driver = { - .name = "leds-asic3", - .owner = THIS_MODULE, - }, -}; - -MODULE_ALIAS("platform:leds-asic3"); - -static int __init asic3_led_init(void) -{ - return platform_driver_register(&asic3_led_driver); -} - -static void __exit asic3_led_exit(void) -{ - platform_driver_unregister(&asic3_led_driver); -} - -module_init(asic3_led_init); -module_exit(asic3_led_exit); - -MODULE_AUTHOR("Paul Parsons "); -MODULE_DESCRIPTION("HTC ASIC3 LED driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/leds/leds-mc13783.c b/trunk/drivers/leds/leds-mc13783.c index f369e56d6547..126ca7955f6e 100644 --- a/trunk/drivers/leds/leds-mc13783.c +++ b/trunk/drivers/leds/leds-mc13783.c @@ -22,6 +22,7 @@ #include #include #include +#include #include struct mc13783_led { @@ -183,7 +184,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current) static int __devinit mc13783_leds_prepare(struct platform_device *pdev) { - struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); int ret = 0; int reg = 0; @@ -264,7 +265,7 @@ static int __devinit mc13783_leds_prepare(struct platform_device *pdev) static int __devinit mc13783_led_probe(struct platform_device *pdev) { - struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); struct mc13783_led_platform_data *led_cur; struct mc13783_led *led, *led_dat; int ret, i; @@ -351,7 +352,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev) static int __devexit mc13783_led_remove(struct platform_device *pdev) { - struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); struct mc13783_led *led = platform_get_drvdata(pdev); struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); int i; diff --git a/trunk/drivers/media/dvb/dm1105/dm1105.c b/trunk/drivers/media/dvb/dm1105/dm1105.c index b2b0c45f32a9..2d8b4044be36 100644 --- a/trunk/drivers/media/dvb/dm1105/dm1105.c +++ b/trunk/drivers/media/dvb/dm1105/dm1105.c @@ -20,7 +20,6 @@ */ #include -#include #include #include #include @@ -50,12 +49,11 @@ #define UNSET (-1U) -#define DM1105_BOARD_NOAUTO UNSET -#define DM1105_BOARD_UNKNOWN 0 -#define DM1105_BOARD_DVBWORLD_2002 1 -#define DM1105_BOARD_DVBWORLD_2004 2 -#define DM1105_BOARD_AXESS_DM05 3 -#define DM1105_BOARD_UNBRANDED_I2C_ON_GPIO 4 +#define DM1105_BOARD_NOAUTO UNSET +#define DM1105_BOARD_UNKNOWN 0 +#define DM1105_BOARD_DVBWORLD_2002 1 +#define DM1105_BOARD_DVBWORLD_2004 2 +#define DM1105_BOARD_AXESS_DM05 3 /* ----------------------------------------------- */ /* @@ -159,38 +157,22 @@ #define DM1105_MAX 0x04 #define DRIVER_NAME "dm1105" -#define DM1105_I2C_GPIO_NAME "dm1105-gpio" #define DM1105_DMA_PACKETS 47 #define DM1105_DMA_PACKET_LENGTH (128*4) #define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS) -/* */ -#define GPIO08 (1 << 8) -#define GPIO13 (1 << 13) -#define GPIO14 (1 << 14) -#define GPIO15 (1 << 15) -#define GPIO16 (1 << 16) -#define GPIO17 (1 << 17) -#define GPIO_ALL 0x03ffff - /* GPIO's for LNB power control */ -#define DM1105_LNB_MASK (GPIO_ALL & ~(GPIO14 | GPIO13)) -#define DM1105_LNB_OFF GPIO17 -#define DM1105_LNB_13V (GPIO16 | GPIO08) -#define DM1105_LNB_18V GPIO08 +#define DM1105_LNB_MASK 0x00000000 +#define DM1105_LNB_OFF 0x00020000 +#define DM1105_LNB_13V 0x00010100 +#define DM1105_LNB_18V 0x00000100 /* GPIO's for LNB power control for Axess DM05 */ -#define DM05_LNB_MASK (GPIO_ALL & ~(GPIO14 | GPIO13)) -#define DM05_LNB_OFF GPIO17/* actually 13v */ -#define DM05_LNB_13V GPIO17 -#define DM05_LNB_18V (GPIO17 | GPIO16) - -/* GPIO's for LNB power control for unbranded with I2C on GPIO */ -#define UNBR_LNB_MASK (GPIO17 | GPIO16) -#define UNBR_LNB_OFF 0 -#define UNBR_LNB_13V GPIO17 -#define UNBR_LNB_18V (GPIO17 | GPIO16) +#define DM05_LNB_MASK 0x00000000 +#define DM05_LNB_OFF 0x00020000/* actually 13v */ +#define DM05_LNB_13V 0x00020000 +#define DM05_LNB_18V 0x00030000 static unsigned int card[] = {[0 ... 3] = UNSET }; module_param_array(card, int, NULL, 0444); @@ -205,11 +187,7 @@ static unsigned int dm1105_devcount; DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct dm1105_board { - char *name; - struct { - u32 mask, off, v13, v18; - } lnb; - u32 gpio_scl, gpio_sda; + char *name; }; struct dm1105_subid { @@ -221,50 +199,15 @@ struct dm1105_subid { static const struct dm1105_board dm1105_boards[] = { [DM1105_BOARD_UNKNOWN] = { .name = "UNKNOWN/GENERIC", - .lnb = { - .mask = DM1105_LNB_MASK, - .off = DM1105_LNB_OFF, - .v13 = DM1105_LNB_13V, - .v18 = DM1105_LNB_18V, - }, }, [DM1105_BOARD_DVBWORLD_2002] = { .name = "DVBWorld PCI 2002", - .lnb = { - .mask = DM1105_LNB_MASK, - .off = DM1105_LNB_OFF, - .v13 = DM1105_LNB_13V, - .v18 = DM1105_LNB_18V, - }, }, [DM1105_BOARD_DVBWORLD_2004] = { .name = "DVBWorld PCI 2004", - .lnb = { - .mask = DM1105_LNB_MASK, - .off = DM1105_LNB_OFF, - .v13 = DM1105_LNB_13V, - .v18 = DM1105_LNB_18V, - }, }, [DM1105_BOARD_AXESS_DM05] = { .name = "Axess/EasyTv DM05", - .lnb = { - .mask = DM05_LNB_MASK, - .off = DM05_LNB_OFF, - .v13 = DM05_LNB_13V, - .v18 = DM05_LNB_18V, - }, - }, - [DM1105_BOARD_UNBRANDED_I2C_ON_GPIO] = { - .name = "Unbranded DM1105 with i2c on GPIOs", - .lnb = { - .mask = UNBR_LNB_MASK, - .off = UNBR_LNB_OFF, - .v13 = UNBR_LNB_13V, - .v18 = UNBR_LNB_18V, - }, - .gpio_scl = GPIO14, - .gpio_sda = GPIO13, }, }; @@ -350,8 +293,6 @@ struct dm1105_dev { /* i2c */ struct i2c_adapter i2c_adap; - struct i2c_adapter i2c_bb_adap; - struct i2c_algo_bit_data i2c_bit; /* irq */ struct work_struct work; @@ -387,103 +328,6 @@ struct dm1105_dev { #define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit)) #define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0) -/* The chip has 18 GPIOs. In HOST mode GPIO's used as 15 bit address lines, - so we can use only 3 GPIO's from GPIO15 to GPIO17. - Here I don't check whether HOST is enebled as it is not implemented yet. - */ -static void dm1105_gpio_set(struct dm1105_dev *dev, u32 mask) -{ - if (mask & 0xfffc0000) - printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); - - if (mask & 0x0003ffff) - dm_setl(DM1105_GPIOVAL, mask & 0x0003ffff); - -} - -static void dm1105_gpio_clear(struct dm1105_dev *dev, u32 mask) -{ - if (mask & 0xfffc0000) - printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); - - if (mask & 0x0003ffff) - dm_clearl(DM1105_GPIOVAL, mask & 0x0003ffff); - -} - -static void dm1105_gpio_andor(struct dm1105_dev *dev, u32 mask, u32 val) -{ - if (mask & 0xfffc0000) - printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); - - if (mask & 0x0003ffff) - dm_andorl(DM1105_GPIOVAL, mask & 0x0003ffff, val); - -} - -static u32 dm1105_gpio_get(struct dm1105_dev *dev, u32 mask) -{ - if (mask & 0xfffc0000) - printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); - - if (mask & 0x0003ffff) - return dm_readl(DM1105_GPIOVAL) & mask & 0x0003ffff; - - return 0; -} - -static void dm1105_gpio_enable(struct dm1105_dev *dev, u32 mask, int asoutput) -{ - if (mask & 0xfffc0000) - printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); - - if ((mask & 0x0003ffff) && asoutput) - dm_clearl(DM1105_GPIOCTR, mask & 0x0003ffff); - else if ((mask & 0x0003ffff) && !asoutput) - dm_setl(DM1105_GPIOCTR, mask & 0x0003ffff); - -} - -static void dm1105_setline(struct dm1105_dev *dev, u32 line, int state) -{ - if (state) - dm1105_gpio_enable(dev, line, 0); - else { - dm1105_gpio_enable(dev, line, 1); - dm1105_gpio_clear(dev, line); - } -} - -static void dm1105_setsda(void *data, int state) -{ - struct dm1105_dev *dev = data; - - dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_sda, state); -} - -static void dm1105_setscl(void *data, int state) -{ - struct dm1105_dev *dev = data; - - dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_scl, state); -} - -static int dm1105_getsda(void *data) -{ - struct dm1105_dev *dev = data; - - return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_sda) - ? 1 : 0; -} - -static int dm1105_getscl(void *data) -{ - struct dm1105_dev *dev = data; - - return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_scl) - ? 1 : 0; -} - static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { @@ -592,20 +436,31 @@ static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe) static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct dm1105_dev *dev = frontend_to_dm1105_dev(fe); + u32 lnb_mask, lnb_13v, lnb_18v, lnb_off; - dm1105_gpio_enable(dev, dm1105_boards[dev->boardnr].lnb.mask, 1); + switch (dev->boardnr) { + case DM1105_BOARD_AXESS_DM05: + lnb_mask = DM05_LNB_MASK; + lnb_off = DM05_LNB_OFF; + lnb_13v = DM05_LNB_13V; + lnb_18v = DM05_LNB_18V; + break; + case DM1105_BOARD_DVBWORLD_2002: + case DM1105_BOARD_DVBWORLD_2004: + default: + lnb_mask = DM1105_LNB_MASK; + lnb_off = DM1105_LNB_OFF; + lnb_13v = DM1105_LNB_13V; + lnb_18v = DM1105_LNB_18V; + } + + dm_writel(DM1105_GPIOCTR, lnb_mask); if (voltage == SEC_VOLTAGE_18) - dm1105_gpio_andor(dev, - dm1105_boards[dev->boardnr].lnb.mask, - dm1105_boards[dev->boardnr].lnb.v18); + dm_writel(DM1105_GPIOVAL, lnb_18v); else if (voltage == SEC_VOLTAGE_13) - dm1105_gpio_andor(dev, - dm1105_boards[dev->boardnr].lnb.mask, - dm1105_boards[dev->boardnr].lnb.v13); + dm_writel(DM1105_GPIOVAL, lnb_13v); else - dm1105_gpio_andor(dev, - dm1105_boards[dev->boardnr].lnb.mask, - dm1105_boards[dev->boardnr].lnb.off); + dm_writel(DM1105_GPIOVAL, lnb_off); return 0; } @@ -853,38 +708,6 @@ static int __devinit frontend_init(struct dm1105_dev *dev) int ret; switch (dev->boardnr) { - case DM1105_BOARD_UNBRANDED_I2C_ON_GPIO: - dm1105_gpio_enable(dev, GPIO15, 1); - dm1105_gpio_clear(dev, GPIO15); - msleep(100); - dm1105_gpio_set(dev, GPIO15); - msleep(200); - dev->fe = dvb_attach( - stv0299_attach, &sharp_z0194a_config, - &dev->i2c_bb_adap); - if (dev->fe) { - dev->fe->ops.set_voltage = dm1105_set_voltage; - dvb_attach(dvb_pll_attach, dev->fe, 0x60, - &dev->i2c_bb_adap, DVB_PLL_OPERA1); - break; - } - - dev->fe = dvb_attach( - stv0288_attach, &earda_config, - &dev->i2c_bb_adap); - if (dev->fe) { - dev->fe->ops.set_voltage = dm1105_set_voltage; - dvb_attach(stb6000_attach, dev->fe, 0x61, - &dev->i2c_bb_adap); - break; - } - - dev->fe = dvb_attach( - si21xx_attach, &serit_config, - &dev->i2c_bb_adap); - if (dev->fe) - dev->fe->ops.set_voltage = dm1105_set_voltage; - break; case DM1105_BOARD_DVBWORLD_2004: dev->fe = dvb_attach( cx24116_attach, &serit_sp2633_config, @@ -1047,32 +870,11 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, if (ret < 0) goto err_dm1105_hw_exit; - i2c_set_adapdata(&dev->i2c_bb_adap, dev); - strcpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME); - dev->i2c_bb_adap.owner = THIS_MODULE; - dev->i2c_bb_adap.dev.parent = &pdev->dev; - dev->i2c_bb_adap.algo_data = &dev->i2c_bit; - dev->i2c_bit.data = dev; - dev->i2c_bit.setsda = dm1105_setsda; - dev->i2c_bit.setscl = dm1105_setscl; - dev->i2c_bit.getsda = dm1105_getsda; - dev->i2c_bit.getscl = dm1105_getscl; - dev->i2c_bit.udelay = 10; - dev->i2c_bit.timeout = 10; - - /* Raise SCL and SDA */ - dm1105_setsda(dev, 1); - dm1105_setscl(dev, 1); - - ret = i2c_bit_add_bus(&dev->i2c_bb_adap); - if (ret < 0) - goto err_i2c_del_adapter; - /* dvb */ ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev, adapter_nr); if (ret < 0) - goto err_i2c_del_adapters; + goto err_i2c_del_adapter; dvb_adapter = &dev->dvb_adapter; @@ -1150,8 +952,6 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, dvb_dmx_release(dvbdemux); err_dvb_unregister_adapter: dvb_unregister_adapter(dvb_adapter); -err_i2c_del_adapters: - i2c_del_adapter(&dev->i2c_bb_adap); err_i2c_del_adapter: i2c_del_adapter(&dev->i2c_adap); err_dm1105_hw_exit: diff --git a/trunk/drivers/media/dvb/dvb-usb/lmedm04.c b/trunk/drivers/media/dvb/dvb-usb/lmedm04.c index 37b146961ae2..f36f471deae2 100644 --- a/trunk/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/trunk/drivers/media/dvb/dvb-usb/lmedm04.c @@ -207,6 +207,17 @@ static int lme2510_stream_restart(struct dvb_usb_device *d) rbuff, sizeof(rbuff)); return ret; } +static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u32 keypress) +{ + struct dvb_usb_device *d = adap->dev; + + deb_info(1, "INT Key Keypress =%04x", keypress); + + if (keypress > 0) + rc_keydown(d->rc_dev, keypress, 0); + + return 0; +} static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) { @@ -245,7 +256,6 @@ static void lme2510_int_response(struct urb *lme_urb) struct lme2510_state *st = adap->dev->priv; static u8 *ibuf, *rbuf; int i = 0, offset; - u32 key; switch (lme_urb->status) { case 0: @@ -272,16 +282,10 @@ static void lme2510_int_response(struct urb *lme_urb) switch (ibuf[0]) { case 0xaa: - debug_data_snipet(1, "INT Remote data snipet", ibuf); - if ((ibuf[4] + ibuf[5]) == 0xff) { - key = ibuf[5]; - key += (ibuf[3] > 0) - ? (ibuf[3] ^ 0xff) << 8 : 0; - key += (ibuf[2] ^ 0xff) << 16; - deb_info(1, "INT Key =%08x", key); - if (adap->dev->rc_dev != NULL) - rc_keydown(adap->dev->rc_dev, key, 0); - } + debug_data_snipet(1, "INT Remote data snipet in", ibuf); + lme2510_remote_keypress(adap, + (u32)(ibuf[2] << 24) + (ibuf[3] << 16) + + (ibuf[4] << 8) + ibuf[5]); break; case 0xbb: switch (st->tuner_config) { @@ -687,6 +691,45 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) return (ret < 0) ? -ENODEV : 0; } +static int lme2510_int_service(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap->dev; + struct rc_dev *rc; + int ret; + + info("STA Configuring Remote"); + + rc = rc_allocate_device(); + if (!rc) + return -ENOMEM; + + usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); + strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); + + rc->input_name = "LME2510 Remote Control"; + rc->input_phys = d->rc_phys; + rc->map_name = RC_MAP_LME2510; + rc->driver_name = "LME 2510"; + usb_to_input_id(d->udev, &rc->input_id); + + ret = rc_register_device(rc); + if (ret) { + rc_free_device(rc); + return ret; + } + d->rc_dev = rc; + + /* Start the Interrupt */ + ret = lme2510_int_read(adap); + if (ret < 0) { + rc_unregister_device(rc); + info("INT Unable to start Interrupt Service"); + return -ENODEV; + } + + return 0; +} + static u8 check_sum(u8 *p, u8 len) { u8 sum = 0; @@ -788,7 +831,7 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) cold_fw = !cold; - if (le16_to_cpu(udev->descriptor.idProduct) == 0x1122) { + if (udev->descriptor.idProduct == 0x1122) { switch (dvb_usb_lme2510_firmware) { default: dvb_usb_lme2510_firmware = TUNER_S0194; @@ -1010,11 +1053,8 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) end: if (ret) { - if (adap->fe) { - dvb_frontend_detach(adap->fe); - adap->fe = NULL; - } - adap->dev->props.rc.core.rc_codes = NULL; + kfree(adap->fe); + adap->fe = NULL; return -ENODEV; } @@ -1057,12 +1097,8 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) return -ENODEV; } - /* Start the Interrupt*/ - ret = lme2510_int_read(adap); - if (ret < 0) { - info("INT Unable to start Interrupt Service"); - return -ENODEV; - } + /* Start the Interrupt & Remote*/ + ret = lme2510_int_service(adap); return ret; } @@ -1168,12 +1204,6 @@ static struct dvb_usb_device_properties lme2510_properties = { } } }, - .rc.core = { - .protocol = RC_TYPE_NEC, - .module_name = "LME2510 Remote Control", - .allowed_protos = RC_TYPE_NEC, - .rc_codes = RC_MAP_LME2510, - }, .power_ctrl = lme2510_powerup, .identify_state = lme2510_identify_state, .i2c_algo = &lme2510_i2c_algo, @@ -1216,12 +1246,6 @@ static struct dvb_usb_device_properties lme2510c_properties = { } } }, - .rc.core = { - .protocol = RC_TYPE_NEC, - .module_name = "LME2510 Remote Control", - .allowed_protos = RC_TYPE_NEC, - .rc_codes = RC_MAP_LME2510, - }, .power_ctrl = lme2510_powerup, .identify_state = lme2510_identify_state, .i2c_algo = &lme2510_i2c_algo, @@ -1245,21 +1269,19 @@ static void *lme2510_exit_int(struct dvb_usb_device *d) adap->feedcount = 0; } - if (st->usb_buffer != NULL) { + if (st->lme_urb != NULL) { st->i2c_talk_onoff = 1; st->signal_lock = 0; st->signal_level = 0; st->signal_sn = 0; buffer = st->usb_buffer; - } - - if (st->lme_urb != NULL) { usb_kill_urb(st->lme_urb); usb_free_coherent(d->udev, 5000, st->buffer, st->lme_urb->transfer_dma); info("Interrupt Service Stopped"); + rc_unregister_device(d->rc_dev); + info("Remote Stopped"); } - return buffer; } @@ -1271,8 +1293,7 @@ static void lme2510_exit(struct usb_interface *intf) if (d != NULL) { usb_buffer = lme2510_exit_int(d); dvb_usb_device_exit(intf); - if (usb_buffer != NULL) - kfree(usb_buffer); + kfree(usb_buffer); } } @@ -1306,5 +1327,5 @@ module_exit(lme2510_module_exit); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.88"); +MODULE_VERSION("1.86"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/media/dvb/frontends/stb0899_algo.c b/trunk/drivers/media/dvb/frontends/stb0899_algo.c index d70eee00f33a..2da55ec20392 100644 --- a/trunk/drivers/media/dvb/frontends/stb0899_algo.c +++ b/trunk/drivers/media/dvb/frontends/stb0899_algo.c @@ -23,7 +23,7 @@ #include "stb0899_priv.h" #include "stb0899_reg.h" -static inline u32 stb0899_do_div(u64 n, u32 d) +inline u32 stb0899_do_div(u64 n, u32 d) { /* wrap do_div() for ease of use */ diff --git a/trunk/drivers/media/dvb/frontends/tda8261.c b/trunk/drivers/media/dvb/frontends/tda8261.c index 53c7d8f1df28..1742056a34e8 100644 --- a/trunk/drivers/media/dvb/frontends/tda8261.c +++ b/trunk/drivers/media/dvb/frontends/tda8261.c @@ -224,6 +224,7 @@ struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe, } EXPORT_SYMBOL(tda8261_attach); +MODULE_PARM_DESC(verbose, "Set verbosity level"); MODULE_AUTHOR("Manu Abraham"); MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner"); diff --git a/trunk/drivers/media/radio/radio-maxiradio.c b/trunk/drivers/media/radio/radio-maxiradio.c index e83e84003025..5c2a9058c09f 100644 --- a/trunk/drivers/media/radio/radio-maxiradio.c +++ b/trunk/drivers/media/radio/radio-maxiradio.c @@ -412,7 +412,8 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d goto err_out_free_region; } - v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n"); + v4l2_info(v4l2_dev, "version " DRIVER_VERSION + " time " __TIME__ " " __DATE__ "\n"); v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n", dev->io); diff --git a/trunk/drivers/media/radio/radio-timb.c b/trunk/drivers/media/radio/radio-timb.c index a185610b376b..1e3a8dd820a4 100644 --- a/trunk/drivers/media/radio/radio-timb.c +++ b/trunk/drivers/media/radio/radio-timb.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -148,7 +149,7 @@ static const struct v4l2_file_operations timbradio_fops = { static int __devinit timbradio_probe(struct platform_device *pdev) { - struct timb_radio_platform_data *pdata = pdev->dev.platform_data; + struct timb_radio_platform_data *pdata = mfd_get_data(pdev); struct timbradio *tr; int err; diff --git a/trunk/drivers/media/radio/radio-wl1273.c b/trunk/drivers/media/radio/radio-wl1273.c index 459f7272d326..e2550dc2944f 100644 --- a/trunk/drivers/media/radio/radio-wl1273.c +++ b/trunk/drivers/media/radio/radio-wl1273.c @@ -1382,7 +1382,7 @@ static int wl1273_fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_TUNE_ANTENNA_CAPACITOR: - ctrl->cur.val = wl1273_fm_get_tx_ctune(radio); + ctrl->val = wl1273_fm_get_tx_ctune(radio); break; default: @@ -1990,7 +1990,7 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev) static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) { - struct wl1273_core **core = pdev->dev.platform_data; + struct wl1273_core **core = mfd_get_data(pdev); struct wl1273_device *radio; struct v4l2_ctrl *ctrl; int r = 0; diff --git a/trunk/drivers/media/radio/wl128x/fmdrv_v4l2.c b/trunk/drivers/media/radio/wl128x/fmdrv_v4l2.c index 87010724f914..d50e5ac75ab6 100644 --- a/trunk/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/trunk/drivers/media/radio/wl128x/fmdrv_v4l2.c @@ -191,7 +191,7 @@ static int fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_TUNE_ANTENNA_CAPACITOR: - ctrl->cur.val = fm_tx_get_tune_cap_val(fmdev); + ctrl->val = fm_tx_get_tune_cap_val(fmdev); break; default: fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id); diff --git a/trunk/drivers/media/rc/Kconfig b/trunk/drivers/media/rc/Kconfig index 7d4bbc226d06..154c337f00fd 100644 --- a/trunk/drivers/media/rc/Kconfig +++ b/trunk/drivers/media/rc/Kconfig @@ -148,18 +148,6 @@ config IR_ITE_CIR To compile this driver as a module, choose M here: the module will be called ite-cir. -config IR_FINTEK - tristate "Fintek Consumer Infrared Transceiver" - depends on PNP - depends on RC_CORE - ---help--- - Say Y here to enable support for integrated infrared receiver - /transciever made by Fintek. This chip is found on assorted - Jetway motherboards (and of course, possibly others). - - To compile this driver as a module, choose M here: the - module will be called fintek-cir. - config IR_NUVOTON tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" depends on PNP diff --git a/trunk/drivers/media/rc/Makefile b/trunk/drivers/media/rc/Makefile index 52830e5f4eaa..1f90a219a162 100644 --- a/trunk/drivers/media/rc/Makefile +++ b/trunk/drivers/media/rc/Makefile @@ -16,7 +16,6 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o obj-$(CONFIG_IR_IMON) += imon.o obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o obj-$(CONFIG_IR_MCEUSB) += mceusb.o -obj-$(CONFIG_IR_FINTEK) += fintek-cir.o obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o obj-$(CONFIG_IR_ENE) += ene_ir.o obj-$(CONFIG_IR_REDRAT3) += redrat3.o diff --git a/trunk/drivers/media/rc/fintek-cir.c b/trunk/drivers/media/rc/fintek-cir.c deleted file mode 100644 index 8fa539dde1b4..000000000000 --- a/trunk/drivers/media/rc/fintek-cir.c +++ /dev/null @@ -1,684 +0,0 @@ -/* - * Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR - * - * Copyright (C) 2011 Jarod Wilson - * - * Special thanks to Fintek for providing hardware and spec sheets. - * This driver is based upon the nuvoton, ite and ene drivers for - * similar hardware. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fintek-cir.h" - -/* write val to config reg */ -static inline void fintek_cr_write(struct fintek_dev *fintek, u8 val, u8 reg) -{ - fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)", - __func__, reg, val, fintek->cr_ip, fintek->cr_dp); - outb(reg, fintek->cr_ip); - outb(val, fintek->cr_dp); -} - -/* read val from config reg */ -static inline u8 fintek_cr_read(struct fintek_dev *fintek, u8 reg) -{ - u8 val; - - outb(reg, fintek->cr_ip); - val = inb(fintek->cr_dp); - - fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)", - __func__, reg, val, fintek->cr_ip, fintek->cr_dp); - return val; -} - -/* update config register bit without changing other bits */ -static inline void fintek_set_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg) -{ - u8 tmp = fintek_cr_read(fintek, reg) | val; - fintek_cr_write(fintek, tmp, reg); -} - -/* clear config register bit without changing other bits */ -static inline void fintek_clear_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg) -{ - u8 tmp = fintek_cr_read(fintek, reg) & ~val; - fintek_cr_write(fintek, tmp, reg); -} - -/* enter config mode */ -static inline void fintek_config_mode_enable(struct fintek_dev *fintek) -{ - /* Enabling Config Mode explicitly requires writing 2x */ - outb(CONFIG_REG_ENABLE, fintek->cr_ip); - outb(CONFIG_REG_ENABLE, fintek->cr_ip); -} - -/* exit config mode */ -static inline void fintek_config_mode_disable(struct fintek_dev *fintek) -{ - outb(CONFIG_REG_DISABLE, fintek->cr_ip); -} - -/* - * When you want to address a specific logical device, write its logical - * device number to GCR_LOGICAL_DEV_NO - */ -static inline void fintek_select_logical_dev(struct fintek_dev *fintek, u8 ldev) -{ - fintek_cr_write(fintek, ldev, GCR_LOGICAL_DEV_NO); -} - -/* write val to cir config register */ -static inline void fintek_cir_reg_write(struct fintek_dev *fintek, u8 val, u8 offset) -{ - outb(val, fintek->cir_addr + offset); -} - -/* read val from cir config register */ -static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset) -{ - u8 val; - - val = inb(fintek->cir_addr + offset); - - return val; -} - -#define pr_reg(text, ...) \ - printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__) - -/* dump current cir register contents */ -static void cir_dump_regs(struct fintek_dev *fintek) -{ - fintek_config_mode_enable(fintek); - fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); - - pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME); - pr_reg(" * CR CIR BASE ADDR: 0x%x\n", - (fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) | - fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO)); - pr_reg(" * CR CIR IRQ NUM: 0x%x\n", - fintek_cr_read(fintek, CIR_CR_IRQ_SEL)); - - fintek_config_mode_disable(fintek); - - pr_reg("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME); - pr_reg(" * STATUS: 0x%x\n", fintek_cir_reg_read(fintek, CIR_STATUS)); - pr_reg(" * CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_CONTROL)); - pr_reg(" * RX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_RX_DATA)); - pr_reg(" * TX_CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_CONTROL)); - pr_reg(" * TX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_DATA)); -} - -/* detect hardware features */ -static int fintek_hw_detect(struct fintek_dev *fintek) -{ - unsigned long flags; - u8 chip_major, chip_minor; - u8 vendor_major, vendor_minor; - u8 portsel, ir_class; - u16 vendor; - int ret = 0; - - fintek_config_mode_enable(fintek); - - /* Check if we're using config port 0x4e or 0x2e */ - portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL); - if (portsel == 0xff) { - fit_pr(KERN_INFO, "first portsel read was bunk, trying alt"); - fintek_config_mode_disable(fintek); - fintek->cr_ip = CR_INDEX_PORT2; - fintek->cr_dp = CR_DATA_PORT2; - fintek_config_mode_enable(fintek); - portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL); - } - fit_dbg("portsel reg: 0x%02x", portsel); - - ir_class = fintek_cir_reg_read(fintek, CIR_CR_CLASS); - fit_dbg("ir_class reg: 0x%02x", ir_class); - - switch (ir_class) { - case CLASS_RX_2TX: - case CLASS_RX_1TX: - fintek->hw_tx_capable = true; - break; - case CLASS_RX_ONLY: - default: - fintek->hw_tx_capable = false; - break; - } - - chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI); - chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO); - - vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI); - vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO); - vendor = vendor_major << 8 | vendor_minor; - - if (vendor != VENDOR_ID_FINTEK) - fit_pr(KERN_WARNING, "Unknown vendor ID: 0x%04x", vendor); - else - fit_dbg("Read Fintek vendor ID from chip"); - - fintek_config_mode_disable(fintek); - - spin_lock_irqsave(&fintek->fintek_lock, flags); - fintek->chip_major = chip_major; - fintek->chip_minor = chip_minor; - fintek->chip_vendor = vendor; - spin_unlock_irqrestore(&fintek->fintek_lock, flags); - - return ret; -} - -static void fintek_cir_ldev_init(struct fintek_dev *fintek) -{ - /* Select CIR logical device and enable */ - fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); - fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); - - /* Write allocated CIR address and IRQ information to hardware */ - fintek_cr_write(fintek, fintek->cir_addr >> 8, CIR_CR_BASE_ADDR_HI); - fintek_cr_write(fintek, fintek->cir_addr & 0xff, CIR_CR_BASE_ADDR_LO); - - fintek_cr_write(fintek, fintek->cir_irq, CIR_CR_IRQ_SEL); - - fit_dbg("CIR initialized, base io address: 0x%lx, irq: %d (len: %d)", - fintek->cir_addr, fintek->cir_irq, fintek->cir_port_len); -} - -/* enable CIR interrupts */ -static void fintek_enable_cir_irq(struct fintek_dev *fintek) -{ - fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS); -} - -static void fintek_cir_regs_init(struct fintek_dev *fintek) -{ - /* clear any and all stray interrupts */ - fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); - - /* and finally, enable interrupts */ - fintek_enable_cir_irq(fintek); -} - -static void fintek_enable_wake(struct fintek_dev *fintek) -{ - fintek_config_mode_enable(fintek); - fintek_select_logical_dev(fintek, LOGICAL_DEV_ACPI); - - /* Allow CIR PME's to wake system */ - fintek_set_reg_bit(fintek, ACPI_WAKE_EN_CIR_BIT, LDEV_ACPI_WAKE_EN_REG); - /* Enable CIR PME's */ - fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_EN_REG); - /* Clear CIR PME status register */ - fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_CLR_REG); - /* Save state */ - fintek_set_reg_bit(fintek, ACPI_STATE_CIR_BIT, LDEV_ACPI_STATE_REG); - - fintek_config_mode_disable(fintek); -} - -static int fintek_cmdsize(u8 cmd, u8 subcmd) -{ - int datasize = 0; - - switch (cmd) { - case BUF_COMMAND_NULL: - if (subcmd == BUF_HW_CMD_HEADER) - datasize = 1; - break; - case BUF_HW_CMD_HEADER: - if (subcmd == BUF_CMD_G_REVISION) - datasize = 2; - break; - case BUF_COMMAND_HEADER: - switch (subcmd) { - case BUF_CMD_S_CARRIER: - case BUF_CMD_S_TIMEOUT: - case BUF_RSP_PULSE_COUNT: - datasize = 2; - break; - case BUF_CMD_SIG_END: - case BUF_CMD_S_TXMASK: - case BUF_CMD_S_RXSENSOR: - datasize = 1; - break; - } - } - - return datasize; -} - -/* process ir data stored in driver buffer */ -static void fintek_process_rx_ir_data(struct fintek_dev *fintek) -{ - DEFINE_IR_RAW_EVENT(rawir); - u8 sample; - int i; - - for (i = 0; i < fintek->pkts; i++) { - sample = fintek->buf[i]; - switch (fintek->parser_state) { - case CMD_HEADER: - fintek->cmd = sample; - if ((fintek->cmd == BUF_COMMAND_HEADER) || - ((fintek->cmd & BUF_COMMAND_MASK) != - BUF_PULSE_BIT)) { - fintek->parser_state = SUBCMD; - continue; - } - fintek->rem = (fintek->cmd & BUF_LEN_MASK); - fit_dbg("%s: rem: 0x%02x", __func__, fintek->rem); - if (fintek->rem) - fintek->parser_state = PARSE_IRDATA; - else - ir_raw_event_reset(fintek->rdev); - break; - case SUBCMD: - fintek->rem = fintek_cmdsize(fintek->cmd, sample); - fintek->parser_state = CMD_DATA; - break; - case CMD_DATA: - fintek->rem--; - break; - case PARSE_IRDATA: - fintek->rem--; - init_ir_raw_event(&rawir); - rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); - rawir.duration = US_TO_NS((sample & BUF_SAMPLE_MASK) - * CIR_SAMPLE_PERIOD); - - fit_dbg("Storing %s with duration %d", - rawir.pulse ? "pulse" : "space", - rawir.duration); - ir_raw_event_store_with_filter(fintek->rdev, &rawir); - break; - } - - if ((fintek->parser_state != CMD_HEADER) && !fintek->rem) - fintek->parser_state = CMD_HEADER; - } - - fintek->pkts = 0; - - fit_dbg("Calling ir_raw_event_handle"); - ir_raw_event_handle(fintek->rdev); -} - -/* copy data from hardware rx register into driver buffer */ -static void fintek_get_rx_ir_data(struct fintek_dev *fintek, u8 rx_irqs) -{ - unsigned long flags; - u8 sample, status; - - spin_lock_irqsave(&fintek->fintek_lock, flags); - - /* - * We must read data from CIR_RX_DATA until the hardware IR buffer - * is empty and clears the RX_TIMEOUT and/or RX_RECEIVE flags in - * the CIR_STATUS register - */ - do { - sample = fintek_cir_reg_read(fintek, CIR_RX_DATA); - fit_dbg("%s: sample: 0x%02x", __func__, sample); - - fintek->buf[fintek->pkts] = sample; - fintek->pkts++; - - status = fintek_cir_reg_read(fintek, CIR_STATUS); - if (!(status & CIR_STATUS_IRQ_EN)) - break; - } while (status & rx_irqs); - - fintek_process_rx_ir_data(fintek); - - spin_unlock_irqrestore(&fintek->fintek_lock, flags); -} - -static void fintek_cir_log_irqs(u8 status) -{ - fit_pr(KERN_INFO, "IRQ 0x%02x:%s%s%s%s%s", status, - status & CIR_STATUS_IRQ_EN ? " IRQEN" : "", - status & CIR_STATUS_TX_FINISH ? " TXF" : "", - status & CIR_STATUS_TX_UNDERRUN ? " TXU" : "", - status & CIR_STATUS_RX_TIMEOUT ? " RXTO" : "", - status & CIR_STATUS_RX_RECEIVE ? " RXOK" : ""); -} - -/* interrupt service routine for incoming and outgoing CIR data */ -static irqreturn_t fintek_cir_isr(int irq, void *data) -{ - struct fintek_dev *fintek = data; - u8 status, rx_irqs; - - fit_dbg_verbose("%s firing", __func__); - - fintek_config_mode_enable(fintek); - fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); - fintek_config_mode_disable(fintek); - - /* - * Get IR Status register contents. Write 1 to ack/clear - * - * bit: reg name - description - * 3: TX_FINISH - TX is finished - * 2: TX_UNDERRUN - TX underrun - * 1: RX_TIMEOUT - RX data timeout - * 0: RX_RECEIVE - RX data received - */ - status = fintek_cir_reg_read(fintek, CIR_STATUS); - if (!(status & CIR_STATUS_IRQ_MASK) || status == 0xff) { - fit_dbg_verbose("%s exiting, IRSTS 0x%02x", __func__, status); - fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); - return IRQ_RETVAL(IRQ_NONE); - } - - if (debug) - fintek_cir_log_irqs(status); - - rx_irqs = status & (CIR_STATUS_RX_RECEIVE | CIR_STATUS_RX_TIMEOUT); - if (rx_irqs) - fintek_get_rx_ir_data(fintek, rx_irqs); - - /* ack/clear all irq flags we've got */ - fintek_cir_reg_write(fintek, status, CIR_STATUS); - - fit_dbg_verbose("%s done", __func__); - return IRQ_RETVAL(IRQ_HANDLED); -} - -static void fintek_enable_cir(struct fintek_dev *fintek) -{ - /* set IRQ enabled */ - fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS); - - fintek_config_mode_enable(fintek); - - /* enable the CIR logical device */ - fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); - fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); - - fintek_config_mode_disable(fintek); - - /* clear all pending interrupts */ - fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); - - /* enable interrupts */ - fintek_enable_cir_irq(fintek); -} - -static void fintek_disable_cir(struct fintek_dev *fintek) -{ - fintek_config_mode_enable(fintek); - - /* disable the CIR logical device */ - fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); - fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); - - fintek_config_mode_disable(fintek); -} - -static int fintek_open(struct rc_dev *dev) -{ - struct fintek_dev *fintek = dev->priv; - unsigned long flags; - - spin_lock_irqsave(&fintek->fintek_lock, flags); - fintek_enable_cir(fintek); - spin_unlock_irqrestore(&fintek->fintek_lock, flags); - - return 0; -} - -static void fintek_close(struct rc_dev *dev) -{ - struct fintek_dev *fintek = dev->priv; - unsigned long flags; - - spin_lock_irqsave(&fintek->fintek_lock, flags); - fintek_disable_cir(fintek); - spin_unlock_irqrestore(&fintek->fintek_lock, flags); -} - -/* Allocate memory, probe hardware, and initialize everything */ -static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) -{ - struct fintek_dev *fintek; - struct rc_dev *rdev; - int ret = -ENOMEM; - - fintek = kzalloc(sizeof(struct fintek_dev), GFP_KERNEL); - if (!fintek) - return ret; - - /* input device for IR remote (and tx) */ - rdev = rc_allocate_device(); - if (!rdev) - goto failure; - - ret = -ENODEV; - /* validate pnp resources */ - if (!pnp_port_valid(pdev, 0)) { - dev_err(&pdev->dev, "IR PNP Port not valid!\n"); - goto failure; - } - - if (!pnp_irq_valid(pdev, 0)) { - dev_err(&pdev->dev, "IR PNP IRQ not valid!\n"); - goto failure; - } - - fintek->cir_addr = pnp_port_start(pdev, 0); - fintek->cir_irq = pnp_irq(pdev, 0); - fintek->cir_port_len = pnp_port_len(pdev, 0); - - fintek->cr_ip = CR_INDEX_PORT; - fintek->cr_dp = CR_DATA_PORT; - - spin_lock_init(&fintek->fintek_lock); - - ret = -EBUSY; - /* now claim resources */ - if (!request_region(fintek->cir_addr, - fintek->cir_port_len, FINTEK_DRIVER_NAME)) - goto failure; - - if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED, - FINTEK_DRIVER_NAME, (void *)fintek)) - goto failure; - - pnp_set_drvdata(pdev, fintek); - fintek->pdev = pdev; - - ret = fintek_hw_detect(fintek); - if (ret) - goto failure; - - /* Initialize CIR & CIR Wake Logical Devices */ - fintek_config_mode_enable(fintek); - fintek_cir_ldev_init(fintek); - fintek_config_mode_disable(fintek); - - /* Initialize CIR & CIR Wake Config Registers */ - fintek_cir_regs_init(fintek); - - /* Set up the rc device */ - rdev->priv = fintek; - rdev->driver_type = RC_DRIVER_IR_RAW; - rdev->allowed_protos = RC_TYPE_ALL; - rdev->open = fintek_open; - rdev->close = fintek_close; - rdev->input_name = FINTEK_DESCRIPTION; - rdev->input_phys = "fintek/cir0"; - rdev->input_id.bustype = BUS_HOST; - rdev->input_id.vendor = VENDOR_ID_FINTEK; - rdev->input_id.product = fintek->chip_major; - rdev->input_id.version = fintek->chip_minor; - rdev->dev.parent = &pdev->dev; - rdev->driver_name = FINTEK_DRIVER_NAME; - rdev->map_name = RC_MAP_RC6_MCE; - rdev->timeout = US_TO_NS(1000); - /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ - rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); - - ret = rc_register_device(rdev); - if (ret) - goto failure; - - device_init_wakeup(&pdev->dev, true); - fintek->rdev = rdev; - fit_pr(KERN_NOTICE, "driver has been successfully loaded\n"); - if (debug) - cir_dump_regs(fintek); - - return 0; - -failure: - if (fintek->cir_irq) - free_irq(fintek->cir_irq, fintek); - if (fintek->cir_addr) - release_region(fintek->cir_addr, fintek->cir_port_len); - - rc_free_device(rdev); - kfree(fintek); - - return ret; -} - -static void __devexit fintek_remove(struct pnp_dev *pdev) -{ - struct fintek_dev *fintek = pnp_get_drvdata(pdev); - unsigned long flags; - - spin_lock_irqsave(&fintek->fintek_lock, flags); - /* disable CIR */ - fintek_disable_cir(fintek); - fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); - /* enable CIR Wake (for IR power-on) */ - fintek_enable_wake(fintek); - spin_unlock_irqrestore(&fintek->fintek_lock, flags); - - /* free resources */ - free_irq(fintek->cir_irq, fintek); - release_region(fintek->cir_addr, fintek->cir_port_len); - - rc_unregister_device(fintek->rdev); - - kfree(fintek); -} - -static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state) -{ - struct fintek_dev *fintek = pnp_get_drvdata(pdev); - - fit_dbg("%s called", __func__); - - /* disable all CIR interrupts */ - fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); - - fintek_config_mode_enable(fintek); - - /* disable cir logical dev */ - fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); - fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); - - fintek_config_mode_disable(fintek); - - /* make sure wake is enabled */ - fintek_enable_wake(fintek); - - return 0; -} - -static int fintek_resume(struct pnp_dev *pdev) -{ - int ret = 0; - struct fintek_dev *fintek = pnp_get_drvdata(pdev); - - fit_dbg("%s called", __func__); - - /* open interrupt */ - fintek_enable_cir_irq(fintek); - - /* Enable CIR logical device */ - fintek_config_mode_enable(fintek); - fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); - fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); - - fintek_config_mode_disable(fintek); - - fintek_cir_regs_init(fintek); - - return ret; -} - -static void fintek_shutdown(struct pnp_dev *pdev) -{ - struct fintek_dev *fintek = pnp_get_drvdata(pdev); - fintek_enable_wake(fintek); -} - -static const struct pnp_device_id fintek_ids[] = { - { "FIT0002", 0 }, /* CIR */ - { "", 0 }, -}; - -static struct pnp_driver fintek_driver = { - .name = FINTEK_DRIVER_NAME, - .id_table = fintek_ids, - .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, - .probe = fintek_probe, - .remove = __devexit_p(fintek_remove), - .suspend = fintek_suspend, - .resume = fintek_resume, - .shutdown = fintek_shutdown, -}; - -int fintek_init(void) -{ - return pnp_register_driver(&fintek_driver); -} - -void fintek_exit(void) -{ - pnp_unregister_driver(&fintek_driver); -} - -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging output"); - -MODULE_DEVICE_TABLE(pnp, fintek_ids); -MODULE_DESCRIPTION(FINTEK_DESCRIPTION " driver"); - -MODULE_AUTHOR("Jarod Wilson "); -MODULE_LICENSE("GPL"); - -module_init(fintek_init); -module_exit(fintek_exit); diff --git a/trunk/drivers/media/rc/fintek-cir.h b/trunk/drivers/media/rc/fintek-cir.h deleted file mode 100644 index 1b10b2011f5e..000000000000 --- a/trunk/drivers/media/rc/fintek-cir.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR - * - * Copyright (C) 2011 Jarod Wilson - * - * Special thanks to Fintek for providing hardware and spec sheets. - * This driver is based upon the nuvoton, ite and ene drivers for - * similar hardware. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include -#include - -/* platform driver name to register */ -#define FINTEK_DRIVER_NAME "fintek-cir" -#define FINTEK_DESCRIPTION "Fintek LPC SuperIO Consumer IR Transceiver" -#define VENDOR_ID_FINTEK 0x1934 - - -/* debugging module parameter */ -static int debug; - -#define fit_pr(level, text, ...) \ - printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) - -#define fit_dbg(text, ...) \ - if (debug) \ - printk(KERN_DEBUG \ - KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) - -#define fit_dbg_verbose(text, ...) \ - if (debug > 1) \ - printk(KERN_DEBUG \ - KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) - -#define fit_dbg_wake(text, ...) \ - if (debug > 2) \ - printk(KERN_DEBUG \ - KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) - - -#define TX_BUF_LEN 256 -#define RX_BUF_LEN 32 - -struct fintek_dev { - struct pnp_dev *pdev; - struct rc_dev *rdev; - - spinlock_t fintek_lock; - - /* for rx */ - u8 buf[RX_BUF_LEN]; - unsigned int pkts; - - struct { - spinlock_t lock; - u8 buf[TX_BUF_LEN]; - unsigned int buf_count; - unsigned int cur_buf_num; - wait_queue_head_t queue; - } tx; - - /* Config register index/data port pair */ - u8 cr_ip; - u8 cr_dp; - - /* hardware I/O settings */ - unsigned long cir_addr; - int cir_irq; - int cir_port_len; - - /* hardware id */ - u8 chip_major; - u8 chip_minor; - u16 chip_vendor; - - /* hardware features */ - bool hw_learning_capable; - bool hw_tx_capable; - - /* rx settings */ - bool learning_enabled; - bool carrier_detect_enabled; - - enum { - CMD_HEADER = 0, - SUBCMD, - CMD_DATA, - PARSE_IRDATA, - } parser_state; - - u8 cmd, rem; - - /* carrier period = 1 / frequency */ - u32 carrier; -}; - -/* buffer packet constants, largely identical to mceusb.c */ -#define BUF_PULSE_BIT 0x80 -#define BUF_LEN_MASK 0x1f -#define BUF_SAMPLE_MASK 0x7f - -#define BUF_COMMAND_HEADER 0x9f -#define BUF_COMMAND_MASK 0xe0 -#define BUF_COMMAND_NULL 0x00 -#define BUF_HW_CMD_HEADER 0xff -#define BUF_CMD_G_REVISION 0x0b -#define BUF_CMD_S_CARRIER 0x06 -#define BUF_CMD_S_TIMEOUT 0x0c -#define BUF_CMD_SIG_END 0x01 -#define BUF_CMD_S_TXMASK 0x08 -#define BUF_CMD_S_RXSENSOR 0x14 -#define BUF_RSP_PULSE_COUNT 0x15 - -#define CIR_SAMPLE_PERIOD 50 - -/* - * Configuration Register: - * Index Port - * Data Port - */ -#define CR_INDEX_PORT 0x2e -#define CR_DATA_PORT 0x2f - -/* Possible alternate values, depends on how the chip is wired */ -#define CR_INDEX_PORT2 0x4e -#define CR_DATA_PORT2 0x4f - -/* - * GCR_CONFIG_PORT_SEL bit 4 specifies which Index Port value is - * active. 1 = 0x4e, 0 = 0x2e - */ -#define PORT_SEL_PORT_4E_EN 0x10 - -/* Extended Function Mode enable/disable magic values */ -#define CONFIG_REG_ENABLE 0x87 -#define CONFIG_REG_DISABLE 0xaa - -/* Chip IDs found in CR_CHIP_ID_{HI,LO} */ -#define CHIP_ID_HIGH_F71809U 0x04 -#define CHIP_ID_LOW_F71809U 0x08 - -/* - * Global control regs we need to care about: - * Global Control def. - * Register name addr val. */ -#define GCR_SOFTWARE_RESET 0x02 /* 0x00 */ -#define GCR_LOGICAL_DEV_NO 0x07 /* 0x00 */ -#define GCR_CHIP_ID_HI 0x20 /* 0x04 */ -#define GCR_CHIP_ID_LO 0x21 /* 0x08 */ -#define GCR_VENDOR_ID_HI 0x23 /* 0x19 */ -#define GCR_VENDOR_ID_LO 0x24 /* 0x34 */ -#define GCR_CONFIG_PORT_SEL 0x25 /* 0x01 */ -#define GCR_KBMOUSE_WAKEUP 0x27 - -#define LOGICAL_DEV_DISABLE 0x00 -#define LOGICAL_DEV_ENABLE 0x01 - -/* Logical device number of the CIR function */ -#define LOGICAL_DEV_CIR 0x05 - -/* CIR Logical Device (LDN 0x08) config registers */ -#define CIR_CR_COMMAND_INDEX 0x04 -#define CIR_CR_IRCS 0x05 /* Before host writes command to IR, host - must set to 1. When host finshes write - command to IR, host must clear to 0. */ -#define CIR_CR_COMMAND_DATA 0x06 /* Host read or write comand data */ -#define CIR_CR_CLASS 0x07 /* 0xff = rx-only, 0x66 = rx + 2 tx, - 0x33 = rx + 1 tx */ -#define CIR_CR_DEV_EN 0x30 /* bit0 = 1 enables CIR */ -#define CIR_CR_BASE_ADDR_HI 0x60 /* MSB of CIR IO base addr */ -#define CIR_CR_BASE_ADDR_LO 0x61 /* LSB of CIR IO base addr */ -#define CIR_CR_IRQ_SEL 0x70 /* bits3-0 store CIR IRQ */ -#define CIR_CR_PSOUT_STATUS 0xf1 -#define CIR_CR_WAKE_KEY3_ADDR 0xf8 -#define CIR_CR_WAKE_KEY3_CODE 0xf9 -#define CIR_CR_WAKE_KEY3_DC 0xfa -#define CIR_CR_WAKE_CONTROL 0xfb -#define CIR_CR_WAKE_KEY12_ADDR 0xfc -#define CIR_CR_WAKE_KEY4_ADDR 0xfd -#define CIR_CR_WAKE_KEY5_ADDR 0xfe - -#define CLASS_RX_ONLY 0xff -#define CLASS_RX_2TX 0x66 -#define CLASS_RX_1TX 0x33 - -/* CIR device registers */ -#define CIR_STATUS 0x00 -#define CIR_RX_DATA 0x01 -#define CIR_TX_CONTROL 0x02 -#define CIR_TX_DATA 0x03 -#define CIR_CONTROL 0x04 - -/* Bits to enable CIR wake */ -#define LOGICAL_DEV_ACPI 0x01 -#define LDEV_ACPI_WAKE_EN_REG 0xe8 -#define ACPI_WAKE_EN_CIR_BIT 0x04 - -#define LDEV_ACPI_PME_EN_REG 0xf0 -#define LDEV_ACPI_PME_CLR_REG 0xf1 -#define ACPI_PME_CIR_BIT 0x02 - -#define LDEV_ACPI_STATE_REG 0xf4 -#define ACPI_STATE_CIR_BIT 0x20 - -/* - * CIR status register (0x00): - * 7 - CIR_IRQ_EN (1 = enable CIR IRQ, 0 = disable) - * 3 - TX_FINISH (1 when TX finished, write 1 to clear) - * 2 - TX_UNDERRUN (1 on TX underrun, write 1 to clear) - * 1 - RX_TIMEOUT (1 on RX timeout, write 1 to clear) - * 0 - RX_RECEIVE (1 on RX receive, write 1 to clear) - */ -#define CIR_STATUS_IRQ_EN 0x80 -#define CIR_STATUS_TX_FINISH 0x08 -#define CIR_STATUS_TX_UNDERRUN 0x04 -#define CIR_STATUS_RX_TIMEOUT 0x02 -#define CIR_STATUS_RX_RECEIVE 0x01 -#define CIR_STATUS_IRQ_MASK 0x0f - -/* - * CIR TX control register (0x02): - * 7 - TX_START (1 to indicate TX start, auto-cleared when done) - * 6 - TX_END (1 to indicate TX data written to TX fifo) - */ -#define CIR_TX_CONTROL_TX_START 0x80 -#define CIR_TX_CONTROL_TX_END 0x40 - diff --git a/trunk/drivers/media/rc/keymaps/rc-lme2510.c b/trunk/drivers/media/rc/keymaps/rc-lme2510.c index 129d3f9a461d..afae14fd152e 100644 --- a/trunk/drivers/media/rc/keymaps/rc-lme2510.c +++ b/trunk/drivers/media/rc/keymaps/rc-lme2510.c @@ -14,81 +14,81 @@ static struct rc_map_table lme2510_rc[] = { /* Type 1 - 26 buttons */ - { 0x10ed45, KEY_0 }, - { 0x10ed5f, KEY_1 }, - { 0x10ed50, KEY_2 }, - { 0x10ed5d, KEY_3 }, - { 0x10ed41, KEY_4 }, - { 0x10ed0a, KEY_5 }, - { 0x10ed42, KEY_6 }, - { 0x10ed47, KEY_7 }, - { 0x10ed49, KEY_8 }, - { 0x10ed05, KEY_9 }, - { 0x10ed43, KEY_POWER }, - { 0x10ed46, KEY_SUBTITLE }, - { 0x10ed06, KEY_PAUSE }, - { 0x10ed03, KEY_MEDIA_REPEAT}, - { 0x10ed02, KEY_PAUSE }, - { 0x10ed5e, KEY_VOLUMEUP }, - { 0x10ed5c, KEY_VOLUMEDOWN }, - { 0x10ed09, KEY_CHANNELUP }, - { 0x10ed1a, KEY_CHANNELDOWN }, - { 0x10ed1e, KEY_PLAY }, - { 0x10ed1b, KEY_ZOOM }, - { 0x10ed59, KEY_MUTE }, - { 0x10ed5a, KEY_TV }, - { 0x10ed18, KEY_RECORD }, - { 0x10ed07, KEY_EPG }, - { 0x10ed01, KEY_STOP }, + { 0xef12ba45, KEY_0 }, + { 0xef12a05f, KEY_1 }, + { 0xef12af50, KEY_2 }, + { 0xef12a25d, KEY_3 }, + { 0xef12be41, KEY_4 }, + { 0xef12f50a, KEY_5 }, + { 0xef12bd42, KEY_6 }, + { 0xef12b847, KEY_7 }, + { 0xef12b649, KEY_8 }, + { 0xef12fa05, KEY_9 }, + { 0xef12bc43, KEY_POWER }, + { 0xef12b946, KEY_SUBTITLE }, + { 0xef12f906, KEY_PAUSE }, + { 0xef12fc03, KEY_MEDIA_REPEAT}, + { 0xef12fd02, KEY_PAUSE }, + { 0xef12a15e, KEY_VOLUMEUP }, + { 0xef12a35c, KEY_VOLUMEDOWN }, + { 0xef12f609, KEY_CHANNELUP }, + { 0xef12e51a, KEY_CHANNELDOWN }, + { 0xef12e11e, KEY_PLAY }, + { 0xef12e41b, KEY_ZOOM }, + { 0xef12a659, KEY_MUTE }, + { 0xef12a55a, KEY_TV }, + { 0xef12e718, KEY_RECORD }, + { 0xef12f807, KEY_EPG }, + { 0xef12fe01, KEY_STOP }, /* Type 2 - 20 buttons */ - { 0xbf15, KEY_0 }, - { 0xbf08, KEY_1 }, - { 0xbf09, KEY_2 }, - { 0xbf0a, KEY_3 }, - { 0xbf0c, KEY_4 }, - { 0xbf0d, KEY_5 }, - { 0xbf0e, KEY_6 }, - { 0xbf10, KEY_7 }, - { 0xbf11, KEY_8 }, - { 0xbf12, KEY_9 }, - { 0xbf00, KEY_POWER }, - { 0xbf04, KEY_MEDIA_REPEAT}, /* Recall */ - { 0xbf1a, KEY_PAUSE }, /* Timeshift */ - { 0xbf02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ - { 0xbf06, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ - { 0xbf01, KEY_CHANNELUP }, - { 0xbf05, KEY_CHANNELDOWN }, - { 0xbf14, KEY_ZOOM }, - { 0xbf18, KEY_RECORD }, - { 0xbf16, KEY_STOP }, + { 0xff40ea15, KEY_0 }, + { 0xff40f708, KEY_1 }, + { 0xff40f609, KEY_2 }, + { 0xff40f50a, KEY_3 }, + { 0xff40f30c, KEY_4 }, + { 0xff40f20d, KEY_5 }, + { 0xff40f10e, KEY_6 }, + { 0xff40ef10, KEY_7 }, + { 0xff40ee11, KEY_8 }, + { 0xff40ed12, KEY_9 }, + { 0xff40ff00, KEY_POWER }, + { 0xff40fb04, KEY_MEDIA_REPEAT}, /* Recall */ + { 0xff40e51a, KEY_PAUSE }, /* Timeshift */ + { 0xff40fd02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ + { 0xff40f906, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ + { 0xff40fe01, KEY_CHANNELUP }, + { 0xff40fa05, KEY_CHANNELDOWN }, + { 0xff40eb14, KEY_ZOOM }, + { 0xff40e718, KEY_RECORD }, + { 0xff40e916, KEY_STOP }, /* Type 3 - 20 buttons */ - { 0x1c, KEY_0 }, - { 0x07, KEY_1 }, - { 0x15, KEY_2 }, - { 0x09, KEY_3 }, - { 0x16, KEY_4 }, - { 0x19, KEY_5 }, - { 0x0d, KEY_6 }, - { 0x0c, KEY_7 }, - { 0x18, KEY_8 }, - { 0x5e, KEY_9 }, - { 0x45, KEY_POWER }, - { 0x44, KEY_MEDIA_REPEAT}, /* Recall */ - { 0x4a, KEY_PAUSE }, /* Timeshift */ - { 0x47, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ - { 0x43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ - { 0x46, KEY_CHANNELUP }, - { 0x40, KEY_CHANNELDOWN }, - { 0x08, KEY_ZOOM }, - { 0x42, KEY_RECORD }, - { 0x5a, KEY_STOP }, + { 0xff00e31c, KEY_0 }, + { 0xff00f807, KEY_1 }, + { 0xff00ea15, KEY_2 }, + { 0xff00f609, KEY_3 }, + { 0xff00e916, KEY_4 }, + { 0xff00e619, KEY_5 }, + { 0xff00f20d, KEY_6 }, + { 0xff00f30c, KEY_7 }, + { 0xff00e718, KEY_8 }, + { 0xff00a15e, KEY_9 }, + { 0xff00ba45, KEY_POWER }, + { 0xff00bb44, KEY_MEDIA_REPEAT}, /* Recall */ + { 0xff00b54a, KEY_PAUSE }, /* Timeshift */ + { 0xff00b847, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ + { 0xff00bc43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ + { 0xff00b946, KEY_CHANNELUP }, + { 0xff00bf40, KEY_CHANNELDOWN }, + { 0xff00f708, KEY_ZOOM }, + { 0xff00bd42, KEY_RECORD }, + { 0xff00a55a, KEY_STOP }, }; static struct rc_map_list lme2510_map = { .map = { .scan = lme2510_rc, .size = ARRAY_SIZE(lme2510_rc), - .rc_type = RC_TYPE_NEC, + .rc_type = RC_TYPE_UNKNOWN, .name = RC_MAP_LME2510, } }; diff --git a/trunk/drivers/media/video/Kconfig b/trunk/drivers/media/video/Kconfig index bb53de7fe408..3be180b3ba27 100644 --- a/trunk/drivers/media/video/Kconfig +++ b/trunk/drivers/media/video/Kconfig @@ -687,7 +687,7 @@ config VIDEO_HEXIUM_GEMINI config VIDEO_TIMBERDALE tristate "Support for timberdale Video In/LogiWIN" - depends on VIDEO_V4L2 && I2C && DMADEVICES + depends on VIDEO_V4L2 && I2C select DMA_ENGINE select TIMB_DMA select VIDEO_ADV7180 @@ -757,8 +757,6 @@ config VIDEO_NOON010PC30 ---help--- This driver supports NOON010PC30 CIF camera from Siliconfile -source "drivers/media/video/m5mols/Kconfig" - config VIDEO_OMAP3 tristate "OMAP 3 Camera support (EXPERIMENTAL)" select OMAP_IOMMU @@ -954,7 +952,7 @@ config VIDEO_SAMSUNG_S5P_FIMC config VIDEO_S5P_MIPI_CSIS tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" - depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P && VIDEO_V4L2_SUBDEV_API + depends on VIDEO_V4L2 && PM_RUNTIME && VIDEO_V4L2_SUBDEV_API ---help--- This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. diff --git a/trunk/drivers/media/video/Makefile b/trunk/drivers/media/video/Makefile index f0fecd6f6a33..9519160c2e01 100644 --- a/trunk/drivers/media/video/Makefile +++ b/trunk/drivers/media/video/Makefile @@ -69,7 +69,6 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o -obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o diff --git a/trunk/drivers/media/video/cpia2/cpia2_v4l.c b/trunk/drivers/media/video/cpia2/cpia2_v4l.c index 40eb6326e48a..0073a8c55336 100644 --- a/trunk/drivers/media/video/cpia2/cpia2_v4l.c +++ b/trunk/drivers/media/video/cpia2/cpia2_v4l.c @@ -438,7 +438,7 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v strcat(vc->card, " (676/"); break; default: - strcat(vc->card, " (XXX/"); + strcat(vc->card, " (???/"); break; } switch (cam->params.version.sensor_flags) { @@ -458,7 +458,7 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v strcat(vc->card, "500)"); break; default: - strcat(vc->card, "XXX)"); + strcat(vc->card, "???)"); break; } diff --git a/trunk/drivers/media/video/cx231xx/cx231xx-avcore.c b/trunk/drivers/media/video/cx231xx/cx231xx-avcore.c index 8d7813415760..280df43ca446 100644 --- a/trunk/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/trunk/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -1354,7 +1354,7 @@ void cx231xx_dump_SC_reg(struct cx231xx *dev) { u8 value[4] = { 0, 0, 0, 0 }; int status = 0; - cx231xx_info("cx231xx_dump_SC_reg!\n"); + cx231xx_info("cx231xx_dump_SC_reg %s!\n", __TIME__); status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, value, 4); diff --git a/trunk/drivers/media/video/gspca/kinect.c b/trunk/drivers/media/video/gspca/kinect.c index 26fc206f095e..66671a4092e4 100644 --- a/trunk/drivers/media/video/gspca/kinect.c +++ b/trunk/drivers/media/video/gspca/kinect.c @@ -34,7 +34,7 @@ MODULE_AUTHOR("Antonio Ospite "); MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver"); MODULE_LICENSE("GPL"); -#ifdef GSPCA_DEBUG +#ifdef DEBUG int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK | D_USBI | D_USBO | D_V4L2; #endif diff --git a/trunk/drivers/media/video/m5mols/Kconfig b/trunk/drivers/media/video/m5mols/Kconfig deleted file mode 100644 index 302dc3d70193..000000000000 --- a/trunk/drivers/media/video/m5mols/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -config VIDEO_M5MOLS - tristate "Fujitsu M-5MOLS 8MP sensor support" - depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API - ---help--- - This driver supports Fujitsu M-5MOLS camera sensor with ISP diff --git a/trunk/drivers/media/video/m5mols/Makefile b/trunk/drivers/media/video/m5mols/Makefile deleted file mode 100644 index 0a44e028edc7..000000000000 --- a/trunk/drivers/media/video/m5mols/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -m5mols-objs := m5mols_core.o m5mols_controls.o m5mols_capture.o - -obj-$(CONFIG_VIDEO_M5MOLS) += m5mols.o diff --git a/trunk/drivers/media/video/m5mols/m5mols.h b/trunk/drivers/media/video/m5mols/m5mols.h deleted file mode 100644 index 10b55c854487..000000000000 --- a/trunk/drivers/media/video/m5mols/m5mols.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Header for M-5MOLS 8M Pixel camera sensor with ISP - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com - * - * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef M5MOLS_H -#define M5MOLS_H - -#include -#include "m5mols_reg.h" - -extern int m5mols_debug; - -#define to_m5mols(__sd) container_of(__sd, struct m5mols_info, sd) - -#define to_sd(__ctrl) \ - (&container_of(__ctrl->handler, struct m5mols_info, handle)->sd) - -enum m5mols_restype { - M5MOLS_RESTYPE_MONITOR, - M5MOLS_RESTYPE_CAPTURE, - M5MOLS_RESTYPE_MAX, -}; - -/** - * struct m5mols_resolution - structure for the resolution - * @type: resolution type according to the pixel code - * @width: width of the resolution - * @height: height of the resolution - * @reg: resolution preset register value - */ -struct m5mols_resolution { - u8 reg; - enum m5mols_restype type; - u16 width; - u16 height; -}; - -/** - * struct m5mols_exif - structure for the EXIF information of M-5MOLS - * @exposure_time: exposure time register value - * @shutter_speed: speed of the shutter register value - * @aperture: aperture register value - * @exposure_bias: it calls also EV bias - * @iso_speed: ISO register value - * @flash: status register value of the flash - * @sdr: status register value of the Subject Distance Range - * @qval: not written exact meaning in document - */ -struct m5mols_exif { - u32 exposure_time; - u32 shutter_speed; - u32 aperture; - u32 brightness; - u32 exposure_bias; - u16 iso_speed; - u16 flash; - u16 sdr; - u16 qval; -}; - -/** - * struct m5mols_capture - Structure for the capture capability - * @exif: EXIF information - * @main: size in bytes of the main image - * @thumb: size in bytes of the thumb image, if it was accompanied - * @total: total size in bytes of the produced image - */ -struct m5mols_capture { - struct m5mols_exif exif; - u32 main; - u32 thumb; - u32 total; -}; - -/** - * struct m5mols_scenemode - structure for the scenemode capability - * @metering: metering light register value - * @ev_bias: EV bias register value - * @wb_mode: mode which means the WhiteBalance is Auto or Manual - * @wb_preset: whitebalance preset register value in the Manual mode - * @chroma_en: register value whether the Chroma capability is enabled or not - * @chroma_lvl: chroma's level register value - * @edge_en: register value Whether the Edge capability is enabled or not - * @edge_lvl: edge's level register value - * @af_range: Auto Focus's range - * @fd_mode: Face Detection mode - * @mcc: Multi-axis Color Conversion which means emotion color - * @light: status of the Light - * @flash: status of the Flash - * @tone: Tone color which means Contrast - * @iso: ISO register value - * @capt_mode: Mode of the Image Stabilization while the camera capturing - * @wdr: Wide Dynamic Range register value - * - * The each value according to each scenemode is recommended in the documents. - */ -struct m5mols_scenemode { - u32 metering; - u32 ev_bias; - u32 wb_mode; - u32 wb_preset; - u32 chroma_en; - u32 chroma_lvl; - u32 edge_en; - u32 edge_lvl; - u32 af_range; - u32 fd_mode; - u32 mcc; - u32 light; - u32 flash; - u32 tone; - u32 iso; - u32 capt_mode; - u32 wdr; -}; - -/** - * struct m5mols_version - firmware version information - * @customer: customer information - * @project: version of project information according to customer - * @fw: firmware revision - * @hw: hardware revision - * @param: version of the parameter - * @awb: Auto WhiteBalance algorithm version - * @str: information about manufacturer and packaging vendor - * @af: Auto Focus version - * - * The register offset starts the customer version at 0x0, and it ends - * the awb version at 0x09. The customer, project information occupies 1 bytes - * each. And also the fw, hw, param, awb each requires 2 bytes. The str is - * unique string associated with firmware's version. It includes information - * about manufacturer and the vendor of the sensor's packaging. The least - * significant 2 bytes of the string indicate packaging manufacturer. - */ -#define VERSION_STRING_SIZE 22 -struct m5mols_version { - u8 customer; - u8 project; - u16 fw; - u16 hw; - u16 param; - u16 awb; - u8 str[VERSION_STRING_SIZE]; - u8 af; -}; -#define VERSION_SIZE sizeof(struct m5mols_version) - -/** - * struct m5mols_info - M-5MOLS driver data structure - * @pdata: platform data - * @sd: v4l-subdev instance - * @pad: media pad - * @ffmt: current fmt according to resolution type - * @res_type: current resolution type - * @code: current code - * @irq_waitq: waitqueue for the capture - * @work_irq: workqueue for the IRQ - * @flags: state variable for the interrupt handler - * @handle: control handler - * @autoexposure: Auto Exposure control - * @exposure: Exposure control - * @autowb: Auto White Balance control - * @colorfx: Color effect control - * @saturation: Saturation control - * @zoom: Zoom control - * @ver: information of the version - * @cap: the capture mode attributes - * @power: current sensor's power status - * @ctrl_sync: true means all controls of the sensor are initialized - * @int_capture: true means the capture interrupt is issued once - * @lock_ae: true means the Auto Exposure is locked - * @lock_awb: true means the Aut WhiteBalance is locked - * @resolution: register value for current resolution - * @interrupt: register value for current interrupt status - * @mode: register value for current operation mode - * @mode_save: register value for current operation mode for saving - * @set_power: optional power callback to the board code - */ -struct m5mols_info { - const struct m5mols_platform_data *pdata; - struct v4l2_subdev sd; - struct media_pad pad; - struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; - int res_type; - enum v4l2_mbus_pixelcode code; - wait_queue_head_t irq_waitq; - struct work_struct work_irq; - unsigned long flags; - - struct v4l2_ctrl_handler handle; - /* Autoexposure/exposure control cluster */ - struct { - struct v4l2_ctrl *autoexposure; - struct v4l2_ctrl *exposure; - }; - struct v4l2_ctrl *autowb; - struct v4l2_ctrl *colorfx; - struct v4l2_ctrl *saturation; - struct v4l2_ctrl *zoom; - - struct m5mols_version ver; - struct m5mols_capture cap; - bool power; - bool ctrl_sync; - bool lock_ae; - bool lock_awb; - u8 resolution; - u32 interrupt; - u32 mode; - u32 mode_save; - int (*set_power)(struct device *dev, int on); -}; - -#define ST_CAPT_IRQ 0 - -#define is_powered(__info) (__info->power) -#define is_ctrl_synced(__info) (__info->ctrl_sync) -#define is_available_af(__info) (__info->ver.af) -#define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code) -#define is_manufacturer(__info, __manufacturer) \ - (__info->ver.str[0] == __manufacturer[0] && \ - __info->ver.str[1] == __manufacturer[1]) -/* - * I2C operation of the M-5MOLS - * - * The I2C read operation of the M-5MOLS requires 2 messages. The first - * message sends the information about the command, command category, and total - * message size. The second message is used to retrieve the data specifed in - * the first message - * - * 1st message 2nd message - * +-------+---+----------+-----+-------+ +------+------+------+------+ - * | size1 | R | category | cmd | size2 | | d[0] | d[1] | d[2] | d[3] | - * +-------+---+----------+-----+-------+ +------+------+------+------+ - * - size1: message data size(5 in this case) - * - size2: desired buffer size of the 2nd message - * - d[0..3]: according to size2 - * - * The I2C write operation needs just one message. The message includes - * category, command, total size, and desired data. - * - * 1st message - * +-------+---+----------+-----+------+------+------+------+ - * | size1 | W | category | cmd | d[0] | d[1] | d[2] | d[3] | - * +-------+---+----------+-----+------+------+------+------+ - * - d[0..3]: according to size1 - */ -int m5mols_read(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); -int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); -int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value); - -/* - * Mode operation of the M-5MOLS - * - * Changing the mode of the M-5MOLS is needed right executing order. - * There are three modes(PARAMETER, MONITOR, CAPTURE) which can be changed - * by user. There are various categories associated with each mode. - * - * +============================================================+ - * | mode | category | - * +============================================================+ - * | FLASH | FLASH(only after Stand-by or Power-on) | - * | SYSTEM | SYSTEM(only after sensor arm-booting) | - * | PARAMETER | PARAMETER | - * | MONITOR | MONITOR(preview), Auto Focus, Face Detection | - * | CAPTURE | Single CAPTURE, Preview(recording) | - * +============================================================+ - * - * The available executing order between each modes are as follows: - * PARAMETER <---> MONITOR <---> CAPTURE - */ -int m5mols_mode(struct m5mols_info *info, u32 mode); - -int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg); -int m5mols_sync_controls(struct m5mols_info *info); -int m5mols_start_capture(struct m5mols_info *info); -int m5mols_do_scenemode(struct m5mols_info *info, u32 mode); -int m5mols_lock_3a(struct m5mols_info *info, bool lock); -int m5mols_set_ctrl(struct v4l2_ctrl *ctrl); - -/* The firmware function */ -int m5mols_update_fw(struct v4l2_subdev *sd, - int (*set_power)(struct m5mols_info *, bool)); - -#endif /* M5MOLS_H */ diff --git a/trunk/drivers/media/video/m5mols/m5mols_capture.c b/trunk/drivers/media/video/m5mols/m5mols_capture.c deleted file mode 100644 index d71a3903b60f..000000000000 --- a/trunk/drivers/media/video/m5mols/m5mols_capture.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * The Capture code for Fujitsu M-5MOLS ISP - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com - * - * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "m5mols.h" -#include "m5mols_reg.h" - -static int m5mols_capture_error_handler(struct m5mols_info *info, - int timeout) -{ - int ret; - - /* Disable all interrupts and clear relevant interrupt staus bits */ - ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE, - info->interrupt & ~(REG_INT_CAPTURE)); - if (ret) - return ret; - - if (timeout == 0) - return -ETIMEDOUT; - - return 0; -} -/** - * m5mols_read_rational - I2C read of a rational number - * - * Read numerator and denominator from registers @addr_num and @addr_den - * respectively and return the division result in @val. - */ -static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num, - u32 addr_den, u32 *val) -{ - u32 num, den; - - int ret = m5mols_read(sd, addr_num, &num); - if (!ret) - ret = m5mols_read(sd, addr_den, &den); - if (ret) - return ret; - *val = den == 0 ? 0 : num / den; - return ret; -} - -/** - * m5mols_capture_info - Gather captured image information - * - * For now it gathers only EXIF information and file size. - */ -static int m5mols_capture_info(struct m5mols_info *info) -{ - struct m5mols_exif *exif = &info->cap.exif; - struct v4l2_subdev *sd = &info->sd; - int ret; - - ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU, - EXIF_INFO_EXPTIME_DE, &exif->exposure_time); - if (ret) - return ret; - ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE, - &exif->shutter_speed); - if (ret) - return ret; - ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE, - &exif->aperture); - if (ret) - return ret; - ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE, - &exif->brightness); - if (ret) - return ret; - ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE, - &exif->exposure_bias); - if (ret) - return ret; - - ret = m5mols_read(sd, EXIF_INFO_ISO, (u32 *)&exif->iso_speed); - if (!ret) - ret = m5mols_read(sd, EXIF_INFO_FLASH, (u32 *)&exif->flash); - if (!ret) - ret = m5mols_read(sd, EXIF_INFO_SDR, (u32 *)&exif->sdr); - if (!ret) - ret = m5mols_read(sd, EXIF_INFO_QVAL, (u32 *)&exif->qval); - if (ret) - return ret; - - if (!ret) - ret = m5mols_read(sd, CAPC_IMAGE_SIZE, &info->cap.main); - if (!ret) - ret = m5mols_read(sd, CAPC_THUMB_SIZE, &info->cap.thumb); - if (!ret) - info->cap.total = info->cap.main + info->cap.thumb; - - return ret; -} - -int m5mols_start_capture(struct m5mols_info *info) -{ - struct v4l2_subdev *sd = &info->sd; - u32 resolution = info->resolution; - int timeout; - int ret; - - /* - * Preparing capture. Setting control & interrupt before entering - * capture mode - * - * 1) change to MONITOR mode for operating control & interrupt - * 2) set controls (considering v4l2_control value & lock 3A) - * 3) set interrupt - * 4) change to CAPTURE mode - */ - ret = m5mols_mode(info, REG_MONITOR); - if (!ret) - ret = m5mols_sync_controls(info); - if (!ret) - ret = m5mols_lock_3a(info, true); - if (!ret) - ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); - if (!ret) - ret = m5mols_mode(info, REG_CAPTURE); - if (!ret) { - /* Wait for capture interrupt, after changing capture mode */ - timeout = wait_event_interruptible_timeout(info->irq_waitq, - test_bit(ST_CAPT_IRQ, &info->flags), - msecs_to_jiffies(2000)); - if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) - ret = m5mols_capture_error_handler(info, timeout); - } - if (!ret) - ret = m5mols_lock_3a(info, false); - if (ret) - return ret; - /* - * Starting capture. Setting capture frame count and resolution and - * the format(available format: JPEG, Bayer RAW, YUV). - * - * 1) select single or multi(enable to 25), format, size - * 2) set interrupt - * 3) start capture(for main image, now) - * 4) get information - * 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device) - */ - ret = m5mols_write(sd, CAPC_SEL_FRAME, 1); - if (!ret) - ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); - if (!ret) - ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution); - if (!ret) - ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); - if (!ret) - ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN); - if (!ret) { - /* Wait for the capture completion interrupt */ - timeout = wait_event_interruptible_timeout(info->irq_waitq, - test_bit(ST_CAPT_IRQ, &info->flags), - msecs_to_jiffies(2000)); - if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) { - ret = m5mols_capture_info(info); - if (!ret) - v4l2_subdev_notify(sd, 0, &info->cap.total); - } - } - - return m5mols_capture_error_handler(info, timeout); -} diff --git a/trunk/drivers/media/video/m5mols/m5mols_controls.c b/trunk/drivers/media/video/m5mols/m5mols_controls.c deleted file mode 100644 index 817c16fec368..000000000000 --- a/trunk/drivers/media/video/m5mols/m5mols_controls.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Controls for M-5MOLS 8M Pixel camera sensor with ISP - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com - * - * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include - -#include "m5mols.h" -#include "m5mols_reg.h" - -static struct m5mols_scenemode m5mols_default_scenemode[] = { - [REG_SCENE_NORMAL] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF, - 5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_PORTRAIT] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 4, - REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_LANDSCAPE] = { - REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 4, REG_EDGE_ON, 6, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_SPORTS] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_PARTY_INDOOR] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 4, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_BEACH_SNOW] = { - REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 4, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_SUNSET] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET, - REG_AWB_DAYLIGHT, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_DAWN_DUSK] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET, - REG_AWB_FLUORESCENT_1, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_FALL] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 5, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_NIGHT] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_AGAINST_LIGHT] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_FIRE] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_TEXT] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 7, - REG_AF_MACRO, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON, - }, - [REG_SCENE_CANDLE] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, -}; - -/** - * m5mols_do_scenemode() - Change current scenemode - * @mode: Desired mode of the scenemode - * - * WARNING: The execution order is important. Do not change the order. - */ -int m5mols_do_scenemode(struct m5mols_info *info, u32 mode) -{ - struct v4l2_subdev *sd = &info->sd; - struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode]; - int ret; - - if (mode > REG_SCENE_CANDLE) - return -EINVAL; - - ret = m5mols_lock_3a(info, false); - if (!ret) - ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode); - if (!ret) - ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode); - if (!ret) - ret = m5mols_write(sd, AE_MODE, scenemode.metering); - if (!ret) - ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias); - if (!ret) - ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode); - if (!ret) - ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset); - if (!ret) - ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en); - if (!ret) - ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl); - if (!ret) - ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en); - if (!ret) - ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl); - if (!ret && is_available_af(info)) - ret = m5mols_write(sd, AF_MODE, scenemode.af_range); - if (!ret && is_available_af(info)) - ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode); - if (!ret) - ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone); - if (!ret) - ret = m5mols_write(sd, AE_ISO, scenemode.iso); - if (!ret) - ret = m5mols_mode(info, REG_CAPTURE); - if (!ret) - ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr); - if (!ret) - ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc); - if (!ret) - ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light); - if (!ret) - ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash); - if (!ret) - ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode); - if (!ret) - ret = m5mols_mode(info, REG_MONITOR); - - return ret; -} - -static int m5mols_lock_ae(struct m5mols_info *info, bool lock) -{ - int ret = 0; - - if (info->lock_ae != lock) - ret = m5mols_write(&info->sd, AE_LOCK, - lock ? REG_AE_LOCK : REG_AE_UNLOCK); - if (!ret) - info->lock_ae = lock; - - return ret; -} - -static int m5mols_lock_awb(struct m5mols_info *info, bool lock) -{ - int ret = 0; - - if (info->lock_awb != lock) - ret = m5mols_write(&info->sd, AWB_LOCK, - lock ? REG_AWB_LOCK : REG_AWB_UNLOCK); - if (!ret) - info->lock_awb = lock; - - return ret; -} - -/* m5mols_lock_3a() - Lock 3A(Auto Exposure, Auto Whitebalance, Auto Focus) */ -int m5mols_lock_3a(struct m5mols_info *info, bool lock) -{ - int ret; - - ret = m5mols_lock_ae(info, lock); - if (!ret) - ret = m5mols_lock_awb(info, lock); - /* Don't need to handle unlocking AF */ - if (!ret && is_available_af(info) && lock) - ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP); - - return ret; -} - -/* m5mols_set_ctrl() - The main s_ctrl function called by m5mols_set_ctrl() */ -int m5mols_set_ctrl(struct v4l2_ctrl *ctrl) -{ - struct v4l2_subdev *sd = to_sd(ctrl); - struct m5mols_info *info = to_m5mols(sd); - int ret; - - switch (ctrl->id) { - case V4L2_CID_ZOOM_ABSOLUTE: - return m5mols_write(sd, MON_ZOOM, ctrl->val); - - case V4L2_CID_EXPOSURE_AUTO: - ret = m5mols_lock_ae(info, - ctrl->val == V4L2_EXPOSURE_AUTO ? false : true); - if (!ret && ctrl->val == V4L2_EXPOSURE_AUTO) - ret = m5mols_write(sd, AE_MODE, REG_AE_ALL); - if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL) { - int val = info->exposure->val; - ret = m5mols_write(sd, AE_MODE, REG_AE_OFF); - if (!ret) - ret = m5mols_write(sd, AE_MAN_GAIN_MON, val); - if (!ret) - ret = m5mols_write(sd, AE_MAN_GAIN_CAP, val); - } - return ret; - - case V4L2_CID_AUTO_WHITE_BALANCE: - ret = m5mols_lock_awb(info, ctrl->val ? false : true); - if (!ret) - ret = m5mols_write(sd, AWB_MODE, ctrl->val ? - REG_AWB_AUTO : REG_AWB_PRESET); - return ret; - - case V4L2_CID_SATURATION: - ret = m5mols_write(sd, MON_CHROMA_LVL, ctrl->val); - if (!ret) - ret = m5mols_write(sd, MON_CHROMA_EN, REG_CHROMA_ON); - return ret; - - case V4L2_CID_COLORFX: - /* - * This control uses two kinds of registers: normal & color. - * The normal effect belongs to category 1, while the color - * one belongs to category 2. - * - * The normal effect uses one register: CAT1_EFFECT. - * The color effect uses three registers: - * CAT2_COLOR_EFFECT, CAT2_CFIXR, CAT2_CFIXB. - */ - ret = m5mols_write(sd, PARM_EFFECT, - ctrl->val == V4L2_COLORFX_NEGATIVE ? REG_EFFECT_NEGA : - ctrl->val == V4L2_COLORFX_EMBOSS ? REG_EFFECT_EMBOSS : - REG_EFFECT_OFF); - if (!ret) - ret = m5mols_write(sd, MON_EFFECT, - ctrl->val == V4L2_COLORFX_SEPIA ? - REG_COLOR_EFFECT_ON : REG_COLOR_EFFECT_OFF); - if (!ret) - ret = m5mols_write(sd, MON_CFIXR, - ctrl->val == V4L2_COLORFX_SEPIA ? - REG_CFIXR_SEPIA : 0); - if (!ret) - ret = m5mols_write(sd, MON_CFIXB, - ctrl->val == V4L2_COLORFX_SEPIA ? - REG_CFIXB_SEPIA : 0); - return ret; - } - - return -EINVAL; -} diff --git a/trunk/drivers/media/video/m5mols/m5mols_core.c b/trunk/drivers/media/video/m5mols/m5mols_core.c deleted file mode 100644 index 76eac26e84ae..000000000000 --- a/trunk/drivers/media/video/m5mols/m5mols_core.c +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * Driver for M-5MOLS 8M Pixel camera sensor with ISP - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com - * - * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "m5mols.h" -#include "m5mols_reg.h" - -int m5mols_debug; -module_param(m5mols_debug, int, 0644); - -#define MODULE_NAME "M5MOLS" -#define M5MOLS_I2C_CHECK_RETRY 500 - -/* The regulator consumer names for external voltage regulators */ -static struct regulator_bulk_data supplies[] = { - { - .supply = "core", /* ARM core power, 1.2V */ - }, { - .supply = "dig_18", /* digital power 1, 1.8V */ - }, { - .supply = "d_sensor", /* sensor power 1, 1.8V */ - }, { - .supply = "dig_28", /* digital power 2, 2.8V */ - }, { - .supply = "a_sensor", /* analog power */ - }, { - .supply = "dig_12", /* digital power 3, 1.2V */ - }, -}; - -static struct v4l2_mbus_framefmt m5mols_default_ffmt[M5MOLS_RESTYPE_MAX] = { - [M5MOLS_RESTYPE_MONITOR] = { - .width = 1920, - .height = 1080, - .code = V4L2_MBUS_FMT_VYUY8_2X8, - .field = V4L2_FIELD_NONE, - .colorspace = V4L2_COLORSPACE_JPEG, - }, - [M5MOLS_RESTYPE_CAPTURE] = { - .width = 1920, - .height = 1080, - .code = V4L2_MBUS_FMT_JPEG_1X8, - .field = V4L2_FIELD_NONE, - .colorspace = V4L2_COLORSPACE_JPEG, - }, -}; -#define SIZE_DEFAULT_FFMT ARRAY_SIZE(m5mols_default_ffmt) - -static const struct m5mols_resolution m5mols_reg_res[] = { - { 0x01, M5MOLS_RESTYPE_MONITOR, 128, 96 }, /* SUB-QCIF */ - { 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 }, /* QQVGA */ - { 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 }, /* QCIF */ - { 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 }, - { 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 }, /* QVGA */ - { 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 }, /* QVGA */ - { 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 }, /* WQVGA */ - { 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 }, /* WQVGA */ - { 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 }, /* CIF */ - { 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 }, - { 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 }, /* qHD */ - { 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 }, /* VGA */ - { 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 }, - { 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 }, /* WVGA */ - { 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 }, /* SVGA */ - { 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 }, /* HD */ - { 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 }, /* 1080p */ - { 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 }, /* 2.63fps 8M */ - { 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 }, /* AHS_MON debug */ - - { 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 }, /* QVGA */ - { 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 }, /* WQVGA */ - { 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 }, - { 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 }, /* qHD */ - { 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 }, /* VGA */ - { 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 }, /* WVGA */ - { 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 }, /* HD */ - { 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 }, /* 1M */ - { 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 }, /* 2M */ - { 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 }, /* Full-HD */ - { 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 }, /* 3Mega */ - { 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 }, - { 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 }, /* 4Mega */ - { 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 }, - { 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 }, /* 5Mega */ - { 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 }, /* 6Mega */ - { 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 }, - { 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 }, /* 8Mega */ -}; - -/** - * m5mols_swap_byte - an byte array to integer conversion function - * @size: size in bytes of I2C packet defined in the M-5MOLS datasheet - * - * Convert I2C data byte array with performing any required byte - * reordering to assure proper values for each data type, regardless - * of the architecture endianness. - */ -static u32 m5mols_swap_byte(u8 *data, u8 length) -{ - if (length == 1) - return *data; - else if (length == 2) - return be16_to_cpu(*((u16 *)data)); - else - return be32_to_cpu(*((u32 *)data)); -} - -/** - * m5mols_read - I2C read function - * @reg: combination of size, category and command for the I2C packet - * @val: read value - */ -int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1]; - u8 size = I2C_SIZE(reg); - u8 category = I2C_CATEGORY(reg); - u8 cmd = I2C_COMMAND(reg); - struct i2c_msg msg[2]; - u8 wbuf[5]; - int ret; - - if (!client->adapter) - return -ENODEV; - - if (size != 1 && size != 2 && size != 4) { - v4l2_err(sd, "Wrong data size\n"); - return -EINVAL; - } - - msg[0].addr = client->addr; - msg[0].flags = 0; - msg[0].len = 5; - msg[0].buf = wbuf; - wbuf[0] = 5; - wbuf[1] = M5MOLS_BYTE_READ; - wbuf[2] = category; - wbuf[3] = cmd; - wbuf[4] = size; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].len = size + 1; - msg[1].buf = rbuf; - - /* minimum stabilization time */ - usleep_range(200, 200); - - ret = i2c_transfer(client->adapter, msg, 2); - if (ret < 0) { - v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n", - size, category, cmd, ret); - return ret; - } - - *val = m5mols_swap_byte(&rbuf[1], size); - - return 0; -} - -/** - * m5mols_write - I2C command write function - * @reg: combination of size, category and command for the I2C packet - * @val: value to write - */ -int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4]; - u8 category = I2C_CATEGORY(reg); - u8 cmd = I2C_COMMAND(reg); - u8 size = I2C_SIZE(reg); - u32 *buf = (u32 *)&wbuf[4]; - struct i2c_msg msg[1]; - int ret; - - if (!client->adapter) - return -ENODEV; - - if (size != 1 && size != 2 && size != 4) { - v4l2_err(sd, "Wrong data size\n"); - return -EINVAL; - } - - msg->addr = client->addr; - msg->flags = 0; - msg->len = (u16)size + 4; - msg->buf = wbuf; - wbuf[0] = size + 4; - wbuf[1] = M5MOLS_BYTE_WRITE; - wbuf[2] = category; - wbuf[3] = cmd; - - *buf = m5mols_swap_byte((u8 *)&val, size); - - usleep_range(200, 200); - - ret = i2c_transfer(client->adapter, msg, 1); - if (ret < 0) { - v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n", - size, category, cmd, ret); - return ret; - } - - return 0; -} - -int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 mask) -{ - u32 busy, i; - int ret; - - for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { - ret = m5mols_read(sd, I2C_REG(category, cmd, 1), &busy); - if (ret < 0) - return ret; - if ((busy & mask) == mask) - return 0; - } - return -EBUSY; -} - -/** - * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts - * - * Before writing desired interrupt value the INT_FACTOR register should - * be read to clear pending interrupts. - */ -int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg) -{ - struct m5mols_info *info = to_m5mols(sd); - u32 mask = is_available_af(info) ? REG_INT_AF : 0; - u32 dummy; - int ret; - - ret = m5mols_read(sd, SYSTEM_INT_FACTOR, &dummy); - if (!ret) - ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask); - return ret; -} - -/** - * m5mols_reg_mode - Write the mode and check busy status - * - * It always accompanies a little delay changing the M-5MOLS mode, so it is - * needed checking current busy status to guarantee right mode. - */ -static int m5mols_reg_mode(struct v4l2_subdev *sd, u32 mode) -{ - int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); - - return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode); -} - -/** - * m5mols_mode - manage the M-5MOLS's mode - * @mode: the required operation mode - * - * The commands of M-5MOLS are grouped into specific modes. Each functionality - * can be guaranteed only when the sensor is operating in mode which which - * a command belongs to. - */ -int m5mols_mode(struct m5mols_info *info, u32 mode) -{ - struct v4l2_subdev *sd = &info->sd; - int ret = -EINVAL; - u32 reg; - - if (mode < REG_PARAMETER && mode > REG_CAPTURE) - return ret; - - ret = m5mols_read(sd, SYSTEM_SYSMODE, ®); - if ((!ret && reg == mode) || ret) - return ret; - - switch (reg) { - case REG_PARAMETER: - ret = m5mols_reg_mode(sd, REG_MONITOR); - if (!ret && mode == REG_MONITOR) - break; - if (!ret) - ret = m5mols_reg_mode(sd, REG_CAPTURE); - break; - - case REG_MONITOR: - if (mode == REG_PARAMETER) { - ret = m5mols_reg_mode(sd, REG_PARAMETER); - break; - } - - ret = m5mols_reg_mode(sd, REG_CAPTURE); - break; - - case REG_CAPTURE: - ret = m5mols_reg_mode(sd, REG_MONITOR); - if (!ret && mode == REG_MONITOR) - break; - if (!ret) - ret = m5mols_reg_mode(sd, REG_PARAMETER); - break; - - default: - v4l2_warn(sd, "Wrong mode: %d\n", mode); - } - - if (!ret) - info->mode = mode; - - return ret; -} - -/** - * m5mols_get_version - retrieve full revisions information of M-5MOLS - * - * The version information includes revisions of hardware and firmware, - * AutoFocus alghorithm version and the version string. - */ -static int m5mols_get_version(struct v4l2_subdev *sd) -{ - struct m5mols_info *info = to_m5mols(sd); - union { - struct m5mols_version ver; - u8 bytes[VERSION_SIZE]; - } version; - u32 *value; - u8 cmd = CAT0_VER_CUSTOMER; - int ret; - - do { - value = (u32 *)&version.bytes[cmd]; - ret = m5mols_read(sd, SYSTEM_CMD(cmd), value); - if (ret) - return ret; - } while (cmd++ != CAT0_VER_AWB); - - do { - value = (u32 *)&version.bytes[cmd]; - ret = m5mols_read(sd, SYSTEM_VER_STRING, value); - if (ret) - return ret; - if (cmd >= VERSION_SIZE - 1) - return -EINVAL; - } while (version.bytes[cmd++]); - - value = (u32 *)&version.bytes[cmd]; - ret = m5mols_read(sd, AF_VERSION, value); - if (ret) - return ret; - - /* store version information swapped for being readable */ - info->ver = version.ver; - info->ver.fw = be16_to_cpu(info->ver.fw); - info->ver.hw = be16_to_cpu(info->ver.hw); - info->ver.param = be16_to_cpu(info->ver.param); - info->ver.awb = be16_to_cpu(info->ver.awb); - - v4l2_info(sd, "Manufacturer\t[%s]\n", - is_manufacturer(info, REG_SAMSUNG_ELECTRO) ? - "Samsung Electro-Machanics" : - is_manufacturer(info, REG_SAMSUNG_OPTICS) ? - "Samsung Fiber-Optics" : - is_manufacturer(info, REG_SAMSUNG_TECHWIN) ? - "Samsung Techwin" : "None"); - v4l2_info(sd, "Customer/Project\t[0x%02x/0x%02x]\n", - info->ver.customer, info->ver.project); - - if (!is_available_af(info)) - v4l2_info(sd, "No support Auto Focus on this firmware\n"); - - return ret; -} - -/** - * __find_restype - Lookup M-5MOLS resolution type according to pixel code - * @code: pixel code - */ -static enum m5mols_restype __find_restype(enum v4l2_mbus_pixelcode code) -{ - enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR; - - do { - if (code == m5mols_default_ffmt[type].code) - return type; - } while (type++ != SIZE_DEFAULT_FFMT); - - return 0; -} - -/** - * __find_resolution - Lookup preset and type of M-5MOLS's resolution - * @mf: pixel format to find/negotiate the resolution preset for - * @type: M-5MOLS resolution type - * @resolution: M-5MOLS resolution preset register value - * - * Find nearest resolution matching resolution preset and adjust mf - * to supported values. - */ -static int __find_resolution(struct v4l2_subdev *sd, - struct v4l2_mbus_framefmt *mf, - enum m5mols_restype *type, - u32 *resolution) -{ - const struct m5mols_resolution *fsize = &m5mols_reg_res[0]; - const struct m5mols_resolution *match = NULL; - enum m5mols_restype stype = __find_restype(mf->code); - int i = ARRAY_SIZE(m5mols_reg_res); - unsigned int min_err = ~0; - - while (i--) { - int err; - if (stype == fsize->type) { - err = abs(fsize->width - mf->width) - + abs(fsize->height - mf->height); - - if (err < min_err) { - min_err = err; - match = fsize; - } - } - fsize++; - } - if (match) { - mf->width = match->width; - mf->height = match->height; - *resolution = match->reg; - *type = stype; - return 0; - } - - return -EINVAL; -} - -static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info, - struct v4l2_subdev_fh *fh, - enum v4l2_subdev_format_whence which, - enum m5mols_restype type) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL; - - return &info->ffmt[type]; -} - -static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, - struct v4l2_subdev_format *fmt) -{ - struct m5mols_info *info = to_m5mols(sd); - struct v4l2_mbus_framefmt *format; - - if (fmt->pad != 0) - return -EINVAL; - - format = __find_format(info, fh, fmt->which, info->res_type); - if (!format) - return -EINVAL; - - fmt->format = *format; - return 0; -} - -static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, - struct v4l2_subdev_format *fmt) -{ - struct m5mols_info *info = to_m5mols(sd); - struct v4l2_mbus_framefmt *format = &fmt->format; - struct v4l2_mbus_framefmt *sfmt; - enum m5mols_restype type; - u32 resolution = 0; - int ret; - - if (fmt->pad != 0) - return -EINVAL; - - ret = __find_resolution(sd, format, &type, &resolution); - if (ret < 0) - return ret; - - sfmt = __find_format(info, fh, fmt->which, type); - if (!sfmt) - return 0; - - *sfmt = m5mols_default_ffmt[type]; - sfmt->width = format->width; - sfmt->height = format->height; - - if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - info->resolution = resolution; - info->code = format->code; - info->res_type = type; - } - - return 0; -} - -static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_mbus_code_enum *code) -{ - if (!code || code->index >= SIZE_DEFAULT_FFMT) - return -EINVAL; - - code->code = m5mols_default_ffmt[code->index].code; - - return 0; -} - -static struct v4l2_subdev_pad_ops m5mols_pad_ops = { - .enum_mbus_code = m5mols_enum_mbus_code, - .get_fmt = m5mols_get_fmt, - .set_fmt = m5mols_set_fmt, -}; - -/** - * m5mols_sync_controls - Apply default scene mode and the current controls - * - * This is used only streaming for syncing between v4l2_ctrl framework and - * m5mols's controls. First, do the scenemode to the sensor, then call - * v4l2_ctrl_handler_setup. It can be same between some commands and - * the scenemode's in the default v4l2_ctrls. But, such commands of control - * should be prior to the scenemode's one. - */ -int m5mols_sync_controls(struct m5mols_info *info) -{ - int ret = -EINVAL; - - if (!is_ctrl_synced(info)) { - ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL); - if (ret) - return ret; - - v4l2_ctrl_handler_setup(&info->handle); - info->ctrl_sync = true; - } - - return ret; -} - -/** - * m5mols_start_monitor - Start the monitor mode - * - * Before applying the controls setup the resolution and frame rate - * in PARAMETER mode, and then switch over to MONITOR mode. - */ -static int m5mols_start_monitor(struct m5mols_info *info) -{ - struct v4l2_subdev *sd = &info->sd; - int ret; - - ret = m5mols_mode(info, REG_PARAMETER); - if (!ret) - ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution); - if (!ret) - ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30); - if (!ret) - ret = m5mols_mode(info, REG_MONITOR); - if (!ret) - ret = m5mols_sync_controls(info); - - return ret; -} - -static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) -{ - struct m5mols_info *info = to_m5mols(sd); - - if (enable) { - int ret = -EINVAL; - - if (is_code(info->code, M5MOLS_RESTYPE_MONITOR)) - ret = m5mols_start_monitor(info); - if (is_code(info->code, M5MOLS_RESTYPE_CAPTURE)) - ret = m5mols_start_capture(info); - - return ret; - } - - return m5mols_mode(info, REG_PARAMETER); -} - -static const struct v4l2_subdev_video_ops m5mols_video_ops = { - .s_stream = m5mols_s_stream, -}; - -static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct v4l2_subdev *sd = to_sd(ctrl); - struct m5mols_info *info = to_m5mols(sd); - int ret; - - info->mode_save = info->mode; - - ret = m5mols_mode(info, REG_PARAMETER); - if (!ret) - ret = m5mols_set_ctrl(ctrl); - if (!ret) - ret = m5mols_mode(info, info->mode_save); - - return ret; -} - -static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { - .s_ctrl = m5mols_s_ctrl, -}; - -static int m5mols_sensor_power(struct m5mols_info *info, bool enable) -{ - struct v4l2_subdev *sd = &info->sd; - struct i2c_client *client = v4l2_get_subdevdata(sd); - const struct m5mols_platform_data *pdata = info->pdata; - int ret; - - if (enable) { - if (is_powered(info)) - return 0; - - if (info->set_power) { - ret = info->set_power(&client->dev, 1); - if (ret) - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies); - if (ret) { - info->set_power(&client->dev, 0); - return ret; - } - - gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity); - usleep_range(1000, 1000); - info->power = true; - - return ret; - } - - if (!is_powered(info)) - return 0; - - ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); - if (ret) - return ret; - - if (info->set_power) - info->set_power(&client->dev, 0); - - gpio_set_value(pdata->gpio_reset, pdata->reset_polarity); - usleep_range(1000, 1000); - info->power = false; - - return ret; -} - -/* m5mols_update_fw - optional firmware update routine */ -int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd, - int (*set_power)(struct m5mols_info *, bool)) -{ - return 0; -} - -/** - * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core. - * - * Booting internal ARM core makes the M-5MOLS is ready for getting commands - * with I2C. It's the first thing to be done after it powered up. It must wait - * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting. - */ -static int m5mols_sensor_armboot(struct v4l2_subdev *sd) -{ - int ret; - - ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT); - if (ret < 0) - return ret; - - msleep(520); - - ret = m5mols_get_version(sd); - if (!ret) - ret = m5mols_update_fw(sd, m5mols_sensor_power); - if (ret) - return ret; - - v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n"); - - ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI); - if (!ret) - ret = m5mols_enable_interrupt(sd, REG_INT_AF); - - return ret; -} - -static int m5mols_init_controls(struct m5mols_info *info) -{ - struct v4l2_subdev *sd = &info->sd; - u16 max_exposure; - u16 step_zoom; - int ret; - - /* Determine value's range & step of controls for various FW version */ - ret = m5mols_read(sd, AE_MAX_GAIN_MON, (u32 *)&max_exposure); - if (!ret) - step_zoom = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1; - if (ret) - return ret; - - v4l2_ctrl_handler_init(&info->handle, 6); - info->autowb = v4l2_ctrl_new_std(&info->handle, - &m5mols_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE, - 0, 1, 1, 0); - info->saturation = v4l2_ctrl_new_std(&info->handle, - &m5mols_ctrl_ops, V4L2_CID_SATURATION, - 1, 5, 1, 3); - info->zoom = v4l2_ctrl_new_std(&info->handle, - &m5mols_ctrl_ops, V4L2_CID_ZOOM_ABSOLUTE, - 1, 70, step_zoom, 1); - info->exposure = v4l2_ctrl_new_std(&info->handle, - &m5mols_ctrl_ops, V4L2_CID_EXPOSURE, - 0, max_exposure, 1, (int)max_exposure/2); - info->colorfx = v4l2_ctrl_new_std_menu(&info->handle, - &m5mols_ctrl_ops, V4L2_CID_COLORFX, - 4, (1 << V4L2_COLORFX_BW), V4L2_COLORFX_NONE); - info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle, - &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, - 1, 0, V4L2_EXPOSURE_MANUAL); - - sd->ctrl_handler = &info->handle; - if (info->handle.error) { - v4l2_err(sd, "Failed to initialize controls: %d\n", ret); - v4l2_ctrl_handler_free(&info->handle); - return info->handle.error; - } - - v4l2_ctrl_cluster(2, &info->autoexposure); - - return 0; -} - -/** - * m5mols_s_power - Main sensor power control function - * - * To prevent breaking the lens when the sensor is powered off the Soft-Landing - * algorithm is called where available. The Soft-Landing algorithm availability - * dependends on the firmware provider. - */ -static int m5mols_s_power(struct v4l2_subdev *sd, int on) -{ - struct m5mols_info *info = to_m5mols(sd); - int ret; - - if (on) { - ret = m5mols_sensor_power(info, true); - if (!ret) - ret = m5mols_sensor_armboot(sd); - if (!ret) - ret = m5mols_init_controls(info); - if (ret) - return ret; - - info->ffmt[M5MOLS_RESTYPE_MONITOR] = - m5mols_default_ffmt[M5MOLS_RESTYPE_MONITOR]; - info->ffmt[M5MOLS_RESTYPE_CAPTURE] = - m5mols_default_ffmt[M5MOLS_RESTYPE_CAPTURE]; - return ret; - } - - if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { - ret = m5mols_mode(info, REG_MONITOR); - if (!ret) - ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP); - if (!ret) - ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); - if (!ret) - ret = m5mols_busy(sd, CAT_SYSTEM, CAT0_STATUS, - REG_AF_IDLE); - if (!ret) - v4l2_info(sd, "Success soft-landing lens\n"); - } - - ret = m5mols_sensor_power(info, false); - if (!ret) { - v4l2_ctrl_handler_free(&info->handle); - info->ctrl_sync = false; - } - - return ret; -} - -static int m5mols_log_status(struct v4l2_subdev *sd) -{ - struct m5mols_info *info = to_m5mols(sd); - - v4l2_ctrl_handler_log_status(&info->handle, sd->name); - - return 0; -} - -static const struct v4l2_subdev_core_ops m5mols_core_ops = { - .s_power = m5mols_s_power, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .log_status = m5mols_log_status, -}; - -static const struct v4l2_subdev_ops m5mols_ops = { - .core = &m5mols_core_ops, - .pad = &m5mols_pad_ops, - .video = &m5mols_video_ops, -}; - -static void m5mols_irq_work(struct work_struct *work) -{ - struct m5mols_info *info = - container_of(work, struct m5mols_info, work_irq); - struct v4l2_subdev *sd = &info->sd; - u32 reg; - int ret; - - if (!is_powered(info) || - m5mols_read(sd, SYSTEM_INT_FACTOR, &info->interrupt)) - return; - - switch (info->interrupt & REG_INT_MASK) { - case REG_INT_AF: - if (!is_available_af(info)) - break; - ret = m5mols_read(sd, AF_STATUS, ®); - v4l2_dbg(2, m5mols_debug, sd, "AF %s\n", - reg == REG_AF_FAIL ? "Failed" : - reg == REG_AF_SUCCESS ? "Success" : - reg == REG_AF_IDLE ? "Idle" : "Busy"); - break; - case REG_INT_CAPTURE: - if (!test_and_set_bit(ST_CAPT_IRQ, &info->flags)) - wake_up_interruptible(&info->irq_waitq); - - v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n"); - break; - default: - v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg); - break; - }; -} - -static irqreturn_t m5mols_irq_handler(int irq, void *data) -{ - struct v4l2_subdev *sd = data; - struct m5mols_info *info = to_m5mols(sd); - - schedule_work(&info->work_irq); - - return IRQ_HANDLED; -} - -static int __devinit m5mols_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - const struct m5mols_platform_data *pdata = client->dev.platform_data; - struct m5mols_info *info; - struct v4l2_subdev *sd; - int ret; - - if (pdata == NULL) { - dev_err(&client->dev, "No platform data\n"); - return -EINVAL; - } - - if (!gpio_is_valid(pdata->gpio_reset)) { - dev_err(&client->dev, "No valid RESET GPIO specified\n"); - return -EINVAL; - } - - if (!pdata->irq) { - dev_err(&client->dev, "Interrupt not assigned\n"); - return -EINVAL; - } - - info = kzalloc(sizeof(struct m5mols_info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->pdata = pdata; - info->set_power = pdata->set_power; - - ret = gpio_request(pdata->gpio_reset, "M5MOLS_NRST"); - if (ret) { - dev_err(&client->dev, "Failed to request gpio: %d\n", ret); - goto out_free; - } - gpio_direction_output(pdata->gpio_reset, pdata->reset_polarity); - - ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies); - if (ret) { - dev_err(&client->dev, "Failed to get regulators: %d\n", ret); - goto out_gpio; - } - - sd = &info->sd; - strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); - v4l2_i2c_subdev_init(sd, client, &m5mols_ops); - - info->pad.flags = MEDIA_PAD_FL_SOURCE; - ret = media_entity_init(&sd->entity, 1, &info->pad, 0); - if (ret < 0) - goto out_reg; - sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; - - init_waitqueue_head(&info->irq_waitq); - INIT_WORK(&info->work_irq, m5mols_irq_work); - ret = request_irq(pdata->irq, m5mols_irq_handler, - IRQF_TRIGGER_RISING, MODULE_NAME, sd); - if (ret) { - dev_err(&client->dev, "Interrupt request failed: %d\n", ret); - goto out_me; - } - info->res_type = M5MOLS_RESTYPE_MONITOR; - return 0; -out_me: - media_entity_cleanup(&sd->entity); -out_reg: - regulator_bulk_free(ARRAY_SIZE(supplies), supplies); -out_gpio: - gpio_free(pdata->gpio_reset); -out_free: - kfree(info); - return ret; -} - -static int __devexit m5mols_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct m5mols_info *info = to_m5mols(sd); - - v4l2_device_unregister_subdev(sd); - free_irq(info->pdata->irq, sd); - - regulator_bulk_free(ARRAY_SIZE(supplies), supplies); - gpio_free(info->pdata->gpio_reset); - media_entity_cleanup(&sd->entity); - kfree(info); - return 0; -} - -static const struct i2c_device_id m5mols_id[] = { - { MODULE_NAME, 0 }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, m5mols_id); - -static struct i2c_driver m5mols_i2c_driver = { - .driver = { - .name = MODULE_NAME, - }, - .probe = m5mols_probe, - .remove = __devexit_p(m5mols_remove), - .id_table = m5mols_id, -}; - -static int __init m5mols_mod_init(void) -{ - return i2c_add_driver(&m5mols_i2c_driver); -} - -static void __exit m5mols_mod_exit(void) -{ - i2c_del_driver(&m5mols_i2c_driver); -} - -module_init(m5mols_mod_init); -module_exit(m5mols_mod_exit); - -MODULE_AUTHOR("HeungJun Kim "); -MODULE_AUTHOR("Dongsoo Kim "); -MODULE_DESCRIPTION("Fujitsu M-5MOLS 8M Pixel camera driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/media/video/m5mols/m5mols_reg.h b/trunk/drivers/media/video/m5mols/m5mols_reg.h deleted file mode 100644 index b83e36fc6ac6..000000000000 --- a/trunk/drivers/media/video/m5mols/m5mols_reg.h +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Register map for M-5MOLS 8M Pixel camera sensor with ISP - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com - * - * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef M5MOLS_REG_H -#define M5MOLS_REG_H - -#define M5MOLS_I2C_MAX_SIZE 4 -#define M5MOLS_BYTE_READ 0x01 -#define M5MOLS_BYTE_WRITE 0x02 - -#define I2C_CATEGORY(__cat) ((__cat >> 16) & 0xff) -#define I2C_COMMAND(__comm) ((__comm >> 8) & 0xff) -#define I2C_SIZE(__reg_s) ((__reg_s) & 0xff) -#define I2C_REG(__cat, __cmd, __reg_s) ((__cat << 16) | (__cmd << 8) | __reg_s) - -/* - * Category section register - * - * The category means set including relevant command of M-5MOLS. - */ -#define CAT_SYSTEM 0x00 -#define CAT_PARAM 0x01 -#define CAT_MONITOR 0x02 -#define CAT_AE 0x03 -#define CAT_WB 0x06 -#define CAT_EXIF 0x07 -#define CAT_FD 0x09 -#define CAT_LENS 0x0a -#define CAT_CAPT_PARM 0x0b -#define CAT_CAPT_CTRL 0x0c -#define CAT_FLASH 0x0f /* related to FW, revisions, booting */ - -/* - * Category 0 - SYSTEM mode - * - * The SYSTEM mode in the M-5MOLS means area available to handle with the whole - * & all-round system of sensor. It deals with version/interrupt/setting mode & - * even sensor's status. Especially, the M-5MOLS sensor with ISP varies by - * packaging & manufacturer, even the customer and project code. And the - * function details may vary among them. The version information helps to - * determine what methods shall be used in the driver. - * - * There is many registers between customer version address and awb one. For - * more specific contents, see definition if file m5mols.h. - */ -#define CAT0_VER_CUSTOMER 0x00 /* customer version */ -#define CAT0_VER_AWB 0x09 /* Auto WB version */ -#define CAT0_VER_STRING 0x0a /* string including M-5MOLS */ -#define CAT0_SYSMODE 0x0b /* SYSTEM mode register */ -#define CAT0_STATUS 0x0c /* SYSTEM mode status register */ -#define CAT0_INT_FACTOR 0x10 /* interrupt pending register */ -#define CAT0_INT_ENABLE 0x11 /* interrupt enable register */ - -#define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1) -#define REG_SYSINIT 0x00 /* SYSTEM mode */ -#define REG_PARAMETER 0x01 /* PARAMETER mode */ -#define REG_MONITOR 0x02 /* MONITOR mode */ -#define REG_CAPTURE 0x03 /* CAPTURE mode */ - -#define SYSTEM_CMD(__cmd) I2C_REG(CAT_SYSTEM, cmd, 1) -#define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, CAT0_VER_STRING, 1) -#define REG_SAMSUNG_ELECTRO "SE" /* Samsung Electro-Mechanics */ -#define REG_SAMSUNG_OPTICS "OP" /* Samsung Fiber-Optics */ -#define REG_SAMSUNG_TECHWIN "TB" /* Samsung Techwin */ - -#define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, CAT0_INT_FACTOR, 1) -#define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, CAT0_INT_ENABLE, 1) -#define REG_INT_MODE (1 << 0) -#define REG_INT_AF (1 << 1) -#define REG_INT_ZOOM (1 << 2) -#define REG_INT_CAPTURE (1 << 3) -#define REG_INT_FRAMESYNC (1 << 4) -#define REG_INT_FD (1 << 5) -#define REG_INT_LENS_INIT (1 << 6) -#define REG_INT_SOUND (1 << 7) -#define REG_INT_MASK 0x0f - -/* - * category 1 - PARAMETER mode - * - * This category supports function of camera features of M-5MOLS. It means we - * can handle with preview(MONITOR) resolution size/frame per second/interface - * between the sensor and the Application Processor/even the image effect. - */ -#define CAT1_DATA_INTERFACE 0x00 /* interface between sensor and AP */ -#define CAT1_MONITOR_SIZE 0x01 /* resolution at the MONITOR mode */ -#define CAT1_MONITOR_FPS 0x02 /* frame per second at this mode */ -#define CAT1_EFFECT 0x0b /* image effects */ - -#define PARM_MON_SIZE I2C_REG(CAT_PARAM, CAT1_MONITOR_SIZE, 1) - -#define PARM_MON_FPS I2C_REG(CAT_PARAM, CAT1_MONITOR_FPS, 1) -#define REG_FPS_30 0x02 - -#define PARM_INTERFACE I2C_REG(CAT_PARAM, CAT1_DATA_INTERFACE, 1) -#define REG_INTERFACE_MIPI 0x02 - -#define PARM_EFFECT I2C_REG(CAT_PARAM, CAT1_EFFECT, 1) -#define REG_EFFECT_OFF 0x00 -#define REG_EFFECT_NEGA 0x01 -#define REG_EFFECT_EMBOSS 0x06 -#define REG_EFFECT_OUTLINE 0x07 -#define REG_EFFECT_WATERCOLOR 0x08 - -/* - * Category 2 - MONITOR mode - * - * The MONITOR mode is same as preview mode as we said. The M-5MOLS has another - * mode named "Preview", but this preview mode is used at the case specific - * vider-recording mode. This mmode supports only YUYV format. On the other - * hand, the JPEG & RAW formats is supports by CAPTURE mode. And, there are - * another options like zoom/color effect(different with effect in PARAMETER - * mode)/anti hand shaking algorithm. - */ -#define CAT2_ZOOM 0x01 /* set the zoom position & execute */ -#define CAT2_ZOOM_STEP 0x03 /* set the zoom step */ -#define CAT2_CFIXB 0x09 /* CB value for color effect */ -#define CAT2_CFIXR 0x0a /* CR value for color effect */ -#define CAT2_COLOR_EFFECT 0x0b /* set on/off of color effect */ -#define CAT2_CHROMA_LVL 0x0f /* set chroma level */ -#define CAT2_CHROMA_EN 0x10 /* set on/off of choroma */ -#define CAT2_EDGE_LVL 0x11 /* set sharpness level */ -#define CAT2_EDGE_EN 0x12 /* set on/off sharpness */ -#define CAT2_TONE_CTL 0x25 /* set tone color(contrast) */ - -#define MON_ZOOM I2C_REG(CAT_MONITOR, CAT2_ZOOM, 1) - -#define MON_CFIXR I2C_REG(CAT_MONITOR, CAT2_CFIXR, 1) -#define MON_CFIXB I2C_REG(CAT_MONITOR, CAT2_CFIXB, 1) -#define REG_CFIXB_SEPIA 0xd8 -#define REG_CFIXR_SEPIA 0x18 - -#define MON_EFFECT I2C_REG(CAT_MONITOR, CAT2_COLOR_EFFECT, 1) -#define REG_COLOR_EFFECT_OFF 0x00 -#define REG_COLOR_EFFECT_ON 0x01 - -#define MON_CHROMA_EN I2C_REG(CAT_MONITOR, CAT2_CHROMA_EN, 1) -#define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, CAT2_CHROMA_LVL, 1) -#define REG_CHROMA_OFF 0x00 -#define REG_CHROMA_ON 0x01 - -#define MON_EDGE_EN I2C_REG(CAT_MONITOR, CAT2_EDGE_EN, 1) -#define MON_EDGE_LVL I2C_REG(CAT_MONITOR, CAT2_EDGE_LVL, 1) -#define REG_EDGE_OFF 0x00 -#define REG_EDGE_ON 0x01 - -#define MON_TONE_CTL I2C_REG(CAT_MONITOR, CAT2_TONE_CTL, 1) - -/* - * Category 3 - Auto Exposure - * - * The M-5MOLS exposure capbility is detailed as which is similar to digital - * camera. This category supports AE locking/various AE mode(range of exposure) - * /ISO/flickering/EV bias/shutter/meteoring, and anything else. And the - * maximum/minimum exposure gain value depending on M-5MOLS firmware, may be - * different. So, this category also provide getting the max/min values. And, - * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values. - */ -#define CAT3_AE_LOCK 0x00 /* locking Auto exposure */ -#define CAT3_AE_MODE 0x01 /* set AE mode, mode means range */ -#define CAT3_ISO 0x05 /* set ISO */ -#define CAT3_EV_PRESET_MONITOR 0x0a /* EV(scenemode) preset for MONITOR */ -#define CAT3_EV_PRESET_CAPTURE 0x0b /* EV(scenemode) preset for CAPTURE */ -#define CAT3_MANUAL_GAIN_MON 0x12 /* meteoring value for the MONITOR */ -#define CAT3_MAX_GAIN_MON 0x1a /* max gain value for the MONITOR */ -#define CAT3_MANUAL_GAIN_CAP 0x26 /* meteoring value for the CAPTURE */ -#define CAT3_AE_INDEX 0x38 /* AE index */ - -#define AE_LOCK I2C_REG(CAT_AE, CAT3_AE_LOCK, 1) -#define REG_AE_UNLOCK 0x00 -#define REG_AE_LOCK 0x01 - -#define AE_MODE I2C_REG(CAT_AE, CAT3_AE_MODE, 1) -#define REG_AE_OFF 0x00 /* AE off */ -#define REG_AE_ALL 0x01 /* calc AE in all block integral */ -#define REG_AE_CENTER 0x03 /* calc AE in center weighted */ -#define REG_AE_SPOT 0x06 /* calc AE in specific spot */ - -#define AE_ISO I2C_REG(CAT_AE, CAT3_ISO, 1) -#define REG_ISO_AUTO 0x00 -#define REG_ISO_50 0x01 -#define REG_ISO_100 0x02 -#define REG_ISO_200 0x03 -#define REG_ISO_400 0x04 -#define REG_ISO_800 0x05 - -#define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, CAT3_EV_PRESET_MONITOR, 1) -#define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, CAT3_EV_PRESET_CAPTURE, 1) -#define REG_SCENE_NORMAL 0x00 -#define REG_SCENE_PORTRAIT 0x01 -#define REG_SCENE_LANDSCAPE 0x02 -#define REG_SCENE_SPORTS 0x03 -#define REG_SCENE_PARTY_INDOOR 0x04 -#define REG_SCENE_BEACH_SNOW 0x05 -#define REG_SCENE_SUNSET 0x06 -#define REG_SCENE_DAWN_DUSK 0x07 -#define REG_SCENE_FALL 0x08 -#define REG_SCENE_NIGHT 0x09 -#define REG_SCENE_AGAINST_LIGHT 0x0a -#define REG_SCENE_FIRE 0x0b -#define REG_SCENE_TEXT 0x0c -#define REG_SCENE_CANDLE 0x0d - -#define AE_MAN_GAIN_MON I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_MON, 2) -#define AE_MAX_GAIN_MON I2C_REG(CAT_AE, CAT3_MAX_GAIN_MON, 2) -#define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_CAP, 2) - -#define AE_INDEX I2C_REG(CAT_AE, CAT3_AE_INDEX, 1) -#define REG_AE_INDEX_20_NEG 0x00 -#define REG_AE_INDEX_15_NEG 0x01 -#define REG_AE_INDEX_10_NEG 0x02 -#define REG_AE_INDEX_05_NEG 0x03 -#define REG_AE_INDEX_00 0x04 -#define REG_AE_INDEX_05_POS 0x05 -#define REG_AE_INDEX_10_POS 0x06 -#define REG_AE_INDEX_15_POS 0x07 -#define REG_AE_INDEX_20_POS 0x08 - -/* - * Category 6 - White Balance - * - * This category provide AWB locking/mode/preset/speed/gain bias, etc. - */ -#define CAT6_AWB_LOCK 0x00 /* locking Auto Whitebalance */ -#define CAT6_AWB_MODE 0x02 /* set Auto or Manual */ -#define CAT6_AWB_MANUAL 0x03 /* set Manual(preset) value */ - -#define AWB_LOCK I2C_REG(CAT_WB, CAT6_AWB_LOCK, 1) -#define REG_AWB_UNLOCK 0x00 -#define REG_AWB_LOCK 0x01 - -#define AWB_MODE I2C_REG(CAT_WB, CAT6_AWB_MODE, 1) -#define REG_AWB_AUTO 0x01 /* AWB off */ -#define REG_AWB_PRESET 0x02 /* AWB preset */ - -#define AWB_MANUAL I2C_REG(CAT_WB, CAT6_AWB_MANUAL, 1) -#define REG_AWB_INCANDESCENT 0x01 -#define REG_AWB_FLUORESCENT_1 0x02 -#define REG_AWB_FLUORESCENT_2 0x03 -#define REG_AWB_DAYLIGHT 0x04 -#define REG_AWB_CLOUDY 0x05 -#define REG_AWB_SHADE 0x06 -#define REG_AWB_HORIZON 0x07 -#define REG_AWB_LEDLIGHT 0x09 - -/* - * Category 7 - EXIF information - */ -#define CAT7_INFO_EXPTIME_NU 0x00 -#define CAT7_INFO_EXPTIME_DE 0x04 -#define CAT7_INFO_TV_NU 0x08 -#define CAT7_INFO_TV_DE 0x0c -#define CAT7_INFO_AV_NU 0x10 -#define CAT7_INFO_AV_DE 0x14 -#define CAT7_INFO_BV_NU 0x18 -#define CAT7_INFO_BV_DE 0x1c -#define CAT7_INFO_EBV_NU 0x20 -#define CAT7_INFO_EBV_DE 0x24 -#define CAT7_INFO_ISO 0x28 -#define CAT7_INFO_FLASH 0x2a -#define CAT7_INFO_SDR 0x2c -#define CAT7_INFO_QVAL 0x2e - -#define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_NU, 4) -#define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_DE, 4) -#define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, CAT7_INFO_TV_NU, 4) -#define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, CAT7_INFO_TV_DE, 4) -#define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, CAT7_INFO_AV_NU, 4) -#define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, CAT7_INFO_AV_DE, 4) -#define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, CAT7_INFO_BV_NU, 4) -#define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, CAT7_INFO_BV_DE, 4) -#define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, CAT7_INFO_EBV_NU, 4) -#define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, CAT7_INFO_EBV_DE, 4) -#define EXIF_INFO_ISO I2C_REG(CAT_EXIF, CAT7_INFO_ISO, 2) -#define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, CAT7_INFO_FLASH, 2) -#define EXIF_INFO_SDR I2C_REG(CAT_EXIF, CAT7_INFO_SDR, 2) -#define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, CAT7_INFO_QVAL, 2) - -/* - * Category 9 - Face Detection - */ -#define CAT9_FD_CTL 0x00 - -#define FD_CTL I2C_REG(CAT_FD, CAT9_FD_CTL, 1) -#define BIT_FD_EN 0 -#define BIT_FD_DRAW_FACE_FRAME 4 -#define BIT_FD_DRAW_SMILE_LVL 6 -#define REG_FD(shift) (1 << shift) -#define REG_FD_OFF 0x0 - -/* - * Category A - Lens Parameter - */ -#define CATA_AF_MODE 0x01 -#define CATA_AF_EXECUTE 0x02 -#define CATA_AF_STATUS 0x03 -#define CATA_AF_VERSION 0x0a - -#define AF_MODE I2C_REG(CAT_LENS, CATA_AF_MODE, 1) -#define REG_AF_NORMAL 0x00 /* Normal AF, one time */ -#define REG_AF_MACRO 0x01 /* Macro AF, one time */ -#define REG_AF_POWEROFF 0x07 - -#define AF_EXECUTE I2C_REG(CAT_LENS, CATA_AF_EXECUTE, 1) -#define REG_AF_STOP 0x00 -#define REG_AF_EXE_AUTO 0x01 -#define REG_AF_EXE_CAF 0x02 - -#define AF_STATUS I2C_REG(CAT_LENS, CATA_AF_STATUS, 1) -#define REG_AF_FAIL 0x00 -#define REG_AF_SUCCESS 0x02 -#define REG_AF_IDLE 0x04 -#define REG_AF_BUSY 0x05 - -#define AF_VERSION I2C_REG(CAT_LENS, CATA_AF_VERSION, 1) - -/* - * Category B - CAPTURE Parameter - */ -#define CATB_YUVOUT_MAIN 0x00 -#define CATB_MAIN_IMAGE_SIZE 0x01 -#define CATB_MCC_MODE 0x1d -#define CATB_WDR_EN 0x2c -#define CATB_LIGHT_CTRL 0x40 -#define CATB_FLASH_CTRL 0x41 - -#define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, CATB_YUVOUT_MAIN, 1) -#define REG_YUV422 0x00 -#define REG_BAYER10 0x05 -#define REG_BAYER8 0x06 -#define REG_JPEG 0x10 - -#define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, CATB_MAIN_IMAGE_SIZE, 1) - -#define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, CATB_MCC_MODE, 1) -#define REG_MCC_OFF 0x00 -#define REG_MCC_NORMAL 0x01 - -#define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, CATB_WDR_EN, 1) -#define REG_WDR_OFF 0x00 -#define REG_WDR_ON 0x01 -#define REG_WDR_AUTO 0x02 - -#define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, CATB_LIGHT_CTRL, 1) -#define REG_LIGHT_OFF 0x00 -#define REG_LIGHT_ON 0x01 -#define REG_LIGHT_AUTO 0x02 - -#define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, CATB_FLASH_CTRL, 1) -#define REG_FLASH_OFF 0x00 -#define REG_FLASH_ON 0x01 -#define REG_FLASH_AUTO 0x02 - -/* - * Category C - CAPTURE Control - */ -#define CATC_CAP_MODE 0x00 -#define CATC_CAP_SEL_FRAME 0x06 /* It determines Single or Multi */ -#define CATC_CAP_START 0x09 -#define CATC_CAP_IMAGE_SIZE 0x0d -#define CATC_CAP_THUMB_SIZE 0x11 - -#define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_MODE, 1) -#define REG_CAP_NONE 0x00 -#define REG_CAP_ANTI_SHAKE 0x02 - -#define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, CATC_CAP_SEL_FRAME, 1) - -#define CAPC_START I2C_REG(CAT_CAPT_CTRL, CATC_CAP_START, 1) -#define REG_CAP_START_MAIN 0x01 -#define REG_CAP_START_THUMB 0x03 - -#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 1) -#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 1) - -/* - * Category F - Flash - * - * This mode provides functions about internal flash stuff and system startup. - */ -#define CATF_CAM_START 0x12 /* It starts internal ARM core booting - * after power-up */ - -#define FLASH_CAM_START I2C_REG(CAT_FLASH, CATF_CAM_START, 1) -#define REG_START_ARM_BOOT 0x01 - -#endif /* M5MOLS_REG_H */ diff --git a/trunk/drivers/media/video/timblogiw.c b/trunk/drivers/media/video/timblogiw.c index fc611ebeb82c..84d4c7c83435 100644 --- a/trunk/drivers/media/video/timblogiw.c +++ b/trunk/drivers/media/video/timblogiw.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -790,7 +791,7 @@ static int __devinit timblogiw_probe(struct platform_device *pdev) { int err; struct timblogiw *lw = NULL; - struct timb_video_platform_data *pdata = pdev->dev.platform_data; + struct timb_video_platform_data *pdata = mfd_get_data(pdev); if (!pdata) { dev_err(&pdev->dev, "No platform data\n"); diff --git a/trunk/drivers/media/video/uvc/Makefile b/trunk/drivers/media/video/uvc/Makefile index 2071ca8a2f03..968c1994eda0 100644 --- a/trunk/drivers/media/video/uvc/Makefile +++ b/trunk/drivers/media/video/uvc/Makefile @@ -1,6 +1,3 @@ uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ uvc_status.o uvc_isight.o -ifeq ($(CONFIG_MEDIA_CONTROLLER),y) -uvcvideo-objs += uvc_entity.o -endif obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o diff --git a/trunk/drivers/media/video/uvc/uvc_driver.c b/trunk/drivers/media/video/uvc/uvc_driver.c index b6eae48d7fb8..823f4b389745 100644 --- a/trunk/drivers/media/video/uvc/uvc_driver.c +++ b/trunk/drivers/media/video/uvc/uvc_driver.c @@ -248,7 +248,7 @@ uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator) * Terminal and unit management */ -struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) +static struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) { struct uvc_entity *entity; @@ -795,12 +795,9 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, struct uvc_entity *entity; unsigned int num_inputs; unsigned int size; - unsigned int i; - extra_size = ALIGN(extra_size, sizeof(*entity->pads)); num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; - size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads - + num_inputs; + size = sizeof(*entity) + extra_size + num_inputs; entity = kzalloc(size, GFP_KERNEL); if (entity == NULL) return NULL; @@ -808,17 +805,8 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, entity->id = id; entity->type = type; - entity->num_links = 0; - entity->num_pads = num_pads; - entity->pads = ((void *)(entity + 1)) + extra_size; - - for (i = 0; i < num_inputs; ++i) - entity->pads[i].flags = MEDIA_PAD_FL_SINK; - if (!UVC_ENTITY_IS_OTERM(entity)) - entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE; - entity->bNrInPins = num_inputs; - entity->baSourceID = (__u8 *)(&entity->pads[num_pads]); + entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size; return entity; } @@ -1597,13 +1585,6 @@ static void uvc_delete(struct uvc_device *dev) uvc_status_cleanup(dev); uvc_ctrl_cleanup_device(dev); - if (dev->vdev.dev) - v4l2_device_unregister(&dev->vdev); -#ifdef CONFIG_MEDIA_CONTROLLER - if (media_devnode_is_registered(&dev->mdev.devnode)) - media_device_unregister(&dev->mdev); -#endif - list_for_each_safe(p, n, &dev->chains) { struct uvc_video_chain *chain; chain = list_entry(p, struct uvc_video_chain, list); @@ -1613,13 +1594,6 @@ static void uvc_delete(struct uvc_device *dev) list_for_each_safe(p, n, &dev->entities) { struct uvc_entity *entity; entity = list_entry(p, struct uvc_entity, list); -#ifdef CONFIG_MEDIA_CONTROLLER - uvc_mc_cleanup_entity(entity); -#endif - if (entity->vdev) { - video_device_release(entity->vdev); - entity->vdev = NULL; - } kfree(entity); } @@ -1642,6 +1616,8 @@ static void uvc_release(struct video_device *vdev) struct uvc_streaming *stream = video_get_drvdata(vdev); struct uvc_device *dev = stream->dev; + video_device_release(vdev); + /* Decrement the registered streams count and delete the device when it * reaches zero. */ @@ -1706,7 +1682,7 @@ static int uvc_register_video(struct uvc_device *dev, * unregistered before the reference is released, so we don't need to * get another one. */ - vdev->v4l2_dev = &dev->vdev; + vdev->parent = &dev->intf->dev; vdev->fops = &uvc_fops; vdev->release = uvc_release; strlcpy(vdev->name, dev->name, sizeof vdev->name); @@ -1755,8 +1731,6 @@ static int uvc_register_terms(struct uvc_device *dev, ret = uvc_register_video(dev, stream); if (ret < 0) return ret; - - term->vdev = stream->vdev; } return 0; @@ -1771,14 +1745,6 @@ static int uvc_register_chains(struct uvc_device *dev) ret = uvc_register_terms(dev, chain); if (ret < 0) return ret; - -#ifdef CONFIG_MEDIA_CONTROLLER - ret = uvc_mc_register_entities(chain); - if (ret < 0) { - uvc_printk(KERN_INFO, "Failed to register entites " - "(%d).\n", ret); - } -#endif } return 0; @@ -1848,24 +1814,6 @@ static int uvc_probe(struct usb_interface *intf, "linux-uvc-devel mailing list.\n"); } - /* Register the media and V4L2 devices. */ -#ifdef CONFIG_MEDIA_CONTROLLER - dev->mdev.dev = &intf->dev; - strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); - if (udev->serial) - strlcpy(dev->mdev.serial, udev->serial, - sizeof(dev->mdev.serial)); - strcpy(dev->mdev.bus_info, udev->devpath); - dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - dev->mdev.driver_version = DRIVER_VERSION_NUMBER; - if (media_device_register(&dev->mdev) < 0) - goto error; - - dev->vdev.mdev = &dev->mdev; -#endif - if (v4l2_device_register(&intf->dev, &dev->vdev) < 0) - goto error; - /* Initialize controls. */ if (uvc_ctrl_init_device(dev) < 0) goto error; @@ -1874,7 +1822,7 @@ static int uvc_probe(struct usb_interface *intf, if (uvc_scan_device(dev) < 0) goto error; - /* Register video device nodes. */ + /* Register video devices. */ if (uvc_register_chains(dev) < 0) goto error; diff --git a/trunk/drivers/media/video/uvc/uvc_entity.c b/trunk/drivers/media/video/uvc/uvc_entity.c deleted file mode 100644 index ede7852bb1df..000000000000 --- a/trunk/drivers/media/video/uvc/uvc_entity.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * uvc_entity.c -- USB Video Class driver - * - * Copyright (C) 2005-2011 - * Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include - -#include - -#include "uvcvideo.h" - -/* ------------------------------------------------------------------------ - * Video subdevices registration and unregistration - */ - -static int uvc_mc_register_entity(struct uvc_video_chain *chain, - struct uvc_entity *entity) -{ - const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; - struct uvc_entity *remote; - unsigned int i; - u8 remote_pad; - int ret; - - for (i = 0; i < entity->num_pads; ++i) { - struct media_entity *source; - struct media_entity *sink; - - if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK)) - continue; - - remote = uvc_entity_by_id(chain->dev, entity->baSourceID[i]); - if (remote == NULL) - return -EINVAL; - - source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) - ? &remote->vdev->entity : &remote->subdev.entity; - sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) - ? &entity->vdev->entity : &entity->subdev.entity; - - remote_pad = remote->num_pads - 1; - ret = media_entity_create_link(source, remote_pad, - sink, i, flags); - if (ret < 0) - return ret; - } - - if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) - ret = v4l2_device_register_subdev(&chain->dev->vdev, - &entity->subdev); - - return ret; -} - -static struct v4l2_subdev_ops uvc_subdev_ops = { -}; - -void uvc_mc_cleanup_entity(struct uvc_entity *entity) -{ - if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) - media_entity_cleanup(&entity->subdev.entity); - else if (entity->vdev != NULL) - media_entity_cleanup(&entity->vdev->entity); -} - -static int uvc_mc_init_entity(struct uvc_entity *entity) -{ - int ret; - - if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) { - v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops); - strlcpy(entity->subdev.name, entity->name, - sizeof(entity->subdev.name)); - - ret = media_entity_init(&entity->subdev.entity, - entity->num_pads, entity->pads, 0); - } else - ret = media_entity_init(&entity->vdev->entity, - entity->num_pads, entity->pads, 0); - - return ret; -} - -int uvc_mc_register_entities(struct uvc_video_chain *chain) -{ - struct uvc_entity *entity; - int ret; - - list_for_each_entry(entity, &chain->entities, chain) { - ret = uvc_mc_init_entity(entity); - if (ret < 0) { - uvc_printk(KERN_INFO, "Failed to initialize entity for " - "entity %u\n", entity->id); - return ret; - } - } - - list_for_each_entry(entity, &chain->entities, chain) { - ret = uvc_mc_register_entity(chain, entity); - if (ret < 0) { - uvc_printk(KERN_INFO, "Failed to register entity for " - "entity %u\n", entity->id); - return ret; - } - } - - return 0; -} diff --git a/trunk/drivers/media/video/uvc/uvcvideo.h b/trunk/drivers/media/video/uvc/uvcvideo.h index 20107fd3574d..7cf224bae2e5 100644 --- a/trunk/drivers/media/video/uvc/uvcvideo.h +++ b/trunk/drivers/media/video/uvc/uvcvideo.h @@ -98,11 +98,8 @@ struct uvc_xu_control { #ifdef __KERNEL__ #include -#include #include #include -#include -#include /* -------------------------------------------------------------------------- * UVC constants @@ -304,13 +301,6 @@ struct uvc_entity { __u16 type; char name[64]; - /* Media controller-related fields. */ - struct video_device *vdev; - struct v4l2_subdev subdev; - unsigned int num_pads; - unsigned int num_links; - struct media_pad *pads; - union { struct { __u16 wObjectiveFocalLengthMin; @@ -514,10 +504,6 @@ struct uvc_device { atomic_t nmappings; /* Video control interface */ -#ifdef CONFIG_MEDIA_CONTROLLER - struct media_device mdev; -#endif - struct v4l2_device vdev; __u16 uvc_version; __u32 clock_frequency; @@ -597,8 +583,6 @@ extern unsigned int uvc_timeout_param; /* Core driver */ extern struct uvc_driver uvc_driver; -extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id); - /* Video buffers queue management. */ extern void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, int drop_corrupted); @@ -632,10 +616,6 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue) /* V4L2 interface */ extern const struct v4l2_file_operations uvc_fops; -/* Media controller */ -extern int uvc_mc_register_entities(struct uvc_video_chain *chain); -extern void uvc_mc_cleanup_entity(struct uvc_entity *entity); - /* Video */ extern int uvc_video_init(struct uvc_streaming *stream); extern int uvc_video_suspend(struct uvc_streaming *stream); diff --git a/trunk/drivers/mfd/88pm860x-core.c b/trunk/drivers/mfd/88pm860x-core.c index 17dfe9bb6d27..011cb6ce861b 100644 --- a/trunk/drivers/mfd/88pm860x-core.c +++ b/trunk/drivers/mfd/88pm860x-core.c @@ -21,13 +21,13 @@ #define INT_STATUS_NUM 3 -static struct resource bk_resources[] __devinitdata = { +static struct resource bk_resources[] __initdata = { {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,}, {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,}, {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,}, }; -static struct resource led_resources[] __devinitdata = { +static struct resource led_resources[] __initdata = { {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,}, {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,}, {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,}, @@ -36,7 +36,7 @@ static struct resource led_resources[] __devinitdata = { {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,}, }; -static struct resource regulator_resources[] __devinitdata = { +static struct resource regulator_resources[] __initdata = { {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,}, {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,}, {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,}, @@ -57,15 +57,15 @@ static struct resource regulator_resources[] __devinitdata = { {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,}, }; -static struct resource touch_resources[] __devinitdata = { +static struct resource touch_resources[] __initdata = { {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,}, }; -static struct resource onkey_resources[] __devinitdata = { +static struct resource onkey_resources[] __initdata = { {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,}, }; -static struct resource codec_resources[] __devinitdata = { +static struct resource codec_resources[] __initdata = { /* Headset microphone insertion or removal */ {PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,}, /* Hook-switch press or release */ @@ -76,12 +76,12 @@ static struct resource codec_resources[] __devinitdata = { {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,}, }; -static struct resource battery_resources[] __devinitdata = { +static struct resource battery_resources[] __initdata = { {PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,}, {PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,}, }; -static struct resource charger_resources[] __devinitdata = { +static struct resource charger_resources[] __initdata = { {PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,}, {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,}, {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout", IORESOURCE_IRQ,}, @@ -90,17 +90,13 @@ static struct resource charger_resources[] __devinitdata = { {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, }; -static struct resource rtc_resources[] __devinitdata = { - {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,}, -}; - -static struct mfd_cell bk_devs[] = { +static struct mfd_cell bk_devs[] __initdata = { {"88pm860x-backlight", 0,}, {"88pm860x-backlight", 1,}, {"88pm860x-backlight", 2,}, }; -static struct mfd_cell led_devs[] = { +static struct mfd_cell led_devs[] __initdata = { {"88pm860x-led", 0,}, {"88pm860x-led", 1,}, {"88pm860x-led", 2,}, @@ -109,7 +105,7 @@ static struct mfd_cell led_devs[] = { {"88pm860x-led", 5,}, }; -static struct mfd_cell regulator_devs[] = { +static struct mfd_cell regulator_devs[] __initdata = { {"88pm860x-regulator", 0,}, {"88pm860x-regulator", 1,}, {"88pm860x-regulator", 2,}, @@ -130,15 +126,15 @@ static struct mfd_cell regulator_devs[] = { {"88pm860x-regulator", 17,}, }; -static struct mfd_cell touch_devs[] = { +static struct mfd_cell touch_devs[] __initdata = { {"88pm860x-touch", -1,}, }; -static struct mfd_cell onkey_devs[] = { +static struct mfd_cell onkey_devs[] __initdata = { {"88pm860x-onkey", -1,}, }; -static struct mfd_cell codec_devs[] = { +static struct mfd_cell codec_devs[] __initdata = { {"88pm860x-codec", -1,}, }; @@ -147,10 +143,11 @@ static struct mfd_cell power_devs[] = { {"88pm860x-charger", -1,}, }; -static struct mfd_cell rtc_devs[] = { - {"88pm860x-rtc", -1,}, -}; - +static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)]; +static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)]; +static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)]; +static struct pm860x_touch_pdata touch_pdata; +static struct pm860x_power_pdata power_pdata; struct pm860x_irq_data { int reg; @@ -504,6 +501,7 @@ static void device_irq_exit(struct pm860x_chip *chip) } static void __devinit device_bk_init(struct pm860x_chip *chip, + struct i2c_client *i2c, struct pm860x_platform_data *pdata) { int ret; @@ -516,12 +514,13 @@ static void __devinit device_bk_init(struct pm860x_chip *chip, pdata->num_backlights = ARRAY_SIZE(bk_devs); for (i = 0; i < pdata->num_backlights; i++) { - bk_devs[i].platform_data = &pdata->backlight[i]; - bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata); + memcpy(&bk_pdata[i], &pdata->backlight[i], + sizeof(struct pm860x_backlight_pdata)); + bk_devs[i].mfd_data = &bk_pdata[i]; for (j = 0; j < ARRAY_SIZE(bk_devs); j++) { id = bk_resources[j].start; - if (pdata->backlight[i].flags != id) + if (bk_pdata[i].flags != id) continue; bk_devs[i].num_resources = 1; @@ -539,6 +538,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip, } static void __devinit device_led_init(struct pm860x_chip *chip, + struct i2c_client *i2c, struct pm860x_platform_data *pdata) { int ret; @@ -551,12 +551,13 @@ static void __devinit device_led_init(struct pm860x_chip *chip, pdata->num_leds = ARRAY_SIZE(led_devs); for (i = 0; i < pdata->num_leds; i++) { - led_devs[i].platform_data = &pdata->led[i]; - led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata); + memcpy(&led_pdata[i], &pdata->led[i], + sizeof(struct pm860x_led_pdata)); + led_devs[i].mfd_data = &led_pdata[i]; for (j = 0; j < ARRAY_SIZE(led_devs); j++) { id = led_resources[j].start; - if (pdata->led[i].flags != id) + if (led_pdata[i].flags != id) continue; led_devs[i].num_resources = 1; @@ -574,11 +575,12 @@ static void __devinit device_led_init(struct pm860x_chip *chip, } static void __devinit device_regulator_init(struct pm860x_chip *chip, + struct i2c_client *i2c, struct pm860x_platform_data *pdata) { struct regulator_init_data *initdata; int ret; - int i, seq; + int i, j; if ((pdata == NULL) || (pdata->regulator == NULL)) return; @@ -586,21 +588,41 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip, if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) pdata->num_regulators = ARRAY_SIZE(regulator_devs); - for (i = 0, seq = -1; i < pdata->num_regulators; i++) { + for (i = 0, j = -1; i < pdata->num_regulators; i++) { initdata = &pdata->regulator[i]; - seq = *(unsigned int *)initdata->driver_data; - if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) { - dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n", - seq, initdata->constraints.name); + if (strstr(initdata->constraints.name, "BUCK")) { + sscanf(initdata->constraints.name, "BUCK%d", &j); + /* BUCK1 ~ BUCK3 */ + if ((j < 1) || (j > 3)) { + dev_err(chip->dev, "Failed to add constraint " + "(%s)\n", initdata->constraints.name); + goto out; + } + j = (j - 1) + PM8607_ID_BUCK1; + } + if (strstr(initdata->constraints.name, "LDO")) { + sscanf(initdata->constraints.name, "LDO%d", &j); + /* LDO1 ~ LDO15 */ + if ((j < 1) || (j > 15)) { + dev_err(chip->dev, "Failed to add constraint " + "(%s)\n", initdata->constraints.name); + goto out; + } + j = (j - 1) + PM8607_ID_LDO1; + } + if (j == -1) { + dev_err(chip->dev, "Failed to add constraint (%s)\n", + initdata->constraints.name); goto out; } - regulator_devs[i].platform_data = &pdata->regulator[i]; - regulator_devs[i].pdata_size = sizeof(struct regulator_init_data); + memcpy(®ulator_pdata[i], &pdata->regulator[i], + sizeof(struct regulator_init_data)); + regulator_devs[i].mfd_data = ®ulator_pdata[i]; regulator_devs[i].num_resources = 1; - regulator_devs[i].resources = ®ulator_resources[seq]; + regulator_devs[i].resources = ®ulator_resources[j]; ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, - ®ulator_resources[seq], 0); + ®ulator_resources[j], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add regulator subdev\n"); goto out; @@ -610,35 +632,17 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip, return; } -static void __devinit device_rtc_init(struct pm860x_chip *chip, - struct pm860x_platform_data *pdata) -{ - int ret; - - if ((pdata == NULL)) - return; - - rtc_devs[0].platform_data = pdata->rtc; - rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata); - rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources); - rtc_devs[0].resources = &rtc_resources[0]; - ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], - ARRAY_SIZE(rtc_devs), &rtc_resources[0], - chip->irq_base); - if (ret < 0) - dev_err(chip->dev, "Failed to add rtc subdev\n"); -} - static void __devinit device_touch_init(struct pm860x_chip *chip, + struct i2c_client *i2c, struct pm860x_platform_data *pdata) { int ret; - if (pdata == NULL) + if ((pdata == NULL) || (pdata->touch == NULL)) return; - touch_devs[0].platform_data = pdata->touch; - touch_devs[0].pdata_size = sizeof(struct pm860x_touch_pdata); + memcpy(&touch_pdata, pdata->touch, sizeof(struct pm860x_touch_pdata)); + touch_devs[0].mfd_data = &touch_pdata; touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); touch_devs[0].resources = &touch_resources[0]; ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], @@ -649,15 +653,16 @@ static void __devinit device_touch_init(struct pm860x_chip *chip, } static void __devinit device_power_init(struct pm860x_chip *chip, + struct i2c_client *i2c, struct pm860x_platform_data *pdata) { int ret; - if (pdata == NULL) + if ((pdata == NULL) || (pdata->power == NULL)) return; - power_devs[0].platform_data = pdata->power; - power_devs[0].pdata_size = sizeof(struct pm860x_power_pdata); + memcpy(&power_pdata, pdata->power, sizeof(struct pm860x_power_pdata)); + power_devs[0].mfd_data = &power_pdata; power_devs[0].num_resources = ARRAY_SIZE(battery_resources); power_devs[0].resources = &battery_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, @@ -665,8 +670,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, if (ret < 0) dev_err(chip->dev, "Failed to add battery subdev\n"); - power_devs[1].platform_data = pdata->power; - power_devs[1].pdata_size = sizeof(struct pm860x_power_pdata); + power_devs[1].mfd_data = &power_pdata; power_devs[1].num_resources = ARRAY_SIZE(charger_resources); power_devs[1].resources = &charger_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, @@ -676,6 +680,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, } static void __devinit device_onkey_init(struct pm860x_chip *chip, + struct i2c_client *i2c, struct pm860x_platform_data *pdata) { int ret; @@ -690,6 +695,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip, } static void __devinit device_codec_init(struct pm860x_chip *chip, + struct i2c_client *i2c, struct pm860x_platform_data *pdata) { int ret; @@ -757,12 +763,11 @@ static void __devinit device_8607_init(struct pm860x_chip *chip, if (ret < 0) goto out; - device_regulator_init(chip, pdata); - device_rtc_init(chip, pdata); - device_onkey_init(chip, pdata); - device_touch_init(chip, pdata); - device_power_init(chip, pdata); - device_codec_init(chip, pdata); + device_regulator_init(chip, i2c, pdata); + device_onkey_init(chip, i2c, pdata); + device_touch_init(chip, i2c, pdata); + device_power_init(chip, i2c, pdata); + device_codec_init(chip, i2c, pdata); out: return; } @@ -774,8 +779,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip, switch (chip->id) { case CHIP_PM8606: - device_bk_init(chip, pdata); - device_led_init(chip, pdata); + device_bk_init(chip, chip->client, pdata); + device_led_init(chip, chip->client, pdata); break; case CHIP_PM8607: device_8607_init(chip, chip->client, pdata); @@ -785,8 +790,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip, if (chip->companion) { switch (chip->id) { case CHIP_PM8607: - device_bk_init(chip, pdata); - device_led_init(chip, pdata); + device_bk_init(chip, chip->companion, pdata); + device_led_init(chip, chip->companion, pdata); break; case CHIP_PM8606: device_8607_init(chip, chip->companion, pdata); diff --git a/trunk/drivers/mfd/Kconfig b/trunk/drivers/mfd/Kconfig index b6c267724e14..481770ab2716 100644 --- a/trunk/drivers/mfd/Kconfig +++ b/trunk/drivers/mfd/Kconfig @@ -157,20 +157,6 @@ config TPS6507X This driver can also be built as a module. If so, the module will be called tps6507x. -config MFD_TPS6586X - bool "TPS6586x Power Management chips" - depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS - select MFD_CORE - help - If you say yes here you get support for the TPS6586X series of - Power Management chips. - This driver provides common support for accessing the device, - additional drivers must be enabled in order to use the - functionality of the device. - - This driver can also be built as a module. If so, the module - will be called tps6586x. - config MENELAUS bool "Texas Instruments TWL92330/Menelaus PM chip" depends on I2C=y && ARCH_OMAP2 @@ -469,20 +455,6 @@ config MFD_PCF50633 facilities, and registers devices for the various functions so that function-specific drivers can bind to them. -config PCF50633_ADC - tristate "Support for NXP PCF50633 ADC" - depends on MFD_PCF50633 - help - Say yes here if you want to include support for ADC in the - NXP PCF50633 chip. - -config PCF50633_GPIO - tristate "Support for NXP PCF50633 GPIO" - depends on MFD_PCF50633 - help - Say yes here if you want to include support GPIO for pins on - the PCF50633 chip. - config MFD_MC13783 tristate @@ -498,6 +470,20 @@ config MFD_MC13XXX additional drivers must be enabled in order to use the functionality of the device. +config PCF50633_ADC + tristate "Support for NXP PCF50633 ADC" + depends on MFD_PCF50633 + help + Say yes here if you want to include support for ADC in the + NXP PCF50633 chip. + +config PCF50633_GPIO + tristate "Support for NXP PCF50633 GPIO" + depends on MFD_PCF50633 + help + Say yes here if you want to include support GPIO for pins on + the PCF50633 chip. + config ABX500_CORE bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions" default y if ARCH_U300 || ARCH_U8500 @@ -663,6 +649,20 @@ config MFD_JZ4740_ADC Say yes here if you want support for the ADC unit in the JZ4740 SoC. This driver is necessary for jz4740-battery and jz4740-hwmon driver. +config MFD_TPS6586X + bool "TPS6586x Power Management chips" + depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS + select MFD_CORE + help + If you say yes here you get support for the TPS6586X series of + Power Management chips. + This driver provides common support for accessing the device, + additional drivers must be enabled in order to use the + functionality of the device. + + This driver can also be built as a module. If so, the module + will be called tps6586x. + config MFD_VX855 tristate "Support for VIA VX855/VX875 integrated south bridge" depends on PCI @@ -691,43 +691,6 @@ config MFD_OMAP_USB_HOST This MFD driver does the required setup functionalities for OMAP USB Host drivers. -config MFD_PM8XXX - tristate - -config MFD_PM8921_CORE - tristate "Qualcomm PM8921 PMIC chip" - depends on MSM_SSBI - select MFD_CORE - select MFD_PM8XXX - help - If you say yes to this option, support will be included for the - built-in PM8921 PMIC chip. - - This is required if your board has a PM8921 and uses its features, - such as: MPPs, GPIOs, regulators, interrupts, and PWM. - - Say M here if you want to include support for PM8921 chip as a module. - This will build a module called "pm8921-core". - -config MFD_PM8XXX_IRQ - bool "Support for Qualcomm PM8xxx IRQ features" - depends on MFD_PM8XXX - default y if MFD_PM8XXX - help - This is the IRQ driver for Qualcomm PM 8xxx PMIC chips. - - This is required to use certain other PM 8xxx features, such as GPIO - and MPP. - -config MFD_TPS65910 - bool "TPS65910 Power Management chip" - depends on I2C=y - select MFD_CORE - select GPIO_TPS65910 - help - if you say yes here you get support for the TPS65910 series of - Power Management chips. - endif # MFD_SUPPORT menu "Multimedia Capabilities Port drivers" diff --git a/trunk/drivers/mfd/Makefile b/trunk/drivers/mfd/Makefile index efe3cc33ed92..24aa44448daf 100644 --- a/trunk/drivers/mfd/Makefile +++ b/trunk/drivers/mfd/Makefile @@ -91,6 +91,3 @@ obj-$(CONFIG_MFD_VX855) += vx855.o obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o -obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o -obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o -obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o diff --git a/trunk/drivers/mfd/ab3100-core.c b/trunk/drivers/mfd/ab3100-core.c index a20e1c41bed2..a751927047ac 100644 --- a/trunk/drivers/mfd/ab3100-core.c +++ b/trunk/drivers/mfd/ab3100-core.c @@ -949,10 +949,8 @@ static int __devinit ab3100_probe(struct i2c_client *client, goto exit_no_ops; /* Set up and register the platform devices. */ - for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) { - ab3100_devs[i].platform_data = ab3100_plf_data; - ab3100_devs[i].pdata_size = sizeof(struct ab3100_platform_data); - } + for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) + ab3100_devs[i].mfd_data = ab3100_plf_data; err = mfd_add_devices(&client->dev, 0, ab3100_devs, ARRAY_SIZE(ab3100_devs), NULL, 0); diff --git a/trunk/drivers/mfd/ab3550-core.c b/trunk/drivers/mfd/ab3550-core.c index 3d7dce671b93..ff86acf3e6bd 100644 --- a/trunk/drivers/mfd/ab3550-core.c +++ b/trunk/drivers/mfd/ab3550-core.c @@ -1320,10 +1320,8 @@ static int __init ab3550_probe(struct i2c_client *client, goto exit_no_ops; /* Set up and register the platform devices. */ - for (i = 0; i < AB3550_NUM_DEVICES; i++) { - ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i]; - ab3550_devs[i].pdata_size = ab3550_plf_data->dev_data_sz[i]; - } + for (i = 0; i < AB3550_NUM_DEVICES; i++) + ab3550_devs[i].mfd_data = ab3550_plf_data->dev_data[i]; err = mfd_add_devices(&client->dev, 0, ab3550_devs, ARRAY_SIZE(ab3550_devs), NULL, diff --git a/trunk/drivers/mfd/ab8500-core.c b/trunk/drivers/mfd/ab8500-core.c index fc0c1af1566e..67d01c938284 100644 --- a/trunk/drivers/mfd/ab8500-core.c +++ b/trunk/drivers/mfd/ab8500-core.c @@ -254,9 +254,8 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) if (new == old) continue; - /* Interrupt register 12 doesn't exist prior to version 2.0 */ - if (ab8500_irq_regoffset[i] == 11 && - ab8500->chip_id < AB8500_CUT2P0) + /* Interrupt register 12 does'nt exist prior to version 0x20 */ + if (ab8500_irq_regoffset[i] == 11 && ab8500->chip_id < 0x20) continue; ab8500->oldmask[i] = new; @@ -308,8 +307,8 @@ static irqreturn_t ab8500_irq(int irq, void *dev) int status; u8 value; - /* Interrupt register 12 doesn't exist prior to version 2.0 */ - if (regoffset == 11 && ab8500->chip_id < AB8500_CUT2P0) + /* Interrupt register 12 does'nt exist prior to version 0x20 */ + if (regoffset == 11 && ab8500->chip_id < 0x20) continue; status = get_register_interruptible(ab8500, AB8500_INTERRUPT, @@ -725,15 +724,17 @@ int __devinit ab8500_init(struct ab8500 *ab8500) if (ret < 0) return ret; - switch (value) { - case AB8500_CUTEARLY: - case AB8500_CUT1P0: - case AB8500_CUT1P1: - case AB8500_CUT2P0: - case AB8500_CUT3P0: + /* + * 0x0 - Early Drop + * 0x10 - Cut 1.0 + * 0x11 - Cut 1.1 + * 0x20 - Cut 2.0 + * 0x30 - Cut 3.0 + */ + if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20 || + value == 0x30) { dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); - break; - default: + } else { dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value); return -EINVAL; } @@ -762,9 +763,8 @@ int __devinit ab8500_init(struct ab8500 *ab8500) /* Clear and mask all interrupts */ for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { - /* Interrupt register 12 doesn't exist prior to version 2.0 */ - if (ab8500_irq_regoffset[i] == 11 && - ab8500->chip_id < AB8500_CUT2P0) + /* Interrupt register 12 does'nt exist prior to version 0x20 */ + if (ab8500_irq_regoffset[i] == 11 && ab8500->chip_id < 0x20) continue; get_register_interruptible(ab8500, AB8500_INTERRUPT, diff --git a/trunk/drivers/mfd/ab8500-gpadc.c b/trunk/drivers/mfd/ab8500-gpadc.c index f16afb234ff9..6421ad1160de 100644 --- a/trunk/drivers/mfd/ab8500-gpadc.c +++ b/trunk/drivers/mfd/ab8500-gpadc.c @@ -57,7 +57,6 @@ #define SW_AVG_16 0x60 #define ADC_SW_CONV 0x04 #define EN_ICHAR 0x80 -#define BTEMP_PULL_UP 0x08 #define EN_BUF 0x40 #define DIS_ZERO 0x00 #define GPADC_BUSY 0x01 @@ -102,7 +101,6 @@ struct adc_cal_data { /** * struct ab8500_gpadc - AB8500 GPADC device information - * @chip_id ABB chip id * @dev: pointer to the struct device * @node: a list of AB8500 GPADCs, hence prepared for reentrance @@ -114,7 +112,6 @@ struct adc_cal_data { * @cal_data array of ADC calibration data structs */ struct ab8500_gpadc { - u8 chip_id; struct device *dev; struct list_head node; struct completion ab8500_gpadc_complete; @@ -277,7 +274,6 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) dev_err(gpadc->dev, "gpadc_conversion: enable gpadc failed\n"); goto out; } - /* Select the input source and set average samples to 16 */ ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16)); @@ -286,11 +282,9 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) "gpadc_conversion: set avg samples failed\n"); goto out; } - /* * Enable ADC, buffering, select rising edge and enable ADC path - * charging current sense if it needed, ABB 3.0 needs some special - * treatment too. + * charging current sense if it needed */ switch (input) { case MAIN_CHARGER_C: @@ -300,23 +294,6 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) EN_BUF | EN_ICHAR, EN_BUF | EN_ICHAR); break; - case BTEMP_BALL: - if (gpadc->chip_id >= AB8500_CUT3P0) { - /* Turn on btemp pull-up on ABB 3.0 */ - ret = abx500_mask_and_set_register_interruptible( - gpadc->dev, - AB8500_GPADC, AB8500_GPADC_CTRL1_REG, - EN_BUF | BTEMP_PULL_UP, - EN_BUF | BTEMP_PULL_UP); - - /* - * Delay might be needed for ABB8500 cut 3.0, if not, remove - * when hardware will be availible - */ - msleep(1); - break; - } - /* Intentional fallthrough */ default: ret = abx500_mask_and_set_register_interruptible(gpadc->dev, AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF); @@ -327,7 +304,6 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) "gpadc_conversion: select falling edge failed\n"); goto out; } - ret = abx500_mask_and_set_register_interruptible(gpadc->dev, AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ADC_SW_CONV, ADC_SW_CONV); if (ret < 0) { @@ -576,14 +552,6 @@ static int __devinit ab8500_gpadc_probe(struct platform_device *pdev) goto fail; } - /* Get Chip ID of the ABB ASIC */ - ret = abx500_get_chip_id(gpadc->dev); - if (ret < 0) { - dev_err(gpadc->dev, "failed to get chip ID\n"); - goto fail_irq; - } - gpadc->chip_id = (u8) ret; - /* VTVout LDO used to power up ab8500-GPADC */ gpadc->regu = regulator_get(&pdev->dev, "vddadc"); if (IS_ERR(gpadc->regu)) { diff --git a/trunk/drivers/mfd/asic3.c b/trunk/drivers/mfd/asic3.c index c27fd1fc3b86..0b4d5b23bec9 100644 --- a/trunk/drivers/mfd/asic3.c +++ b/trunk/drivers/mfd/asic3.c @@ -88,19 +88,19 @@ struct asic3 { static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset); -void asic3_write_register(struct asic3 *asic, unsigned int reg, u32 value) +static inline void asic3_write_register(struct asic3 *asic, + unsigned int reg, u32 value) { iowrite16(value, asic->mapping + (reg >> asic->bus_shift)); } -EXPORT_SYMBOL_GPL(asic3_write_register); -u32 asic3_read_register(struct asic3 *asic, unsigned int reg) +static inline u32 asic3_read_register(struct asic3 *asic, + unsigned int reg) { return ioread16(asic->mapping + (reg >> asic->bus_shift)); } -EXPORT_SYMBOL_GPL(asic3_read_register); static void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set) { @@ -676,8 +676,7 @@ static struct mfd_cell asic3_cell_ds1wm = { .name = "ds1wm", .enable = ds1wm_enable, .disable = ds1wm_disable, - .platform_data = &ds1wm_pdata, - .pdata_size = sizeof(ds1wm_pdata), + .mfd_data = &ds1wm_pdata, .num_resources = ARRAY_SIZE(ds1wm_resources), .resources = ds1wm_resources, }; @@ -778,61 +777,12 @@ static struct mfd_cell asic3_cell_mmc = { .name = "tmio-mmc", .enable = asic3_mmc_enable, .disable = asic3_mmc_disable, - .platform_data = &asic3_mmc_data, - .pdata_size = sizeof(asic3_mmc_data), + .mfd_data = &asic3_mmc_data, .num_resources = ARRAY_SIZE(asic3_mmc_resources), .resources = asic3_mmc_resources, }; -static const int clock_ledn[ASIC3_NUM_LEDS] = { - [0] = ASIC3_CLOCK_LED0, - [1] = ASIC3_CLOCK_LED1, - [2] = ASIC3_CLOCK_LED2, -}; - -static int asic3_leds_enable(struct platform_device *pdev) -{ - const struct mfd_cell *cell = mfd_get_cell(pdev); - struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); - - asic3_clk_enable(asic, &asic->clocks[clock_ledn[cell->id]]); - - return 0; -} - -static int asic3_leds_disable(struct platform_device *pdev) -{ - const struct mfd_cell *cell = mfd_get_cell(pdev); - struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); - - asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]); - - return 0; -} - -static struct mfd_cell asic3_cell_leds[ASIC3_NUM_LEDS] = { - [0] = { - .name = "leds-asic3", - .id = 0, - .enable = asic3_leds_enable, - .disable = asic3_leds_disable, - }, - [1] = { - .name = "leds-asic3", - .id = 1, - .enable = asic3_leds_enable, - .disable = asic3_leds_disable, - }, - [2] = { - .name = "leds-asic3", - .id = 2, - .enable = asic3_leds_enable, - .disable = asic3_leds_disable, - }, -}; - static int __init asic3_mfd_probe(struct platform_device *pdev, - struct asic3_platform_data *pdata, struct resource *mem) { struct asic3 *asic = platform_get_drvdata(pdev); @@ -856,8 +806,7 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, /* MMC */ asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) + - mem_sdio->start, - ASIC3_SD_CONFIG_SIZE >> asic->bus_shift); + mem_sdio->start, 0x400 >> asic->bus_shift); if (!asic->tmio_cnf) { ret = -ENOMEM; dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n"); @@ -871,23 +820,9 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, if (ret < 0) goto out; - if (mem_sdio && (irq >= 0)) { + if (mem_sdio && (irq >= 0)) ret = mfd_add_devices(&pdev->dev, pdev->id, &asic3_cell_mmc, 1, mem_sdio, irq); - if (ret < 0) - goto out; - } - - if (pdata->leds) { - int i; - - for (i = 0; i < ASIC3_NUM_LEDS; ++i) { - asic3_cell_leds[i].platform_data = &pdata->leds[i]; - asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]); - } - ret = mfd_add_devices(&pdev->dev, 0, - asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0); - } out: return ret; @@ -968,7 +903,7 @@ static int __init asic3_probe(struct platform_device *pdev) */ memcpy(asic->clocks, asic3_clk_init, sizeof(asic3_clk_init)); - asic3_mfd_probe(pdev, pdata, mem); + asic3_mfd_probe(pdev, mem); dev_info(asic->dev, "ASIC3 Core driver\n"); diff --git a/trunk/drivers/mfd/davinci_voicecodec.c b/trunk/drivers/mfd/davinci_voicecodec.c index 4e2af2cb2d26..414783b04849 100644 --- a/trunk/drivers/mfd/davinci_voicecodec.c +++ b/trunk/drivers/mfd/davinci_voicecodec.c @@ -119,14 +119,12 @@ static int __init davinci_vc_probe(struct platform_device *pdev) /* Voice codec interface client */ cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL]; cell->name = "davinci-vcif"; - cell->platform_data = davinci_vc; - cell->pdata_size = sizeof(*davinci_vc); + cell->mfd_data = davinci_vc; /* Voice codec CQ93VC client */ cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL]; cell->name = "cq93vc-codec"; - cell->platform_data = davinci_vc; - cell->pdata_size = sizeof(*davinci_vc); + cell->mfd_data = davinci_vc; ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, DAVINCI_VC_CELLS, NULL, 0); diff --git a/trunk/drivers/mfd/htc-pasic3.c b/trunk/drivers/mfd/htc-pasic3.c index 2808bd125d13..fb9770b39a32 100644 --- a/trunk/drivers/mfd/htc-pasic3.c +++ b/trunk/drivers/mfd/htc-pasic3.c @@ -117,8 +117,7 @@ static struct mfd_cell ds1wm_cell __initdata = { .name = "ds1wm", .enable = ds1wm_enable, .disable = ds1wm_disable, - .platform_data = &ds1wm_pdata, - .pdata_size = sizeof(ds1wm_pdata), + .mfd_data = &ds1wm_pdata, .num_resources = 2, .resources = ds1wm_resources, }; @@ -173,8 +172,6 @@ static int __init pasic3_probe(struct platform_device *pdev) } if (pdata && pdata->led_pdata) { - led_cell.platform_data = pdata->led_pdata; - led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo); ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); if (ret < 0) dev_warn(dev, "failed to register LED device\n"); diff --git a/trunk/drivers/mfd/janz-cmodio.c b/trunk/drivers/mfd/janz-cmodio.c index 5c2a06acb77f..fc4191137e90 100644 --- a/trunk/drivers/mfd/janz-cmodio.c +++ b/trunk/drivers/mfd/janz-cmodio.c @@ -86,8 +86,7 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv, /* Add platform data */ pdata->modno = modno; - cell->platform_data = pdata; - cell->pdata_size = sizeof(*pdata); + cell->mfd_data = pdata; /* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */ res->flags = IORESOURCE_MEM; diff --git a/trunk/drivers/mfd/max8925-core.c b/trunk/drivers/mfd/max8925-core.c index e1e59c92f758..58cc5fdde016 100644 --- a/trunk/drivers/mfd/max8925-core.c +++ b/trunk/drivers/mfd/max8925-core.c @@ -627,7 +627,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, goto out_dev; } - if (pdata) { + if (pdata && pdata->regulator[0]) { ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], ARRAY_SIZE(regulator_devs), ®ulator_resources[0], 0); diff --git a/trunk/drivers/mfd/mc13xxx-core.c b/trunk/drivers/mfd/mc13xxx-core.c index 7e4d44bf92ab..668634e89e81 100644 --- a/trunk/drivers/mfd/mc13xxx-core.c +++ b/trunk/drivers/mfd/mc13xxx-core.c @@ -683,14 +683,13 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, - const char *format, void *pdata, size_t pdata_size) + const char *format, void *pdata) { char buf[30]; const char *name = mc13xxx_get_chipname(mc13xxx); struct mfd_cell cell = { - .platform_data = pdata, - .pdata_size = pdata_size, + .mfd_data = pdata, }; /* there is no asnprintf in the kernel :-( */ @@ -706,7 +705,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) { - return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0); + return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL); } static int mc13xxx_probe(struct spi_device *spi) @@ -765,7 +764,7 @@ static int mc13xxx_probe(struct spi_device *spi) if (pdata->flags & MC13XXX_USE_REGULATOR) { mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", - &pdata->regulators, sizeof(pdata->regulators)); + &pdata->regulators); } if (pdata->flags & MC13XXX_USE_RTC) @@ -775,8 +774,7 @@ static int mc13xxx_probe(struct spi_device *spi) mc13xxx_add_subdevice(mc13xxx, "%s-ts"); if (pdata->flags & MC13XXX_USE_LED) - mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", - pdata->leds, sizeof(*pdata->leds)); + mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", pdata->leds); return 0; } diff --git a/trunk/drivers/mfd/mfd-core.c b/trunk/drivers/mfd/mfd-core.c index 0902523af62d..f4c8c844b913 100644 --- a/trunk/drivers/mfd/mfd-core.c +++ b/trunk/drivers/mfd/mfd-core.c @@ -88,13 +88,6 @@ static int mfd_add_device(struct device *parent, int id, pdev->dev.parent = parent; - if (cell->pdata_size) { - ret = platform_device_add_data(pdev, - cell->platform_data, cell->pdata_size); - if (ret) - goto fail_res; - } - ret = mfd_platform_add_cell(pdev, cell); if (ret) goto fail_res; diff --git a/trunk/drivers/mfd/omap-usb-host.c b/trunk/drivers/mfd/omap-usb-host.c index 855219526ccb..3ab9ffa00aad 100644 --- a/trunk/drivers/mfd/omap-usb-host.c +++ b/trunk/drivers/mfd/omap-usb-host.c @@ -26,7 +26,6 @@ #include #include #include -#include #define USBHS_DRIVER_NAME "usbhs-omap" #define OMAP_EHCI_DEVICE "ehci-omap" @@ -147,6 +146,9 @@ struct usbhs_hcd_omap { + struct clk *usbhost_ick; + struct clk *usbhost_hs_fck; + struct clk *usbhost_fs_fck; struct clk *xclk60mhsp1_ck; struct clk *xclk60mhsp2_ck; struct clk *utmi_p1_fck; @@ -156,6 +158,8 @@ struct usbhs_hcd_omap { struct clk *usbhost_p2_fck; struct clk *usbtll_p2_fck; struct clk *init_60m_fclk; + struct clk *usbtll_fck; + struct clk *usbtll_ick; void __iomem *uhh_base; void __iomem *tll_base; @@ -277,7 +281,6 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev) if (!ehci) { dev_err(dev, "omap_usbhs_alloc_child failed\n"); - ret = -ENOMEM; goto err_end; } @@ -301,14 +304,13 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev) sizeof(*ohci_data), dev); if (!ohci) { dev_err(dev, "omap_usbhs_alloc_child failed\n"); - ret = -ENOMEM; goto err_ehci; } return 0; err_ehci: - platform_device_unregister(ehci); + platform_device_put(ehci); err_end: return ret; @@ -349,13 +351,46 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) omap->platdata.ehci_data = pdata->ehci_data; omap->platdata.ohci_data = pdata->ohci_data; - pm_runtime_enable(&pdev->dev); + omap->usbhost_ick = clk_get(dev, "usbhost_ick"); + if (IS_ERR(omap->usbhost_ick)) { + ret = PTR_ERR(omap->usbhost_ick); + dev_err(dev, "usbhost_ick failed error:%d\n", ret); + goto err_end; + } + + omap->usbhost_hs_fck = clk_get(dev, "hs_fck"); + if (IS_ERR(omap->usbhost_hs_fck)) { + ret = PTR_ERR(omap->usbhost_hs_fck); + dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret); + goto err_usbhost_ick; + } + + omap->usbhost_fs_fck = clk_get(dev, "fs_fck"); + if (IS_ERR(omap->usbhost_fs_fck)) { + ret = PTR_ERR(omap->usbhost_fs_fck); + dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret); + goto err_usbhost_hs_fck; + } + + omap->usbtll_fck = clk_get(dev, "usbtll_fck"); + if (IS_ERR(omap->usbtll_fck)) { + ret = PTR_ERR(omap->usbtll_fck); + dev_err(dev, "usbtll_fck failed error:%d\n", ret); + goto err_usbhost_fs_fck; + } + + omap->usbtll_ick = clk_get(dev, "usbtll_ick"); + if (IS_ERR(omap->usbtll_ick)) { + ret = PTR_ERR(omap->usbtll_ick); + dev_err(dev, "usbtll_ick failed error:%d\n", ret); + goto err_usbtll_fck; + } omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); if (IS_ERR(omap->utmi_p1_fck)) { ret = PTR_ERR(omap->utmi_p1_fck); dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); - goto err_end; + goto err_usbtll_ick; } omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); @@ -485,8 +520,22 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) err_utmi_p1_fck: clk_put(omap->utmi_p1_fck); +err_usbtll_ick: + clk_put(omap->usbtll_ick); + +err_usbtll_fck: + clk_put(omap->usbtll_fck); + +err_usbhost_fs_fck: + clk_put(omap->usbhost_fs_fck); + +err_usbhost_hs_fck: + clk_put(omap->usbhost_hs_fck); + +err_usbhost_ick: + clk_put(omap->usbhost_ick); + err_end: - pm_runtime_disable(&pdev->dev); kfree(omap); end_probe: @@ -520,7 +569,11 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev) clk_put(omap->utmi_p2_fck); clk_put(omap->xclk60mhsp1_ck); clk_put(omap->utmi_p1_fck); - pm_runtime_disable(&pdev->dev); + clk_put(omap->usbtll_ick); + clk_put(omap->usbtll_fck); + clk_put(omap->usbhost_fs_fck); + clk_put(omap->usbhost_hs_fck); + clk_put(omap->usbhost_ick); kfree(omap); return 0; @@ -640,6 +693,7 @@ static int usbhs_enable(struct device *dev) struct usbhs_omap_platform_data *pdata = &omap->platdata; unsigned long flags = 0; int ret = 0; + unsigned long timeout; unsigned reg; dev_dbg(dev, "starting TI HSUSB Controller\n"); @@ -652,7 +706,11 @@ static int usbhs_enable(struct device *dev) if (omap->count > 0) goto end_count; - pm_runtime_get_sync(dev); + clk_enable(omap->usbhost_ick); + clk_enable(omap->usbhost_hs_fck); + clk_enable(omap->usbhost_fs_fck); + clk_enable(omap->usbtll_fck); + clk_enable(omap->usbtll_ick); if (pdata->ehci_data->phy_reset) { if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) { @@ -676,6 +734,50 @@ static int usbhs_enable(struct device *dev) omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); + /* perform TLL soft reset, and wait until reset is complete */ + usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, + OMAP_USBTLL_SYSCONFIG_SOFTRESET); + + /* Wait for TLL reset to complete */ + timeout = jiffies + msecs_to_jiffies(1000); + while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) + & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { + cpu_relax(); + + if (time_after(jiffies, timeout)) { + dev_dbg(dev, "operation timed out\n"); + ret = -EINVAL; + goto err_tll; + } + } + + dev_dbg(dev, "TLL RESET DONE\n"); + + /* (1<<3) = no idle mode only for initial debugging */ + usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, + OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | + OMAP_USBTLL_SYSCONFIG_SIDLEMODE | + OMAP_USBTLL_SYSCONFIG_AUTOIDLE); + + /* Put UHH in NoIdle/NoStandby mode */ + reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG); + if (is_omap_usbhs_rev1(omap)) { + reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP + | OMAP_UHH_SYSCONFIG_SIDLEMODE + | OMAP_UHH_SYSCONFIG_CACTIVITY + | OMAP_UHH_SYSCONFIG_MIDLEMODE); + reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; + + + } else if (is_omap_usbhs_rev2(omap)) { + reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; + reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; + reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; + reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; + } + + usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); + reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); /* setup ULPI bypass and burst configurations */ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN @@ -815,8 +917,6 @@ static int usbhs_enable(struct device *dev) return 0; err_tll: - pm_runtime_put_sync(dev); - spin_unlock_irqrestore(&omap->lock, flags); if (pdata->ehci_data->phy_reset) { if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) gpio_free(pdata->ehci_data->reset_gpio_port[0]); @@ -824,6 +924,13 @@ static int usbhs_enable(struct device *dev) if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) gpio_free(pdata->ehci_data->reset_gpio_port[1]); } + + clk_disable(omap->usbtll_ick); + clk_disable(omap->usbtll_fck); + clk_disable(omap->usbhost_fs_fck); + clk_disable(omap->usbhost_hs_fck); + clk_disable(omap->usbhost_ick); + spin_unlock_irqrestore(&omap->lock, flags); return ret; } @@ -887,20 +994,6 @@ static void usbhs_disable(struct device *dev) dev_dbg(dev, "operation timed out\n"); } - if (is_omap_usbhs_rev2(omap)) { - if (is_ehci_tll_mode(pdata->port_mode[0])) - clk_enable(omap->usbtll_p1_fck); - if (is_ehci_tll_mode(pdata->port_mode[1])) - clk_enable(omap->usbtll_p2_fck); - clk_disable(omap->utmi_p2_fck); - clk_disable(omap->utmi_p1_fck); - } - - pm_runtime_put_sync(dev); - - /* The gpio_free migh sleep; so unlock the spinlock */ - spin_unlock_irqrestore(&omap->lock, flags); - if (pdata->ehci_data->phy_reset) { if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) gpio_free(pdata->ehci_data->reset_gpio_port[0]); @@ -908,7 +1001,14 @@ static void usbhs_disable(struct device *dev) if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) gpio_free(pdata->ehci_data->reset_gpio_port[1]); } - return; + + clk_disable(omap->utmi_p2_fck); + clk_disable(omap->utmi_p1_fck); + clk_disable(omap->usbtll_ick); + clk_disable(omap->usbtll_fck); + clk_disable(omap->usbhost_fs_fck); + clk_disable(omap->usbhost_hs_fck); + clk_disable(omap->usbhost_ick); end_disble: spin_unlock_irqrestore(&omap->lock, flags); diff --git a/trunk/drivers/mfd/pm8921-core.c b/trunk/drivers/mfd/pm8921-core.c deleted file mode 100644 index e873b15753d8..000000000000 --- a/trunk/drivers/mfd/pm8921-core.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define REG_HWREV 0x002 /* PMIC4 revision */ -#define REG_HWREV_2 0x0E8 /* PMIC4 revision 2 */ - -struct pm8921 { - struct device *dev; - struct pm_irq_chip *irq_chip; -}; - -static int pm8921_readb(const struct device *dev, u16 addr, u8 *val) -{ - const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev); - const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data; - - return msm_ssbi_read(pmic->dev->parent, addr, val, 1); -} - -static int pm8921_writeb(const struct device *dev, u16 addr, u8 val) -{ - const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev); - const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data; - - return msm_ssbi_write(pmic->dev->parent, addr, &val, 1); -} - -static int pm8921_read_buf(const struct device *dev, u16 addr, u8 *buf, - int cnt) -{ - const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev); - const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data; - - return msm_ssbi_read(pmic->dev->parent, addr, buf, cnt); -} - -static int pm8921_write_buf(const struct device *dev, u16 addr, u8 *buf, - int cnt) -{ - const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev); - const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data; - - return msm_ssbi_write(pmic->dev->parent, addr, buf, cnt); -} - -static int pm8921_read_irq_stat(const struct device *dev, int irq) -{ - const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev); - const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data; - - return pm8xxx_get_irq_stat(pmic->irq_chip, irq); -} - -static struct pm8xxx_drvdata pm8921_drvdata = { - .pmic_readb = pm8921_readb, - .pmic_writeb = pm8921_writeb, - .pmic_read_buf = pm8921_read_buf, - .pmic_write_buf = pm8921_write_buf, - .pmic_read_irq_stat = pm8921_read_irq_stat, -}; - -static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data - *pdata, - struct pm8921 *pmic, - u32 rev) -{ - int ret = 0, irq_base = 0; - struct pm_irq_chip *irq_chip; - - if (pdata->irq_pdata) { - pdata->irq_pdata->irq_cdata.nirqs = PM8921_NR_IRQS; - pdata->irq_pdata->irq_cdata.rev = rev; - irq_base = pdata->irq_pdata->irq_base; - irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata); - - if (IS_ERR(irq_chip)) { - pr_err("Failed to init interrupts ret=%ld\n", - PTR_ERR(irq_chip)); - return PTR_ERR(irq_chip); - } - pmic->irq_chip = irq_chip; - } - return ret; -} - -static int __devinit pm8921_probe(struct platform_device *pdev) -{ - const struct pm8921_platform_data *pdata = pdev->dev.platform_data; - struct pm8921 *pmic; - int rc; - u8 val; - u32 rev; - - if (!pdata) { - pr_err("missing platform data\n"); - return -EINVAL; - } - - pmic = kzalloc(sizeof(struct pm8921), GFP_KERNEL); - if (!pmic) { - pr_err("Cannot alloc pm8921 struct\n"); - return -ENOMEM; - } - - /* Read PMIC chip revision */ - rc = msm_ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val)); - if (rc) { - pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc); - goto err_read_rev; - } - pr_info("PMIC revision 1: %02X\n", val); - rev = val; - - /* Read PMIC chip revision 2 */ - rc = msm_ssbi_read(pdev->dev.parent, REG_HWREV_2, &val, sizeof(val)); - if (rc) { - pr_err("Failed to read hw rev 2 reg %d:rc=%d\n", - REG_HWREV_2, rc); - goto err_read_rev; - } - pr_info("PMIC revision 2: %02X\n", val); - rev |= val << BITS_PER_BYTE; - - pmic->dev = &pdev->dev; - pm8921_drvdata.pm_chip_data = pmic; - platform_set_drvdata(pdev, &pm8921_drvdata); - - rc = pm8921_add_subdevices(pdata, pmic, rev); - if (rc) { - pr_err("Cannot add subdevices rc=%d\n", rc); - goto err; - } - - /* gpio might not work if no irq device is found */ - WARN_ON(pmic->irq_chip == NULL); - - return 0; - -err: - mfd_remove_devices(pmic->dev); - platform_set_drvdata(pdev, NULL); -err_read_rev: - kfree(pmic); - return rc; -} - -static int __devexit pm8921_remove(struct platform_device *pdev) -{ - struct pm8xxx_drvdata *drvdata; - struct pm8921 *pmic = NULL; - - drvdata = platform_get_drvdata(pdev); - if (drvdata) - pmic = drvdata->pm_chip_data; - if (pmic) - mfd_remove_devices(pmic->dev); - if (pmic->irq_chip) { - pm8xxx_irq_exit(pmic->irq_chip); - pmic->irq_chip = NULL; - } - platform_set_drvdata(pdev, NULL); - kfree(pmic); - - return 0; -} - -static struct platform_driver pm8921_driver = { - .probe = pm8921_probe, - .remove = __devexit_p(pm8921_remove), - .driver = { - .name = "pm8921-core", - .owner = THIS_MODULE, - }, -}; - -static int __init pm8921_init(void) -{ - return platform_driver_register(&pm8921_driver); -} -subsys_initcall(pm8921_init); - -static void __exit pm8921_exit(void) -{ - platform_driver_unregister(&pm8921_driver); -} -module_exit(pm8921_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("PMIC 8921 core driver"); -MODULE_VERSION("1.0"); -MODULE_ALIAS("platform:pm8921-core"); diff --git a/trunk/drivers/mfd/pm8xxx-irq.c b/trunk/drivers/mfd/pm8xxx-irq.c deleted file mode 100644 index d452dd013081..000000000000 --- a/trunk/drivers/mfd/pm8xxx-irq.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* PMIC8xxx IRQ */ - -#define SSBI_REG_ADDR_IRQ_BASE 0x1BB - -#define SSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0) -#define SSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1) -#define SSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2) -#define SSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3) -#define SSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4) -#define SSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5) -#define SSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6) -#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7) -#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8) - -#define PM_IRQF_LVL_SEL 0x01 /* level select */ -#define PM_IRQF_MASK_FE 0x02 /* mask falling edge */ -#define PM_IRQF_MASK_RE 0x04 /* mask rising edge */ -#define PM_IRQF_CLR 0x08 /* clear interrupt */ -#define PM_IRQF_BITS_MASK 0x70 -#define PM_IRQF_BITS_SHIFT 4 -#define PM_IRQF_WRITE 0x80 - -#define PM_IRQF_MASK_ALL (PM_IRQF_MASK_FE | \ - PM_IRQF_MASK_RE) - -struct pm_irq_chip { - struct device *dev; - spinlock_t pm_irq_lock; - unsigned int devirq; - unsigned int irq_base; - unsigned int num_irqs; - unsigned int num_blocks; - unsigned int num_masters; - u8 config[0]; -}; - -static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp) -{ - return pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp); -} - -static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp) -{ - return pm8xxx_readb(chip->dev, - SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp); -} - -static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip) -{ - int rc; - - spin_lock(&chip->pm_irq_lock); - rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); - if (rc) { - pr_err("Failed Selecting Block %d rc=%d\n", bp, rc); - goto bail; - } - - rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip); - if (rc) - pr_err("Failed Reading Status rc=%d\n", rc); -bail: - spin_unlock(&chip->pm_irq_lock); - return rc; -} - -static int pm8xxx_config_irq(struct pm_irq_chip *chip, u8 bp, u8 cp) -{ - int rc; - - spin_lock(&chip->pm_irq_lock); - rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); - if (rc) { - pr_err("Failed Selecting Block %d rc=%d\n", bp, rc); - goto bail; - } - - cp |= PM_IRQF_WRITE; - rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp); - if (rc) - pr_err("Failed Configuring IRQ rc=%d\n", rc); -bail: - spin_unlock(&chip->pm_irq_lock); - return rc; -} - -static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block) -{ - int pmirq, irq, i, ret = 0; - u8 bits; - - ret = pm8xxx_read_block_irq(chip, block, &bits); - if (ret) { - pr_err("Failed reading %d block ret=%d", block, ret); - return ret; - } - if (!bits) { - pr_err("block bit set in master but no irqs: %d", block); - return 0; - } - - /* Check IRQ bits */ - for (i = 0; i < 8; i++) { - if (bits & (1 << i)) { - pmirq = block * 8 + i; - irq = pmirq + chip->irq_base; - generic_handle_irq(irq); - } - } - return 0; -} - -static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master) -{ - u8 blockbits; - int block_number, i, ret = 0; - - ret = pm8xxx_read_master_irq(chip, master, &blockbits); - if (ret) { - pr_err("Failed to read master %d ret=%d\n", master, ret); - return ret; - } - if (!blockbits) { - pr_err("master bit set in root but no blocks: %d", master); - return 0; - } - - for (i = 0; i < 8; i++) - if (blockbits & (1 << i)) { - block_number = master * 8 + i; /* block # */ - ret |= pm8xxx_irq_block_handler(chip, block_number); - } - return ret; -} - -static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - struct pm_irq_chip *chip = irq_desc_get_handler_data(desc); - struct irq_chip *irq_chip = irq_desc_get_chip(desc); - u8 root; - int i, ret, masters = 0; - - ret = pm8xxx_read_root_irq(chip, &root); - if (ret) { - pr_err("Can't read root status ret=%d\n", ret); - return; - } - - /* on pm8xxx series masters start from bit 1 of the root */ - masters = root >> 1; - - /* Read allowed masters for blocks. */ - for (i = 0; i < chip->num_masters; i++) - if (masters & (1 << i)) - pm8xxx_irq_master_handler(chip, i); - - irq_chip->irq_ack(&desc->irq_data); -} - -static void pm8xxx_irq_mask_ack(struct irq_data *d) -{ - struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); - unsigned int pmirq = d->irq - chip->irq_base; - int master, irq_bit; - u8 block, config; - - block = pmirq / 8; - master = block / 8; - irq_bit = pmirq % 8; - - config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR; - pm8xxx_config_irq(chip, block, config); -} - -static void pm8xxx_irq_unmask(struct irq_data *d) -{ - struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); - unsigned int pmirq = d->irq - chip->irq_base; - int master, irq_bit; - u8 block, config; - - block = pmirq / 8; - master = block / 8; - irq_bit = pmirq % 8; - - config = chip->config[pmirq]; - pm8xxx_config_irq(chip, block, config); -} - -static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type) -{ - struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); - unsigned int pmirq = d->irq - chip->irq_base; - int master, irq_bit; - u8 block, config; - - block = pmirq / 8; - master = block / 8; - irq_bit = pmirq % 8; - - chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT) - | PM_IRQF_MASK_ALL; - if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { - if (flow_type & IRQF_TRIGGER_RISING) - chip->config[pmirq] &= ~PM_IRQF_MASK_RE; - if (flow_type & IRQF_TRIGGER_FALLING) - chip->config[pmirq] &= ~PM_IRQF_MASK_FE; - } else { - chip->config[pmirq] |= PM_IRQF_LVL_SEL; - - if (flow_type & IRQF_TRIGGER_HIGH) - chip->config[pmirq] &= ~PM_IRQF_MASK_RE; - else - chip->config[pmirq] &= ~PM_IRQF_MASK_FE; - } - - config = chip->config[pmirq] | PM_IRQF_CLR; - return pm8xxx_config_irq(chip, block, config); -} - -static int pm8xxx_irq_set_wake(struct irq_data *d, unsigned int on) -{ - return 0; -} - -static struct irq_chip pm8xxx_irq_chip = { - .name = "pm8xxx", - .irq_mask_ack = pm8xxx_irq_mask_ack, - .irq_unmask = pm8xxx_irq_unmask, - .irq_set_type = pm8xxx_irq_set_type, - .irq_set_wake = pm8xxx_irq_set_wake, - .flags = IRQCHIP_MASK_ON_SUSPEND, -}; - -/** - * pm8xxx_get_irq_stat - get the status of the irq line - * @chip: pointer to identify a pmic irq controller - * @irq: the irq number - * - * The pm8xxx gpio and mpp rely on the interrupt block to read - * the values on their pins. This function is to facilitate reading - * the status of a gpio or an mpp line. The caller has to convert the - * gpio number to irq number. - * - * RETURNS: - * an int indicating the value read on that line - */ -int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq) -{ - int pmirq, rc; - u8 block, bits, bit; - unsigned long flags; - - if (chip == NULL || irq < chip->irq_base || - irq >= chip->irq_base + chip->num_irqs) - return -EINVAL; - - pmirq = irq - chip->irq_base; - - block = pmirq / 8; - bit = pmirq % 8; - - spin_lock_irqsave(&chip->pm_irq_lock, flags); - - rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, block); - if (rc) { - pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n", - irq, pmirq, block, rc); - goto bail_out; - } - - rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits); - if (rc) { - pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n", - irq, pmirq, block, rc); - goto bail_out; - } - - rc = (bits & (1 << bit)) ? 1 : 0; - -bail_out: - spin_unlock_irqrestore(&chip->pm_irq_lock, flags); - - return rc; -} -EXPORT_SYMBOL_GPL(pm8xxx_get_irq_stat); - -struct pm_irq_chip * __devinit pm8xxx_irq_init(struct device *dev, - const struct pm8xxx_irq_platform_data *pdata) -{ - struct pm_irq_chip *chip; - int devirq, rc; - unsigned int pmirq; - - if (!pdata) { - pr_err("No platform data\n"); - return ERR_PTR(-EINVAL); - } - - devirq = pdata->devirq; - if (devirq < 0) { - pr_err("missing devirq\n"); - rc = devirq; - return ERR_PTR(-EINVAL); - } - - chip = kzalloc(sizeof(struct pm_irq_chip) - + sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL); - if (!chip) { - pr_err("Cannot alloc pm_irq_chip struct\n"); - return ERR_PTR(-EINVAL); - } - - chip->dev = dev; - chip->devirq = devirq; - chip->irq_base = pdata->irq_base; - chip->num_irqs = pdata->irq_cdata.nirqs; - chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8); - chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8); - spin_lock_init(&chip->pm_irq_lock); - - for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) { - irq_set_chip_and_handler(chip->irq_base + pmirq, - &pm8xxx_irq_chip, - handle_level_irq); - irq_set_chip_data(chip->irq_base + pmirq, chip); -#ifdef CONFIG_ARM - set_irq_flags(chip->irq_base + pmirq, IRQF_VALID); -#else - irq_set_noprobe(chip->irq_base + pmirq); -#endif - } - - irq_set_irq_type(devirq, pdata->irq_trigger_flag); - irq_set_handler_data(devirq, chip); - irq_set_chained_handler(devirq, pm8xxx_irq_handler); - set_irq_wake(devirq, 1); - - return chip; -} - -int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip) -{ - irq_set_chained_handler(chip->devirq, NULL); - kfree(chip); - return 0; -} diff --git a/trunk/drivers/mfd/rdc321x-southbridge.c b/trunk/drivers/mfd/rdc321x-southbridge.c index 809bd4a61089..10dbe6374a89 100644 --- a/trunk/drivers/mfd/rdc321x-southbridge.c +++ b/trunk/drivers/mfd/rdc321x-southbridge.c @@ -61,14 +61,12 @@ static struct mfd_cell rdc321x_sb_cells[] = { .name = "rdc321x-wdt", .resources = rdc321x_wdt_resource, .num_resources = ARRAY_SIZE(rdc321x_wdt_resource), - .platform_data = &rdc321x_wdt_pdata, - .pdata_size = sizeof(rdc321x_wdt_pdata), + .mfd_data = &rdc321x_wdt_pdata, }, { .name = "rdc321x-gpio", .resources = rdc321x_gpio_resources, .num_resources = ARRAY_SIZE(rdc321x_gpio_resources), - .platform_data = &rdc321x_gpio_pdata, - .pdata_size = sizeof(rdc321x_gpio_pdata), + .mfd_data = &rdc321x_gpio_pdata, }, }; diff --git a/trunk/drivers/mfd/t7l66xb.c b/trunk/drivers/mfd/t7l66xb.c index 91ad21ef7721..42830e692964 100644 --- a/trunk/drivers/mfd/t7l66xb.c +++ b/trunk/drivers/mfd/t7l66xb.c @@ -170,8 +170,7 @@ static struct mfd_cell t7l66xb_cells[] = { .name = "tmio-mmc", .enable = t7l66xb_mmc_enable, .disable = t7l66xb_mmc_disable, - .platform_data = &t7166xb_mmc_data, - .pdata_size = sizeof(t7166xb_mmc_data), + .mfd_data = &t7166xb_mmc_data, .num_resources = ARRAY_SIZE(t7l66xb_mmc_resources), .resources = t7l66xb_mmc_resources, }, @@ -383,8 +382,7 @@ static int t7l66xb_probe(struct platform_device *dev) t7l66xb_attach_irq(dev); - t7l66xb_cells[T7L66XB_CELL_NAND].platform_data = pdata->nand_data; - t7l66xb_cells[T7L66XB_CELL_NAND].pdata_size = sizeof(*pdata->nand_data); + t7l66xb_cells[T7L66XB_CELL_NAND].mfd_data = pdata->nand_data; ret = mfd_add_devices(&dev->dev, dev->id, t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), diff --git a/trunk/drivers/mfd/tc6387xb.c b/trunk/drivers/mfd/tc6387xb.c index ad715bf49cac..b006f7cee952 100644 --- a/trunk/drivers/mfd/tc6387xb.c +++ b/trunk/drivers/mfd/tc6387xb.c @@ -131,8 +131,7 @@ static struct mfd_cell tc6387xb_cells[] = { .name = "tmio-mmc", .enable = tc6387xb_mmc_enable, .disable = tc6387xb_mmc_disable, - .platform_data = &tc6387xb_mmc_data, - .pdata_size = sizeof(tc6387xb_mmc_data), + .mfd_data = &tc6387xb_mmc_data, .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources), .resources = tc6387xb_mmc_resources, }, diff --git a/trunk/drivers/mfd/tc6393xb.c b/trunk/drivers/mfd/tc6393xb.c index 9612264f0e6d..fc53ce287601 100644 --- a/trunk/drivers/mfd/tc6393xb.c +++ b/trunk/drivers/mfd/tc6393xb.c @@ -393,8 +393,7 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = { .name = "tmio-mmc", .enable = tc6393xb_mmc_enable, .resume = tc6393xb_mmc_resume, - .platform_data = &tc6393xb_mmc_data, - .pdata_size = sizeof(tc6393xb_mmc_data), + .mfd_data = &tc6393xb_mmc_data, .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), .resources = tc6393xb_mmc_resources, }, @@ -693,11 +692,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) goto err_setup; } - tc6393xb_cells[TC6393XB_CELL_NAND].platform_data = tcpd->nand_data; - tc6393xb_cells[TC6393XB_CELL_NAND].pdata_size = - sizeof(*tcpd->nand_data); - tc6393xb_cells[TC6393XB_CELL_FB].platform_data = tcpd->fb_data; - tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data); + tc6393xb_cells[TC6393XB_CELL_NAND].mfd_data = tcpd->nand_data; + tc6393xb_cells[TC6393XB_CELL_FB].mfd_data = tcpd->fb_data; ret = mfd_add_devices(&dev->dev, dev->id, tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), diff --git a/trunk/drivers/mfd/timberdale.c b/trunk/drivers/mfd/timberdale.c index 69272e4e3459..94c6c8afad12 100644 --- a/trunk/drivers/mfd/timberdale.c +++ b/trunk/drivers/mfd/timberdale.c @@ -384,8 +384,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { .name = "timb-dma", .num_resources = ARRAY_SIZE(timberdale_dma_resources), .resources = timberdale_dma_resources, - .platform_data = &timb_dma_platform_data, - .pdata_size = sizeof(timb_dma_platform_data), + .mfd_data = &timb_dma_platform_data, }, { .name = "timb-uart", @@ -396,43 +395,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { .name = "xiic-i2c", .num_resources = ARRAY_SIZE(timberdale_xiic_resources), .resources = timberdale_xiic_resources, - .platform_data = &timberdale_xiic_platform_data, - .pdata_size = sizeof(timberdale_xiic_platform_data), + .mfd_data = &timberdale_xiic_platform_data, }, { .name = "timb-gpio", .num_resources = ARRAY_SIZE(timberdale_gpio_resources), .resources = timberdale_gpio_resources, - .platform_data = &timberdale_gpio_platform_data, - .pdata_size = sizeof(timberdale_gpio_platform_data), + .mfd_data = &timberdale_gpio_platform_data, }, { .name = "timb-video", .num_resources = ARRAY_SIZE(timberdale_video_resources), .resources = timberdale_video_resources, - .platform_data = &timberdale_video_platform_data, - .pdata_size = sizeof(timberdale_video_platform_data), + .mfd_data = &timberdale_video_platform_data, }, { .name = "timb-radio", .num_resources = ARRAY_SIZE(timberdale_radio_resources), .resources = timberdale_radio_resources, - .platform_data = &timberdale_radio_platform_data, - .pdata_size = sizeof(timberdale_radio_platform_data), + .mfd_data = &timberdale_radio_platform_data, }, { .name = "xilinx_spi", .num_resources = ARRAY_SIZE(timberdale_spi_resources), .resources = timberdale_spi_resources, - .platform_data = &timberdale_xspi_platform_data, - .pdata_size = sizeof(timberdale_xspi_platform_data), + .mfd_data = &timberdale_xspi_platform_data, }, { .name = "ks8842", .num_resources = ARRAY_SIZE(timberdale_eth_resources), .resources = timberdale_eth_resources, - .platform_data = &timberdale_ks8842_platform_data, - .pdata_size = sizeof(timberdale_ks8842_platform_data), + .mfd_data = &timberdale_ks8842_platform_data, }, }; @@ -441,8 +434,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { .name = "timb-dma", .num_resources = ARRAY_SIZE(timberdale_dma_resources), .resources = timberdale_dma_resources, - .platform_data = &timb_dma_platform_data, - .pdata_size = sizeof(timb_dma_platform_data), + .mfd_data = &timb_dma_platform_data, }, { .name = "timb-uart", @@ -458,15 +450,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { .name = "xiic-i2c", .num_resources = ARRAY_SIZE(timberdale_xiic_resources), .resources = timberdale_xiic_resources, - .platform_data = &timberdale_xiic_platform_data, - .pdata_size = sizeof(timberdale_xiic_platform_data), + .mfd_data = &timberdale_xiic_platform_data, }, { .name = "timb-gpio", .num_resources = ARRAY_SIZE(timberdale_gpio_resources), .resources = timberdale_gpio_resources, - .platform_data = &timberdale_gpio_platform_data, - .pdata_size = sizeof(timberdale_gpio_platform_data), + .mfd_data = &timberdale_gpio_platform_data, }, { .name = "timb-mlogicore", @@ -477,29 +467,25 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { .name = "timb-video", .num_resources = ARRAY_SIZE(timberdale_video_resources), .resources = timberdale_video_resources, - .platform_data = &timberdale_video_platform_data, - .pdata_size = sizeof(timberdale_video_platform_data), + .mfd_data = &timberdale_video_platform_data, }, { .name = "timb-radio", .num_resources = ARRAY_SIZE(timberdale_radio_resources), .resources = timberdale_radio_resources, - .platform_data = &timberdale_radio_platform_data, - .pdata_size = sizeof(timberdale_radio_platform_data), + .mfd_data = &timberdale_radio_platform_data, }, { .name = "xilinx_spi", .num_resources = ARRAY_SIZE(timberdale_spi_resources), .resources = timberdale_spi_resources, - .platform_data = &timberdale_xspi_platform_data, - .pdata_size = sizeof(timberdale_xspi_platform_data), + .mfd_data = &timberdale_xspi_platform_data, }, { .name = "ks8842", .num_resources = ARRAY_SIZE(timberdale_eth_resources), .resources = timberdale_eth_resources, - .platform_data = &timberdale_ks8842_platform_data, - .pdata_size = sizeof(timberdale_ks8842_platform_data), + .mfd_data = &timberdale_ks8842_platform_data, }, }; @@ -508,8 +494,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { .name = "timb-dma", .num_resources = ARRAY_SIZE(timberdale_dma_resources), .resources = timberdale_dma_resources, - .platform_data = &timb_dma_platform_data, - .pdata_size = sizeof(timb_dma_platform_data), + .mfd_data = &timb_dma_platform_data, }, { .name = "timb-uart", @@ -520,36 +505,31 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { .name = "xiic-i2c", .num_resources = ARRAY_SIZE(timberdale_xiic_resources), .resources = timberdale_xiic_resources, - .platform_data = &timberdale_xiic_platform_data, - .pdata_size = sizeof(timberdale_xiic_platform_data), + .mfd_data = &timberdale_xiic_platform_data, }, { .name = "timb-gpio", .num_resources = ARRAY_SIZE(timberdale_gpio_resources), .resources = timberdale_gpio_resources, - .platform_data = &timberdale_gpio_platform_data, - .pdata_size = sizeof(timberdale_gpio_platform_data), + .mfd_data = &timberdale_gpio_platform_data, }, { .name = "timb-video", .num_resources = ARRAY_SIZE(timberdale_video_resources), .resources = timberdale_video_resources, - .platform_data = &timberdale_video_platform_data, - .pdata_size = sizeof(timberdale_video_platform_data), + .mfd_data = &timberdale_video_platform_data, }, { .name = "timb-radio", .num_resources = ARRAY_SIZE(timberdale_radio_resources), .resources = timberdale_radio_resources, - .platform_data = &timberdale_radio_platform_data, - .pdata_size = sizeof(timberdale_radio_platform_data), + .mfd_data = &timberdale_radio_platform_data, }, { .name = "xilinx_spi", .num_resources = ARRAY_SIZE(timberdale_spi_resources), .resources = timberdale_spi_resources, - .platform_data = &timberdale_xspi_platform_data, - .pdata_size = sizeof(timberdale_xspi_platform_data), + .mfd_data = &timberdale_xspi_platform_data, }, }; @@ -558,8 +538,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { .name = "timb-dma", .num_resources = ARRAY_SIZE(timberdale_dma_resources), .resources = timberdale_dma_resources, - .platform_data = &timb_dma_platform_data, - .pdata_size = sizeof(timb_dma_platform_data), + .mfd_data = &timb_dma_platform_data, }, { .name = "timb-uart", @@ -570,43 +549,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { .name = "ocores-i2c", .num_resources = ARRAY_SIZE(timberdale_ocores_resources), .resources = timberdale_ocores_resources, - .platform_data = &timberdale_ocores_platform_data, - .pdata_size = sizeof(timberdale_ocores_platform_data), + .mfd_data = &timberdale_ocores_platform_data, }, { .name = "timb-gpio", .num_resources = ARRAY_SIZE(timberdale_gpio_resources), .resources = timberdale_gpio_resources, - .platform_data = &timberdale_gpio_platform_data, - .pdata_size = sizeof(timberdale_gpio_platform_data), + .mfd_data = &timberdale_gpio_platform_data, }, { .name = "timb-video", .num_resources = ARRAY_SIZE(timberdale_video_resources), .resources = timberdale_video_resources, - .platform_data = &timberdale_video_platform_data, - .pdata_size = sizeof(timberdale_video_platform_data), + .mfd_data = &timberdale_video_platform_data, }, { .name = "timb-radio", .num_resources = ARRAY_SIZE(timberdale_radio_resources), .resources = timberdale_radio_resources, - .platform_data = &timberdale_radio_platform_data, - .pdata_size = sizeof(timberdale_radio_platform_data), + .mfd_data = &timberdale_radio_platform_data, }, { .name = "xilinx_spi", .num_resources = ARRAY_SIZE(timberdale_spi_resources), .resources = timberdale_spi_resources, - .platform_data = &timberdale_xspi_platform_data, - .pdata_size = sizeof(timberdale_xspi_platform_data), + .mfd_data = &timberdale_xspi_platform_data, }, { .name = "ks8842", .num_resources = ARRAY_SIZE(timberdale_eth_resources), .resources = timberdale_eth_resources, - .platform_data = &timberdale_ks8842_platform_data, - .pdata_size = sizeof(timberdale_ks8842_platform_data), + .mfd_data = &timberdale_ks8842_platform_data, }, }; diff --git a/trunk/drivers/mfd/tps6105x.c b/trunk/drivers/mfd/tps6105x.c index a293b978e27c..46d8205646b6 100644 --- a/trunk/drivers/mfd/tps6105x.c +++ b/trunk/drivers/mfd/tps6105x.c @@ -183,8 +183,7 @@ static int __devinit tps6105x_probe(struct i2c_client *client, /* Set up and register the platform devices. */ for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) { /* One state holder for all drivers, this is simple */ - tps6105x_cells[i].platform_data = tps6105x; - tps6105x_cells[i].pdata_size = sizeof(*tps6105x); + tps6105x_cells[i].mfd_data = tps6105x; } ret = mfd_add_devices(&client->dev, 0, tps6105x_cells, diff --git a/trunk/drivers/mfd/tps6586x.c b/trunk/drivers/mfd/tps6586x.c index bba26d96c240..b600808690c1 100644 --- a/trunk/drivers/mfd/tps6586x.c +++ b/trunk/drivers/mfd/tps6586x.c @@ -270,8 +270,8 @@ static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset, { struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); - tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET2, - value << offset, 1 << offset); + __tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2, + value << offset); } static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, diff --git a/trunk/drivers/mfd/tps65910-irq.c b/trunk/drivers/mfd/tps65910-irq.c deleted file mode 100644 index 2bfad5c86cc7..000000000000 --- a/trunk/drivers/mfd/tps65910-irq.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * tps65910-irq.c -- TI TPS6591x - * - * Copyright 2010 Texas Instruments Inc. - * - * Author: Graeme Gregory - * Author: Jorge Eduardo Candelaria - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static inline int irq_to_tps65910_irq(struct tps65910 *tps65910, - int irq) -{ - return (irq - tps65910->irq_base); -} - -/* - * This is a threaded IRQ handler so can access I2C/SPI. Since all - * interrupts are clear on read the IRQ line will be reasserted and - * the physical IRQ will be handled again if another interrupt is - * asserted while we run - in the normal course of events this is a - * rare occurrence so we save I2C/SPI reads. We're also assuming that - * it's rare to get lots of interrupts firing simultaneously so try to - * minimise I/O. - */ -static irqreturn_t tps65910_irq(int irq, void *irq_data) -{ - struct tps65910 *tps65910 = irq_data; - u32 irq_sts; - u32 irq_mask; - u8 reg; - int i; - - tps65910->read(tps65910, TPS65910_INT_STS, 1, ®); - irq_sts = reg; - tps65910->read(tps65910, TPS65910_INT_STS2, 1, ®); - irq_sts |= reg << 8; - switch (tps65910_chip_id(tps65910)) { - case TPS65911: - tps65910->read(tps65910, TPS65910_INT_STS3, 1, ®); - irq_sts |= reg << 16; - } - - tps65910->read(tps65910, TPS65910_INT_MSK, 1, ®); - irq_mask = reg; - tps65910->read(tps65910, TPS65910_INT_MSK2, 1, ®); - irq_mask |= reg << 8; - switch (tps65910_chip_id(tps65910)) { - case TPS65911: - tps65910->read(tps65910, TPS65910_INT_MSK3, 1, ®); - irq_mask |= reg << 16; - } - - irq_sts &= ~irq_mask; - - if (!irq_sts) - return IRQ_NONE; - - for (i = 0; i < tps65910->irq_num; i++) { - - if (!(irq_sts & (1 << i))) - continue; - - handle_nested_irq(tps65910->irq_base + i); - } - - /* Write the STS register back to clear IRQs we handled */ - reg = irq_sts & 0xFF; - irq_sts >>= 8; - tps65910->write(tps65910, TPS65910_INT_STS, 1, ®); - reg = irq_sts & 0xFF; - tps65910->write(tps65910, TPS65910_INT_STS2, 1, ®); - switch (tps65910_chip_id(tps65910)) { - case TPS65911: - reg = irq_sts >> 8; - tps65910->write(tps65910, TPS65910_INT_STS3, 1, ®); - } - - return IRQ_HANDLED; -} - -static void tps65910_irq_lock(struct irq_data *data) -{ - struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); - - mutex_lock(&tps65910->irq_lock); -} - -static void tps65910_irq_sync_unlock(struct irq_data *data) -{ - struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); - u32 reg_mask; - u8 reg; - - tps65910->read(tps65910, TPS65910_INT_MSK, 1, ®); - reg_mask = reg; - tps65910->read(tps65910, TPS65910_INT_MSK2, 1, ®); - reg_mask |= reg << 8; - switch (tps65910_chip_id(tps65910)) { - case TPS65911: - tps65910->read(tps65910, TPS65910_INT_MSK3, 1, ®); - reg_mask |= reg << 16; - } - - if (tps65910->irq_mask != reg_mask) { - reg = tps65910->irq_mask & 0xFF; - tps65910->write(tps65910, TPS65910_INT_MSK, 1, ®); - reg = tps65910->irq_mask >> 8 & 0xFF; - tps65910->write(tps65910, TPS65910_INT_MSK2, 1, ®); - switch (tps65910_chip_id(tps65910)) { - case TPS65911: - reg = tps65910->irq_mask >> 16; - tps65910->write(tps65910, TPS65910_INT_MSK3, 1, ®); - } - } - mutex_unlock(&tps65910->irq_lock); -} - -static void tps65910_irq_enable(struct irq_data *data) -{ - struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); - - tps65910->irq_mask &= ~( 1 << irq_to_tps65910_irq(tps65910, data->irq)); -} - -static void tps65910_irq_disable(struct irq_data *data) -{ - struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); - - tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq)); -} - -static struct irq_chip tps65910_irq_chip = { - .name = "tps65910", - .irq_bus_lock = tps65910_irq_lock, - .irq_bus_sync_unlock = tps65910_irq_sync_unlock, - .irq_disable = tps65910_irq_disable, - .irq_enable = tps65910_irq_enable, -}; - -int tps65910_irq_init(struct tps65910 *tps65910, int irq, - struct tps65910_platform_data *pdata) -{ - int ret, cur_irq; - int flags = IRQF_ONESHOT; - - if (!irq) { - dev_warn(tps65910->dev, "No interrupt support, no core IRQ\n"); - return -EINVAL; - } - - if (!pdata || !pdata->irq_base) { - dev_warn(tps65910->dev, "No interrupt support, no IRQ base\n"); - return -EINVAL; - } - - tps65910->irq_mask = 0xFFFFFF; - - mutex_init(&tps65910->irq_lock); - tps65910->chip_irq = irq; - tps65910->irq_base = pdata->irq_base; - - switch (tps65910_chip_id(tps65910)) { - case TPS65910: - tps65910->irq_num = TPS65910_NUM_IRQ; - case TPS65911: - tps65910->irq_num = TPS65911_NUM_IRQ; - } - - /* Register with genirq */ - for (cur_irq = tps65910->irq_base; - cur_irq < tps65910->irq_num + tps65910->irq_base; - cur_irq++) { - irq_set_chip_data(cur_irq, tps65910); - irq_set_chip_and_handler(cur_irq, &tps65910_irq_chip, - handle_edge_irq); - irq_set_nested_thread(cur_irq, 1); - - /* ARM needs us to explicitly flag the IRQ as valid - * and will set them noprobe when we do so. */ -#ifdef CONFIG_ARM - set_irq_flags(cur_irq, IRQF_VALID); -#else - irq_set_noprobe(cur_irq); -#endif - } - - ret = request_threaded_irq(irq, NULL, tps65910_irq, flags, - "tps65910", tps65910); - - irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW); - - if (ret != 0) - dev_err(tps65910->dev, "Failed to request IRQ: %d\n", ret); - - return ret; -} - -int tps65910_irq_exit(struct tps65910 *tps65910) -{ - free_irq(tps65910->chip_irq, tps65910); - return 0; -} diff --git a/trunk/drivers/mfd/tps65910.c b/trunk/drivers/mfd/tps65910.c deleted file mode 100644 index 2229e66d80db..000000000000 --- a/trunk/drivers/mfd/tps65910.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * tps65910.c -- TI TPS6591x - * - * Copyright 2010 Texas Instruments Inc. - * - * Author: Graeme Gregory - * Author: Jorge Eduardo Candelaria - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static struct mfd_cell tps65910s[] = { - { - .name = "tps65910-pmic", - }, - { - .name = "tps65910-rtc", - }, - { - .name = "tps65910-power", - }, -}; - - -static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg, - int bytes, void *dest) -{ - struct i2c_client *i2c = tps65910->i2c_client; - struct i2c_msg xfer[2]; - int ret; - - /* Write register */ - xfer[0].addr = i2c->addr; - xfer[0].flags = 0; - xfer[0].len = 1; - xfer[0].buf = ® - - /* Read data */ - xfer[1].addr = i2c->addr; - xfer[1].flags = I2C_M_RD; - xfer[1].len = bytes; - xfer[1].buf = dest; - - ret = i2c_transfer(i2c->adapter, xfer, 2); - if (ret == 2) - ret = 0; - else if (ret >= 0) - ret = -EIO; - - return ret; -} - -static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg, - int bytes, void *src) -{ - struct i2c_client *i2c = tps65910->i2c_client; - /* we add 1 byte for device register */ - u8 msg[TPS65910_MAX_REGISTER + 1]; - int ret; - - if (bytes > TPS65910_MAX_REGISTER) - return -EINVAL; - - msg[0] = reg; - memcpy(&msg[1], src, bytes); - - ret = i2c_master_send(i2c, msg, bytes + 1); - if (ret < 0) - return ret; - if (ret != bytes + 1) - return -EIO; - return 0; -} - -int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask) -{ - u8 data; - int err; - - mutex_lock(&tps65910->io_mutex); - err = tps65910_i2c_read(tps65910, reg, 1, &data); - if (err) { - dev_err(tps65910->dev, "read from reg %x failed\n", reg); - goto out; - } - - data |= mask; - err = tps65910_i2c_write(tps65910, reg, 1, &data); - if (err) - dev_err(tps65910->dev, "write to reg %x failed\n", reg); - -out: - mutex_unlock(&tps65910->io_mutex); - return err; -} -EXPORT_SYMBOL_GPL(tps65910_set_bits); - -int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask) -{ - u8 data; - int err; - - mutex_lock(&tps65910->io_mutex); - err = tps65910_i2c_read(tps65910, reg, 1, &data); - if (err) { - dev_err(tps65910->dev, "read from reg %x failed\n", reg); - goto out; - } - - data &= mask; - err = tps65910_i2c_write(tps65910, reg, 1, &data); - if (err) - dev_err(tps65910->dev, "write to reg %x failed\n", reg); - -out: - mutex_unlock(&tps65910->io_mutex); - return err; -} -EXPORT_SYMBOL_GPL(tps65910_clear_bits); - -static int tps65910_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct tps65910 *tps65910; - struct tps65910_board *pmic_plat_data; - struct tps65910_platform_data *init_data; - int ret = 0; - - pmic_plat_data = dev_get_platdata(&i2c->dev); - if (!pmic_plat_data) - return -EINVAL; - - init_data = kzalloc(sizeof(struct tps65910_platform_data), GFP_KERNEL); - if (init_data == NULL) - return -ENOMEM; - - init_data->irq = pmic_plat_data->irq; - init_data->irq_base = pmic_plat_data->irq; - - tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL); - if (tps65910 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, tps65910); - tps65910->dev = &i2c->dev; - tps65910->i2c_client = i2c; - tps65910->id = id->driver_data; - tps65910->read = tps65910_i2c_read; - tps65910->write = tps65910_i2c_write; - mutex_init(&tps65910->io_mutex); - - ret = mfd_add_devices(tps65910->dev, -1, - tps65910s, ARRAY_SIZE(tps65910s), - NULL, 0); - if (ret < 0) - goto err; - - tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base); - - ret = tps65910_irq_init(tps65910, init_data->irq, init_data); - if (ret < 0) - goto err; - - return ret; - -err: - mfd_remove_devices(tps65910->dev); - kfree(tps65910); - return ret; -} - -static int tps65910_i2c_remove(struct i2c_client *i2c) -{ - struct tps65910 *tps65910 = i2c_get_clientdata(i2c); - - mfd_remove_devices(tps65910->dev); - kfree(tps65910); - - return 0; -} - -static const struct i2c_device_id tps65910_i2c_id[] = { - { "tps65910", TPS65910 }, - { "tps65911", TPS65911 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tps65910_i2c_id); - - -static struct i2c_driver tps65910_i2c_driver = { - .driver = { - .name = "tps65910", - .owner = THIS_MODULE, - }, - .probe = tps65910_i2c_probe, - .remove = tps65910_i2c_remove, - .id_table = tps65910_i2c_id, -}; - -static int __init tps65910_i2c_init(void) -{ - return i2c_add_driver(&tps65910_i2c_driver); -} -/* init early so consumer devices can complete system boot */ -subsys_initcall(tps65910_i2c_init); - -static void __exit tps65910_i2c_exit(void) -{ - i2c_del_driver(&tps65910_i2c_driver); -} -module_exit(tps65910_i2c_exit); - -MODULE_AUTHOR("Graeme Gregory "); -MODULE_AUTHOR("Jorge Eduardo Candelaria "); -MODULE_DESCRIPTION("TPS6591x chip family multi-function driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/mfd/tps65911-comparator.c b/trunk/drivers/mfd/tps65911-comparator.c deleted file mode 100644 index 3d2dc56a3d40..000000000000 --- a/trunk/drivers/mfd/tps65911-comparator.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * tps65910.c -- TI TPS6591x - * - * Copyright 2010 Texas Instruments Inc. - * - * Author: Jorge Eduardo Candelaria - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define COMP 0 -#define COMP1 1 -#define COMP2 2 - -/* Comparator 1 voltage selection table in milivolts */ -static const u16 COMP_VSEL_TABLE[] = { - 0, 2500, 2500, 2500, 2500, 2550, 2600, 2650, - 2700, 2750, 2800, 2850, 2900, 2950, 3000, 3050, - 3100, 3150, 3200, 3250, 3300, 3350, 3400, 3450, - 3500, -}; - -struct comparator { - const char *name; - int reg; - int uV_max; - const u16 *vsel_table; -}; - -static struct comparator tps_comparators[] = { - { - .name = "COMP1", - .reg = TPS65911_VMBCH, - .uV_max = 3500, - .vsel_table = COMP_VSEL_TABLE, - }, - { - .name = "COMP2", - .reg = TPS65911_VMBCH2, - .uV_max = 3500, - .vsel_table = COMP_VSEL_TABLE, - }, -}; - -static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage) -{ - struct comparator tps_comp = tps_comparators[id]; - int curr_voltage = 0; - int ret; - u8 index = 0, val; - - if (id == COMP) - return 0; - - while (curr_voltage < tps_comp.uV_max) { - curr_voltage = tps_comp.vsel_table[index]; - if (curr_voltage >= voltage) - break; - else if (curr_voltage < voltage) - index ++; - } - - if (curr_voltage > tps_comp.uV_max) - return -EINVAL; - - val = index << 1; - ret = tps65910->write(tps65910, tps_comp.reg, 1, &val); - - return ret; -} - -static int comp_threshold_get(struct tps65910 *tps65910, int id) -{ - struct comparator tps_comp = tps_comparators[id]; - int ret; - u8 val; - - if (id == COMP) - return 0; - - ret = tps65910->read(tps65910, tps_comp.reg, 1, &val); - if (ret < 0) - return ret; - - val >>= 1; - return tps_comp.vsel_table[val]; -} - -static ssize_t comp_threshold_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct tps65910 *tps65910 = dev_get_drvdata(dev->parent); - struct attribute comp_attr = attr->attr; - int id, uVolt; - - if (!strcmp(comp_attr.name, "comp1_threshold")) - id = COMP1; - else if (!strcmp(comp_attr.name, "comp2_threshold")) - id = COMP2; - else - return -EINVAL; - - uVolt = comp_threshold_get(tps65910, id); - - return sprintf(buf, "%d\n", uVolt); -} - -static DEVICE_ATTR(comp1_threshold, S_IRUGO, comp_threshold_show, NULL); -static DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL); - -static __devinit int tps65911_comparator_probe(struct platform_device *pdev) -{ - struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); - struct tps65910_platform_data *pdata = dev_get_platdata(tps65910->dev); - int ret; - - ret = comp_threshold_set(tps65910, COMP1, pdata->vmbch_threshold); - if (ret < 0) { - dev_err(&pdev->dev, "cannot set COMP1 threshold\n"); - return ret; - } - - ret = comp_threshold_set(tps65910, COMP2, pdata->vmbch2_threshold); - if (ret < 0) { - dev_err(&pdev->dev, "cannot set COMP2 theshold\n"); - return ret; - } - - /* Create sysfs entry */ - ret = device_create_file(&pdev->dev, &dev_attr_comp1_threshold); - if (ret < 0) - dev_err(&pdev->dev, "failed to add COMP1 sysfs file\n"); - - ret = device_create_file(&pdev->dev, &dev_attr_comp2_threshold); - if (ret < 0) - dev_err(&pdev->dev, "failed to add COMP2 sysfs file\n"); - - return ret; -} - -static __devexit int tps65911_comparator_remove(struct platform_device *pdev) -{ - struct tps65910 *tps65910; - - tps65910 = dev_get_drvdata(pdev->dev.parent); - - return 0; -} - -static struct platform_driver tps65911_comparator_driver = { - .driver = { - .name = "tps65911-comparator", - .owner = THIS_MODULE, - }, - .probe = tps65911_comparator_probe, - .remove = __devexit_p(tps65911_comparator_remove), -}; - -static int __init tps65911_comparator_init(void) -{ - return platform_driver_register(&tps65911_comparator_driver); -} -subsys_initcall(tps65911_comparator_init); - -static void __exit tps65911_comparator_exit(void) -{ - platform_driver_unregister(&tps65911_comparator_driver); -} -module_exit(tps65911_comparator_exit); - -MODULE_AUTHOR("Jorge Eduardo Candelaria "); -MODULE_DESCRIPTION("TPS65911 comparator driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tps65911-comparator"); diff --git a/trunk/drivers/mfd/twl-core.c b/trunk/drivers/mfd/twl-core.c index b8f2a4e7f6e7..960b5bed7f52 100644 --- a/trunk/drivers/mfd/twl-core.c +++ b/trunk/drivers/mfd/twl-core.c @@ -198,7 +198,6 @@ #define TWL6030_BASEADD_GASGAUGE 0x00C0 #define TWL6030_BASEADD_PIH 0x00D0 #define TWL6030_BASEADD_CHARGER 0x00E0 -#define TWL6025_BASEADD_CHARGER 0x00DA /* subchip/slave 2 0x4A - DFT */ #define TWL6030_BASEADD_DIEID 0x00C0 @@ -230,9 +229,6 @@ /* is driver active, bound to a chip? */ static bool inuse; -/* TWL IDCODE Register value */ -static u32 twl_idcode; - static unsigned int twl_id; unsigned int twl_rev(void) { @@ -332,7 +328,6 @@ static struct twl_mapping twl6030_map[] = { { SUB_CHIP_ID0, TWL6030_BASEADD_RTC }, { SUB_CHIP_ID0, TWL6030_BASEADD_MEM }, - { SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER }, }; /*----------------------------------------------------------------------*/ @@ -492,58 +487,6 @@ EXPORT_SYMBOL(twl_i2c_read_u8); /*----------------------------------------------------------------------*/ -/** - * twl_read_idcode_register - API to read the IDCODE register. - * - * Unlocks the IDCODE register and read the 32 bit value. - */ -static int twl_read_idcode_register(void) -{ - int err; - - err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, TWL_EEPROM_R_UNLOCK, - REG_UNLOCK_TEST_REG); - if (err) { - pr_err("TWL4030 Unable to unlock IDCODE registers -%d\n", err); - goto fail; - } - - err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_idcode), - REG_IDCODE_7_0, 4); - if (err) { - pr_err("TWL4030: unable to read IDCODE -%d\n", err); - goto fail; - } - - err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x0, REG_UNLOCK_TEST_REG); - if (err) - pr_err("TWL4030 Unable to relock IDCODE registers -%d\n", err); -fail: - return err; -} - -/** - * twl_get_type - API to get TWL Si type. - * - * Api to get the TWL Si type from IDCODE value. - */ -int twl_get_type(void) -{ - return TWL_SIL_TYPE(twl_idcode); -} -EXPORT_SYMBOL_GPL(twl_get_type); - -/** - * twl_get_version - API to get TWL Si version. - * - * Api to get the TWL Si version from IDCODE value. - */ -int twl_get_version(void) -{ - return TWL_SIL_REV(twl_idcode); -} -EXPORT_SYMBOL_GPL(twl_get_version); - static struct device * add_numbered_child(unsigned chip, const char *name, int num, void *pdata, unsigned pdata_len, @@ -606,7 +549,7 @@ static inline struct device *add_child(unsigned chip, const char *name, static struct device * add_regulator_linked(int num, struct regulator_init_data *pdata, struct regulator_consumer_supply *consumers, - unsigned num_consumers, unsigned long features) + unsigned num_consumers) { unsigned sub_chip_id; /* regulator framework demands init_data ... */ @@ -618,8 +561,6 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, pdata->num_consumer_supplies = num_consumers; } - pdata->driver_data = (void *)features; - /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; return add_numbered_child(sub_chip_id, "twl_reg", num, @@ -627,10 +568,9 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, } static struct device * -add_regulator(int num, struct regulator_init_data *pdata, - unsigned long features) +add_regulator(int num, struct regulator_init_data *pdata) { - return add_regulator_linked(num, pdata, NULL, 0, features); + return add_regulator_linked(num, pdata, NULL, 0); } /* @@ -710,20 +650,17 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) }; child = add_regulator_linked(TWL4030_REG_VUSB1V5, - &usb_fixed, &usb1v5, 1, - features); + &usb_fixed, &usb1v5, 1); if (IS_ERR(child)) return PTR_ERR(child); child = add_regulator_linked(TWL4030_REG_VUSB1V8, - &usb_fixed, &usb1v8, 1, - features); + &usb_fixed, &usb1v8, 1); if (IS_ERR(child)) return PTR_ERR(child); child = add_regulator_linked(TWL4030_REG_VUSB3V1, - &usb_fixed, &usb3v1, 1, - features); + &usb_fixed, &usb3v1, 1); if (IS_ERR(child)) return PTR_ERR(child); @@ -748,8 +685,9 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) } if (twl_has_usb() && pdata->usb && twl_class_is_6030()) { - static struct regulator_consumer_supply usb3v3; - int regulator; + static struct regulator_consumer_supply usb3v3 = { + .supply = "vusb", + }; if (twl_has_regulator()) { /* this is a template that gets copied */ @@ -762,22 +700,12 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | REGULATOR_CHANGE_STATUS, }; - if (features & TWL6025_SUBCLASS) { - usb3v3.supply = "ldousb"; - regulator = TWL6025_REG_LDOUSB; - } else { - usb3v3.supply = "vusb"; - regulator = TWL6030_REG_VUSB; - } - child = add_regulator_linked(regulator, &usb_fixed, - &usb3v3, 1, - features); + child = add_regulator_linked(TWL6030_REG_VUSB, + &usb_fixed, &usb3v3, 1); if (IS_ERR(child)) return PTR_ERR(child); } - pdata->usb->features = features; - child = add_child(0, "twl6030_usb", pdata->usb, sizeof(*pdata->usb), true, @@ -790,16 +718,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) /* we need to connect regulators to this transceiver */ if (twl_has_regulator() && child) usb3v3.dev = child; - } else if (twl_has_regulator() && twl_class_is_6030()) { - if (features & TWL6025_SUBCLASS) - child = add_regulator(TWL6025_REG_LDOUSB, - pdata->ldousb, features); - else - child = add_regulator(TWL6030_REG_VUSB, - pdata->vusb, features); - if (IS_ERR(child)) - return PTR_ERR(child); } if (twl_has_watchdog() && twl_class_is_4030()) { @@ -836,55 +755,46 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) /* twl4030 regulators */ if (twl_has_regulator() && twl_class_is_4030()) { - child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1, - features); + child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VIO, pdata->vio, - features); + child = add_regulator(TWL4030_REG_VIO, pdata->vio); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1, - features); + child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2, - features); + child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1, - features); + child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VDAC, pdata->vdac, - features); + child = add_regulator(TWL4030_REG_VDAC, pdata->vdac); if (IS_ERR(child)) return PTR_ERR(child); child = add_regulator((features & TWL4030_VAUX2) ? TWL4030_REG_VAUX2_4030 : TWL4030_REG_VAUX2, - pdata->vaux2, features); + pdata->vaux2); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1, - features); + child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2, - features); + child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig, - features); + child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig); if (IS_ERR(child)) return PTR_ERR(child); } @@ -892,152 +802,72 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) /* maybe add LDOs that are omitted on cost-reduced parts */ if (twl_has_regulator() && !(features & TPS_SUBSET) && twl_class_is_4030()) { - child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2, - features); + child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2, - features); + child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VSIM, pdata->vsim, - features); + child = add_regulator(TWL4030_REG_VSIM, pdata->vsim); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1, - features); + child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3, - features); + child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4, - features); + child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4); if (IS_ERR(child)) return PTR_ERR(child); } /* twl6030 regulators */ - if (twl_has_regulator() && twl_class_is_6030() && - !(features & TWL6025_SUBCLASS)) { - child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VPP, pdata->vpp, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VDAC, pdata->vdac, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - } - - /* 6030 and 6025 share this regulator */ if (twl_has_regulator() && twl_class_is_6030()) { - child = add_regulator(TWL6030_REG_VANA, pdata->vana, - features); + child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc); if (IS_ERR(child)) return PTR_ERR(child); - } - /* twl6025 regulators */ - if (twl_has_regulator() && twl_class_is_6030() && - (features & TWL6025_SUBCLASS)) { - child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5, - features); + child = add_regulator(TWL6030_REG_VPP, pdata->vpp); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1, - features); + child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7, - features); + child = add_regulator(TWL6030_REG_VANA, pdata->vana); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6, - features); + child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln, - features); + child = add_regulator(TWL6030_REG_VDAC, pdata->vdac); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2, - features); + child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4, - features); + child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3, - features); + child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3, - features); + child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg); if (IS_ERR(child)) return PTR_ERR(child); - - child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - - child = add_regulator(TWL6025_REG_VIO, pdata->vio6025, - features); - if (IS_ERR(child)) - return PTR_ERR(child); - } if (twl_has_bci() && pdata->bci && @@ -1184,7 +1014,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) unsigned i; struct twl4030_platform_data *pdata = client->dev.platform_data; u8 temp; - int ret = 0; if (!pdata) { dev_dbg(&client->dev, "no platform data?\n"); @@ -1231,12 +1060,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) /* setup clock framework */ clocks_init(&client->dev, pdata->clock); - /* read TWL IDCODE Register */ - if (twl_id == TWL4030_CLASS_ID) { - ret = twl_read_idcode_register(); - WARN(ret < 0, "Error: reading twl_idcode register value\n"); - } - /* load power event scripts */ if (twl_has_power() && pdata->power) twl4030_power_init(pdata->power); @@ -1285,7 +1108,6 @@ static const struct i2c_device_id twl_ids[] = { { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */ - { "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */ { /* end of list */ }, }; MODULE_DEVICE_TABLE(i2c, twl_ids); diff --git a/trunk/drivers/mfd/twl4030-codec.c b/trunk/drivers/mfd/twl4030-codec.c index 2bf4136464c1..c02fded316c9 100644 --- a/trunk/drivers/mfd/twl4030-codec.c +++ b/trunk/drivers/mfd/twl4030-codec.c @@ -1,7 +1,7 @@ /* * MFD driver for twl4030 codec submodule * - * Author: Peter Ujfalusi + * Author: Peter Ujfalusi * * Copyright: (C) 2009 Nokia Corporation * @@ -208,15 +208,13 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev) if (pdata->audio) { cell = &codec->cells[childs]; cell->name = "twl4030-codec"; - cell->platform_data = pdata->audio; - cell->pdata_size = sizeof(*pdata->audio); + cell->mfd_data = pdata->audio; childs++; } if (pdata->vibra) { cell = &codec->cells[childs]; cell->name = "twl4030-vibra"; - cell->platform_data = pdata->vibra; - cell->pdata_size = sizeof(*pdata->vibra); + cell->mfd_data = pdata->vibra; childs++; } @@ -272,6 +270,6 @@ static void __devexit twl4030_codec_exit(void) } module_exit(twl4030_codec_exit); -MODULE_AUTHOR("Peter Ujfalusi "); +MODULE_AUTHOR("Peter Ujfalusi "); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/mfd/twl4030-power.c b/trunk/drivers/mfd/twl4030-power.c index a764676f0922..2c0d4d16491a 100644 --- a/trunk/drivers/mfd/twl4030-power.c +++ b/trunk/drivers/mfd/twl4030-power.c @@ -120,7 +120,7 @@ static u8 res_config_addrs[] = { [RES_HFCLKOUT] = 0x8b, [RES_32KCLKOUT] = 0x8e, [RES_RESET] = 0x91, - [RES_MAIN_REF] = 0x94, + [RES_Main_Ref] = 0x94, }; static int __init twl4030_write_script_byte(u8 address, u8 byte) @@ -448,7 +448,7 @@ static int __init load_twl4030_script(struct twl4030_script *tscript, goto out; } if (tscript->flags & TWL4030_SLEEP_SCRIPT) { - if (!order) + if (order) pr_warning("TWL4030: Bad order of scripts (sleep "\ "script before wakeup) Leads to boot"\ "failure on some boards\n"); @@ -485,9 +485,9 @@ int twl4030_remove_script(u8 flags) return err; } if (flags & TWL4030_WAKEUP12_SCRIPT) { + if (err) err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, R_SEQ_ADD_S2A12); - if (err) return err; } if (flags & TWL4030_WAKEUP3_SCRIPT) { diff --git a/trunk/drivers/mfd/twl6030-irq.c b/trunk/drivers/mfd/twl6030-irq.c index eb3b5f88e566..dfbae34e1804 100644 --- a/trunk/drivers/mfd/twl6030-irq.c +++ b/trunk/drivers/mfd/twl6030-irq.c @@ -76,8 +76,8 @@ static int twl6030_interrupt_mapping[24] = { USBOTG_INTR_OFFSET, /* Bit 18 ID */ USB_PRES_INTR_OFFSET, /* Bit 19 VBUS */ CHARGER_INTR_OFFSET, /* Bit 20 CHRG_CTRL */ - CHARGERFAULT_INTR_OFFSET, /* Bit 21 EXT_CHRG */ - CHARGERFAULT_INTR_OFFSET, /* Bit 22 INT_CHRG */ + CHARGER_INTR_OFFSET, /* Bit 21 EXT_CHRG */ + CHARGER_INTR_OFFSET, /* Bit 22 INT_CHRG */ RSV_INTR_OFFSET, /* Bit 23 Reserved */ }; /*----------------------------------------------------------------------*/ diff --git a/trunk/drivers/mfd/wl1273-core.c b/trunk/drivers/mfd/wl1273-core.c index d97a86945174..04914f2836c0 100644 --- a/trunk/drivers/mfd/wl1273-core.c +++ b/trunk/drivers/mfd/wl1273-core.c @@ -153,6 +153,7 @@ static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode) */ static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume) { + u16 val; int r; if (volume > WL1273_MAX_VOLUME) @@ -216,8 +217,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, cell = &core->cells[children]; cell->name = "wl1273_fm_radio"; - cell->platform_data = &core; - cell->pdata_size = sizeof(core); + cell->mfd_data = &core; children++; core->read = wl1273_fm_read_reg; @@ -231,8 +231,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, dev_dbg(&client->dev, "%s: Have codec.\n", __func__); cell->name = "wl1273-codec"; - cell->platform_data = &core; - cell->pdata_size = sizeof(core); + cell->mfd_data = &core; children++; } diff --git a/trunk/drivers/mfd/wm831x-core.c b/trunk/drivers/mfd/wm831x-core.c index 265f75fc6a25..3fe9a58fe6c7 100644 --- a/trunk/drivers/mfd/wm831x-core.c +++ b/trunk/drivers/mfd/wm831x-core.c @@ -1442,7 +1442,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) struct wm831x_pdata *pdata = wm831x->dev->platform_data; int rev; enum wm831x_parent parent; - int ret, i; + int ret; mutex_init(&wm831x->io_lock); mutex_init(&wm831x->key_lock); @@ -1581,17 +1581,6 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) } } - if (pdata) { - for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) { - if (!pdata->gpio_defaults[i]) - continue; - - wm831x_reg_write(wm831x, - WM831X_GPIO1_CONTROL + i, - pdata->gpio_defaults[i] & 0xffff); - } - } - ret = wm831x_irq_init(wm831x, irq); if (ret != 0) goto err; diff --git a/trunk/drivers/mfd/wm831x-irq.c b/trunk/drivers/mfd/wm831x-irq.c index 42b928ec891e..23e66af89dea 100644 --- a/trunk/drivers/mfd/wm831x-irq.c +++ b/trunk/drivers/mfd/wm831x-irq.c @@ -515,6 +515,12 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) 0xffff); } + if (!irq) { + dev_warn(wm831x->dev, + "No interrupt specified - functionality limited\n"); + return 0; + } + if (!pdata || !pdata->irq_base) { dev_err(wm831x->dev, "No interrupt base specified, no interrupts\n"); @@ -561,22 +567,15 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) #endif } - if (irq) { - ret = request_threaded_irq(irq, NULL, wm831x_irq_thread, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "wm831x", wm831x); - if (ret != 0) { - dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n", - irq, ret); - return ret; - } - } else { - dev_warn(wm831x->dev, - "No interrupt specified - functionality limited\n"); + ret = request_threaded_irq(irq, NULL, wm831x_irq_thread, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "wm831x", wm831x); + if (ret != 0) { + dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n", + irq, ret); + return ret; } - - /* Enable top level interrupts, we mask at secondary level */ wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); diff --git a/trunk/drivers/mfd/wm8400-core.c b/trunk/drivers/mfd/wm8400-core.c index 597f82edacaa..3a6e78cb0384 100644 --- a/trunk/drivers/mfd/wm8400-core.c +++ b/trunk/drivers/mfd/wm8400-core.c @@ -245,8 +245,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400) { struct mfd_cell cell = { .name = "wm8400-codec", - .platform_data = wm8400, - .pdata_size = sizeof(*wm8400), + .mfd_data = wm8400, }; return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); diff --git a/trunk/drivers/misc/kgdbts.c b/trunk/drivers/misc/kgdbts.c index b0c56313dbbb..74f16f167b8e 100644 --- a/trunk/drivers/misc/kgdbts.c +++ b/trunk/drivers/misc/kgdbts.c @@ -285,26 +285,33 @@ static void hw_break_val_write(void) static int check_and_rewind_pc(char *put_str, char *arg) { unsigned long addr = lookup_addr(arg); - unsigned long ip; int offset = 0; kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs, NUMREGBYTES); gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs); - ip = instruction_pointer(&kgdbts_regs); - v2printk("Stopped at IP: %lx\n", ip); -#ifdef GDB_ADJUSTS_BREAK_OFFSET - /* On some arches, a breakpoint stop requires it to be decremented */ - if (addr + BREAK_INSTR_SIZE == ip) - offset = -BREAK_INSTR_SIZE; + v2printk("Stopped at IP: %lx\n", instruction_pointer(&kgdbts_regs)); +#ifdef CONFIG_X86 + /* On x86 a breakpoint stop requires it to be decremented */ + if (addr + 1 == kgdbts_regs.ip) + offset = -1; +#elif defined(CONFIG_SUPERH) + /* On SUPERH a breakpoint stop requires it to be decremented */ + if (addr + 2 == kgdbts_regs.pc) + offset = -2; #endif - if (strcmp(arg, "silent") && ip + offset != addr) { + if (strcmp(arg, "silent") && + instruction_pointer(&kgdbts_regs) + offset != addr) { eprintk("kgdbts: BP mismatch %lx expected %lx\n", - ip + offset, addr); + instruction_pointer(&kgdbts_regs) + offset, addr); return 1; } - /* Readjust the instruction pointer if needed */ - instruction_pointer_set(&kgdbts_regs, ip + offset); +#ifdef CONFIG_X86 + /* On x86 adjust the instruction pointer if needed */ + kgdbts_regs.ip += offset; +#elif defined(CONFIG_SUPERH) + kgdbts_regs.pc += offset; +#endif return 0; } diff --git a/trunk/drivers/mmc/host/tmio_mmc.c b/trunk/drivers/mmc/host/tmio_mmc.c index 8d185de90d20..14479f9ef53f 100644 --- a/trunk/drivers/mmc/host/tmio_mmc.c +++ b/trunk/drivers/mmc/host/tmio_mmc.c @@ -69,7 +69,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *pdev) if (pdev->num_resources != 2) goto out; - pdata = pdev->dev.platform_data; + pdata = mfd_get_data(pdev); if (!pdata || !pdata->hclk) goto out; diff --git a/trunk/drivers/mtd/nand/tmio_nand.c b/trunk/drivers/mtd/nand/tmio_nand.c index c004e474631b..14c578707824 100644 --- a/trunk/drivers/mtd/nand/tmio_nand.c +++ b/trunk/drivers/mtd/nand/tmio_nand.c @@ -372,7 +372,7 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio) static int tmio_probe(struct platform_device *dev) { - struct tmio_nand_data *data = dev->dev.platform_data; + struct tmio_nand_data *data = mfd_get_data(dev); struct resource *fcr = platform_get_resource(dev, IORESOURCE_MEM, 0); struct resource *ccr = platform_get_resource(dev, diff --git a/trunk/drivers/net/can/janz-ican3.c b/trunk/drivers/net/can/janz-ican3.c index f1942cab35f6..587fba48cdd9 100644 --- a/trunk/drivers/net/can/janz-ican3.c +++ b/trunk/drivers/net/can/janz-ican3.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -1643,7 +1644,7 @@ static int __devinit ican3_probe(struct platform_device *pdev) struct device *dev; int ret; - pdata = pdev->dev.platform_data; + pdata = mfd_get_data(pdev); if (!pdata) return -ENXIO; diff --git a/trunk/drivers/net/hamradio/baycom_epp.c b/trunk/drivers/net/hamradio/baycom_epp.c index 9537aaa50c2f..a3c0dc9d8b98 100644 --- a/trunk/drivers/net/hamradio/baycom_epp.c +++ b/trunk/drivers/net/hamradio/baycom_epp.c @@ -69,7 +69,7 @@ static const char paranoia_str[] = KERN_ERR static const char bc_drvname[] = "baycom_epp"; static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n" -"baycom_epp: version 0.7\n"; +"baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/trunk/drivers/net/hamradio/baycom_par.c b/trunk/drivers/net/hamradio/baycom_par.c index 279d2296290a..5f5af9a606f8 100644 --- a/trunk/drivers/net/hamradio/baycom_par.c +++ b/trunk/drivers/net/hamradio/baycom_par.c @@ -102,7 +102,7 @@ static const char bc_drvname[] = "baycom_par"; static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -"baycom_par: version 0.9\n"; +"baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/trunk/drivers/net/hamradio/baycom_ser_fdx.c b/trunk/drivers/net/hamradio/baycom_ser_fdx.c index 99cdce33df8b..3e25f10cabd6 100644 --- a/trunk/drivers/net/hamradio/baycom_ser_fdx.c +++ b/trunk/drivers/net/hamradio/baycom_ser_fdx.c @@ -92,7 +92,7 @@ static const char bc_drvname[] = "baycom_ser_fdx"; static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -"baycom_ser_fdx: version 0.10\n"; +"baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/trunk/drivers/net/hamradio/baycom_ser_hdx.c b/trunk/drivers/net/hamradio/baycom_ser_hdx.c index d92fe6ca788f..1686f6dcbbce 100644 --- a/trunk/drivers/net/hamradio/baycom_ser_hdx.c +++ b/trunk/drivers/net/hamradio/baycom_ser_hdx.c @@ -80,7 +80,7 @@ static const char bc_drvname[] = "baycom_ser_hdx"; static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -"baycom_ser_hdx: version 0.10\n"; +"baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/trunk/drivers/net/hamradio/hdlcdrv.c b/trunk/drivers/net/hamradio/hdlcdrv.c index a4a3516b6bbf..5b37579e84b7 100644 --- a/trunk/drivers/net/hamradio/hdlcdrv.c +++ b/trunk/drivers/net/hamradio/hdlcdrv.c @@ -749,7 +749,7 @@ EXPORT_SYMBOL(hdlcdrv_unregister); static int __init hdlcdrv_init_driver(void) { printk(KERN_INFO "hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA\n"); - printk(KERN_INFO "hdlcdrv: version 0.8\n"); + printk(KERN_INFO "hdlcdrv: version 0.8 compiled " __TIME__ " " __DATE__ "\n"); return 0; } diff --git a/trunk/drivers/net/ks8842.c b/trunk/drivers/net/ks8842.c index 4d40626b3bfa..f0d8346d0fa5 100644 --- a/trunk/drivers/net/ks8842.c +++ b/trunk/drivers/net/ks8842.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1145,7 +1146,7 @@ static int __devinit ks8842_probe(struct platform_device *pdev) struct resource *iomem; struct net_device *netdev; struct ks8842_adapter *adapter; - struct ks8842_platform_data *pdata = pdev->dev.platform_data; + struct ks8842_platform_data *pdata = mfd_get_data(pdev); u16 id; unsigned i; diff --git a/trunk/drivers/net/wan/pc300_drv.c b/trunk/drivers/net/wan/pc300_drv.c index 9617d3d0ee39..737b59f1a8dc 100644 --- a/trunk/drivers/net/wan/pc300_drv.c +++ b/trunk/drivers/net/wan/pc300_drv.c @@ -3242,7 +3242,8 @@ static inline void show_version(void) rcsdate++; tmp = strrchr(rcsdate, ' '); *tmp = '\0'; - printk(KERN_INFO "Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate); + printk(KERN_INFO "Cyclades-PC300 driver %s %s (built %s %s)\n", + rcsvers, rcsdate, __DATE__, __TIME__); } /* show_version */ static const struct net_device_ops cpc_netdev_ops = { diff --git a/trunk/drivers/parport/parport_ip32.c b/trunk/drivers/parport/parport_ip32.c index 0dc34f12f92e..d3d7809af8bf 100644 --- a/trunk/drivers/parport/parport_ip32.c +++ b/trunk/drivers/parport/parport_ip32.c @@ -2203,6 +2203,7 @@ static __exit void parport_ip32_unregister_port(struct parport *p) static int __init parport_ip32_init(void) { pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n"); + pr_debug1(PPIP32 "Compiled on %s, %s\n", __DATE__, __TIME__); this_port = parport_ip32_probe_port(); return IS_ERR(this_port) ? PTR_ERR(this_port) : 0; } diff --git a/trunk/drivers/power/Kconfig b/trunk/drivers/power/Kconfig index e57b50b38565..52a462fc6b84 100644 --- a/trunk/drivers/power/Kconfig +++ b/trunk/drivers/power/Kconfig @@ -68,13 +68,6 @@ config BATTERY_DS2760 help Say Y here to enable support for batteries with ds2760 chip. -config BATTERY_DS2780 - tristate "DS2780 battery driver" - select W1 - select W1_SLAVE_DS2780 - help - Say Y here to enable support for batteries with ds2780 chip. - config BATTERY_DS2782 tristate "DS2782/DS2786 standalone gas-gauge" depends on I2C @@ -210,15 +203,6 @@ config CHARGER_ISP1704 Say Y to enable support for USB Charger Detection with ISP1707/ISP1704 USB transceivers. -config CHARGER_MAX8903 - tristate "MAX8903 Battery DC-DC Charger for USB and Adapter Power" - depends on GENERIC_HARDIRQS - help - Say Y to enable support for the MAX8903 DC-DC charger and sysfs. - The driver supports controlling charger-enable and current-limit - pins based on the status of charger connections with interrupt - handlers. - config CHARGER_TWL4030 tristate "OMAP TWL4030 BCI charger driver" depends on TWL4030_CORE diff --git a/trunk/drivers/power/Makefile b/trunk/drivers/power/Makefile index 009a90fa8ac9..8385bfae8728 100644 --- a/trunk/drivers/power/Makefile +++ b/trunk/drivers/power/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_WM8350_POWER) += wm8350_power.o obj-$(CONFIG_TEST_POWER) += test_power.o obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o -obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o @@ -33,6 +32,5 @@ obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o -obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o diff --git a/trunk/drivers/power/bq27x00_battery.c b/trunk/drivers/power/bq27x00_battery.c index bb16f5b7e167..59e68dbd028b 100644 --- a/trunk/drivers/power/bq27x00_battery.c +++ b/trunk/drivers/power/bq27x00_battery.c @@ -4,7 +4,6 @@ * Copyright (C) 2008 Rodolfo Giometti * Copyright (C) 2008 Eurotech S.p.A. * Copyright (C) 2010-2011 Lars-Peter Clausen - * Copyright (C) 2011 Pali Rohár * * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. * @@ -77,7 +76,7 @@ struct bq27x00_reg_cache { int time_to_empty_avg; int time_to_full; int charge_full; - int cycle_count; + int charge_counter; int capacity; int flags; @@ -116,7 +115,7 @@ static enum power_supply_property bq27x00_battery_props[] = { POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, - POWER_SUPPLY_PROP_CYCLE_COUNT, + POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_ENERGY_NOW, }; @@ -268,7 +267,7 @@ static void bq27x00_update(struct bq27x00_device_info *di) cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); cache.charge_full = bq27x00_battery_read_lmd(di); - cache.cycle_count = bq27x00_battery_read_cyct(di); + cache.charge_counter = bq27x00_battery_read_cyct(di); if (!is_bq27500) cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false); @@ -497,8 +496,8 @@ static int bq27x00_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: ret = bq27x00_simple_value(di->charge_design_full, val); break; - case POWER_SUPPLY_PROP_CYCLE_COUNT: - ret = bq27x00_simple_value(di->cache.cycle_count, val); + case POWER_SUPPLY_PROP_CHARGE_COUNTER: + ret = bq27x00_simple_value(di->cache.charge_counter, val); break; case POWER_SUPPLY_PROP_ENERGY_NOW: ret = bq27x00_battery_energy(di, val); diff --git a/trunk/drivers/power/ds2760_battery.c b/trunk/drivers/power/ds2760_battery.c index f2c9cc33c0f9..e534290f3256 100644 --- a/trunk/drivers/power/ds2760_battery.c +++ b/trunk/drivers/power/ds2760_battery.c @@ -86,11 +86,7 @@ static int rated_capacities[] = { 920, /* NEC */ 1440, /* Samsung */ 1440, /* BYD */ -#ifdef CONFIG_MACH_H4700 - 1800, /* HP iPAQ hx4700 3.7V 1800mAh (359113-001) */ -#else 1440, /* Lishen */ -#endif 1440, /* NEC */ 2880, /* Samsung */ 2880, /* BYD */ @@ -190,7 +186,7 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di) scale[0] = di->full_active_uAh; for (i = 1; i < 5; i++) - scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 1 + i]; + scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i]; di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10); di->full_active_uAh *= 1000; /* convert to µAh */ diff --git a/trunk/drivers/power/ds2780_battery.c b/trunk/drivers/power/ds2780_battery.c deleted file mode 100644 index 1fefe82e12e3..000000000000 --- a/trunk/drivers/power/ds2780_battery.c +++ /dev/null @@ -1,853 +0,0 @@ -/* - * 1-wire client/driver for the Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC - * - * Copyright (C) 2010 Indesign, LLC - * - * Author: Clifton Barnes - * - * Based on ds2760_battery and ds2782_battery drivers - * - * 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 "../w1/w1.h" -#include "../w1/slaves/w1_ds2780.h" - -/* Current unit measurement in uA for a 1 milli-ohm sense resistor */ -#define DS2780_CURRENT_UNITS 1563 -/* Charge unit measurement in uAh for a 1 milli-ohm sense resistor */ -#define DS2780_CHARGE_UNITS 6250 -/* Number of bytes in user EEPROM space */ -#define DS2780_USER_EEPROM_SIZE (DS2780_EEPROM_BLOCK0_END - \ - DS2780_EEPROM_BLOCK0_START + 1) -/* Number of bytes in parameter EEPROM space */ -#define DS2780_PARAM_EEPROM_SIZE (DS2780_EEPROM_BLOCK1_END - \ - DS2780_EEPROM_BLOCK1_START + 1) - -struct ds2780_device_info { - struct device *dev; - struct power_supply bat; - struct device *w1_dev; -}; - -enum current_types { - CURRENT_NOW, - CURRENT_AVG, -}; - -static const char model[] = "DS2780"; -static const char manufacturer[] = "Maxim/Dallas"; - -static inline struct ds2780_device_info *to_ds2780_device_info( - struct power_supply *psy) -{ - return container_of(psy, struct ds2780_device_info, bat); -} - -static inline struct power_supply *to_power_supply(struct device *dev) -{ - return dev_get_drvdata(dev); -} - -static inline int ds2780_read8(struct device *dev, u8 *val, int addr) -{ - return w1_ds2780_io(dev, val, addr, sizeof(u8), 0); -} - -static int ds2780_read16(struct device *dev, s16 *val, int addr) -{ - int ret; - u8 raw[2]; - - ret = w1_ds2780_io(dev, raw, addr, sizeof(u8) * 2, 0); - if (ret < 0) - return ret; - - *val = (raw[0] << 8) | raw[1]; - - return 0; -} - -static inline int ds2780_read_block(struct device *dev, u8 *val, int addr, - size_t count) -{ - return w1_ds2780_io(dev, val, addr, count, 0); -} - -static inline int ds2780_write(struct device *dev, u8 *val, int addr, - size_t count) -{ - return w1_ds2780_io(dev, val, addr, count, 1); -} - -static inline int ds2780_store_eeprom(struct device *dev, int addr) -{ - return w1_ds2780_eeprom_cmd(dev, addr, W1_DS2780_COPY_DATA); -} - -static inline int ds2780_recall_eeprom(struct device *dev, int addr) -{ - return w1_ds2780_eeprom_cmd(dev, addr, W1_DS2780_RECALL_DATA); -} - -static int ds2780_save_eeprom(struct ds2780_device_info *dev_info, int reg) -{ - int ret; - - ret = ds2780_store_eeprom(dev_info->w1_dev, reg); - if (ret < 0) - return ret; - - ret = ds2780_recall_eeprom(dev_info->w1_dev, reg); - if (ret < 0) - return ret; - - return 0; -} - -/* Set sense resistor value in mhos */ -static int ds2780_set_sense_register(struct ds2780_device_info *dev_info, - u8 conductance) -{ - int ret; - - ret = ds2780_write(dev_info->w1_dev, &conductance, - DS2780_RSNSP_REG, sizeof(u8)); - if (ret < 0) - return ret; - - return ds2780_save_eeprom(dev_info, DS2780_RSNSP_REG); -} - -/* Get RSGAIN value from 0 to 1.999 in steps of 0.001 */ -static int ds2780_get_rsgain_register(struct ds2780_device_info *dev_info, - u16 *rsgain) -{ - return ds2780_read16(dev_info->w1_dev, rsgain, DS2780_RSGAIN_MSB_REG); -} - -/* Set RSGAIN value from 0 to 1.999 in steps of 0.001 */ -static int ds2780_set_rsgain_register(struct ds2780_device_info *dev_info, - u16 rsgain) -{ - int ret; - u8 raw[] = {rsgain >> 8, rsgain & 0xFF}; - - ret = ds2780_write(dev_info->w1_dev, raw, - DS2780_RSGAIN_MSB_REG, sizeof(u8) * 2); - if (ret < 0) - return ret; - - return ds2780_save_eeprom(dev_info, DS2780_RSGAIN_MSB_REG); -} - -static int ds2780_get_voltage(struct ds2780_device_info *dev_info, - int *voltage_uV) -{ - int ret; - s16 voltage_raw; - - /* - * The voltage value is located in 10 bits across the voltage MSB - * and LSB registers in two's compliment form - * Sign bit of the voltage value is in bit 7 of the voltage MSB register - * Bits 9 - 3 of the voltage value are in bits 6 - 0 of the - * voltage MSB register - * Bits 2 - 0 of the voltage value are in bits 7 - 5 of the - * voltage LSB register - */ - ret = ds2780_read16(dev_info->w1_dev, &voltage_raw, - DS2780_VOLT_MSB_REG); - if (ret < 0) - return ret; - - /* - * DS2780 reports voltage in units of 4.88mV, but the battery class - * reports in units of uV, so convert by multiplying by 4880. - */ - *voltage_uV = (voltage_raw / 32) * 4880; - return 0; -} - -static int ds2780_get_temperature(struct ds2780_device_info *dev_info, - int *temperature) -{ - int ret; - s16 temperature_raw; - - /* - * The temperature value is located in 10 bits across the temperature - * MSB and LSB registers in two's compliment form - * Sign bit of the temperature value is in bit 7 of the temperature - * MSB register - * Bits 9 - 3 of the temperature value are in bits 6 - 0 of the - * temperature MSB register - * Bits 2 - 0 of the temperature value are in bits 7 - 5 of the - * temperature LSB register - */ - ret = ds2780_read16(dev_info->w1_dev, &temperature_raw, - DS2780_TEMP_MSB_REG); - if (ret < 0) - return ret; - - /* - * Temperature is measured in units of 0.125 degrees celcius, the - * power_supply class measures temperature in tenths of degrees - * celsius. The temperature value is stored as a 10 bit number, plus - * sign in the upper bits of a 16 bit register. - */ - *temperature = ((temperature_raw / 32) * 125) / 100; - return 0; -} - -static int ds2780_get_current(struct ds2780_device_info *dev_info, - enum current_types type, int *current_uA) -{ - int ret, sense_res; - s16 current_raw; - u8 sense_res_raw, reg_msb; - - /* - * The units of measurement for current are dependent on the value of - * the sense resistor. - */ - ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG); - if (ret < 0) - return ret; - - if (sense_res_raw == 0) { - dev_err(dev_info->dev, "sense resistor value is 0\n"); - return -ENXIO; - } - sense_res = 1000 / sense_res_raw; - - if (type == CURRENT_NOW) - reg_msb = DS2780_CURRENT_MSB_REG; - else if (type == CURRENT_AVG) - reg_msb = DS2780_IAVG_MSB_REG; - else - return -EINVAL; - - /* - * The current value is located in 16 bits across the current MSB - * and LSB registers in two's compliment form - * Sign bit of the current value is in bit 7 of the current MSB register - * Bits 14 - 8 of the current value are in bits 6 - 0 of the current - * MSB register - * Bits 7 - 0 of the current value are in bits 7 - 0 of the current - * LSB register - */ - ret = ds2780_read16(dev_info->w1_dev, ¤t_raw, reg_msb); - if (ret < 0) - return ret; - - *current_uA = current_raw * (DS2780_CURRENT_UNITS / sense_res); - return 0; -} - -static int ds2780_get_accumulated_current(struct ds2780_device_info *dev_info, - int *accumulated_current) -{ - int ret, sense_res; - s16 current_raw; - u8 sense_res_raw; - - /* - * The units of measurement for accumulated current are dependent on - * the value of the sense resistor. - */ - ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG); - if (ret < 0) - return ret; - - if (sense_res_raw == 0) { - dev_err(dev_info->dev, "sense resistor value is 0\n"); - return -ENXIO; - } - sense_res = 1000 / sense_res_raw; - - /* - * The ACR value is located in 16 bits across the ACR MSB and - * LSB registers - * Bits 15 - 8 of the ACR value are in bits 7 - 0 of the ACR - * MSB register - * Bits 7 - 0 of the ACR value are in bits 7 - 0 of the ACR - * LSB register - */ - ret = ds2780_read16(dev_info->w1_dev, ¤t_raw, DS2780_ACR_MSB_REG); - if (ret < 0) - return ret; - - *accumulated_current = current_raw * (DS2780_CHARGE_UNITS / sense_res); - return 0; -} - -static int ds2780_get_capacity(struct ds2780_device_info *dev_info, - int *capacity) -{ - int ret; - u8 raw; - - ret = ds2780_read8(dev_info->w1_dev, &raw, DS2780_RARC_REG); - if (ret < 0) - return ret; - - *capacity = raw; - return raw; -} - -static int ds2780_get_status(struct ds2780_device_info *dev_info, int *status) -{ - int ret, current_uA, capacity; - - ret = ds2780_get_current(dev_info, CURRENT_NOW, ¤t_uA); - if (ret < 0) - return ret; - - ret = ds2780_get_capacity(dev_info, &capacity); - if (ret < 0) - return ret; - - if (capacity == 100) - *status = POWER_SUPPLY_STATUS_FULL; - else if (current_uA == 0) - *status = POWER_SUPPLY_STATUS_NOT_CHARGING; - else if (current_uA < 0) - *status = POWER_SUPPLY_STATUS_DISCHARGING; - else - *status = POWER_SUPPLY_STATUS_CHARGING; - - return 0; -} - -static int ds2780_get_charge_now(struct ds2780_device_info *dev_info, - int *charge_now) -{ - int ret; - u16 charge_raw; - - /* - * The RAAC value is located in 16 bits across the RAAC MSB and - * LSB registers - * Bits 15 - 8 of the RAAC value are in bits 7 - 0 of the RAAC - * MSB register - * Bits 7 - 0 of the RAAC value are in bits 7 - 0 of the RAAC - * LSB register - */ - ret = ds2780_read16(dev_info->w1_dev, &charge_raw, DS2780_RAAC_MSB_REG); - if (ret < 0) - return ret; - - *charge_now = charge_raw * 1600; - return 0; -} - -static int ds2780_get_control_register(struct ds2780_device_info *dev_info, - u8 *control_reg) -{ - return ds2780_read8(dev_info->w1_dev, control_reg, DS2780_CONTROL_REG); -} - -static int ds2780_set_control_register(struct ds2780_device_info *dev_info, - u8 control_reg) -{ - int ret; - - ret = ds2780_write(dev_info->w1_dev, &control_reg, - DS2780_CONTROL_REG, sizeof(u8)); - if (ret < 0) - return ret; - - return ds2780_save_eeprom(dev_info, DS2780_CONTROL_REG); -} - -static int ds2780_battery_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - int ret = 0; - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - ret = ds2780_get_voltage(dev_info, &val->intval); - break; - - case POWER_SUPPLY_PROP_TEMP: - ret = ds2780_get_temperature(dev_info, &val->intval); - break; - - case POWER_SUPPLY_PROP_MODEL_NAME: - val->strval = model; - break; - - case POWER_SUPPLY_PROP_MANUFACTURER: - val->strval = manufacturer; - break; - - case POWER_SUPPLY_PROP_CURRENT_NOW: - ret = ds2780_get_current(dev_info, CURRENT_NOW, &val->intval); - break; - - case POWER_SUPPLY_PROP_CURRENT_AVG: - ret = ds2780_get_current(dev_info, CURRENT_AVG, &val->intval); - break; - - case POWER_SUPPLY_PROP_STATUS: - ret = ds2780_get_status(dev_info, &val->intval); - break; - - case POWER_SUPPLY_PROP_CAPACITY: - ret = ds2780_get_capacity(dev_info, &val->intval); - break; - - case POWER_SUPPLY_PROP_CHARGE_COUNTER: - ret = ds2780_get_accumulated_current(dev_info, &val->intval); - break; - - case POWER_SUPPLY_PROP_CHARGE_NOW: - ret = ds2780_get_charge_now(dev_info, &val->intval); - break; - - default: - ret = -EINVAL; - } - - return ret; -} - -static enum power_supply_property ds2780_battery_props[] = { - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_MODEL_NAME, - POWER_SUPPLY_PROP_MANUFACTURER, - POWER_SUPPLY_PROP_CURRENT_NOW, - POWER_SUPPLY_PROP_CURRENT_AVG, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_CHARGE_COUNTER, - POWER_SUPPLY_PROP_CHARGE_NOW, -}; - -static ssize_t ds2780_get_pmod_enabled(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u8 control_reg; - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - /* Get power mode */ - ret = ds2780_get_control_register(dev_info, &control_reg); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", - !!(control_reg & DS2780_CONTROL_REG_PMOD)); -} - -static ssize_t ds2780_set_pmod_enabled(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - int ret; - u8 control_reg, new_setting; - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - /* Set power mode */ - ret = ds2780_get_control_register(dev_info, &control_reg); - if (ret < 0) - return ret; - - ret = kstrtou8(buf, 0, &new_setting); - if (ret < 0) - return ret; - - if ((new_setting != 0) && (new_setting != 1)) { - dev_err(dev_info->dev, "Invalid pmod setting (0 or 1)\n"); - return -EINVAL; - } - - if (new_setting) - control_reg |= DS2780_CONTROL_REG_PMOD; - else - control_reg &= ~DS2780_CONTROL_REG_PMOD; - - ret = ds2780_set_control_register(dev_info, control_reg); - if (ret < 0) - return ret; - - return count; -} - -static ssize_t ds2780_get_sense_resistor_value(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u8 sense_resistor; - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - ret = ds2780_read8(dev_info->w1_dev, &sense_resistor, DS2780_RSNSP_REG); - if (ret < 0) - return ret; - - ret = sprintf(buf, "%d\n", sense_resistor); - return ret; -} - -static ssize_t ds2780_set_sense_resistor_value(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - int ret; - u8 new_setting; - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - ret = kstrtou8(buf, 0, &new_setting); - if (ret < 0) - return ret; - - ret = ds2780_set_sense_register(dev_info, new_setting); - if (ret < 0) - return ret; - - return count; -} - -static ssize_t ds2780_get_rsgain_setting(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u16 rsgain; - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - ret = ds2780_get_rsgain_register(dev_info, &rsgain); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", rsgain); -} - -static ssize_t ds2780_set_rsgain_setting(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - int ret; - u16 new_setting; - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - ret = kstrtou16(buf, 0, &new_setting); - if (ret < 0) - return ret; - - /* Gain can only be from 0 to 1.999 in steps of .001 */ - if (new_setting > 1999) { - dev_err(dev_info->dev, "Invalid rsgain setting (0 - 1999)\n"); - return -EINVAL; - } - - ret = ds2780_set_rsgain_register(dev_info, new_setting); - if (ret < 0) - return ret; - - return count; -} - -static ssize_t ds2780_get_pio_pin(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u8 sfr; - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - ret = ds2780_read8(dev_info->w1_dev, &sfr, DS2780_SFR_REG); - if (ret < 0) - return ret; - - ret = sprintf(buf, "%d\n", sfr & DS2780_SFR_REG_PIOSC); - return ret; -} - -static ssize_t ds2780_set_pio_pin(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - int ret; - u8 new_setting; - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - ret = kstrtou8(buf, 0, &new_setting); - if (ret < 0) - return ret; - - if ((new_setting != 0) && (new_setting != 1)) { - dev_err(dev_info->dev, "Invalid pio_pin setting (0 or 1)\n"); - return -EINVAL; - } - - ret = ds2780_write(dev_info->w1_dev, &new_setting, - DS2780_SFR_REG, sizeof(u8)); - if (ret < 0) - return ret; - - return count; -} - -static ssize_t ds2780_read_param_eeprom_bin(struct file *filp, - struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - count = min_t(loff_t, count, - DS2780_EEPROM_BLOCK1_END - - DS2780_EEPROM_BLOCK1_START + 1 - off); - - return ds2780_read_block(dev_info->w1_dev, buf, - DS2780_EEPROM_BLOCK1_START + off, count); -} - -static ssize_t ds2780_write_param_eeprom_bin(struct file *filp, - struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - int ret; - - count = min_t(loff_t, count, - DS2780_EEPROM_BLOCK1_END - - DS2780_EEPROM_BLOCK1_START + 1 - off); - - ret = ds2780_write(dev_info->w1_dev, buf, - DS2780_EEPROM_BLOCK1_START + off, count); - if (ret < 0) - return ret; - - ret = ds2780_save_eeprom(dev_info, DS2780_EEPROM_BLOCK1_START); - if (ret < 0) - return ret; - - return count; -} - -static struct bin_attribute ds2780_param_eeprom_bin_attr = { - .attr = { - .name = "param_eeprom", - .mode = S_IRUGO | S_IWUSR, - }, - .size = DS2780_EEPROM_BLOCK1_END - DS2780_EEPROM_BLOCK1_START + 1, - .read = ds2780_read_param_eeprom_bin, - .write = ds2780_write_param_eeprom_bin, -}; - -static ssize_t ds2780_read_user_eeprom_bin(struct file *filp, - struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - - count = min_t(loff_t, count, - DS2780_EEPROM_BLOCK0_END - - DS2780_EEPROM_BLOCK0_START + 1 - off); - - return ds2780_read_block(dev_info->w1_dev, buf, - DS2780_EEPROM_BLOCK0_START + off, count); - -} - -static ssize_t ds2780_write_user_eeprom_bin(struct file *filp, - struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct power_supply *psy = to_power_supply(dev); - struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); - int ret; - - count = min_t(loff_t, count, - DS2780_EEPROM_BLOCK0_END - - DS2780_EEPROM_BLOCK0_START + 1 - off); - - ret = ds2780_write(dev_info->w1_dev, buf, - DS2780_EEPROM_BLOCK0_START + off, count); - if (ret < 0) - return ret; - - ret = ds2780_save_eeprom(dev_info, DS2780_EEPROM_BLOCK0_START); - if (ret < 0) - return ret; - - return count; -} - -static struct bin_attribute ds2780_user_eeprom_bin_attr = { - .attr = { - .name = "user_eeprom", - .mode = S_IRUGO | S_IWUSR, - }, - .size = DS2780_EEPROM_BLOCK0_END - DS2780_EEPROM_BLOCK0_START + 1, - .read = ds2780_read_user_eeprom_bin, - .write = ds2780_write_user_eeprom_bin, -}; - -static DEVICE_ATTR(pmod_enabled, S_IRUGO | S_IWUSR, ds2780_get_pmod_enabled, - ds2780_set_pmod_enabled); -static DEVICE_ATTR(sense_resistor_value, S_IRUGO | S_IWUSR, - ds2780_get_sense_resistor_value, ds2780_set_sense_resistor_value); -static DEVICE_ATTR(rsgain_setting, S_IRUGO | S_IWUSR, ds2780_get_rsgain_setting, - ds2780_set_rsgain_setting); -static DEVICE_ATTR(pio_pin, S_IRUGO | S_IWUSR, ds2780_get_pio_pin, - ds2780_set_pio_pin); - - -static struct attribute *ds2780_attributes[] = { - &dev_attr_pmod_enabled.attr, - &dev_attr_sense_resistor_value.attr, - &dev_attr_rsgain_setting.attr, - &dev_attr_pio_pin.attr, - NULL -}; - -static const struct attribute_group ds2780_attr_group = { - .attrs = ds2780_attributes, -}; - -static int __devinit ds2780_battery_probe(struct platform_device *pdev) -{ - int ret = 0; - struct ds2780_device_info *dev_info; - - dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL); - if (!dev_info) { - ret = -ENOMEM; - goto fail; - } - - platform_set_drvdata(pdev, dev_info); - - dev_info->dev = &pdev->dev; - dev_info->w1_dev = pdev->dev.parent; - dev_info->bat.name = dev_name(&pdev->dev); - dev_info->bat.type = POWER_SUPPLY_TYPE_BATTERY; - dev_info->bat.properties = ds2780_battery_props; - dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props); - dev_info->bat.get_property = ds2780_battery_get_property; - - ret = power_supply_register(&pdev->dev, &dev_info->bat); - if (ret) { - dev_err(dev_info->dev, "failed to register battery\n"); - goto fail_free_info; - } - - ret = sysfs_create_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); - if (ret) { - dev_err(dev_info->dev, "failed to create sysfs group\n"); - goto fail_unregister; - } - - ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj, - &ds2780_param_eeprom_bin_attr); - if (ret) { - dev_err(dev_info->dev, - "failed to create param eeprom bin file"); - goto fail_remove_group; - } - - ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj, - &ds2780_user_eeprom_bin_attr); - if (ret) { - dev_err(dev_info->dev, - "failed to create user eeprom bin file"); - goto fail_remove_bin_file; - } - - return 0; - -fail_remove_bin_file: - sysfs_remove_bin_file(&dev_info->bat.dev->kobj, - &ds2780_param_eeprom_bin_attr); -fail_remove_group: - sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); -fail_unregister: - power_supply_unregister(&dev_info->bat); -fail_free_info: - kfree(dev_info); -fail: - return ret; -} - -static int __devexit ds2780_battery_remove(struct platform_device *pdev) -{ - struct ds2780_device_info *dev_info = platform_get_drvdata(pdev); - - /* remove attributes */ - sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); - - power_supply_unregister(&dev_info->bat); - - kfree(dev_info); - return 0; -} - -MODULE_ALIAS("platform:ds2780-battery"); - -static struct platform_driver ds2780_battery_driver = { - .driver = { - .name = "ds2780-battery", - }, - .probe = ds2780_battery_probe, - .remove = ds2780_battery_remove, -}; - -static int __init ds2780_battery_init(void) -{ - return platform_driver_register(&ds2780_battery_driver); -} - -static void __exit ds2780_battery_exit(void) -{ - platform_driver_unregister(&ds2780_battery_driver); -} - -module_init(ds2780_battery_init); -module_exit(ds2780_battery_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Clifton Barnes "); -MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauage IC driver"); diff --git a/trunk/drivers/power/gpio-charger.c b/trunk/drivers/power/gpio-charger.c index 718f2c537827..25b88ac1d44c 100644 --- a/trunk/drivers/power/gpio-charger.c +++ b/trunk/drivers/power/gpio-charger.c @@ -161,27 +161,12 @@ static int __devexit gpio_charger_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int gpio_charger_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct gpio_charger *gpio_charger = platform_get_drvdata(pdev); - - power_supply_changed(&gpio_charger->charger); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume); - static struct platform_driver gpio_charger_driver = { .probe = gpio_charger_probe, .remove = __devexit_p(gpio_charger_remove), .driver = { .name = "gpio-charger", .owner = THIS_MODULE, - .pm = &gpio_charger_pm_ops, }, }; diff --git a/trunk/drivers/power/isp1704_charger.c b/trunk/drivers/power/isp1704_charger.c index f6d72b402a8e..2ad9b14a5ce3 100644 --- a/trunk/drivers/power/isp1704_charger.c +++ b/trunk/drivers/power/isp1704_charger.c @@ -33,7 +33,6 @@ #include #include #include -#include /* Vendor specific Power Control register */ #define ISP1704_PWR_CTRL 0x3d @@ -71,18 +70,6 @@ struct isp1704_charger { unsigned max_power; }; -/* - * Disable/enable the power from the isp1704 if a function for it - * has been provided with platform data. - */ -static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on) -{ - struct isp1704_charger_data *board = isp->dev->platform_data; - - if (board->set_power) - board->set_power(on); -} - /* * Determine is the charging port DCP (dedicated charger) or CDP (Host/HUB * chargers). @@ -235,9 +222,6 @@ static void isp1704_charger_work(struct work_struct *data) mutex_lock(&lock); - if (event != USB_EVENT_NONE) - isp1704_charger_set_power(isp, 1); - switch (event) { case USB_EVENT_VBUS: isp->online = true; @@ -285,8 +269,6 @@ static void isp1704_charger_work(struct work_struct *data) */ if (isp->otg->gadget) usb_gadget_disconnect(isp->otg->gadget); - - isp1704_charger_set_power(isp, 0); break; case USB_EVENT_ENUMERATED: if (isp->present) @@ -412,8 +394,6 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) isp->dev = &pdev->dev; platform_set_drvdata(pdev, isp); - isp1704_charger_set_power(isp, 1); - ret = isp1704_test_ulpi(isp); if (ret < 0) goto fail1; @@ -454,7 +434,6 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) /* Detect charger if VBUS is valid (the cable was already plugged). */ ret = otg_io_read(isp->otg, ULPI_USB_INT_STS); - isp1704_charger_set_power(isp, 0); if ((ret & ULPI_INT_VBUS_VALID) && !isp->otg->default_a) { isp->event = USB_EVENT_VBUS; schedule_work(&isp->work); @@ -480,7 +459,6 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev) otg_unregister_notifier(isp->otg, &isp->nb); power_supply_unregister(&isp->psy); otg_put_transceiver(isp->otg); - isp1704_charger_set_power(isp, 0); kfree(isp); return 0; diff --git a/trunk/drivers/power/max8903_charger.c b/trunk/drivers/power/max8903_charger.c deleted file mode 100644 index 33ff0e37809e..000000000000 --- a/trunk/drivers/power/max8903_charger.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * max8903_charger.c - Maxim 8903 USB/Adapter Charger Driver - * - * Copyright (C) 2011 Samsung Electronics - * MyungJoo Ham - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include - -struct max8903_data { - struct max8903_pdata *pdata; - struct device *dev; - struct power_supply psy; - bool fault; - bool usb_in; - bool ta_in; -}; - -static enum power_supply_property max8903_charger_props[] = { - POWER_SUPPLY_PROP_STATUS, /* Charger status output */ - POWER_SUPPLY_PROP_ONLINE, /* External power source */ - POWER_SUPPLY_PROP_HEALTH, /* Fault or OK */ -}; - -static int max8903_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct max8903_data *data = container_of(psy, - struct max8903_data, psy); - - switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - val->intval = POWER_SUPPLY_STATUS_UNKNOWN; - if (data->pdata->chg) { - if (gpio_get_value(data->pdata->chg) == 0) - val->intval = POWER_SUPPLY_STATUS_CHARGING; - else if (data->usb_in || data->ta_in) - val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; - else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - } - break; - case POWER_SUPPLY_PROP_ONLINE: - val->intval = 0; - if (data->usb_in || data->ta_in) - val->intval = 1; - break; - case POWER_SUPPLY_PROP_HEALTH: - val->intval = POWER_SUPPLY_HEALTH_GOOD; - if (data->fault) - val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; - break; - default: - return -EINVAL; - } - return 0; -} - -static irqreturn_t max8903_dcin(int irq, void *_data) -{ - struct max8903_data *data = _data; - struct max8903_pdata *pdata = data->pdata; - bool ta_in; - enum power_supply_type old_type; - - ta_in = gpio_get_value(pdata->dok) ? false : true; - - if (ta_in == data->ta_in) - return IRQ_HANDLED; - - data->ta_in = ta_in; - - /* Set Current-Limit-Mode 1:DC 0:USB */ - if (pdata->dcm) - gpio_set_value(pdata->dcm, ta_in ? 1 : 0); - - /* Charger Enable / Disable (cen is negated) */ - if (pdata->cen) - gpio_set_value(pdata->cen, ta_in ? 0 : - (data->usb_in ? 0 : 1)); - - dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ? - "Connected" : "Disconnected"); - - old_type = data->psy.type; - - if (data->ta_in) - data->psy.type = POWER_SUPPLY_TYPE_MAINS; - else if (data->usb_in) - data->psy.type = POWER_SUPPLY_TYPE_USB; - else - data->psy.type = POWER_SUPPLY_TYPE_BATTERY; - - if (old_type != data->psy.type) - power_supply_changed(&data->psy); - - return IRQ_HANDLED; -} - -static irqreturn_t max8903_usbin(int irq, void *_data) -{ - struct max8903_data *data = _data; - struct max8903_pdata *pdata = data->pdata; - bool usb_in; - enum power_supply_type old_type; - - usb_in = gpio_get_value(pdata->uok) ? false : true; - - if (usb_in == data->usb_in) - return IRQ_HANDLED; - - data->usb_in = usb_in; - - /* Do not touch Current-Limit-Mode */ - - /* Charger Enable / Disable (cen is negated) */ - if (pdata->cen) - gpio_set_value(pdata->cen, usb_in ? 0 : - (data->ta_in ? 0 : 1)); - - dev_dbg(data->dev, "USB Charger %s.\n", usb_in ? - "Connected" : "Disconnected"); - - old_type = data->psy.type; - - if (data->ta_in) - data->psy.type = POWER_SUPPLY_TYPE_MAINS; - else if (data->usb_in) - data->psy.type = POWER_SUPPLY_TYPE_USB; - else - data->psy.type = POWER_SUPPLY_TYPE_BATTERY; - - if (old_type != data->psy.type) - power_supply_changed(&data->psy); - - return IRQ_HANDLED; -} - -static irqreturn_t max8903_fault(int irq, void *_data) -{ - struct max8903_data *data = _data; - struct max8903_pdata *pdata = data->pdata; - bool fault; - - fault = gpio_get_value(pdata->flt) ? false : true; - - if (fault == data->fault) - return IRQ_HANDLED; - - data->fault = fault; - - if (fault) - dev_err(data->dev, "Charger suffers a fault and stops.\n"); - else - dev_err(data->dev, "Charger recovered from a fault.\n"); - - return IRQ_HANDLED; -} - -static __devinit int max8903_probe(struct platform_device *pdev) -{ - struct max8903_data *data; - struct device *dev = &pdev->dev; - struct max8903_pdata *pdata = pdev->dev.platform_data; - int ret = 0; - int gpio; - int ta_in = 0; - int usb_in = 0; - - data = kzalloc(sizeof(struct max8903_data), GFP_KERNEL); - if (data == NULL) { - dev_err(dev, "Cannot allocate memory.\n"); - return -ENOMEM; - } - data->pdata = pdata; - data->dev = dev; - platform_set_drvdata(pdev, data); - - if (pdata->dc_valid == false && pdata->usb_valid == false) { - dev_err(dev, "No valid power sources.\n"); - ret = -EINVAL; - goto err; - } - - if (pdata->dc_valid) { - if (pdata->dok && gpio_is_valid(pdata->dok) && - pdata->dcm && gpio_is_valid(pdata->dcm)) { - gpio = pdata->dok; /* PULL_UPed Interrupt */ - ta_in = gpio_get_value(gpio) ? 0 : 1; - - gpio = pdata->dcm; /* Output */ - gpio_set_value(gpio, ta_in); - } else { - dev_err(dev, "When DC is wired, DOK and DCM should" - " be wired as well.\n"); - ret = -EINVAL; - goto err; - } - } else { - if (pdata->dcm) { - if (gpio_is_valid(pdata->dcm)) - gpio_set_value(pdata->dcm, 0); - else { - dev_err(dev, "Invalid pin: dcm.\n"); - ret = -EINVAL; - goto err; - } - } - } - - if (pdata->usb_valid) { - if (pdata->uok && gpio_is_valid(pdata->uok)) { - gpio = pdata->uok; - usb_in = gpio_get_value(gpio) ? 0 : 1; - } else { - dev_err(dev, "When USB is wired, UOK should be wired." - "as well.\n"); - ret = -EINVAL; - goto err; - } - } - - if (pdata->cen) { - if (gpio_is_valid(pdata->cen)) { - gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1); - } else { - dev_err(dev, "Invalid pin: cen.\n"); - ret = -EINVAL; - goto err; - } - } - - if (pdata->chg) { - if (!gpio_is_valid(pdata->chg)) { - dev_err(dev, "Invalid pin: chg.\n"); - ret = -EINVAL; - goto err; - } - } - - if (pdata->flt) { - if (!gpio_is_valid(pdata->flt)) { - dev_err(dev, "Invalid pin: flt.\n"); - ret = -EINVAL; - goto err; - } - } - - if (pdata->usus) { - if (!gpio_is_valid(pdata->usus)) { - dev_err(dev, "Invalid pin: usus.\n"); - ret = -EINVAL; - goto err; - } - } - - data->fault = false; - data->ta_in = ta_in; - data->usb_in = usb_in; - - data->psy.name = "max8903_charger"; - data->psy.type = (ta_in) ? POWER_SUPPLY_TYPE_MAINS : - ((usb_in) ? POWER_SUPPLY_TYPE_USB : - POWER_SUPPLY_TYPE_BATTERY); - data->psy.get_property = max8903_get_property; - data->psy.properties = max8903_charger_props; - data->psy.num_properties = ARRAY_SIZE(max8903_charger_props); - - ret = power_supply_register(dev, &data->psy); - if (ret) { - dev_err(dev, "failed: power supply register.\n"); - goto err; - } - - if (pdata->dc_valid) { - ret = request_threaded_irq(gpio_to_irq(pdata->dok), - NULL, max8903_dcin, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "MAX8903 DC IN", data); - if (ret) { - dev_err(dev, "Cannot request irq %d for DC (%d)\n", - gpio_to_irq(pdata->dok), ret); - goto err_psy; - } - } - - if (pdata->usb_valid) { - ret = request_threaded_irq(gpio_to_irq(pdata->uok), - NULL, max8903_usbin, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "MAX8903 USB IN", data); - if (ret) { - dev_err(dev, "Cannot request irq %d for USB (%d)\n", - gpio_to_irq(pdata->uok), ret); - goto err_dc_irq; - } - } - - if (pdata->flt) { - ret = request_threaded_irq(gpio_to_irq(pdata->flt), - NULL, max8903_fault, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "MAX8903 Fault", data); - if (ret) { - dev_err(dev, "Cannot request irq %d for Fault (%d)\n", - gpio_to_irq(pdata->flt), ret); - goto err_usb_irq; - } - } - - return 0; - -err_usb_irq: - if (pdata->usb_valid) - free_irq(gpio_to_irq(pdata->uok), data); -err_dc_irq: - if (pdata->dc_valid) - free_irq(gpio_to_irq(pdata->dok), data); -err_psy: - power_supply_unregister(&data->psy); -err: - kfree(data); - return ret; -} - -static __devexit int max8903_remove(struct platform_device *pdev) -{ - struct max8903_data *data = platform_get_drvdata(pdev); - - if (data) { - struct max8903_pdata *pdata = data->pdata; - - if (pdata->flt) - free_irq(gpio_to_irq(pdata->flt), data); - if (pdata->usb_valid) - free_irq(gpio_to_irq(pdata->uok), data); - if (pdata->dc_valid) - free_irq(gpio_to_irq(pdata->dok), data); - power_supply_unregister(&data->psy); - kfree(data); - } - - return 0; -} - -static struct platform_driver max8903_driver = { - .probe = max8903_probe, - .remove = __devexit_p(max8903_remove), - .driver = { - .name = "max8903-charger", - .owner = THIS_MODULE, - }, -}; - -static int __init max8903_init(void) -{ - return platform_driver_register(&max8903_driver); -} -module_init(max8903_init); - -static void __exit max8903_exit(void) -{ - platform_driver_unregister(&max8903_driver); -} -module_exit(max8903_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MAX8903 Charger Driver"); -MODULE_AUTHOR("MyungJoo Ham "); -MODULE_ALIAS("max8903-charger"); diff --git a/trunk/drivers/power/max8925_power.c b/trunk/drivers/power/max8925_power.c index a70e16d3a3dc..8e5aec260866 100644 --- a/trunk/drivers/power/max8925_power.c +++ b/trunk/drivers/power/max8925_power.c @@ -425,11 +425,16 @@ static __devexit int max8925_deinit_charger(struct max8925_power_info *info) static __devinit int max8925_power_probe(struct platform_device *pdev) { struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct max8925_platform_data *max8925_pdata; struct max8925_power_pdata *pdata = NULL; struct max8925_power_info *info; int ret; - pdata = pdev->dev.platform_data; + if (pdev->dev.parent->platform_data) { + max8925_pdata = pdev->dev.parent->platform_data; + pdata = max8925_pdata->power; + } + if (!pdata) { dev_err(&pdev->dev, "platform data isn't assigned to " "power supply\n"); @@ -442,7 +447,6 @@ static __devinit int max8925_power_probe(struct platform_device *pdev) info->chip = chip; info->gpm = chip->i2c; info->adc = chip->adc; - platform_set_drvdata(pdev, info); info->ac.name = "max8925-ac"; info->ac.type = POWER_SUPPLY_TYPE_MAINS; @@ -478,6 +482,8 @@ static __devinit int max8925_power_probe(struct platform_device *pdev) info->topoff_threshold = pdata->topoff_threshold; info->fast_charge = pdata->fast_charge; info->set_charger = pdata->set_charger; + dev_set_drvdata(&pdev->dev, info); + platform_set_drvdata(pdev, info); max8925_init_charger(chip, info); return 0; diff --git a/trunk/drivers/power/test_power.c b/trunk/drivers/power/test_power.c index b527c93bf2f3..0cd9f67d33e5 100644 --- a/trunk/drivers/power/test_power.c +++ b/trunk/drivers/power/test_power.c @@ -3,12 +3,6 @@ * * Copyright 2010 Anton Vorontsov * - * Dynamic module parameter code from the Virtual Battery Driver - * Copyright (C) 2008 Pylone, Inc. - * By: Masashi YOKOTA - * Originally found here: - * http://downloads.pylone.jp/src/virtual_battery/virtual_battery-0.0.1.tar.bz2 - * * 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. @@ -21,12 +15,8 @@ #include #include -static int ac_online = 1; -static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING; -static int battery_health = POWER_SUPPLY_HEALTH_GOOD; -static int battery_present = 1; /* true */ -static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION; -static int battery_capacity = 50; +static int test_power_ac_online = 1; +static int test_power_battery_status = POWER_SUPPLY_STATUS_CHARGING; static int test_power_get_ac_property(struct power_supply *psy, enum power_supply_property psp, @@ -34,7 +24,7 @@ static int test_power_get_ac_property(struct power_supply *psy, { switch (psp) { case POWER_SUPPLY_PROP_ONLINE: - val->intval = ac_online; + val->intval = test_power_ac_online; break; default: return -EINVAL; @@ -57,30 +47,22 @@ static int test_power_get_battery_property(struct power_supply *psy, val->strval = UTS_RELEASE; break; case POWER_SUPPLY_PROP_STATUS: - val->intval = battery_status; + val->intval = test_power_battery_status; break; case POWER_SUPPLY_PROP_CHARGE_TYPE: val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; break; case POWER_SUPPLY_PROP_HEALTH: - val->intval = battery_health; - break; - case POWER_SUPPLY_PROP_PRESENT: - val->intval = battery_present; + val->intval = POWER_SUPPLY_HEALTH_GOOD; break; case POWER_SUPPLY_PROP_TECHNOLOGY: - val->intval = battery_technology; + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; break; case POWER_SUPPLY_PROP_CAPACITY_LEVEL: val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; break; case POWER_SUPPLY_PROP_CAPACITY: - case POWER_SUPPLY_PROP_CHARGE_NOW: - val->intval = battery_capacity; - break; - case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: - case POWER_SUPPLY_PROP_CHARGE_FULL: - val->intval = 100; + val->intval = 50; break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: @@ -102,11 +84,9 @@ static enum power_supply_property test_power_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_CHARGE_TYPE, POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_TECHNOLOGY, - POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_FULL, - POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CHARGE_EMPTY, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_CAPACITY_LEVEL, POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, @@ -138,7 +118,6 @@ static struct power_supply test_power_supplies[] = { }, }; - static int __init test_power_init(void) { int i; @@ -166,8 +145,8 @@ static void __exit test_power_exit(void) int i; /* Let's see how we handle changes... */ - ac_online = 0; - battery_status = POWER_SUPPLY_STATUS_DISCHARGING; + test_power_ac_online = 0; + test_power_battery_status = POWER_SUPPLY_STATUS_DISCHARGING; for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) power_supply_changed(&test_power_supplies[i]); pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n", @@ -179,241 +158,6 @@ static void __exit test_power_exit(void) } module_exit(test_power_exit); - - -#define MAX_KEYLENGTH 256 -struct battery_property_map { - int value; - char const *key; -}; - -static struct battery_property_map map_ac_online[] = { - { 0, "on" }, - { 1, "off" }, - { -1, NULL }, -}; - -static struct battery_property_map map_status[] = { - { POWER_SUPPLY_STATUS_CHARGING, "charging" }, - { POWER_SUPPLY_STATUS_DISCHARGING, "discharging" }, - { POWER_SUPPLY_STATUS_NOT_CHARGING, "not-charging" }, - { POWER_SUPPLY_STATUS_FULL, "full" }, - { -1, NULL }, -}; - -static struct battery_property_map map_health[] = { - { POWER_SUPPLY_HEALTH_GOOD, "good" }, - { POWER_SUPPLY_HEALTH_OVERHEAT, "overheat" }, - { POWER_SUPPLY_HEALTH_DEAD, "dead" }, - { POWER_SUPPLY_HEALTH_OVERVOLTAGE, "overvoltage" }, - { POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, "failure" }, - { -1, NULL }, -}; - -static struct battery_property_map map_present[] = { - { 0, "false" }, - { 1, "true" }, - { -1, NULL }, -}; - -static struct battery_property_map map_technology[] = { - { POWER_SUPPLY_TECHNOLOGY_NiMH, "NiMH" }, - { POWER_SUPPLY_TECHNOLOGY_LION, "LION" }, - { POWER_SUPPLY_TECHNOLOGY_LIPO, "LIPO" }, - { POWER_SUPPLY_TECHNOLOGY_LiFe, "LiFe" }, - { POWER_SUPPLY_TECHNOLOGY_NiCd, "NiCd" }, - { POWER_SUPPLY_TECHNOLOGY_LiMn, "LiMn" }, - { -1, NULL }, -}; - - -static int map_get_value(struct battery_property_map *map, const char *key, - int def_val) -{ - char buf[MAX_KEYLENGTH]; - int cr; - - strncpy(buf, key, MAX_KEYLENGTH); - buf[MAX_KEYLENGTH-1] = '\0'; - - cr = strnlen(buf, MAX_KEYLENGTH) - 1; - if (buf[cr] == '\n') - buf[cr] = '\0'; - - while (map->key) { - if (strncasecmp(map->key, buf, MAX_KEYLENGTH) == 0) - return map->value; - map++; - } - - return def_val; -} - - -static const char *map_get_key(struct battery_property_map *map, int value, - const char *def_key) -{ - while (map->key) { - if (map->value == value) - return map->key; - map++; - } - - return def_key; -} - -static int param_set_ac_online(const char *key, const struct kernel_param *kp) -{ - ac_online = map_get_value(map_ac_online, key, ac_online); - power_supply_changed(&test_power_supplies[0]); - return 0; -} - -static int param_get_ac_online(char *buffer, const struct kernel_param *kp) -{ - strcpy(buffer, map_get_key(map_ac_online, ac_online, "unknown")); - return strlen(buffer); -} - -static int param_set_battery_status(const char *key, - const struct kernel_param *kp) -{ - battery_status = map_get_value(map_status, key, battery_status); - power_supply_changed(&test_power_supplies[1]); - return 0; -} - -static int param_get_battery_status(char *buffer, const struct kernel_param *kp) -{ - strcpy(buffer, map_get_key(map_status, battery_status, "unknown")); - return strlen(buffer); -} - -static int param_set_battery_health(const char *key, - const struct kernel_param *kp) -{ - battery_health = map_get_value(map_health, key, battery_health); - power_supply_changed(&test_power_supplies[1]); - return 0; -} - -static int param_get_battery_health(char *buffer, const struct kernel_param *kp) -{ - strcpy(buffer, map_get_key(map_health, battery_health, "unknown")); - return strlen(buffer); -} - -static int param_set_battery_present(const char *key, - const struct kernel_param *kp) -{ - battery_present = map_get_value(map_present, key, battery_present); - power_supply_changed(&test_power_supplies[0]); - return 0; -} - -static int param_get_battery_present(char *buffer, - const struct kernel_param *kp) -{ - strcpy(buffer, map_get_key(map_present, battery_present, "unknown")); - return strlen(buffer); -} - -static int param_set_battery_technology(const char *key, - const struct kernel_param *kp) -{ - battery_technology = map_get_value(map_technology, key, - battery_technology); - power_supply_changed(&test_power_supplies[1]); - return 0; -} - -static int param_get_battery_technology(char *buffer, - const struct kernel_param *kp) -{ - strcpy(buffer, - map_get_key(map_technology, battery_technology, "unknown")); - return strlen(buffer); -} - -static int param_set_battery_capacity(const char *key, - const struct kernel_param *kp) -{ - int tmp; - - if (1 != sscanf(key, "%d", &tmp)) - return -EINVAL; - - battery_capacity = tmp; - power_supply_changed(&test_power_supplies[1]); - return 0; -} - -#define param_get_battery_capacity param_get_int - - - -static struct kernel_param_ops param_ops_ac_online = { - .set = param_set_ac_online, - .get = param_get_ac_online, -}; - -static struct kernel_param_ops param_ops_battery_status = { - .set = param_set_battery_status, - .get = param_get_battery_status, -}; - -static struct kernel_param_ops param_ops_battery_present = { - .set = param_set_battery_present, - .get = param_get_battery_present, -}; - -static struct kernel_param_ops param_ops_battery_technology = { - .set = param_set_battery_technology, - .get = param_get_battery_technology, -}; - -static struct kernel_param_ops param_ops_battery_health = { - .set = param_set_battery_health, - .get = param_get_battery_health, -}; - -static struct kernel_param_ops param_ops_battery_capacity = { - .set = param_set_battery_capacity, - .get = param_get_battery_capacity, -}; - - -#define param_check_ac_online(name, p) __param_check(name, p, void); -#define param_check_battery_status(name, p) __param_check(name, p, void); -#define param_check_battery_present(name, p) __param_check(name, p, void); -#define param_check_battery_technology(name, p) __param_check(name, p, void); -#define param_check_battery_health(name, p) __param_check(name, p, void); -#define param_check_battery_capacity(name, p) __param_check(name, p, void); - - -module_param(ac_online, ac_online, 0644); -MODULE_PARM_DESC(ac_online, "AC charging state "); - -module_param(battery_status, battery_status, 0644); -MODULE_PARM_DESC(battery_status, - "battery status "); - -module_param(battery_present, battery_present, 0644); -MODULE_PARM_DESC(battery_present, - "battery presence state "); - -module_param(battery_technology, battery_technology, 0644); -MODULE_PARM_DESC(battery_technology, - "battery technology "); - -module_param(battery_health, battery_health, 0644); -MODULE_PARM_DESC(battery_health, - "battery health state "); - -module_param(battery_capacity, battery_capacity, 0644); -MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)"); - - MODULE_DESCRIPTION("Power supply driver for testing"); MODULE_AUTHOR("Anton Vorontsov "); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/power/z2_battery.c b/trunk/drivers/power/z2_battery.c index d119c38b3ff6..e5ced3a4c1ed 100644 --- a/trunk/drivers/power/z2_battery.c +++ b/trunk/drivers/power/z2_battery.c @@ -271,33 +271,24 @@ static int __devexit z2_batt_remove(struct i2c_client *client) } #ifdef CONFIG_PM -static int z2_batt_suspend(struct device *dev) +static int z2_batt_suspend(struct i2c_client *client, pm_message_t state) { - struct i2c_client *client = to_i2c_client(dev); struct z2_charger *charger = i2c_get_clientdata(client); flush_work_sync(&charger->bat_work); return 0; } -static int z2_batt_resume(struct device *dev) +static int z2_batt_resume(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(dev); struct z2_charger *charger = i2c_get_clientdata(client); schedule_work(&charger->bat_work); return 0; } - -static const struct dev_pm_ops z2_battery_pm_ops = { - .suspend = z2_batt_suspend, - .resume = z2_batt_resume, -}; - -#define Z2_BATTERY_PM_OPS (&z2_battery_pm_ops) - #else -#define Z2_BATTERY_PM_OPS (NULL) +#define z2_batt_suspend NULL +#define z2_batt_resume NULL #endif static const struct i2c_device_id z2_batt_id[] = { @@ -310,10 +301,11 @@ static struct i2c_driver z2_batt_driver = { .driver = { .name = "z2-battery", .owner = THIS_MODULE, - .pm = Z2_BATTERY_PM_OPS }, .probe = z2_batt_probe, .remove = z2_batt_remove, + .suspend = z2_batt_suspend, + .resume = z2_batt_resume, .id_table = z2_batt_id, }; diff --git a/trunk/drivers/regulator/88pm8607.c b/trunk/drivers/regulator/88pm8607.c index d63fddb0fbb0..859251250b55 100644 --- a/trunk/drivers/regulator/88pm8607.c +++ b/trunk/drivers/regulator/88pm8607.c @@ -15,6 +15,7 @@ #include #include #include +#include #include struct pm8607_regulator_info { @@ -398,33 +399,36 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); struct pm8607_regulator_info *info = NULL; - struct regulator_init_data *pdata = pdev->dev.platform_data; - struct resource *res; + struct regulator_init_data *pdata; + struct mfd_cell *cell; int i; - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (res == NULL) { - dev_err(&pdev->dev, "No I/O resource!\n"); + cell = pdev->dev.platform_data; + if (cell == NULL) + return -ENODEV; + pdata = cell->mfd_data; + if (pdata == NULL) return -EINVAL; - } + for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) { info = &pm8607_regulator_info[i]; - if (info->desc.id == res->start) + if (!strcmp(info->desc.name, pdata->constraints.name)) break; } - if ((i < 0) || (i > PM8607_ID_RG_MAX)) { - dev_err(&pdev->dev, "Failed to find regulator %llu\n", - (unsigned long long)res->start); + if (i > ARRAY_SIZE(pm8607_regulator_info)) { + dev_err(&pdev->dev, "Failed to find regulator %s\n", + pdata->constraints.name); return -EINVAL; } + info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; info->chip = chip; /* check DVC ramp slope double */ - if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double) - info->slope_double = 1; + if (!strcmp(info->desc.name, "BUCK3")) + if (info->chip->buck3_double) + info->slope_double = 1; - /* replace driver_data with info */ info->regulator = regulator_register(&info->desc, &pdev->dev, pdata, info); if (IS_ERR(info->regulator)) { diff --git a/trunk/drivers/regulator/Kconfig b/trunk/drivers/regulator/Kconfig index d7ed20f293d7..f0b13a0d1851 100644 --- a/trunk/drivers/regulator/Kconfig +++ b/trunk/drivers/regulator/Kconfig @@ -297,11 +297,5 @@ config REGULATOR_TPS6524X serial interface currently supported on the sequencer serial port controller. -config REGULATOR_TPS65910 - tristate "TI TPS65910 Power Regulator" - depends on MFD_TPS65910 - help - This driver supports TPS65910 voltage regulator chips. - endif diff --git a/trunk/drivers/regulator/Makefile b/trunk/drivers/regulator/Makefile index 3932d2ec38f3..165ff5371e9e 100644 --- a/trunk/drivers/regulator/Makefile +++ b/trunk/drivers/regulator/Makefile @@ -42,6 +42,5 @@ obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o -obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG diff --git a/trunk/drivers/regulator/ab3100.c b/trunk/drivers/regulator/ab3100.c index 585e4946fe0a..b1d77946e9c6 100644 --- a/trunk/drivers/regulator/ab3100.c +++ b/trunk/drivers/regulator/ab3100.c @@ -17,6 +17,7 @@ #include #include #include +#include /* LDO registers and some handy masking definitions for AB3100 */ #define AB3100_LDO_A 0x40 @@ -581,7 +582,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { static int __devinit ab3100_regulators_probe(struct platform_device *pdev) { - struct ab3100_platform_data *plfdata = pdev->dev.platform_data; + struct ab3100_platform_data *plfdata = mfd_get_data(pdev); int err = 0; u8 data; int i; diff --git a/trunk/drivers/regulator/core.c b/trunk/drivers/regulator/core.c index d3e38790906e..0fae51c4845a 100644 --- a/trunk/drivers/regulator/core.c +++ b/trunk/drivers/regulator/core.c @@ -158,13 +158,6 @@ static int regulator_check_consumers(struct regulator_dev *rdev, struct regulator *regulator; list_for_each_entry(regulator, &rdev->consumer_list, list) { - /* - * Assume consumers that didn't say anything are OK - * with anything in the constraint range. - */ - if (!regulator->min_uV && !regulator->max_uV) - continue; - if (*max_uV > regulator->max_uV) *max_uV = regulator->max_uV; if (*min_uV < regulator->min_uV) @@ -204,9 +197,9 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, } /* operating mode constraint check */ -static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) +static int regulator_check_mode(struct regulator_dev *rdev, int mode) { - switch (*mode) { + switch (mode) { case REGULATOR_MODE_FAST: case REGULATOR_MODE_NORMAL: case REGULATOR_MODE_IDLE: @@ -224,17 +217,11 @@ static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) rdev_err(rdev, "operation not allowed\n"); return -EPERM; } - - /* The modes are bitmasks, the most power hungry modes having - * the lowest values. If the requested mode isn't supported - * try higher modes. */ - while (*mode) { - if (rdev->constraints->valid_modes_mask & *mode) - return 0; - *mode /= 2; + if (!(rdev->constraints->valid_modes_mask & mode)) { + rdev_err(rdev, "invalid mode %x\n", mode); + return -EINVAL; } - - return -EINVAL; + return 0; } /* dynamic regulator mode switching constraint check */ @@ -625,7 +612,7 @@ static void drms_uA_update(struct regulator_dev *rdev) output_uV, current_uA); /* check the new mode is allowed */ - err = regulator_mode_constrain(rdev, &mode); + err = regulator_check_mode(rdev, mode); if (err == 0) rdev->desc->ops->set_mode(rdev, mode); } @@ -731,10 +718,6 @@ static void print_constraints(struct regulator_dev *rdev) count += sprintf(buf + count, "at %d mV ", ret / 1000); } - if (constraints->uV_offset) - count += sprintf(buf, "%dmV offset ", - constraints->uV_offset / 1000); - if (constraints->min_uA && constraints->max_uA) { if (constraints->min_uA == constraints->max_uA) count += sprintf(buf + count, "%d mA ", @@ -1515,14 +1498,13 @@ static int _regulator_force_disable(struct regulator_dev *rdev, */ int regulator_force_disable(struct regulator *regulator) { - struct regulator_dev *rdev = regulator->rdev; struct regulator_dev *supply_rdev = NULL; int ret; - mutex_lock(&rdev->mutex); + mutex_lock(®ulator->rdev->mutex); regulator->uA_load = 0; - ret = _regulator_force_disable(rdev, &supply_rdev); - mutex_unlock(&rdev->mutex); + ret = _regulator_force_disable(regulator->rdev, &supply_rdev); + mutex_unlock(®ulator->rdev->mutex); if (supply_rdev) regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev))); @@ -1652,9 +1634,6 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); - min_uV += rdev->constraints->uV_offset; - max_uV += rdev->constraints->uV_offset; - if (rdev->desc->ops->set_voltage) { ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, &selector); @@ -1879,22 +1858,18 @@ EXPORT_SYMBOL_GPL(regulator_sync_voltage); static int _regulator_get_voltage(struct regulator_dev *rdev) { - int sel, ret; + int sel; if (rdev->desc->ops->get_voltage_sel) { sel = rdev->desc->ops->get_voltage_sel(rdev); if (sel < 0) return sel; - ret = rdev->desc->ops->list_voltage(rdev, sel); - } else if (rdev->desc->ops->get_voltage) { - ret = rdev->desc->ops->get_voltage(rdev); - } else { - return -EINVAL; + return rdev->desc->ops->list_voltage(rdev, sel); } - - if (ret < 0) - return ret; - return ret - rdev->constraints->uV_offset; + if (rdev->desc->ops->get_voltage) + return rdev->desc->ops->get_voltage(rdev); + else + return -EINVAL; } /** @@ -2030,7 +2005,7 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode) } /* constraints check */ - ret = regulator_mode_constrain(rdev, &mode); + ret = regulator_check_mode(rdev, mode); if (ret < 0) goto out; @@ -2106,26 +2081,16 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) mutex_lock(&rdev->mutex); - /* - * first check to see if we can set modes at all, otherwise just - * tell the consumer everything is OK. - */ regulator->uA_load = uA_load; ret = regulator_check_drms(rdev); - if (ret < 0) { - ret = 0; + if (ret < 0) goto out; - } + ret = -EINVAL; + /* sanity check */ if (!rdev->desc->ops->get_optimum_mode) goto out; - /* - * we can actually do this so any errors are indicators of - * potential real failure. - */ - ret = -EINVAL; - /* get output voltage */ output_uV = _regulator_get_voltage(rdev); if (output_uV <= 0) { @@ -2151,7 +2116,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, output_uV, total_uA_load); - ret = regulator_mode_constrain(rdev, &mode); + ret = regulator_check_mode(rdev, mode); if (ret < 0) { rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", total_uA_load, input_uV, output_uV); @@ -2624,6 +2589,14 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, if (ret < 0) goto scrub; + /* set supply regulator if it exists */ + if (init_data->supply_regulator && init_data->supply_regulator_dev) { + dev_err(dev, + "Supply regulator specified by both name and dev\n"); + ret = -EINVAL; + goto scrub; + } + if (init_data->supply_regulator) { struct regulator_dev *r; int found = 0; @@ -2648,6 +2621,14 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, goto scrub; } + if (init_data->supply_regulator_dev) { + dev_warn(dev, "Uses supply_regulator_dev instead of regulator_supply\n"); + ret = set_supply(rdev, + dev_get_drvdata(init_data->supply_regulator_dev)); + if (ret < 0) + goto scrub; + } + /* add consumers devices */ for (i = 0; i < init_data->num_consumer_supplies; i++) { ret = set_consumer_device_supply(rdev, diff --git a/trunk/drivers/regulator/db8500-prcmu.c b/trunk/drivers/regulator/db8500-prcmu.c index e5f7b8fe51f4..1089a961616e 100644 --- a/trunk/drivers/regulator/db8500-prcmu.c +++ b/trunk/drivers/regulator/db8500-prcmu.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -470,8 +471,7 @@ static struct db8500_regulator_info static int __devinit db8500_regulator_probe(struct platform_device *pdev) { - struct regulator_init_data *db8500_init_data = - dev_get_platdata(&pdev->dev); + struct regulator_init_data *db8500_init_data = mfd_get_data(pdev); int i, err; /* register all regulators */ diff --git a/trunk/drivers/regulator/max8925-regulator.c b/trunk/drivers/regulator/max8925-regulator.c index e4dbd667c043..8ae147549c6a 100644 --- a/trunk/drivers/regulator/max8925-regulator.c +++ b/trunk/drivers/regulator/max8925-regulator.c @@ -23,10 +23,6 @@ #define SD1_DVM_SHIFT 5 /* SDCTL1 bit5 */ #define SD1_DVM_EN 6 /* SDV1 bit 6 */ -/* bit definitions in SD & LDO control registers */ -#define OUT_ENABLE 0x1f /* Power U/D sequence as I2C */ -#define OUT_DISABLE 0x1e /* Power U/D sequence as I2C */ - struct max8925_regulator_info { struct regulator_desc desc; struct regulator_dev *regulator; @@ -97,8 +93,8 @@ static int max8925_enable(struct regulator_dev *rdev) struct max8925_regulator_info *info = rdev_get_drvdata(rdev); return max8925_set_bits(info->i2c, info->enable_reg, - OUT_ENABLE << info->enable_bit, - OUT_ENABLE << info->enable_bit); + 1 << info->enable_bit, + 1 << info->enable_bit); } static int max8925_disable(struct regulator_dev *rdev) @@ -106,8 +102,7 @@ static int max8925_disable(struct regulator_dev *rdev) struct max8925_regulator_info *info = rdev_get_drvdata(rdev); return max8925_set_bits(info->i2c, info->enable_reg, - OUT_ENABLE << info->enable_bit, - OUT_DISABLE << info->enable_bit); + 1 << info->enable_bit, 0); } static int max8925_is_enabled(struct regulator_dev *rdev) diff --git a/trunk/drivers/regulator/max8997.c b/trunk/drivers/regulator/max8997.c index 10d5a1d9768e..77e0cfb30b23 100644 --- a/trunk/drivers/regulator/max8997.c +++ b/trunk/drivers/regulator/max8997.c @@ -267,6 +267,7 @@ static int max8997_get_enable_register(struct regulator_dev *rdev, default: /* Not controllable or not exists */ return -EINVAL; + break; } return 0; @@ -1032,11 +1033,11 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) /* For the safety, set max voltage before setting up */ for (i = 0; i < 8; i++) { - max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i, + max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS(i + 1), max_buck1, 0x3f); - max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i, + max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1), max_buck2, 0x3f); - max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i, + max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1), max_buck5, 0x3f); } @@ -1113,13 +1114,13 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) /* Initialize all the DVS related BUCK registers */ for (i = 0; i < 8; i++) { - max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i, + max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS(i + 1), max8997->buck1_vol[i], 0x3f); - max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i, + max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1), max8997->buck2_vol[i], 0x3f); - max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i, + max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1), max8997->buck5_vol[i], 0x3f); } diff --git a/trunk/drivers/regulator/max8998.c b/trunk/drivers/regulator/max8998.c index 41a1495eec2b..f57e9c42fdb4 100644 --- a/trunk/drivers/regulator/max8998.c +++ b/trunk/drivers/regulator/max8998.c @@ -732,15 +732,13 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) if (!pdata->buck1_set1) { printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n"); WARN_ON(!pdata->buck1_set1); - ret = -EIO; - goto err_free_mem; + return -EIO; } /* Check if SET2 is not equal to 0 */ if (!pdata->buck1_set2) { printk(KERN_ERR "MAX8998 SET2 GPIO defined as 0 !\n"); WARN_ON(!pdata->buck1_set2); - ret = -EIO; - goto err_free_mem; + return -EIO; } gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1"); @@ -760,7 +758,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck1_vol[0] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); if (ret) - goto err_free_mem; + return ret; /* Set predefined value for BUCK1 register 2 */ i = 0; @@ -772,7 +770,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck1_vol[1] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i); if (ret) - goto err_free_mem; + return ret; /* Set predefined value for BUCK1 register 3 */ i = 0; @@ -784,7 +782,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck1_vol[2] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i); if (ret) - goto err_free_mem; + return ret; /* Set predefined value for BUCK1 register 4 */ i = 0; @@ -796,7 +794,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck1_vol[3] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i); if (ret) - goto err_free_mem; + return ret; } @@ -805,8 +803,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) if (!pdata->buck2_set3) { printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n"); WARN_ON(!pdata->buck2_set3); - ret = -EIO; - goto err_free_mem; + return -EIO; } gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3"); gpio_direction_output(pdata->buck2_set3, @@ -821,7 +818,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck2_vol[0] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); if (ret) - goto err_free_mem; + return ret; /* BUCK2 register 2 */ i = 0; @@ -833,7 +830,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck2_vol[1] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); if (ret) - goto err_free_mem; + return ret; } for (i = 0; i < pdata->num_regulators; i++) { @@ -863,7 +860,6 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) if (rdev[i]) regulator_unregister(rdev[i]); -err_free_mem: kfree(max8998->rdev); kfree(max8998); diff --git a/trunk/drivers/regulator/mc13783-regulator.c b/trunk/drivers/regulator/mc13783-regulator.c index 730f43ad415b..b8a00c7fa441 100644 --- a/trunk/drivers/regulator/mc13783-regulator.c +++ b/trunk/drivers/regulator/mc13783-regulator.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -336,8 +337,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) { struct mc13xxx_regulator_priv *priv; struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); - struct mc13783_regulator_platform_data *pdata = - dev_get_platdata(&pdev->dev); + struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev); struct mc13783_regulator_init_data *init_data; int i, ret; @@ -381,8 +381,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) static int __devexit mc13783_regulator_remove(struct platform_device *pdev) { struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); - struct mc13783_regulator_platform_data *pdata = - dev_get_platdata(&pdev->dev); + struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev); int i; platform_set_drvdata(pdev, NULL); diff --git a/trunk/drivers/regulator/mc13892-regulator.c b/trunk/drivers/regulator/mc13892-regulator.c index 3285d41842f2..6f15168e5ed4 100644 --- a/trunk/drivers/regulator/mc13892-regulator.c +++ b/trunk/drivers/regulator/mc13892-regulator.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -431,8 +432,7 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); - int hi, value, mask, id = rdev_get_id(rdev); - u32 valread; + int hi, value, val, mask, id = rdev_get_id(rdev); int ret; dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", @@ -448,16 +448,15 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_read(priv->mc13xxx, - mc13892_regulators[id].vsel_reg, &valread); + mc13892_regulators[id].vsel_reg, &val); if (ret) goto err; - if (value > 1375000) + hi = val & MC13892_SWITCHERS0_SWxHI; + if (value > 1375) hi = 1; - else if (value < 1100000) + if (value < 1100) hi = 0; - else - hi = valread & MC13892_SWITCHERS0_SWxHI; if (hi) { value = (value - 1100000) / 25000; @@ -466,10 +465,8 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, value = (value - 600000) / 25000; mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI; - valread = (valread & ~mask) | - (value << mc13892_regulators[id].vsel_shift); - ret = mc13xxx_reg_write(priv->mc13xxx, mc13892_regulators[id].vsel_reg, - valread); + ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, + mask, value << mc13892_regulators[id].vsel_shift); err: mc13xxx_unlock(priv->mc13xxx); @@ -524,8 +521,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) { struct mc13xxx_regulator_priv *priv; struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); - struct mc13xxx_regulator_platform_data *pdata = - dev_get_platdata(&pdev->dev); + struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev); struct mc13xxx_regulator_init_data *init_data; int i, ret; u32 val; @@ -599,8 +595,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) static int __devexit mc13892_regulator_remove(struct platform_device *pdev) { struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); - struct mc13xxx_regulator_platform_data *pdata = - dev_get_platdata(&pdev->dev); + struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev); int i; platform_set_drvdata(pdev, NULL); diff --git a/trunk/drivers/regulator/mc13xxx-regulator-core.c b/trunk/drivers/regulator/mc13xxx-regulator-core.c index bc27ab136378..2bb5de1f2421 100644 --- a/trunk/drivers/regulator/mc13xxx-regulator-core.c +++ b/trunk/drivers/regulator/mc13xxx-regulator-core.c @@ -174,7 +174,7 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev) dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); - BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages); + BUG_ON(val > mc13xxx_regulators[id].desc.n_voltages); return mc13xxx_regulators[id].voltages[val]; } diff --git a/trunk/drivers/regulator/tps6105x-regulator.c b/trunk/drivers/regulator/tps6105x-regulator.c index 1011873896dc..1661499feda4 100644 --- a/trunk/drivers/regulator/tps6105x-regulator.c +++ b/trunk/drivers/regulator/tps6105x-regulator.c @@ -137,7 +137,7 @@ static struct regulator_desc tps6105x_regulator_desc = { */ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) { - struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev); + struct tps6105x *tps6105x = mfd_get_data(pdev); struct tps6105x_platform_data *pdata = tps6105x->pdata; int ret; @@ -158,14 +158,13 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) "failed to register regulator\n"); return ret; } - platform_set_drvdata(pdev, tps6105x); return 0; } static int __devexit tps6105x_regulator_remove(struct platform_device *pdev) { - struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev); + struct tps6105x *tps6105x = platform_get_drvdata(pdev); regulator_unregister(tps6105x->regulator); return 0; } diff --git a/trunk/drivers/regulator/tps65023-regulator.c b/trunk/drivers/regulator/tps65023-regulator.c index fbddc15e1811..60a7ca5409e9 100644 --- a/trunk/drivers/regulator/tps65023-regulator.c +++ b/trunk/drivers/regulator/tps65023-regulator.c @@ -466,6 +466,7 @@ static struct regulator_ops tps65023_ldo_ops = { static int __devinit tps_65023_probe(struct i2c_client *client, const struct i2c_device_id *id) { + static int desc_id; const struct tps_info *info = (void *)id->driver_data; struct regulator_init_data *init_data; struct regulator_dev *rdev; @@ -498,7 +499,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client, tps->info[i] = info; tps->desc[i].name = info->name; - tps->desc[i].id = i; + tps->desc[i].id = desc_id++; tps->desc[i].n_voltages = num_voltages[i]; tps->desc[i].ops = (i > TPS65023_DCDC_3 ? &tps65023_ldo_ops : &tps65023_dcdc_ops); diff --git a/trunk/drivers/regulator/tps6507x-regulator.c b/trunk/drivers/regulator/tps6507x-regulator.c index bfffabc21eda..064755290599 100644 --- a/trunk/drivers/regulator/tps6507x-regulator.c +++ b/trunk/drivers/regulator/tps6507x-regulator.c @@ -553,6 +553,7 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev) { struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); + static int desc_id; struct tps_info *info = &tps6507x_pmic_regs[0]; struct regulator_init_data *init_data; struct regulator_dev *rdev; @@ -597,7 +598,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev) } tps->desc[i].name = info->name; - tps->desc[i].id = i; + tps->desc[i].id = desc_id++; tps->desc[i].n_voltages = num_voltages[i]; tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? &tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops); diff --git a/trunk/drivers/regulator/tps65910-regulator.c b/trunk/drivers/regulator/tps65910-regulator.c deleted file mode 100644 index 55dd4e6650db..000000000000 --- a/trunk/drivers/regulator/tps65910-regulator.c +++ /dev/null @@ -1,993 +0,0 @@ -/* - * tps65910.c -- TI tps65910 - * - * Copyright 2010 Texas Instruments Inc. - * - * Author: Graeme Gregory - * Author: Jorge Eduardo Candelaria - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TPS65910_REG_VRTC 0 -#define TPS65910_REG_VIO 1 -#define TPS65910_REG_VDD1 2 -#define TPS65910_REG_VDD2 3 -#define TPS65910_REG_VDD3 4 -#define TPS65910_REG_VDIG1 5 -#define TPS65910_REG_VDIG2 6 -#define TPS65910_REG_VPLL 7 -#define TPS65910_REG_VDAC 8 -#define TPS65910_REG_VAUX1 9 -#define TPS65910_REG_VAUX2 10 -#define TPS65910_REG_VAUX33 11 -#define TPS65910_REG_VMMC 12 - -#define TPS65911_REG_VDDCTRL 4 -#define TPS65911_REG_LDO1 5 -#define TPS65911_REG_LDO2 6 -#define TPS65911_REG_LDO3 7 -#define TPS65911_REG_LDO4 8 -#define TPS65911_REG_LDO5 9 -#define TPS65911_REG_LDO6 10 -#define TPS65911_REG_LDO7 11 -#define TPS65911_REG_LDO8 12 - -#define TPS65910_NUM_REGULATOR 13 -#define TPS65910_SUPPLY_STATE_ENABLED 0x1 - -/* supported VIO voltages in milivolts */ -static const u16 VIO_VSEL_table[] = { - 1500, 1800, 2500, 3300, -}; - -/* VSEL tables for TPS65910 specific LDOs and dcdc's */ - -/* supported VDD3 voltages in milivolts */ -static const u16 VDD3_VSEL_table[] = { - 5000, -}; - -/* supported VDIG1 voltages in milivolts */ -static const u16 VDIG1_VSEL_table[] = { - 1200, 1500, 1800, 2700, -}; - -/* supported VDIG2 voltages in milivolts */ -static const u16 VDIG2_VSEL_table[] = { - 1000, 1100, 1200, 1800, -}; - -/* supported VPLL voltages in milivolts */ -static const u16 VPLL_VSEL_table[] = { - 1000, 1100, 1800, 2500, -}; - -/* supported VDAC voltages in milivolts */ -static const u16 VDAC_VSEL_table[] = { - 1800, 2600, 2800, 2850, -}; - -/* supported VAUX1 voltages in milivolts */ -static const u16 VAUX1_VSEL_table[] = { - 1800, 2500, 2800, 2850, -}; - -/* supported VAUX2 voltages in milivolts */ -static const u16 VAUX2_VSEL_table[] = { - 1800, 2800, 2900, 3300, -}; - -/* supported VAUX33 voltages in milivolts */ -static const u16 VAUX33_VSEL_table[] = { - 1800, 2000, 2800, 3300, -}; - -/* supported VMMC voltages in milivolts */ -static const u16 VMMC_VSEL_table[] = { - 1800, 2800, 3000, 3300, -}; - -struct tps_info { - const char *name; - unsigned min_uV; - unsigned max_uV; - u8 table_len; - const u16 *table; -}; - -static struct tps_info tps65910_regs[] = { - { - .name = "VRTC", - }, - { - .name = "VIO", - .min_uV = 1500000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(VIO_VSEL_table), - .table = VIO_VSEL_table, - }, - { - .name = "VDD1", - .min_uV = 600000, - .max_uV = 4500000, - }, - { - .name = "VDD2", - .min_uV = 600000, - .max_uV = 4500000, - }, - { - .name = "VDD3", - .min_uV = 5000000, - .max_uV = 5000000, - .table_len = ARRAY_SIZE(VDD3_VSEL_table), - .table = VDD3_VSEL_table, - }, - { - .name = "VDIG1", - .min_uV = 1200000, - .max_uV = 2700000, - .table_len = ARRAY_SIZE(VDIG1_VSEL_table), - .table = VDIG1_VSEL_table, - }, - { - .name = "VDIG2", - .min_uV = 1000000, - .max_uV = 1800000, - .table_len = ARRAY_SIZE(VDIG2_VSEL_table), - .table = VDIG2_VSEL_table, - }, - { - .name = "VPLL", - .min_uV = 1000000, - .max_uV = 2500000, - .table_len = ARRAY_SIZE(VPLL_VSEL_table), - .table = VPLL_VSEL_table, - }, - { - .name = "VDAC", - .min_uV = 1800000, - .max_uV = 2850000, - .table_len = ARRAY_SIZE(VDAC_VSEL_table), - .table = VDAC_VSEL_table, - }, - { - .name = "VAUX1", - .min_uV = 1800000, - .max_uV = 2850000, - .table_len = ARRAY_SIZE(VAUX1_VSEL_table), - .table = VAUX1_VSEL_table, - }, - { - .name = "VAUX2", - .min_uV = 1800000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(VAUX2_VSEL_table), - .table = VAUX2_VSEL_table, - }, - { - .name = "VAUX33", - .min_uV = 1800000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(VAUX33_VSEL_table), - .table = VAUX33_VSEL_table, - }, - { - .name = "VMMC", - .min_uV = 1800000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(VMMC_VSEL_table), - .table = VMMC_VSEL_table, - }, -}; - -static struct tps_info tps65911_regs[] = { - { - .name = "VIO", - .min_uV = 1500000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(VIO_VSEL_table), - .table = VIO_VSEL_table, - }, - { - .name = "VDD1", - .min_uV = 600000, - .max_uV = 4500000, - }, - { - .name = "VDD2", - .min_uV = 600000, - .max_uV = 4500000, - }, - { - .name = "VDDCTRL", - .min_uV = 600000, - .max_uV = 1400000, - }, - { - .name = "LDO1", - .min_uV = 1000000, - .max_uV = 3300000, - }, - { - .name = "LDO2", - .min_uV = 1000000, - .max_uV = 3300000, - }, - { - .name = "LDO3", - .min_uV = 1000000, - .max_uV = 3300000, - }, - { - .name = "LDO4", - .min_uV = 1000000, - .max_uV = 3300000, - }, - { - .name = "LDO5", - .min_uV = 1000000, - .max_uV = 3300000, - }, - { - .name = "LDO6", - .min_uV = 1000000, - .max_uV = 3300000, - }, - { - .name = "LDO7", - .min_uV = 1000000, - .max_uV = 3300000, - }, - { - .name = "LDO8", - .min_uV = 1000000, - .max_uV = 3300000, - }, -}; - -struct tps65910_reg { - struct regulator_desc desc[TPS65910_NUM_REGULATOR]; - struct tps65910 *mfd; - struct regulator_dev *rdev[TPS65910_NUM_REGULATOR]; - struct tps_info *info[TPS65910_NUM_REGULATOR]; - struct mutex mutex; - int mode; - int (*get_ctrl_reg)(int); -}; - -static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg) -{ - u8 val; - int err; - - err = pmic->mfd->read(pmic->mfd, reg, 1, &val); - if (err) - return err; - - return val; -} - -static inline int tps65910_write(struct tps65910_reg *pmic, u8 reg, u8 val) -{ - return pmic->mfd->write(pmic->mfd, reg, 1, &val); -} - -static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg, - u8 set_mask, u8 clear_mask) -{ - int err, data; - - mutex_lock(&pmic->mutex); - - data = tps65910_read(pmic, reg); - if (data < 0) { - dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg); - err = data; - goto out; - } - - data &= ~clear_mask; - data |= set_mask; - err = tps65910_write(pmic, reg, data); - if (err) - dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); - -out: - mutex_unlock(&pmic->mutex); - return err; -} - -static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg) -{ - int data; - - mutex_lock(&pmic->mutex); - - data = tps65910_read(pmic, reg); - if (data < 0) - dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg); - - mutex_unlock(&pmic->mutex); - return data; -} - -static int tps65910_reg_write(struct tps65910_reg *pmic, u8 reg, u8 val) -{ - int err; - - mutex_lock(&pmic->mutex); - - err = tps65910_write(pmic, reg, val); - if (err < 0) - dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); - - mutex_unlock(&pmic->mutex); - return err; -} - -static int tps65910_get_ctrl_register(int id) -{ - switch (id) { - case TPS65910_REG_VRTC: - return TPS65910_VRTC; - case TPS65910_REG_VIO: - return TPS65910_VIO; - case TPS65910_REG_VDD1: - return TPS65910_VDD1; - case TPS65910_REG_VDD2: - return TPS65910_VDD2; - case TPS65910_REG_VDD3: - return TPS65910_VDD3; - case TPS65910_REG_VDIG1: - return TPS65910_VDIG1; - case TPS65910_REG_VDIG2: - return TPS65910_VDIG2; - case TPS65910_REG_VPLL: - return TPS65910_VPLL; - case TPS65910_REG_VDAC: - return TPS65910_VDAC; - case TPS65910_REG_VAUX1: - return TPS65910_VAUX1; - case TPS65910_REG_VAUX2: - return TPS65910_VAUX2; - case TPS65910_REG_VAUX33: - return TPS65910_VAUX33; - case TPS65910_REG_VMMC: - return TPS65910_VMMC; - default: - return -EINVAL; - } -} - -static int tps65911_get_ctrl_register(int id) -{ - switch (id) { - case TPS65910_REG_VRTC: - return TPS65910_VRTC; - case TPS65910_REG_VIO: - return TPS65910_VIO; - case TPS65910_REG_VDD1: - return TPS65910_VDD1; - case TPS65910_REG_VDD2: - return TPS65910_VDD2; - case TPS65911_REG_VDDCTRL: - return TPS65911_VDDCTRL; - case TPS65911_REG_LDO1: - return TPS65911_LDO1; - case TPS65911_REG_LDO2: - return TPS65911_LDO2; - case TPS65911_REG_LDO3: - return TPS65911_LDO3; - case TPS65911_REG_LDO4: - return TPS65911_LDO4; - case TPS65911_REG_LDO5: - return TPS65911_LDO5; - case TPS65911_REG_LDO6: - return TPS65911_LDO6; - case TPS65911_REG_LDO7: - return TPS65911_LDO7; - case TPS65911_REG_LDO8: - return TPS65911_LDO8; - default: - return -EINVAL; - } -} - -static int tps65910_is_enabled(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int reg, value, id = rdev_get_id(dev); - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - value = tps65910_reg_read(pmic, reg); - if (value < 0) - return value; - - return value & TPS65910_SUPPLY_STATE_ENABLED; -} - -static int tps65910_enable(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - struct tps65910 *mfd = pmic->mfd; - int reg, id = rdev_get_id(dev); - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - return tps65910_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); -} - -static int tps65910_disable(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - struct tps65910 *mfd = pmic->mfd; - int reg, id = rdev_get_id(dev); - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); -} - - -static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - struct tps65910 *mfd = pmic->mfd; - int reg, value, id = rdev_get_id(dev); - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - switch (mode) { - case REGULATOR_MODE_NORMAL: - return tps65910_modify_bits(pmic, reg, LDO_ST_ON_BIT, - LDO_ST_MODE_BIT); - case REGULATOR_MODE_IDLE: - value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT; - return tps65910_set_bits(mfd, reg, value); - case REGULATOR_MODE_STANDBY: - return tps65910_clear_bits(mfd, reg, LDO_ST_ON_BIT); - } - - return -EINVAL; -} - -static unsigned int tps65910_get_mode(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int reg, value, id = rdev_get_id(dev); - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - value = tps65910_reg_read(pmic, reg); - if (value < 0) - return value; - - if (value & LDO_ST_ON_BIT) - return REGULATOR_MODE_STANDBY; - else if (value & LDO_ST_MODE_BIT) - return REGULATOR_MODE_IDLE; - else - return REGULATOR_MODE_NORMAL; -} - -static int tps65910_get_voltage_dcdc(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev), voltage = 0; - int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0; - - switch (id) { - case TPS65910_REG_VDD1: - opvsel = tps65910_reg_read(pmic, TPS65910_VDD1_OP); - mult = tps65910_reg_read(pmic, TPS65910_VDD1); - mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT; - srvsel = tps65910_reg_read(pmic, TPS65910_VDD1_SR); - sr = opvsel & VDD1_OP_CMD_MASK; - opvsel &= VDD1_OP_SEL_MASK; - srvsel &= VDD1_SR_SEL_MASK; - vselmax = 75; - break; - case TPS65910_REG_VDD2: - opvsel = tps65910_reg_read(pmic, TPS65910_VDD2_OP); - mult = tps65910_reg_read(pmic, TPS65910_VDD2); - mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT; - srvsel = tps65910_reg_read(pmic, TPS65910_VDD2_SR); - sr = opvsel & VDD2_OP_CMD_MASK; - opvsel &= VDD2_OP_SEL_MASK; - srvsel &= VDD2_SR_SEL_MASK; - vselmax = 75; - break; - case TPS65911_REG_VDDCTRL: - opvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_OP); - srvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_SR); - sr = opvsel & VDDCTRL_OP_CMD_MASK; - opvsel &= VDDCTRL_OP_SEL_MASK; - srvsel &= VDDCTRL_SR_SEL_MASK; - vselmax = 64; - break; - } - - /* multiplier 0 == 1 but 2,3 normal */ - if (!mult) - mult=1; - - if (sr) { - /* normalise to valid range */ - if (srvsel < 3) - srvsel = 3; - if (srvsel > vselmax) - srvsel = vselmax; - srvsel -= 3; - - voltage = (srvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100; - } else { - - /* normalise to valid range*/ - if (opvsel < 3) - opvsel = 3; - if (opvsel > vselmax) - opvsel = vselmax; - opvsel -= 3; - - voltage = (opvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100; - } - - voltage *= mult; - - return voltage; -} - -static int tps65910_get_voltage(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int reg, value, id = rdev_get_id(dev), voltage = 0; - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - value = tps65910_reg_read(pmic, reg); - if (value < 0) - return value; - - switch (id) { - case TPS65910_REG_VIO: - case TPS65910_REG_VDIG1: - case TPS65910_REG_VDIG2: - case TPS65910_REG_VPLL: - case TPS65910_REG_VDAC: - case TPS65910_REG_VAUX1: - case TPS65910_REG_VAUX2: - case TPS65910_REG_VAUX33: - case TPS65910_REG_VMMC: - value &= LDO_SEL_MASK; - value >>= LDO_SEL_SHIFT; - break; - default: - return -EINVAL; - } - - voltage = pmic->info[id]->table[value] * 1000; - - return voltage; -} - -static int tps65910_get_voltage_vdd3(struct regulator_dev *dev) -{ - return 5 * 1000 * 1000; -} - -static int tps65911_get_voltage(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int step_mv, id = rdev_get_id(dev); - u8 value, reg; - - reg = pmic->get_ctrl_reg(id); - - value = tps65910_reg_read(pmic, reg); - - switch (id) { - case TPS65911_REG_LDO1: - case TPS65911_REG_LDO2: - case TPS65911_REG_LDO4: - value &= LDO1_SEL_MASK; - value >>= LDO_SEL_SHIFT; - /* The first 5 values of the selector correspond to 1V */ - if (value < 5) - value = 0; - else - value -= 4; - - step_mv = 50; - break; - case TPS65911_REG_LDO3: - case TPS65911_REG_LDO5: - case TPS65911_REG_LDO6: - case TPS65911_REG_LDO7: - case TPS65911_REG_LDO8: - value &= LDO3_SEL_MASK; - value >>= LDO_SEL_SHIFT; - /* The first 3 values of the selector correspond to 1V */ - if (value < 3) - value = 0; - else - value -= 2; - - step_mv = 100; - break; - case TPS65910_REG_VIO: - return pmic->info[id]->table[value] * 1000; - break; - default: - return -EINVAL; - } - - return (LDO_MIN_VOLT + value * step_mv) * 1000; -} - -static int tps65910_set_voltage_dcdc(struct regulator_dev *dev, - unsigned selector) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev), vsel; - int dcdc_mult = 0; - - switch (id) { - case TPS65910_REG_VDD1: - dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1; - if (dcdc_mult == 1) - dcdc_mult--; - vsel = (selector % VDD1_2_NUM_VOLTS) + 3; - - tps65910_modify_bits(pmic, TPS65910_VDD1, - (dcdc_mult << VDD1_VGAIN_SEL_SHIFT), - VDD1_VGAIN_SEL_MASK); - tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel); - break; - case TPS65910_REG_VDD2: - dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1; - if (dcdc_mult == 1) - dcdc_mult--; - vsel = (selector % VDD1_2_NUM_VOLTS) + 3; - - tps65910_modify_bits(pmic, TPS65910_VDD2, - (dcdc_mult << VDD2_VGAIN_SEL_SHIFT), - VDD1_VGAIN_SEL_MASK); - tps65910_reg_write(pmic, TPS65910_VDD2_OP, vsel); - break; - case TPS65911_REG_VDDCTRL: - vsel = selector; - tps65910_reg_write(pmic, TPS65911_VDDCTRL_OP, vsel); - } - - return 0; -} - -static int tps65910_set_voltage(struct regulator_dev *dev, unsigned selector) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int reg, id = rdev_get_id(dev); - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - switch (id) { - case TPS65910_REG_VIO: - case TPS65910_REG_VDIG1: - case TPS65910_REG_VDIG2: - case TPS65910_REG_VPLL: - case TPS65910_REG_VDAC: - case TPS65910_REG_VAUX1: - case TPS65910_REG_VAUX2: - case TPS65910_REG_VAUX33: - case TPS65910_REG_VMMC: - return tps65910_modify_bits(pmic, reg, - (selector << LDO_SEL_SHIFT), LDO_SEL_MASK); - } - - return -EINVAL; -} - -static int tps65911_set_voltage(struct regulator_dev *dev, unsigned selector) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int reg, id = rdev_get_id(dev); - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - switch (id) { - case TPS65911_REG_LDO1: - case TPS65911_REG_LDO2: - case TPS65911_REG_LDO4: - return tps65910_modify_bits(pmic, reg, - (selector << LDO_SEL_SHIFT), LDO1_SEL_MASK); - case TPS65911_REG_LDO3: - case TPS65911_REG_LDO5: - case TPS65911_REG_LDO6: - case TPS65911_REG_LDO7: - case TPS65911_REG_LDO8: - case TPS65910_REG_VIO: - return tps65910_modify_bits(pmic, reg, - (selector << LDO_SEL_SHIFT), LDO3_SEL_MASK); - } - - return -EINVAL; -} - - -static int tps65910_list_voltage_dcdc(struct regulator_dev *dev, - unsigned selector) -{ - int volt, mult = 1, id = rdev_get_id(dev); - - switch (id) { - case TPS65910_REG_VDD1: - case TPS65910_REG_VDD2: - mult = (selector / VDD1_2_NUM_VOLTS) + 1; - volt = VDD1_2_MIN_VOLT + - (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET; - case TPS65911_REG_VDDCTRL: - volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET); - } - - return volt * 100 * mult; -} - -static int tps65910_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev), voltage; - - if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC) - return -EINVAL; - - if (selector >= pmic->info[id]->table_len) - return -EINVAL; - else - voltage = pmic->info[id]->table[selector] * 1000; - - return voltage; -} - -static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int step_mv = 0, id = rdev_get_id(dev); - - switch(id) { - case TPS65911_REG_LDO1: - case TPS65911_REG_LDO2: - case TPS65911_REG_LDO4: - /* The first 5 values of the selector correspond to 1V */ - if (selector < 5) - selector = 0; - else - selector -= 4; - - step_mv = 50; - break; - case TPS65911_REG_LDO3: - case TPS65911_REG_LDO5: - case TPS65911_REG_LDO6: - case TPS65911_REG_LDO7: - case TPS65911_REG_LDO8: - /* The first 3 values of the selector correspond to 1V */ - if (selector < 3) - selector = 0; - else - selector -= 2; - - step_mv = 100; - break; - case TPS65910_REG_VIO: - return pmic->info[id]->table[selector] * 1000; - default: - return -EINVAL; - } - - return (LDO_MIN_VOLT + selector * step_mv) * 1000; -} - -/* Regulator ops (except VRTC) */ -static struct regulator_ops tps65910_ops_dcdc = { - .is_enabled = tps65910_is_enabled, - .enable = tps65910_enable, - .disable = tps65910_disable, - .set_mode = tps65910_set_mode, - .get_mode = tps65910_get_mode, - .get_voltage = tps65910_get_voltage_dcdc, - .set_voltage_sel = tps65910_set_voltage_dcdc, - .list_voltage = tps65910_list_voltage_dcdc, -}; - -static struct regulator_ops tps65910_ops_vdd3 = { - .is_enabled = tps65910_is_enabled, - .enable = tps65910_enable, - .disable = tps65910_disable, - .set_mode = tps65910_set_mode, - .get_mode = tps65910_get_mode, - .get_voltage = tps65910_get_voltage_vdd3, - .list_voltage = tps65910_list_voltage, -}; - -static struct regulator_ops tps65910_ops = { - .is_enabled = tps65910_is_enabled, - .enable = tps65910_enable, - .disable = tps65910_disable, - .set_mode = tps65910_set_mode, - .get_mode = tps65910_get_mode, - .get_voltage = tps65910_get_voltage, - .set_voltage_sel = tps65910_set_voltage, - .list_voltage = tps65910_list_voltage, -}; - -static struct regulator_ops tps65911_ops = { - .is_enabled = tps65910_is_enabled, - .enable = tps65910_enable, - .disable = tps65910_disable, - .set_mode = tps65910_set_mode, - .get_mode = tps65910_get_mode, - .get_voltage = tps65911_get_voltage, - .set_voltage_sel = tps65911_set_voltage, - .list_voltage = tps65911_list_voltage, -}; - -static __devinit int tps65910_probe(struct platform_device *pdev) -{ - struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); - struct tps_info *info; - struct regulator_init_data *reg_data; - struct regulator_dev *rdev; - struct tps65910_reg *pmic; - struct tps65910_board *pmic_plat_data; - int i, err; - - pmic_plat_data = dev_get_platdata(tps65910->dev); - if (!pmic_plat_data) - return -EINVAL; - - reg_data = pmic_plat_data->tps65910_pmic_init_data; - - pmic = kzalloc(sizeof(*pmic), GFP_KERNEL); - if (!pmic) - return -ENOMEM; - - mutex_init(&pmic->mutex); - pmic->mfd = tps65910; - platform_set_drvdata(pdev, pmic); - - /* Give control of all register to control port */ - tps65910_set_bits(pmic->mfd, TPS65910_DEVCTRL, - DEVCTRL_SR_CTL_I2C_SEL_MASK); - - switch(tps65910_chip_id(tps65910)) { - case TPS65910: - pmic->get_ctrl_reg = &tps65910_get_ctrl_register; - info = tps65910_regs; - case TPS65911: - pmic->get_ctrl_reg = &tps65911_get_ctrl_register; - info = tps65911_regs; - default: - pr_err("Invalid tps chip version\n"); - return -ENODEV; - } - - for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) { - /* Register the regulators */ - pmic->info[i] = info; - - pmic->desc[i].name = info->name; - pmic->desc[i].id = i; - pmic->desc[i].n_voltages = info->table_len; - - if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) { - pmic->desc[i].ops = &tps65910_ops_dcdc; - } else if (i == TPS65910_REG_VDD3) { - if (tps65910_chip_id(tps65910) == TPS65910) - pmic->desc[i].ops = &tps65910_ops_vdd3; - else - pmic->desc[i].ops = &tps65910_ops_dcdc; - } else { - if (tps65910_chip_id(tps65910) == TPS65910) - pmic->desc[i].ops = &tps65910_ops; - else - pmic->desc[i].ops = &tps65911_ops; - } - - pmic->desc[i].type = REGULATOR_VOLTAGE; - pmic->desc[i].owner = THIS_MODULE; - - rdev = regulator_register(&pmic->desc[i], - tps65910->dev, reg_data, pmic); - if (IS_ERR(rdev)) { - dev_err(tps65910->dev, - "failed to register %s regulator\n", - pdev->name); - err = PTR_ERR(rdev); - goto err; - } - - /* Save regulator for cleanup */ - pmic->rdev[i] = rdev; - } - return 0; - -err: - while (--i >= 0) - regulator_unregister(pmic->rdev[i]); - - kfree(pmic); - return err; -} - -static int __devexit tps65910_remove(struct platform_device *pdev) -{ - struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < TPS65910_NUM_REGULATOR; i++) - regulator_unregister(tps65910_reg->rdev[i]); - - kfree(tps65910_reg); - return 0; -} - -static struct platform_driver tps65910_driver = { - .driver = { - .name = "tps65910-pmic", - .owner = THIS_MODULE, - }, - .probe = tps65910_probe, - .remove = __devexit_p(tps65910_remove), -}; - -static int __init tps65910_init(void) -{ - return platform_driver_register(&tps65910_driver); -} -subsys_initcall(tps65910_init); - -static void __exit tps65910_cleanup(void) -{ - platform_driver_unregister(&tps65910_driver); -} -module_exit(tps65910_cleanup); - -MODULE_AUTHOR("Graeme Gregory "); -MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tps65910-pmic"); diff --git a/trunk/drivers/regulator/twl-regulator.c b/trunk/drivers/regulator/twl-regulator.c index 87fe0f75a56e..6a292852a358 100644 --- a/trunk/drivers/regulator/twl-regulator.c +++ b/trunk/drivers/regulator/twl-regulator.c @@ -51,13 +51,8 @@ struct twlreg_info { u16 min_mV; u16 max_mV; - u8 flags; - /* used by regulator core */ struct regulator_desc desc; - - /* chip specific features */ - unsigned long features; }; @@ -75,35 +70,12 @@ struct twlreg_info { #define VREG_TRANS 1 #define VREG_STATE 2 #define VREG_VOLTAGE 3 -#define VREG_VOLTAGE_SMPS 4 /* TWL6030 Misc register offsets */ #define VREG_BC_ALL 1 #define VREG_BC_REF 2 #define VREG_BC_PROC 3 #define VREG_BC_CLK_RST 4 -/* TWL6030 LDO register values for CFG_STATE */ -#define TWL6030_CFG_STATE_OFF 0x00 -#define TWL6030_CFG_STATE_ON 0x01 -#define TWL6030_CFG_STATE_OFF2 0x02 -#define TWL6030_CFG_STATE_SLEEP 0x03 -#define TWL6030_CFG_STATE_GRP_SHIFT 5 -#define TWL6030_CFG_STATE_APP_SHIFT 2 -#define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT) -#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\ - TWL6030_CFG_STATE_APP_SHIFT) - -/* Flags for SMPS Voltage reading */ -#define SMPS_OFFSET_EN BIT(0) -#define SMPS_EXTENDED_EN BIT(1) - -/* twl6025 SMPS EPROM values */ -#define TWL6030_SMPS_OFFSET 0xB0 -#define TWL6030_SMPS_MULT 0xB3 -#define SMPS_MULTOFFSET_SMPS4 BIT(0) -#define SMPS_MULTOFFSET_VIO BIT(1) -#define SMPS_MULTOFFSET_SMPS3 BIT(6) - static inline int twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset) { @@ -146,38 +118,21 @@ static int twlreg_grp(struct regulator_dev *rdev) #define P2_GRP_6030 BIT(1) /* "peripherals" */ #define P1_GRP_6030 BIT(0) /* CPU/Linux */ -static int twl4030reg_is_enabled(struct regulator_dev *rdev) +static int twlreg_is_enabled(struct regulator_dev *rdev) { int state = twlreg_grp(rdev); if (state < 0) return state; - return state & P1_GRP_4030; -} - -static int twl6030reg_is_enabled(struct regulator_dev *rdev) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - int grp = 0, val; - - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) - grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); - if (grp < 0) - return grp; - - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) - grp &= P1_GRP_6030; + if (twl_class_is_4030()) + state &= P1_GRP_4030; else - grp = 1; - - val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE); - val = TWL6030_CFG_STATE_APP(val); - - return grp && (val == TWL6030_CFG_STATE_ON); + state &= P1_GRP_6030; + return state; } -static int twl4030reg_enable(struct regulator_dev *rdev) +static int twlreg_enable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; @@ -187,7 +142,10 @@ static int twl4030reg_enable(struct regulator_dev *rdev) if (grp < 0) return grp; - grp |= P1_GRP_4030; + if (twl_class_is_4030()) + grp |= P1_GRP_4030; + else + grp |= P1_GRP_6030; ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); @@ -196,64 +154,30 @@ static int twl4030reg_enable(struct regulator_dev *rdev) return ret; } -static int twl6030reg_enable(struct regulator_dev *rdev) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - int grp = 0; - int ret; - - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) - grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); - if (grp < 0) - return grp; - - ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, - grp << TWL6030_CFG_STATE_GRP_SHIFT | - TWL6030_CFG_STATE_ON); - - udelay(info->delay); - - return ret; -} - -static int twl4030reg_disable(struct regulator_dev *rdev) +static int twlreg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; - int ret; grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; - grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030); - - ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); - - return ret; -} - -static int twl6030reg_disable(struct regulator_dev *rdev) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - int grp = 0; - int ret; - - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) - grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030; - - /* For 6030, set the off state for all grps enabled */ - ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, - (grp) << TWL6030_CFG_STATE_GRP_SHIFT | - TWL6030_CFG_STATE_OFF); + if (twl_class_is_4030()) + grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030); + else + grp &= ~(P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030); - return ret; + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); } -static int twl4030reg_get_status(struct regulator_dev *rdev) +static int twlreg_get_status(struct regulator_dev *rdev) { int state = twlreg_grp(rdev); + if (twl_class_is_6030()) + return 0; /* FIXME return for 6030 regulator */ + if (state < 0) return state; state &= 0x0f; @@ -266,39 +190,15 @@ static int twl4030reg_get_status(struct regulator_dev *rdev) : REGULATOR_STATUS_STANDBY; } -static int twl6030reg_get_status(struct regulator_dev *rdev) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - int val; - - val = twlreg_grp(rdev); - if (val < 0) - return val; - - val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE); - - switch (TWL6030_CFG_STATE_APP(val)) { - case TWL6030_CFG_STATE_ON: - return REGULATOR_STATUS_NORMAL; - - case TWL6030_CFG_STATE_SLEEP: - return REGULATOR_STATUS_STANDBY; - - case TWL6030_CFG_STATE_OFF: - case TWL6030_CFG_STATE_OFF2: - default: - break; - } - - return REGULATOR_STATUS_OFF; -} - -static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) +static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) { struct twlreg_info *info = rdev_get_drvdata(rdev); unsigned message; int status; + if (twl_class_is_6030()) + return 0; /* FIXME return for 6030 regulator */ + /* We can only set the mode through state machine commands... */ switch (mode) { case REGULATOR_MODE_NORMAL: @@ -327,36 +227,6 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) message & 0xff, TWL4030_PM_MASTER_PB_WORD_LSB); } -static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - int grp = 0; - int val; - - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) - grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); - - if (grp < 0) - return grp; - - /* Compose the state register settings */ - val = grp << TWL6030_CFG_STATE_GRP_SHIFT; - /* We can only set the mode through state machine commands... */ - switch (mode) { - case REGULATOR_MODE_NORMAL: - val |= TWL6030_CFG_STATE_ON; - break; - case REGULATOR_MODE_STANDBY: - val |= TWL6030_CFG_STATE_SLEEP; - break; - - default: - return -EINVAL; - } - - return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, val); -} - /*----------------------------------------------------------------------*/ /* @@ -505,13 +375,13 @@ static struct regulator_ops twl4030ldo_ops = { .set_voltage = twl4030ldo_set_voltage, .get_voltage = twl4030ldo_get_voltage, - .enable = twl4030reg_enable, - .disable = twl4030reg_disable, - .is_enabled = twl4030reg_is_enabled, + .enable = twlreg_enable, + .disable = twlreg_disable, + .is_enabled = twlreg_is_enabled, - .set_mode = twl4030reg_set_mode, + .set_mode = twlreg_set_mode, - .get_status = twl4030reg_get_status, + .get_status = twlreg_get_status, }; static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) @@ -563,13 +433,13 @@ static struct regulator_ops twl6030ldo_ops = { .set_voltage = twl6030ldo_set_voltage, .get_voltage = twl6030ldo_get_voltage, - .enable = twl6030reg_enable, - .disable = twl6030reg_disable, - .is_enabled = twl6030reg_is_enabled, + .enable = twlreg_enable, + .disable = twlreg_disable, + .is_enabled = twlreg_is_enabled, - .set_mode = twl6030reg_set_mode, + .set_mode = twlreg_set_mode, - .get_status = twl6030reg_get_status, + .get_status = twlreg_get_status, }; /*----------------------------------------------------------------------*/ @@ -591,242 +461,25 @@ static int twlfixed_get_voltage(struct regulator_dev *rdev) return info->min_mV * 1000; } -static struct regulator_ops twl4030fixed_ops = { - .list_voltage = twlfixed_list_voltage, - - .get_voltage = twlfixed_get_voltage, - - .enable = twl4030reg_enable, - .disable = twl4030reg_disable, - .is_enabled = twl4030reg_is_enabled, - - .set_mode = twl4030reg_set_mode, - - .get_status = twl4030reg_get_status, -}; - -static struct regulator_ops twl6030fixed_ops = { +static struct regulator_ops twlfixed_ops = { .list_voltage = twlfixed_list_voltage, .get_voltage = twlfixed_get_voltage, - .enable = twl6030reg_enable, - .disable = twl6030reg_disable, - .is_enabled = twl6030reg_is_enabled, + .enable = twlreg_enable, + .disable = twlreg_disable, + .is_enabled = twlreg_is_enabled, - .set_mode = twl6030reg_set_mode, + .set_mode = twlreg_set_mode, - .get_status = twl6030reg_get_status, + .get_status = twlreg_get_status, }; static struct regulator_ops twl6030_fixed_resource = { - .enable = twl6030reg_enable, - .disable = twl6030reg_disable, - .is_enabled = twl6030reg_is_enabled, - .get_status = twl6030reg_get_status, -}; - -/* - * SMPS status and control - */ - -static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - - int voltage = 0; - - switch (info->flags) { - case SMPS_OFFSET_EN: - voltage = 100000; - /* fall through */ - case 0: - switch (index) { - case 0: - voltage = 0; - break; - case 58: - voltage = 1350 * 1000; - break; - case 59: - voltage = 1500 * 1000; - break; - case 60: - voltage = 1800 * 1000; - break; - case 61: - voltage = 1900 * 1000; - break; - case 62: - voltage = 2100 * 1000; - break; - default: - voltage += (600000 + (12500 * (index - 1))); - } - break; - case SMPS_EXTENDED_EN: - switch (index) { - case 0: - voltage = 0; - break; - case 58: - voltage = 2084 * 1000; - break; - case 59: - voltage = 2315 * 1000; - break; - case 60: - voltage = 2778 * 1000; - break; - case 61: - voltage = 2932 * 1000; - break; - case 62: - voltage = 3241 * 1000; - break; - default: - voltage = (1852000 + (38600 * (index - 1))); - } - break; - case SMPS_OFFSET_EN | SMPS_EXTENDED_EN: - switch (index) { - case 0: - voltage = 0; - break; - case 58: - voltage = 4167 * 1000; - break; - case 59: - voltage = 2315 * 1000; - break; - case 60: - voltage = 2778 * 1000; - break; - case 61: - voltage = 2932 * 1000; - break; - case 62: - voltage = 3241 * 1000; - break; - default: - voltage = (2161000 + (38600 * (index - 1))); - } - break; - } - - return voltage; -} - -static int -twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, - unsigned int *selector) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - int vsel = 0; - - switch (info->flags) { - case 0: - if (min_uV == 0) - vsel = 0; - else if ((min_uV >= 600000) && (max_uV <= 1300000)) { - vsel = (min_uV - 600000) / 125; - if (vsel % 100) - vsel += 100; - vsel /= 100; - vsel++; - } - /* Values 1..57 for vsel are linear and can be calculated - * values 58..62 are non linear. - */ - else if ((min_uV > 1900000) && (max_uV >= 2100000)) - vsel = 62; - else if ((min_uV > 1800000) && (max_uV >= 1900000)) - vsel = 61; - else if ((min_uV > 1500000) && (max_uV >= 1800000)) - vsel = 60; - else if ((min_uV > 1350000) && (max_uV >= 1500000)) - vsel = 59; - else if ((min_uV > 1300000) && (max_uV >= 1350000)) - vsel = 58; - else - return -EINVAL; - break; - case SMPS_OFFSET_EN: - if (min_uV == 0) - vsel = 0; - else if ((min_uV >= 700000) && (max_uV <= 1420000)) { - vsel = (min_uV - 700000) / 125; - if (vsel % 100) - vsel += 100; - vsel /= 100; - vsel++; - } - /* Values 1..57 for vsel are linear and can be calculated - * values 58..62 are non linear. - */ - else if ((min_uV > 1900000) && (max_uV >= 2100000)) - vsel = 62; - else if ((min_uV > 1800000) && (max_uV >= 1900000)) - vsel = 61; - else if ((min_uV > 1350000) && (max_uV >= 1800000)) - vsel = 60; - else if ((min_uV > 1350000) && (max_uV >= 1500000)) - vsel = 59; - else if ((min_uV > 1300000) && (max_uV >= 1350000)) - vsel = 58; - else - return -EINVAL; - break; - case SMPS_EXTENDED_EN: - if (min_uV == 0) - vsel = 0; - else if ((min_uV >= 1852000) && (max_uV <= 4013600)) { - vsel = (min_uV - 1852000) / 386; - if (vsel % 100) - vsel += 100; - vsel /= 100; - vsel++; - } - break; - case SMPS_OFFSET_EN|SMPS_EXTENDED_EN: - if (min_uV == 0) - vsel = 0; - else if ((min_uV >= 2161000) && (max_uV <= 4321000)) { - vsel = (min_uV - 1852000) / 386; - if (vsel % 100) - vsel += 100; - vsel /= 100; - vsel++; - } - break; - } - - *selector = vsel; - - return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS, - vsel); -} - -static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - - return twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS); -} - -static struct regulator_ops twlsmps_ops = { - .list_voltage = twl6030smps_list_voltage, - - .set_voltage = twl6030smps_set_voltage, - .get_voltage_sel = twl6030smps_get_voltage_sel, - - .enable = twl6030reg_enable, - .disable = twl6030reg_disable, - .is_enabled = twl6030reg_is_enabled, - - .set_mode = twl6030reg_set_mode, - - .get_status = twl6030reg_get_status, + .enable = twlreg_enable, + .disable = twlreg_disable, + .is_enabled = twlreg_is_enabled, + .get_status = twlreg_get_status, }; /*----------------------------------------------------------------------*/ @@ -834,10 +487,11 @@ static struct regulator_ops twlsmps_ops = { #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ remap_conf) \ TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ - remap_conf, TWL4030, twl4030fixed_ops) -#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay) \ + remap_conf, TWL4030) +#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ + remap_conf) \ TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ - 0x0, TWL6030, twl6030fixed_ops) + remap_conf, TWL6030) #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \ .base = offset, \ @@ -856,11 +510,13 @@ static struct regulator_ops twlsmps_ops = { }, \ } -#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \ +#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num, \ + remap_conf) { \ .base = offset, \ .id = num, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ + .remap = remap_conf, \ .desc = { \ .name = #label, \ .id = TWL6030_REG_##label, \ @@ -871,23 +527,9 @@ static struct regulator_ops twlsmps_ops = { }, \ } -#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \ - .base = offset, \ - .id = num, \ - .min_mV = min_mVolts, \ - .max_mV = max_mVolts, \ - .desc = { \ - .name = #label, \ - .id = TWL6025_REG_##label, \ - .n_voltages = ((max_mVolts - min_mVolts)/100) + 1, \ - .ops = &twl6030ldo_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - }, \ - } #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \ - family, operations) { \ + family) { \ .base = offset, \ .id = num, \ .min_mV = mVolts, \ @@ -897,16 +539,17 @@ static struct regulator_ops twlsmps_ops = { .name = #label, \ .id = family##_REG_##label, \ .n_voltages = 1, \ - .ops = &operations, \ + .ops = &twlfixed_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ }, \ } -#define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay) { \ +#define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay, remap_conf) { \ .base = offset, \ .id = num, \ .delay = turnon_delay, \ + .remap = remap_conf, \ .desc = { \ .name = #label, \ .id = TWL6030_REG_##label, \ @@ -916,21 +559,6 @@ static struct regulator_ops twlsmps_ops = { }, \ } -#define TWL6025_ADJUSTABLE_SMPS(label, offset, num) { \ - .base = offset, \ - .id = num, \ - .min_mV = 600, \ - .max_mV = 2100, \ - .desc = { \ - .name = #label, \ - .id = TWL6025_REG_##label, \ - .n_voltages = 63, \ - .ops = &twlsmps_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - }, \ - } - /* * We list regulators here if systems need some level of * software control over them after boot. @@ -961,52 +589,19 @@ static struct twlreg_info twl_regs[] = { /* 6030 REG with base as PMC Slave Misc : 0x0030 */ /* Turnon-delay and remap configuration values for 6030 are not verified since the specification is not public */ - TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1), - TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2), - TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3), - TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4), - TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5), - TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7), - TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0), - TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0), - TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0), - TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0), - TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0), - - /* 6025 are renamed compared to 6030 versions */ - TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300, 1), - TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300, 2), - TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300, 3), - TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300, 4), - TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300, 5), - TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300, 7), - TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300, 16), - TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300, 17), - TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300, 18), - - TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34, 1), - TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10, 2), - TWL6025_ADJUSTABLE_SMPS(VIO, 0x16, 3), + TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1, 0x21), + TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2, 0x21), + TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3, 0x21), + TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4, 0x21), + TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5, 0x21), + TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7, 0x21), + TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x21), + TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x21), + TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x21), + TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x21), + TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0, 0x21), }; -static u8 twl_get_smps_offset(void) -{ - u8 value; - - twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value, - TWL6030_SMPS_OFFSET); - return value; -} - -static u8 twl_get_smps_mult(void) -{ - u8 value; - - twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value, - TWL6030_SMPS_MULT); - return value; -} - static int __devinit twlreg_probe(struct platform_device *pdev) { int i; @@ -1028,9 +623,6 @@ static int __devinit twlreg_probe(struct platform_device *pdev) if (!initdata) return -EINVAL; - /* copy the features into regulator data */ - info->features = (unsigned long)initdata->driver_data; - /* Constrain board-specific capabilities according to what * this driver and the chip itself can actually do. */ @@ -1053,27 +645,6 @@ static int __devinit twlreg_probe(struct platform_device *pdev) break; } - switch (pdev->id) { - case TWL6025_REG_SMPS3: - if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3) - info->flags |= SMPS_EXTENDED_EN; - if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3) - info->flags |= SMPS_OFFSET_EN; - break; - case TWL6025_REG_SMPS4: - if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4) - info->flags |= SMPS_EXTENDED_EN; - if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4) - info->flags |= SMPS_OFFSET_EN; - break; - case TWL6025_REG_VIO: - if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO) - info->flags |= SMPS_EXTENDED_EN; - if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO) - info->flags |= SMPS_OFFSET_EN; - break; - } - rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", @@ -1082,8 +653,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, rdev); - if (twl_class_is_4030()) - twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, + twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, info->remap); /* NOTE: many regulators support short-circuit IRQs (presentable diff --git a/trunk/drivers/regulator/wm831x-dcdc.c b/trunk/drivers/regulator/wm831x-dcdc.c index a0982e809851..e93453b1b978 100644 --- a/trunk/drivers/regulator/wm831x-dcdc.c +++ b/trunk/drivers/regulator/wm831x-dcdc.c @@ -600,6 +600,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) static __devexit int wm831x_buckv_remove(struct platform_device *pdev) { struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); + struct wm831x *wm831x = dcdc->wm831x; platform_set_drvdata(pdev, NULL); @@ -775,6 +776,7 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) static __devexit int wm831x_buckp_remove(struct platform_device *pdev) { struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); + struct wm831x *wm831x = dcdc->wm831x; platform_set_drvdata(pdev, NULL); diff --git a/trunk/drivers/regulator/wm8400-regulator.c b/trunk/drivers/regulator/wm8400-regulator.c index 0f12c70bebc9..b42d01cef35a 100644 --- a/trunk/drivers/regulator/wm8400-regulator.c +++ b/trunk/drivers/regulator/wm8400-regulator.c @@ -55,7 +55,7 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev, return 1600000 + ((selector - 14) * 100000); } -static int wm8400_ldo_get_voltage_sel(struct regulator_dev *dev) +static int wm8400_ldo_get_voltage(struct regulator_dev *dev) { struct wm8400 *wm8400 = rdev_get_drvdata(dev); u16 val; @@ -63,7 +63,7 @@ static int wm8400_ldo_get_voltage_sel(struct regulator_dev *dev) val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev)); val &= WM8400_LDO1_VSEL_MASK; - return val; + return wm8400_ldo_list_voltage(dev, val); } static int wm8400_ldo_set_voltage(struct regulator_dev *dev, @@ -104,7 +104,7 @@ static struct regulator_ops wm8400_ldo_ops = { .enable = wm8400_ldo_enable, .disable = wm8400_ldo_disable, .list_voltage = wm8400_ldo_list_voltage, - .get_voltage_sel = wm8400_ldo_get_voltage_sel, + .get_voltage = wm8400_ldo_get_voltage, .set_voltage = wm8400_ldo_set_voltage, }; @@ -145,7 +145,7 @@ static int wm8400_dcdc_list_voltage(struct regulator_dev *dev, return 850000 + (selector * 25000); } -static int wm8400_dcdc_get_voltage_sel(struct regulator_dev *dev) +static int wm8400_dcdc_get_voltage(struct regulator_dev *dev) { struct wm8400 *wm8400 = rdev_get_drvdata(dev); u16 val; @@ -154,7 +154,7 @@ static int wm8400_dcdc_get_voltage_sel(struct regulator_dev *dev) val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset); val &= WM8400_DC1_VSEL_MASK; - return val; + return 850000 + (25000 * val); } static int wm8400_dcdc_set_voltage(struct regulator_dev *dev, @@ -261,7 +261,7 @@ static struct regulator_ops wm8400_dcdc_ops = { .enable = wm8400_dcdc_enable, .disable = wm8400_dcdc_disable, .list_voltage = wm8400_dcdc_list_voltage, - .get_voltage_sel = wm8400_dcdc_get_voltage_sel, + .get_voltage = wm8400_dcdc_get_voltage, .set_voltage = wm8400_dcdc_set_voltage, .get_mode = wm8400_dcdc_get_mode, .set_mode = wm8400_dcdc_set_mode, diff --git a/trunk/drivers/rtc/Kconfig b/trunk/drivers/rtc/Kconfig index f822e13dc04b..b8f4e9e66cd5 100644 --- a/trunk/drivers/rtc/Kconfig +++ b/trunk/drivers/rtc/Kconfig @@ -125,16 +125,6 @@ comment "I2C RTC drivers" if I2C -config RTC_DRV_88PM860X - tristate "Marvell 88PM860x" - depends on RTC_CLASS && I2C && MFD_88PM860X - help - If you say yes here you get support for RTC function in Marvell - 88PM860x chips. - - This driver can also be built as a module. If so, the module - will be called rtc-88pm860x. - config RTC_DRV_DS1307 tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025" help @@ -361,39 +351,12 @@ config RTC_DRV_RX8025 This driver can also be built as a module. If so, the module will be called rtc-rx8025. -config RTC_DRV_EM3027 - tristate "EM Microelectronic EM3027" - help - If you say yes here you get support for the EM - Microelectronic EM3027 RTC chips. - - This driver can also be built as a module. If so, the module - will be called rtc-em3027. - -config RTC_DRV_RV3029C2 - tristate "Micro Crystal RTC" - help - If you say yes here you get support for the Micro Crystal - RV3029-C2 RTC chips. - - This driver can also be built as a module. If so, the module - will be called rtc-rv3029c2. - endif # I2C comment "SPI RTC drivers" if SPI_MASTER -config RTC_DRV_M41T93 - tristate "ST M41T93" - help - If you say yes here you will get support for the - ST M41T93 SPI RTC chip. - - This driver can also be built as a module. If so, the module - will be called rtc-m41t93. - config RTC_DRV_M41T94 tristate "ST M41T94" help @@ -682,14 +645,6 @@ config RTC_DRV_WM8350 This driver can also be built as a module. If so, the module will be called "rtc-wm8350". -config RTC_DRV_SPEAR - tristate "SPEAR ST RTC" - depends on PLAT_SPEAR - default y - help - If you say Y here you will get support for the RTC found on - spear - config RTC_DRV_PCF50633 depends on MFD_PCF50633 tristate "NXP PCF50633 RTC" @@ -919,13 +874,6 @@ config RTC_DRV_PXA This RTC driver uses PXA RTC registers available since pxa27x series (RDxR, RYxR) instead of legacy RCNR, RTAR. -config RTC_DRV_VT8500 - tristate "VIA/WonderMedia 85xx SoC RTC" - depends on ARCH_VT8500 - help - If you say Y here you will get access to the real time clock - built into your VIA VT8500 SoC or its relatives. - config RTC_DRV_SUN4V bool "SUN4V Hypervisor RTC" diff --git a/trunk/drivers/rtc/Makefile b/trunk/drivers/rtc/Makefile index 213d725f16d4..9574748d1c73 100644 --- a/trunk/drivers/rtc/Makefile +++ b/trunk/drivers/rtc/Makefile @@ -15,7 +15,6 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o # Keep the list ordered. -obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o @@ -44,7 +43,6 @@ obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.o obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o -obj-$(CONFIG_RTC_DRV_EM3027) += rtc-em3027.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o @@ -54,7 +52,6 @@ obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o -obj-$(CONFIG_RTC_DRV_M41T93) += rtc-m41t93.o obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o @@ -84,14 +81,12 @@ obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o -obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o -obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o @@ -103,7 +98,6 @@ obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o -obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o diff --git a/trunk/drivers/rtc/rtc-88pm860x.c b/trunk/drivers/rtc/rtc-88pm860x.c deleted file mode 100644 index 64b847b7f970..000000000000 --- a/trunk/drivers/rtc/rtc-88pm860x.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Real Time Clock driver for Marvell 88PM860x PMIC - * - * Copyright (c) 2010 Marvell International Ltd. - * Author: Haojian Zhuang - * - * 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 VRTC_CALIBRATION - -struct pm860x_rtc_info { - struct pm860x_chip *chip; - struct i2c_client *i2c; - struct rtc_device *rtc_dev; - struct device *dev; - struct delayed_work calib_work; - - int irq; - int vrtc; - int (*sync)(unsigned int ticks); -}; - -#define REG_VRTC_MEAS1 0x7D - -#define REG0_ADDR 0xB0 -#define REG1_ADDR 0xB2 -#define REG2_ADDR 0xB4 -#define REG3_ADDR 0xB6 - -#define REG0_DATA 0xB1 -#define REG1_DATA 0xB3 -#define REG2_DATA 0xB5 -#define REG3_DATA 0xB7 - -/* bit definitions of Measurement Enable Register 2 (0x51) */ -#define MEAS2_VRTC (1 << 0) - -/* bit definitions of RTC Register 1 (0xA0) */ -#define ALARM_EN (1 << 3) -#define ALARM_WAKEUP (1 << 4) -#define ALARM (1 << 5) -#define RTC1_USE_XO (1 << 7) - -#define VRTC_CALIB_INTERVAL (HZ * 60 * 10) /* 10 minutes */ - -static irqreturn_t rtc_update_handler(int irq, void *data) -{ - struct pm860x_rtc_info *info = (struct pm860x_rtc_info *)data; - int mask; - - mask = ALARM | ALARM_WAKEUP; - pm860x_set_bits(info->i2c, PM8607_RTC1, mask | ALARM_EN, mask); - rtc_update_irq(info->rtc_dev, 1, RTC_AF); - return IRQ_HANDLED; -} - -static int pm860x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct pm860x_rtc_info *info = dev_get_drvdata(dev); - - if (enabled) - pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, ALARM); - else - pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, 0); - return 0; -} - -/* - * Calculate the next alarm time given the requested alarm time mask - * and the current time. - */ -static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, - struct rtc_time *alrm) -{ - unsigned long next_time; - unsigned long now_time; - - next->tm_year = now->tm_year; - next->tm_mon = now->tm_mon; - next->tm_mday = now->tm_mday; - next->tm_hour = alrm->tm_hour; - next->tm_min = alrm->tm_min; - next->tm_sec = alrm->tm_sec; - - rtc_tm_to_time(now, &now_time); - rtc_tm_to_time(next, &next_time); - - if (next_time < now_time) { - /* Advance one day */ - next_time += 60 * 60 * 24; - rtc_time_to_tm(next_time, next); - } -} - -static int pm860x_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct pm860x_rtc_info *info = dev_get_drvdata(dev); - unsigned char buf[8]; - unsigned long ticks, base, data; - - pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf); - dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1], - buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7]; - - /* load 32-bit read-only counter */ - pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; - ticks = base + data; - dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", - base, data, ticks); - - rtc_time_to_tm(ticks, tm); - - return 0; -} - -static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct pm860x_rtc_info *info = dev_get_drvdata(dev); - unsigned char buf[4]; - unsigned long ticks, base, data; - - if ((tm->tm_year < 70) || (tm->tm_year > 138)) { - dev_dbg(info->dev, "Set time %d out of range. " - "Please set time between 1970 to 2038.\n", - 1900 + tm->tm_year); - return -EINVAL; - } - rtc_tm_to_time(tm, &ticks); - - /* load 32-bit read-only counter */ - pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; - base = ticks - data; - dev_dbg(info->dev, "set base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", - base, data, ticks); - - pm860x_page_reg_write(info->i2c, REG0_DATA, (base >> 24) & 0xFF); - pm860x_page_reg_write(info->i2c, REG1_DATA, (base >> 16) & 0xFF); - pm860x_page_reg_write(info->i2c, REG2_DATA, (base >> 8) & 0xFF); - pm860x_page_reg_write(info->i2c, REG3_DATA, base & 0xFF); - - if (info->sync) - info->sync(ticks); - return 0; -} - -static int pm860x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct pm860x_rtc_info *info = dev_get_drvdata(dev); - unsigned char buf[8]; - unsigned long ticks, base, data; - int ret; - - pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf); - dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1], - buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7]; - - pm860x_bulk_read(info->i2c, PM8607_RTC_EXPIRE1, 4, buf); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; - ticks = base + data; - dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", - base, data, ticks); - - rtc_time_to_tm(ticks, &alrm->time); - ret = pm860x_reg_read(info->i2c, PM8607_RTC1); - alrm->enabled = (ret & ALARM_EN) ? 1 : 0; - alrm->pending = (ret & (ALARM | ALARM_WAKEUP)) ? 1 : 0; - return 0; -} - -static int pm860x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct pm860x_rtc_info *info = dev_get_drvdata(dev); - struct rtc_time now_tm, alarm_tm; - unsigned long ticks, base, data; - unsigned char buf[8]; - int mask; - - pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, 0); - - pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf); - dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1], - buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7]; - - /* load 32-bit read-only counter */ - pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; - ticks = base + data; - dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", - base, data, ticks); - - rtc_time_to_tm(ticks, &now_tm); - rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time); - /* get new ticks for alarm in 24 hours */ - rtc_tm_to_time(&alarm_tm, &ticks); - data = ticks - base; - - buf[0] = data & 0xff; - buf[1] = (data >> 8) & 0xff; - buf[2] = (data >> 16) & 0xff; - buf[3] = (data >> 24) & 0xff; - pm860x_bulk_write(info->i2c, PM8607_RTC_EXPIRE1, 4, buf); - if (alrm->enabled) { - mask = ALARM | ALARM_WAKEUP | ALARM_EN; - pm860x_set_bits(info->i2c, PM8607_RTC1, mask, mask); - } else { - mask = ALARM | ALARM_WAKEUP | ALARM_EN; - pm860x_set_bits(info->i2c, PM8607_RTC1, mask, - ALARM | ALARM_WAKEUP); - } - return 0; -} - -static const struct rtc_class_ops pm860x_rtc_ops = { - .read_time = pm860x_rtc_read_time, - .set_time = pm860x_rtc_set_time, - .read_alarm = pm860x_rtc_read_alarm, - .set_alarm = pm860x_rtc_set_alarm, - .alarm_irq_enable = pm860x_rtc_alarm_irq_enable, -}; - -#ifdef VRTC_CALIBRATION -static void calibrate_vrtc_work(struct work_struct *work) -{ - struct pm860x_rtc_info *info = container_of(work, - struct pm860x_rtc_info, calib_work.work); - unsigned char buf[2]; - unsigned int sum, data, mean, vrtc_set; - int i; - - for (i = 0, sum = 0; i < 16; i++) { - msleep(100); - pm860x_bulk_read(info->i2c, REG_VRTC_MEAS1, 2, buf); - data = (buf[0] << 4) | buf[1]; - data = (data * 5400) >> 12; /* convert to mv */ - sum += data; - } - mean = sum >> 4; - vrtc_set = 2700 + (info->vrtc & 0x3) * 200; - dev_dbg(info->dev, "mean:%d, vrtc_set:%d\n", mean, vrtc_set); - - sum = pm860x_reg_read(info->i2c, PM8607_RTC_MISC1); - data = sum & 0x3; - if ((mean + 200) < vrtc_set) { - /* try higher voltage */ - if (++data == 4) - goto out; - data = (sum & 0xf8) | (data & 0x3); - pm860x_reg_write(info->i2c, PM8607_RTC_MISC1, data); - } else if ((mean - 200) > vrtc_set) { - /* try lower voltage */ - if (data-- == 0) - goto out; - data = (sum & 0xf8) | (data & 0x3); - pm860x_reg_write(info->i2c, PM8607_RTC_MISC1, data); - } else - goto out; - dev_dbg(info->dev, "set 0x%x to RTC_MISC1\n", data); - /* trigger next calibration since VRTC is updated */ - schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL); - return; -out: - /* disable measurement */ - pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, 0); - dev_dbg(info->dev, "finish VRTC calibration\n"); - return; -} -#endif - -static int __devinit pm860x_rtc_probe(struct platform_device *pdev) -{ - struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct pm860x_rtc_pdata *pdata = NULL; - struct pm860x_rtc_info *info; - struct rtc_time tm; - unsigned long ticks = 0; - int ret; - - pdata = pdev->dev.platform_data; - if (pdata == NULL) - dev_warn(&pdev->dev, "No platform data!\n"); - - info = kzalloc(sizeof(struct pm860x_rtc_info), GFP_KERNEL); - if (!info) - return -ENOMEM; - info->irq = platform_get_irq(pdev, 0); - if (info->irq < 0) { - dev_err(&pdev->dev, "No IRQ resource!\n"); - ret = -EINVAL; - goto out; - } - - info->chip = chip; - info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; - info->dev = &pdev->dev; - dev_set_drvdata(&pdev->dev, info); - - ret = request_threaded_irq(info->irq, NULL, rtc_update_handler, - IRQF_ONESHOT, "rtc", info); - if (ret < 0) { - dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", - info->irq, ret); - goto out; - } - - /* set addresses of 32-bit base value for RTC time */ - pm860x_page_reg_write(info->i2c, REG0_ADDR, REG0_DATA); - pm860x_page_reg_write(info->i2c, REG1_ADDR, REG1_DATA); - pm860x_page_reg_write(info->i2c, REG2_ADDR, REG2_DATA); - pm860x_page_reg_write(info->i2c, REG3_ADDR, REG3_DATA); - - ret = pm860x_rtc_read_time(&pdev->dev, &tm); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to read initial time.\n"); - goto out_rtc; - } - if ((tm.tm_year < 70) || (tm.tm_year > 138)) { - tm.tm_year = 70; - tm.tm_mon = 0; - tm.tm_mday = 1; - tm.tm_hour = 0; - tm.tm_min = 0; - tm.tm_sec = 0; - ret = pm860x_rtc_set_time(&pdev->dev, &tm); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to set initial time.\n"); - goto out_rtc; - } - } - rtc_tm_to_time(&tm, &ticks); - if (pdata && pdata->sync) { - pdata->sync(ticks); - info->sync = pdata->sync; - } - - info->rtc_dev = rtc_device_register("88pm860x-rtc", &pdev->dev, - &pm860x_rtc_ops, THIS_MODULE); - ret = PTR_ERR(info->rtc_dev); - if (IS_ERR(info->rtc_dev)) { - dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); - goto out_rtc; - } - - /* - * enable internal XO instead of internal 3.25MHz clock since it can - * free running in PMIC power-down state. - */ - pm860x_set_bits(info->i2c, PM8607_RTC1, RTC1_USE_XO, RTC1_USE_XO); - -#ifdef VRTC_CALIBRATION - /* <00> -- 2.7V, <01> -- 2.9V, <10> -- 3.1V, <11> -- 3.3V */ - if (pdata && pdata->vrtc) - info->vrtc = pdata->vrtc & 0x3; - else - info->vrtc = 1; - pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, MEAS2_VRTC); - - /* calibrate VRTC */ - INIT_DELAYED_WORK(&info->calib_work, calibrate_vrtc_work); - schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL); -#endif /* VRTC_CALIBRATION */ - return 0; -out_rtc: - free_irq(info->irq, info); -out: - kfree(info); - return ret; -} - -static int __devexit pm860x_rtc_remove(struct platform_device *pdev) -{ - struct pm860x_rtc_info *info = platform_get_drvdata(pdev); - -#ifdef VRTC_CALIBRATION - flush_scheduled_work(); - /* disable measurement */ - pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, 0); -#endif /* VRTC_CALIBRATION */ - - platform_set_drvdata(pdev, NULL); - rtc_device_unregister(info->rtc_dev); - free_irq(info->irq, info); - kfree(info); - return 0; -} - -static struct platform_driver pm860x_rtc_driver = { - .driver = { - .name = "88pm860x-rtc", - .owner = THIS_MODULE, - }, - .probe = pm860x_rtc_probe, - .remove = __devexit_p(pm860x_rtc_remove), -}; - -static int __init pm860x_rtc_init(void) -{ - return platform_driver_register(&pm860x_rtc_driver); -} -module_init(pm860x_rtc_init); - -static void __exit pm860x_rtc_exit(void) -{ - platform_driver_unregister(&pm860x_rtc_driver); -} -module_exit(pm860x_rtc_exit); - -MODULE_DESCRIPTION("Marvell 88PM860x RTC driver"); -MODULE_AUTHOR("Haojian Zhuang "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/rtc/rtc-em3027.c b/trunk/drivers/rtc/rtc-em3027.c deleted file mode 100644 index d8e1c2578553..000000000000 --- a/trunk/drivers/rtc/rtc-em3027.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * An rtc/i2c driver for the EM Microelectronic EM3027 - * Copyright 2011 CompuLab, Ltd. - * - * Author: Mike Rapoport - * - * Based on rtc-ds1672.c by Alessandro Zummo - * - * 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 - -/* Registers */ -#define EM3027_REG_ON_OFF_CTRL 0x00 -#define EM3027_REG_IRQ_CTRL 0x01 -#define EM3027_REG_IRQ_FLAGS 0x02 -#define EM3027_REG_STATUS 0x03 -#define EM3027_REG_RST_CTRL 0x04 - -#define EM3027_REG_WATCH_SEC 0x08 -#define EM3027_REG_WATCH_MIN 0x09 -#define EM3027_REG_WATCH_HOUR 0x0a -#define EM3027_REG_WATCH_DATE 0x0b -#define EM3027_REG_WATCH_DAY 0x0c -#define EM3027_REG_WATCH_MON 0x0d -#define EM3027_REG_WATCH_YEAR 0x0e - -#define EM3027_REG_ALARM_SEC 0x10 -#define EM3027_REG_ALARM_MIN 0x11 -#define EM3027_REG_ALARM_HOUR 0x12 -#define EM3027_REG_ALARM_DATE 0x13 -#define EM3027_REG_ALARM_DAY 0x14 -#define EM3027_REG_ALARM_MON 0x15 -#define EM3027_REG_ALARM_YEAR 0x16 - -static struct i2c_driver em3027_driver; - -static int em3027_get_time(struct device *dev, struct rtc_time *tm) -{ - struct i2c_client *client = to_i2c_client(dev); - - unsigned char addr = EM3027_REG_WATCH_SEC; - unsigned char buf[7]; - - struct i2c_msg msgs[] = { - {client->addr, 0, 1, &addr}, /* setup read addr */ - {client->addr, I2C_M_RD, 7, buf}, /* read time/date */ - }; - - /* read time/date registers */ - if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { - dev_err(&client->dev, "%s: read error\n", __func__); - return -EIO; - } - - tm->tm_sec = bcd2bin(buf[0]); - tm->tm_min = bcd2bin(buf[1]); - tm->tm_hour = bcd2bin(buf[2]); - tm->tm_mday = bcd2bin(buf[3]); - tm->tm_wday = bcd2bin(buf[4]); - tm->tm_mon = bcd2bin(buf[5]); - tm->tm_year = bcd2bin(buf[6]) + 100; - - return 0; -} - -static int em3027_set_time(struct device *dev, struct rtc_time *tm) -{ - struct i2c_client *client = to_i2c_client(dev); - unsigned char buf[8]; - - struct i2c_msg msg = { - client->addr, 0, 8, buf, /* write time/date */ - }; - - buf[0] = EM3027_REG_WATCH_SEC; - buf[1] = bin2bcd(tm->tm_sec); - buf[2] = bin2bcd(tm->tm_min); - buf[3] = bin2bcd(tm->tm_hour); - buf[4] = bin2bcd(tm->tm_mday); - buf[5] = bin2bcd(tm->tm_wday); - buf[6] = bin2bcd(tm->tm_mon); - buf[7] = bin2bcd(tm->tm_year % 100); - - /* write time/date registers */ - if ((i2c_transfer(client->adapter, &msg, 1)) != 1) { - dev_err(&client->dev, "%s: write error\n", __func__); - return -EIO; - } - - return 0; -} - -static const struct rtc_class_ops em3027_rtc_ops = { - .read_time = em3027_get_time, - .set_time = em3027_set_time, -}; - -static int em3027_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct rtc_device *rtc; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) - return -ENODEV; - - rtc = rtc_device_register(em3027_driver.driver.name, &client->dev, - &em3027_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) - return PTR_ERR(rtc); - - i2c_set_clientdata(client, rtc); - - return 0; -} - -static int em3027_remove(struct i2c_client *client) -{ - struct rtc_device *rtc = i2c_get_clientdata(client); - - if (rtc) - rtc_device_unregister(rtc); - - return 0; -} - -static struct i2c_device_id em3027_id[] = { - { "em3027", 0 }, - { } -}; - -static struct i2c_driver em3027_driver = { - .driver = { - .name = "rtc-em3027", - }, - .probe = &em3027_probe, - .remove = &em3027_remove, - .id_table = em3027_id, -}; - -static int __init em3027_init(void) -{ - return i2c_add_driver(&em3027_driver); -} - -static void __exit em3027_exit(void) -{ - i2c_del_driver(&em3027_driver); -} - -MODULE_AUTHOR("Mike Rapoport "); -MODULE_DESCRIPTION("EM Microelectronic EM3027 RTC driver"); -MODULE_LICENSE("GPL"); - -module_init(em3027_init); -module_exit(em3027_exit); diff --git a/trunk/drivers/rtc/rtc-m41t93.c b/trunk/drivers/rtc/rtc-m41t93.c deleted file mode 100644 index 1a84b3e227d1..000000000000 --- a/trunk/drivers/rtc/rtc-m41t93.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * - * Driver for ST M41T93 SPI RTC - * - * (c) 2010 Nikolaus Voss, Weinmann Medical GmbH - * - * 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 - -#define M41T93_REG_SSEC 0 -#define M41T93_REG_ST_SEC 1 -#define M41T93_REG_MIN 2 -#define M41T93_REG_CENT_HOUR 3 -#define M41T93_REG_WDAY 4 -#define M41T93_REG_DAY 5 -#define M41T93_REG_MON 6 -#define M41T93_REG_YEAR 7 - - -#define M41T93_REG_ALM_HOUR_HT 0xc -#define M41T93_REG_FLAGS 0xf - -#define M41T93_FLAG_ST (1 << 7) -#define M41T93_FLAG_OF (1 << 2) -#define M41T93_FLAG_BL (1 << 4) -#define M41T93_FLAG_HT (1 << 6) - -static inline int m41t93_set_reg(struct spi_device *spi, u8 addr, u8 data) -{ - u8 buf[2]; - - /* MSB must be '1' to write */ - buf[0] = addr | 0x80; - buf[1] = data; - - return spi_write(spi, buf, sizeof(buf)); -} - -static int m41t93_set_time(struct device *dev, struct rtc_time *tm) -{ - struct spi_device *spi = to_spi_device(dev); - u8 buf[9] = {0x80}; /* write cmd + 8 data bytes */ - u8 * const data = &buf[1]; /* ptr to first data byte */ - - dev_dbg(dev, "%s secs=%d, mins=%d, " - "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", - "write", tm->tm_sec, tm->tm_min, - tm->tm_hour, tm->tm_mday, - tm->tm_mon, tm->tm_year, tm->tm_wday); - - if (tm->tm_year < 100) { - dev_warn(&spi->dev, "unsupported date (before 2000-01-01).\n"); - return -EINVAL; - } - - data[M41T93_REG_SSEC] = 0; - data[M41T93_REG_ST_SEC] = bin2bcd(tm->tm_sec); - data[M41T93_REG_MIN] = bin2bcd(tm->tm_min); - data[M41T93_REG_CENT_HOUR] = bin2bcd(tm->tm_hour) | - ((tm->tm_year/100-1) << 6); - data[M41T93_REG_DAY] = bin2bcd(tm->tm_mday); - data[M41T93_REG_WDAY] = bin2bcd(tm->tm_wday + 1); - data[M41T93_REG_MON] = bin2bcd(tm->tm_mon + 1); - data[M41T93_REG_YEAR] = bin2bcd(tm->tm_year % 100); - - return spi_write(spi, buf, sizeof(buf)); -} - - -static int m41t93_get_time(struct device *dev, struct rtc_time *tm) -{ - struct spi_device *spi = to_spi_device(dev); - const u8 start_addr = 0; - u8 buf[8]; - int century_after_1900; - int tmp; - int ret = 0; - - /* Check status of clock. Two states must be considered: - 1. halt bit (HT) is set: the clock is running but update of readout - registers has been disabled due to power failure. This is normal - case after poweron. Time is valid after resetting HT bit. - 2. oscillator fail bit (OF) is set. Oscillator has be stopped and - time is invalid: - a) OF can be immeditely reset. - b) OF cannot be immediately reset: oscillator has to be restarted. - */ - tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT); - if (tmp < 0) - return tmp; - - if (tmp & M41T93_FLAG_HT) { - dev_dbg(&spi->dev, "HT bit is set, reenable clock update.\n"); - m41t93_set_reg(spi, M41T93_REG_ALM_HOUR_HT, - tmp & ~M41T93_FLAG_HT); - } - - tmp = spi_w8r8(spi, M41T93_REG_FLAGS); - if (tmp < 0) - return tmp; - - if (tmp & M41T93_FLAG_OF) { - ret = -EINVAL; - dev_warn(&spi->dev, "OF bit is set, resetting.\n"); - m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF); - - tmp = spi_w8r8(spi, M41T93_REG_FLAGS); - if (tmp < 0) - return tmp; - else if (tmp & M41T93_FLAG_OF) { - u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST; - - dev_warn(&spi->dev, - "OF bit is still set, kickstarting clock.\n"); - m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc); - reset_osc &= ~M41T93_FLAG_ST; - m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc); - } - } - - if (tmp & M41T93_FLAG_BL) - dev_warn(&spi->dev, "BL bit is set, replace battery.\n"); - - /* read actual time/date */ - tmp = spi_write_then_read(spi, &start_addr, 1, buf, sizeof(buf)); - if (tmp < 0) - return tmp; - - tm->tm_sec = bcd2bin(buf[M41T93_REG_ST_SEC]); - tm->tm_min = bcd2bin(buf[M41T93_REG_MIN]); - tm->tm_hour = bcd2bin(buf[M41T93_REG_CENT_HOUR] & 0x3f); - tm->tm_mday = bcd2bin(buf[M41T93_REG_DAY]); - tm->tm_mon = bcd2bin(buf[M41T93_REG_MON]) - 1; - tm->tm_wday = bcd2bin(buf[M41T93_REG_WDAY] & 0x0f) - 1; - - century_after_1900 = (buf[M41T93_REG_CENT_HOUR] >> 6) + 1; - tm->tm_year = bcd2bin(buf[M41T93_REG_YEAR]) + century_after_1900 * 100; - - dev_dbg(dev, "%s secs=%d, mins=%d, " - "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", - "read", tm->tm_sec, tm->tm_min, - tm->tm_hour, tm->tm_mday, - tm->tm_mon, tm->tm_year, tm->tm_wday); - - return ret < 0 ? ret : rtc_valid_tm(tm); -} - - -static const struct rtc_class_ops m41t93_rtc_ops = { - .read_time = m41t93_get_time, - .set_time = m41t93_set_time, -}; - -static struct spi_driver m41t93_driver; - -static int __devinit m41t93_probe(struct spi_device *spi) -{ - struct rtc_device *rtc; - int res; - - spi->bits_per_word = 8; - spi_setup(spi); - - res = spi_w8r8(spi, M41T93_REG_WDAY); - if (res < 0 || (res & 0xf8) != 0) { - dev_err(&spi->dev, "not found 0x%x.\n", res); - return -ENODEV; - } - - rtc = rtc_device_register(m41t93_driver.driver.name, - &spi->dev, &m41t93_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) - return PTR_ERR(rtc); - - dev_set_drvdata(&spi->dev, rtc); - - return 0; -} - - -static int __devexit m41t93_remove(struct spi_device *spi) -{ - struct rtc_device *rtc = platform_get_drvdata(spi); - - if (rtc) - rtc_device_unregister(rtc); - - return 0; -} - -static struct spi_driver m41t93_driver = { - .driver = { - .name = "rtc-m41t93", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = m41t93_probe, - .remove = __devexit_p(m41t93_remove), -}; - -static __init int m41t93_init(void) -{ - return spi_register_driver(&m41t93_driver); -} -module_init(m41t93_init); - -static __exit void m41t93_exit(void) -{ - spi_unregister_driver(&m41t93_driver); -} -module_exit(m41t93_exit); - -MODULE_AUTHOR("Nikolaus Voss "); -MODULE_DESCRIPTION("Driver for ST M41T93 SPI RTC"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:rtc-m41t93"); diff --git a/trunk/drivers/rtc/rtc-mrst.c b/trunk/drivers/rtc/rtc-mrst.c index 0cec5650d56a..b2f096871a97 100644 --- a/trunk/drivers/rtc/rtc-mrst.c +++ b/trunk/drivers/rtc/rtc-mrst.c @@ -380,7 +380,7 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) cleanup0: dev_set_drvdata(dev, NULL); mrst_rtc.dev = NULL; - release_mem_region(iomem->start, resource_size(iomem)); + release_region(iomem->start, iomem->end + 1 - iomem->start); dev_err(dev, "rtc-mrst: unable to initialise\n"); return retval; } @@ -406,7 +406,7 @@ static void __devexit rtc_mrst_do_remove(struct device *dev) mrst->rtc = NULL; iomem = mrst->iomem; - release_mem_region(iomem->start, resource_size(iomem)); + release_region(iomem->start, iomem->end + 1 - iomem->start); mrst->iomem = NULL; mrst->dev = NULL; diff --git a/trunk/drivers/rtc/rtc-mxc.c b/trunk/drivers/rtc/rtc-mxc.c index 39e41fbdf08b..d814417bee8c 100644 --- a/trunk/drivers/rtc/rtc-mxc.c +++ b/trunk/drivers/rtc/rtc-mxc.c @@ -55,6 +55,12 @@ static const u32 PIE_BIT_DEF[MAX_PIE_NUM][2] = { { MAX_PIE_FREQ, RTC_SAM7_BIT }, }; +/* Those are the bits from a classic RTC we want to mimic */ +#define RTC_IRQF 0x80 /* any of the following 3 is active */ +#define RTC_PF 0x40 /* Periodic interrupt */ +#define RTC_AF 0x20 /* Alarm interrupt */ +#define RTC_UF 0x10 /* Update interrupt for 1Hz RTC */ + #define MXC_RTC_TIME 0 #define MXC_RTC_ALARM 1 diff --git a/trunk/drivers/rtc/rtc-pcf50633.c b/trunk/drivers/rtc/rtc-pcf50633.c index 0c423892923c..f90c574f9d05 100644 --- a/trunk/drivers/rtc/rtc-pcf50633.c +++ b/trunk/drivers/rtc/rtc-pcf50633.c @@ -58,6 +58,7 @@ struct pcf50633_time { struct pcf50633_rtc { int alarm_enabled; + int second_enabled; int alarm_pending; struct pcf50633 *pcf; @@ -142,7 +143,7 @@ static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct pcf50633_rtc *rtc; struct pcf50633_time pcf_tm; - int alarm_masked, ret = 0; + int second_masked, alarm_masked, ret = 0; rtc = dev_get_drvdata(dev); @@ -161,8 +162,11 @@ static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) pcf_tm.time[PCF50633_TI_SEC]); + second_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_SECOND); alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM); + if (!second_masked) + pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND); if (!alarm_masked) pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); @@ -171,6 +175,8 @@ static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) PCF50633_TI_EXTENT, &pcf_tm.time[0]); + if (!second_masked) + pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND); if (!alarm_masked) pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); @@ -244,8 +250,15 @@ static void pcf50633_rtc_irq(int irq, void *data) { struct pcf50633_rtc *rtc = data; - rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); - rtc->alarm_pending = 1; + switch (irq) { + case PCF50633_IRQ_ALARM: + rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); + rtc->alarm_pending = 1; + break; + case PCF50633_IRQ_SECOND: + rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); + break; + } } static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) @@ -269,6 +282,9 @@ static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM, pcf50633_rtc_irq, rtc); + pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_SECOND, + pcf50633_rtc_irq, rtc); + return 0; } @@ -279,6 +295,7 @@ static int __devexit pcf50633_rtc_remove(struct platform_device *pdev) rtc = platform_get_drvdata(pdev); pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM); + pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_SECOND); rtc_device_unregister(rtc->rtc_dev); kfree(rtc); diff --git a/trunk/drivers/rtc/rtc-rv3029c2.c b/trunk/drivers/rtc/rtc-rv3029c2.c deleted file mode 100644 index ea09ff211dc6..000000000000 --- a/trunk/drivers/rtc/rtc-rv3029c2.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Micro Crystal RV-3029C2 rtc class driver - * - * Author: Gregory Hermant - * - * based on previously existing rtc class drivers - * - * 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. - * - * NOTE: Currently this driver only supports the bare minimum for read - * and write the RTC and alarms. The extra features provided by this chip - * (trickle charger, eeprom, T° compensation) are unavailable. - */ - -#include -#include -#include -#include - -/* Register map */ -/* control section */ -#define RV3029C2_ONOFF_CTRL 0x00 -#define RV3029C2_IRQ_CTRL 0x01 -#define RV3029C2_IRQ_CTRL_AIE (1 << 0) -#define RV3029C2_IRQ_FLAGS 0x02 -#define RV3029C2_IRQ_FLAGS_AF (1 << 0) -#define RV3029C2_STATUS 0x03 -#define RV3029C2_STATUS_VLOW1 (1 << 2) -#define RV3029C2_STATUS_VLOW2 (1 << 3) -#define RV3029C2_STATUS_SR (1 << 4) -#define RV3029C2_STATUS_PON (1 << 5) -#define RV3029C2_STATUS_EEBUSY (1 << 7) -#define RV3029C2_RST_CTRL 0x04 -#define RV3029C2_CONTROL_SECTION_LEN 0x05 - -/* watch section */ -#define RV3029C2_W_SEC 0x08 -#define RV3029C2_W_MINUTES 0x09 -#define RV3029C2_W_HOURS 0x0A -#define RV3029C2_REG_HR_12_24 (1<<6) /* 24h/12h mode */ -#define RV3029C2_REG_HR_PM (1<<5) /* PM/AM bit in 12h mode */ -#define RV3029C2_W_DATE 0x0B -#define RV3029C2_W_DAYS 0x0C -#define RV3029C2_W_MONTHS 0x0D -#define RV3029C2_W_YEARS 0x0E -#define RV3029C2_WATCH_SECTION_LEN 0x07 - -/* alarm section */ -#define RV3029C2_A_SC 0x10 -#define RV3029C2_A_MN 0x11 -#define RV3029C2_A_HR 0x12 -#define RV3029C2_A_DT 0x13 -#define RV3029C2_A_DW 0x14 -#define RV3029C2_A_MO 0x15 -#define RV3029C2_A_YR 0x16 -#define RV3029C2_ALARM_SECTION_LEN 0x07 - -/* timer section */ -#define RV3029C2_TIMER_LOW 0x18 -#define RV3029C2_TIMER_HIGH 0x19 - -/* temperature section */ -#define RV3029C2_TEMP_PAGE 0x20 - -/* eeprom data section */ -#define RV3029C2_E2P_EEDATA1 0x28 -#define RV3029C2_E2P_EEDATA2 0x29 - -/* eeprom control section */ -#define RV3029C2_CONTROL_E2P_EECTRL 0x30 -#define RV3029C2_TRICKLE_1K (1<<0) /* 1K resistance */ -#define RV3029C2_TRICKLE_5K (1<<1) /* 5K resistance */ -#define RV3029C2_TRICKLE_20K (1<<2) /* 20K resistance */ -#define RV3029C2_TRICKLE_80K (1<<3) /* 80K resistance */ -#define RV3029C2_CONTROL_E2P_XTALOFFSET 0x31 -#define RV3029C2_CONTROL_E2P_QCOEF 0x32 -#define RV3029C2_CONTROL_E2P_TURNOVER 0x33 - -/* user ram section */ -#define RV3029C2_USR1_RAM_PAGE 0x38 -#define RV3029C2_USR1_SECTION_LEN 0x04 -#define RV3029C2_USR2_RAM_PAGE 0x3C -#define RV3029C2_USR2_SECTION_LEN 0x04 - -static int -rv3029c2_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf, - unsigned len) -{ - int ret; - - if ((reg > RV3029C2_USR1_RAM_PAGE + 7) || - (reg + len > RV3029C2_USR1_RAM_PAGE + 8)) - return -EINVAL; - - ret = i2c_smbus_read_i2c_block_data(client, reg, len, buf); - if (ret < 0) - return ret; - if (ret < len) - return -EIO; - return 0; -} - -static int -rv3029c2_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[], - unsigned len) -{ - if ((reg > RV3029C2_USR1_RAM_PAGE + 7) || - (reg + len > RV3029C2_USR1_RAM_PAGE + 8)) - return -EINVAL; - - return i2c_smbus_write_i2c_block_data(client, reg, len, buf); -} - -static int -rv3029c2_i2c_get_sr(struct i2c_client *client, u8 *buf) -{ - int ret = rv3029c2_i2c_read_regs(client, RV3029C2_STATUS, buf, 1); - - if (ret < 0) - return -EIO; - dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]); - return 0; -} - -static int -rv3029c2_i2c_set_sr(struct i2c_client *client, u8 val) -{ - u8 buf[1]; - int sr; - - buf[0] = val; - sr = rv3029c2_i2c_write_regs(client, RV3029C2_STATUS, buf, 1); - dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]); - if (sr < 0) - return -EIO; - return 0; -} - -static int -rv3029c2_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) -{ - u8 buf[1]; - int ret; - u8 regs[RV3029C2_WATCH_SECTION_LEN] = { 0, }; - - ret = rv3029c2_i2c_get_sr(client, buf); - if (ret < 0) { - dev_err(&client->dev, "%s: reading SR failed\n", __func__); - return -EIO; - } - - ret = rv3029c2_i2c_read_regs(client, RV3029C2_W_SEC , regs, - RV3029C2_WATCH_SECTION_LEN); - if (ret < 0) { - dev_err(&client->dev, "%s: reading RTC section failed\n", - __func__); - return ret; - } - - tm->tm_sec = bcd2bin(regs[RV3029C2_W_SEC-RV3029C2_W_SEC]); - tm->tm_min = bcd2bin(regs[RV3029C2_W_MINUTES-RV3029C2_W_SEC]); - - /* HR field has a more complex interpretation */ - { - const u8 _hr = regs[RV3029C2_W_HOURS-RV3029C2_W_SEC]; - if (_hr & RV3029C2_REG_HR_12_24) { - /* 12h format */ - tm->tm_hour = bcd2bin(_hr & 0x1f); - if (_hr & RV3029C2_REG_HR_PM) /* PM flag set */ - tm->tm_hour += 12; - } else /* 24h format */ - tm->tm_hour = bcd2bin(_hr & 0x3f); - } - - tm->tm_mday = bcd2bin(regs[RV3029C2_W_DATE-RV3029C2_W_SEC]); - tm->tm_mon = bcd2bin(regs[RV3029C2_W_MONTHS-RV3029C2_W_SEC]) - 1; - tm->tm_year = bcd2bin(regs[RV3029C2_W_YEARS-RV3029C2_W_SEC]) + 100; - tm->tm_wday = bcd2bin(regs[RV3029C2_W_DAYS-RV3029C2_W_SEC]) - 1; - - return 0; -} - -static int rv3029c2_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - return rv3029c2_i2c_read_time(to_i2c_client(dev), tm); -} - -static int -rv3029c2_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm) -{ - struct rtc_time *const tm = &alarm->time; - int ret; - u8 regs[8]; - - ret = rv3029c2_i2c_get_sr(client, regs); - if (ret < 0) { - dev_err(&client->dev, "%s: reading SR failed\n", __func__); - return -EIO; - } - - ret = rv3029c2_i2c_read_regs(client, RV3029C2_A_SC, regs, - RV3029C2_ALARM_SECTION_LEN); - - if (ret < 0) { - dev_err(&client->dev, "%s: reading alarm section failed\n", - __func__); - return ret; - } - - tm->tm_sec = bcd2bin(regs[RV3029C2_A_SC-RV3029C2_A_SC] & 0x7f); - tm->tm_min = bcd2bin(regs[RV3029C2_A_MN-RV3029C2_A_SC] & 0x7f); - tm->tm_hour = bcd2bin(regs[RV3029C2_A_HR-RV3029C2_A_SC] & 0x3f); - tm->tm_mday = bcd2bin(regs[RV3029C2_A_DT-RV3029C2_A_SC] & 0x3f); - tm->tm_mon = bcd2bin(regs[RV3029C2_A_MO-RV3029C2_A_SC] & 0x1f) - 1; - tm->tm_year = bcd2bin(regs[RV3029C2_A_YR-RV3029C2_A_SC] & 0x7f) + 100; - tm->tm_wday = bcd2bin(regs[RV3029C2_A_DW-RV3029C2_A_SC] & 0x07) - 1; - - return 0; -} - -static int -rv3029c2_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) -{ - return rv3029c2_i2c_read_alarm(to_i2c_client(dev), alarm); -} - -static int rv3029c2_rtc_i2c_alarm_set_irq(struct i2c_client *client, - int enable) -{ - int ret; - u8 buf[1]; - - /* enable AIE irq */ - ret = rv3029c2_i2c_read_regs(client, RV3029C2_IRQ_CTRL, buf, 1); - if (ret < 0) { - dev_err(&client->dev, "can't read INT reg\n"); - return ret; - } - if (enable) - buf[0] |= RV3029C2_IRQ_CTRL_AIE; - else - buf[0] &= ~RV3029C2_IRQ_CTRL_AIE; - - ret = rv3029c2_i2c_write_regs(client, RV3029C2_IRQ_CTRL, buf, 1); - if (ret < 0) { - dev_err(&client->dev, "can't set INT reg\n"); - return ret; - } - - return 0; -} - -static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client, - struct rtc_wkalrm *alarm) -{ - struct rtc_time *const tm = &alarm->time; - int ret; - u8 regs[8]; - - /* - * The clock has an 8 bit wide bcd-coded register (they never learn) - * for the year. tm_year is an offset from 1900 and we are interested - * in the 2000-2099 range, so any value less than 100 is invalid. - */ - if (tm->tm_year < 100) - return -EINVAL; - - ret = rv3029c2_i2c_get_sr(client, regs); - if (ret < 0) { - dev_err(&client->dev, "%s: reading SR failed\n", __func__); - return -EIO; - } - regs[RV3029C2_A_SC-RV3029C2_A_SC] = bin2bcd(tm->tm_sec & 0x7f); - regs[RV3029C2_A_MN-RV3029C2_A_SC] = bin2bcd(tm->tm_min & 0x7f); - regs[RV3029C2_A_HR-RV3029C2_A_SC] = bin2bcd(tm->tm_hour & 0x3f); - regs[RV3029C2_A_DT-RV3029C2_A_SC] = bin2bcd(tm->tm_mday & 0x3f); - regs[RV3029C2_A_MO-RV3029C2_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1); - regs[RV3029C2_A_DW-RV3029C2_A_SC] = bin2bcd((tm->tm_wday & 7) - 1); - regs[RV3029C2_A_YR-RV3029C2_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100); - - ret = rv3029c2_i2c_write_regs(client, RV3029C2_A_SC, regs, - RV3029C2_ALARM_SECTION_LEN); - if (ret < 0) - return ret; - - if (alarm->enabled) { - u8 buf[1]; - - /* clear AF flag */ - ret = rv3029c2_i2c_read_regs(client, RV3029C2_IRQ_FLAGS, - buf, 1); - if (ret < 0) { - dev_err(&client->dev, "can't read alarm flag\n"); - return ret; - } - buf[0] &= ~RV3029C2_IRQ_FLAGS_AF; - ret = rv3029c2_i2c_write_regs(client, RV3029C2_IRQ_FLAGS, - buf, 1); - if (ret < 0) { - dev_err(&client->dev, "can't set alarm flag\n"); - return ret; - } - /* enable AIE irq */ - ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 1); - if (ret) - return ret; - - dev_dbg(&client->dev, "alarm IRQ armed\n"); - } else { - /* disable AIE irq */ - ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 1); - if (ret) - return ret; - - dev_dbg(&client->dev, "alarm IRQ disabled\n"); - } - - return 0; -} - -static int rv3029c2_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) -{ - return rv3029c2_rtc_i2c_set_alarm(to_i2c_client(dev), alarm); -} - -static int -rv3029c2_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) -{ - u8 regs[8]; - int ret; - - /* - * The clock has an 8 bit wide bcd-coded register (they never learn) - * for the year. tm_year is an offset from 1900 and we are interested - * in the 2000-2099 range, so any value less than 100 is invalid. - */ - if (tm->tm_year < 100) - return -EINVAL; - - regs[RV3029C2_W_SEC-RV3029C2_W_SEC] = bin2bcd(tm->tm_sec); - regs[RV3029C2_W_MINUTES-RV3029C2_W_SEC] = bin2bcd(tm->tm_min); - regs[RV3029C2_W_HOURS-RV3029C2_W_SEC] = bin2bcd(tm->tm_hour); - regs[RV3029C2_W_DATE-RV3029C2_W_SEC] = bin2bcd(tm->tm_mday); - regs[RV3029C2_W_MONTHS-RV3029C2_W_SEC] = bin2bcd(tm->tm_mon+1); - regs[RV3029C2_W_DAYS-RV3029C2_W_SEC] = bin2bcd((tm->tm_wday & 7)+1); - regs[RV3029C2_W_YEARS-RV3029C2_W_SEC] = bin2bcd(tm->tm_year - 100); - - ret = rv3029c2_i2c_write_regs(client, RV3029C2_W_SEC, regs, - RV3029C2_WATCH_SECTION_LEN); - if (ret < 0) - return ret; - - ret = rv3029c2_i2c_get_sr(client, regs); - if (ret < 0) { - dev_err(&client->dev, "%s: reading SR failed\n", __func__); - return ret; - } - /* clear PON bit */ - ret = rv3029c2_i2c_set_sr(client, (regs[0] & ~RV3029C2_STATUS_PON)); - if (ret < 0) { - dev_err(&client->dev, "%s: reading SR failed\n", __func__); - return ret; - } - - return 0; -} - -static int rv3029c2_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - return rv3029c2_i2c_set_time(to_i2c_client(dev), tm); -} - -static const struct rtc_class_ops rv3029c2_rtc_ops = { - .read_time = rv3029c2_rtc_read_time, - .set_time = rv3029c2_rtc_set_time, - .read_alarm = rv3029c2_rtc_read_alarm, - .set_alarm = rv3029c2_rtc_set_alarm, -}; - -static struct i2c_device_id rv3029c2_id[] = { - { "rv3029c2", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, rv3029c2_id); - -static int __devinit -rv3029c2_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct rtc_device *rtc; - int rc = 0; - u8 buf[1]; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL)) - return -ENODEV; - - rtc = rtc_device_register(client->name, - &client->dev, &rv3029c2_rtc_ops, - THIS_MODULE); - - if (IS_ERR(rtc)) - return PTR_ERR(rtc); - - i2c_set_clientdata(client, rtc); - - rc = rv3029c2_i2c_get_sr(client, buf); - if (rc < 0) { - dev_err(&client->dev, "reading status failed\n"); - goto exit_unregister; - } - - return 0; - -exit_unregister: - rtc_device_unregister(rtc); - - return rc; -} - -static int __devexit rv3029c2_remove(struct i2c_client *client) -{ - struct rtc_device *rtc = i2c_get_clientdata(client); - - rtc_device_unregister(rtc); - - return 0; -} - -static struct i2c_driver rv3029c2_driver = { - .driver = { - .name = "rtc-rv3029c2", - }, - .probe = rv3029c2_probe, - .remove = __devexit_p(rv3029c2_remove), - .id_table = rv3029c2_id, -}; - -static int __init rv3029c2_init(void) -{ - return i2c_add_driver(&rv3029c2_driver); -} - -static void __exit rv3029c2_exit(void) -{ - i2c_del_driver(&rv3029c2_driver); -} - -module_init(rv3029c2_init); -module_exit(rv3029c2_exit); - -MODULE_AUTHOR("Gregory Hermant "); -MODULE_DESCRIPTION("Micro Crystal RV3029C2 RTC driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/rtc/rtc-spear.c b/trunk/drivers/rtc/rtc-spear.c deleted file mode 100644 index 893bac2bb21b..000000000000 --- a/trunk/drivers/rtc/rtc-spear.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * drivers/rtc/rtc-spear.c - * - * Copyright (C) 2010 ST Microelectronics - * Rajeev Kumar - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* RTC registers */ -#define TIME_REG 0x00 -#define DATE_REG 0x04 -#define ALARM_TIME_REG 0x08 -#define ALARM_DATE_REG 0x0C -#define CTRL_REG 0x10 -#define STATUS_REG 0x14 - -/* TIME_REG & ALARM_TIME_REG */ -#define SECONDS_UNITS (0xf<<0) /* seconds units position */ -#define SECONDS_TENS (0x7<<4) /* seconds tens position */ -#define MINUTES_UNITS (0xf<<8) /* minutes units position */ -#define MINUTES_TENS (0x7<<12) /* minutes tens position */ -#define HOURS_UNITS (0xf<<16) /* hours units position */ -#define HOURS_TENS (0x3<<20) /* hours tens position */ - -/* DATE_REG & ALARM_DATE_REG */ -#define DAYS_UNITS (0xf<<0) /* days units position */ -#define DAYS_TENS (0x3<<4) /* days tens position */ -#define MONTHS_UNITS (0xf<<8) /* months units position */ -#define MONTHS_TENS (0x1<<12) /* months tens position */ -#define YEARS_UNITS (0xf<<16) /* years units position */ -#define YEARS_TENS (0xf<<20) /* years tens position */ -#define YEARS_HUNDREDS (0xf<<24) /* years hundereds position */ -#define YEARS_MILLENIUMS (0xf<<28) /* years millenium position */ - -/* MASK SHIFT TIME_REG & ALARM_TIME_REG*/ -#define SECOND_SHIFT 0x00 /* seconds units */ -#define MINUTE_SHIFT 0x08 /* minutes units position */ -#define HOUR_SHIFT 0x10 /* hours units position */ -#define MDAY_SHIFT 0x00 /* Month day shift */ -#define MONTH_SHIFT 0x08 /* Month shift */ -#define YEAR_SHIFT 0x10 /* Year shift */ - -#define SECOND_MASK 0x7F -#define MIN_MASK 0x7F -#define HOUR_MASK 0x3F -#define DAY_MASK 0x3F -#define MONTH_MASK 0x7F -#define YEAR_MASK 0xFFFF - -/* date reg equal to time reg, for debug only */ -#define TIME_BYP (1<<9) -#define INT_ENABLE (1<<31) /* interrupt enable */ - -/* STATUS_REG */ -#define CLK_UNCONNECTED (1<<0) -#define PEND_WR_TIME (1<<2) -#define PEND_WR_DATE (1<<3) -#define LOST_WR_TIME (1<<4) -#define LOST_WR_DATE (1<<5) -#define RTC_INT_MASK (1<<31) -#define STATUS_BUSY (PEND_WR_TIME | PEND_WR_DATE) -#define STATUS_FAIL (LOST_WR_TIME | LOST_WR_DATE) - -struct spear_rtc_config { - struct clk *clk; - spinlock_t lock; - void __iomem *ioaddr; -}; - -static inline void spear_rtc_clear_interrupt(struct spear_rtc_config *config) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&config->lock, flags); - val = readl(config->ioaddr + STATUS_REG); - val |= RTC_INT_MASK; - writel(val, config->ioaddr + STATUS_REG); - spin_unlock_irqrestore(&config->lock, flags); -} - -static inline void spear_rtc_enable_interrupt(struct spear_rtc_config *config) -{ - unsigned int val; - - val = readl(config->ioaddr + CTRL_REG); - if (!(val & INT_ENABLE)) { - spear_rtc_clear_interrupt(config); - val |= INT_ENABLE; - writel(val, config->ioaddr + CTRL_REG); - } -} - -static inline void spear_rtc_disable_interrupt(struct spear_rtc_config *config) -{ - unsigned int val; - - val = readl(config->ioaddr + CTRL_REG); - if (val & INT_ENABLE) { - val &= ~INT_ENABLE; - writel(val, config->ioaddr + CTRL_REG); - } -} - -static inline int is_write_complete(struct spear_rtc_config *config) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&config->lock, flags); - if ((readl(config->ioaddr + STATUS_REG)) & STATUS_FAIL) - ret = -EIO; - spin_unlock_irqrestore(&config->lock, flags); - - return ret; -} - -static void rtc_wait_not_busy(struct spear_rtc_config *config) -{ - int status, count = 0; - unsigned long flags; - - /* Assuming BUSY may stay active for 80 msec) */ - for (count = 0; count < 80; count++) { - spin_lock_irqsave(&config->lock, flags); - status = readl(config->ioaddr + STATUS_REG); - spin_unlock_irqrestore(&config->lock, flags); - if ((status & STATUS_BUSY) == 0) - break; - /* check status busy, after each msec */ - msleep(1); - } -} - -static irqreturn_t spear_rtc_irq(int irq, void *dev_id) -{ - struct rtc_device *rtc = (struct rtc_device *)dev_id; - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); - unsigned long flags, events = 0; - unsigned int irq_data; - - spin_lock_irqsave(&config->lock, flags); - irq_data = readl(config->ioaddr + STATUS_REG); - spin_unlock_irqrestore(&config->lock, flags); - - if ((irq_data & RTC_INT_MASK)) { - spear_rtc_clear_interrupt(config); - events = RTC_IRQF | RTC_AF; - rtc_update_irq(rtc, 1, events); - return IRQ_HANDLED; - } else - return IRQ_NONE; - -} - -static int tm2bcd(struct rtc_time *tm) -{ - if (rtc_valid_tm(tm) != 0) - return -EINVAL; - tm->tm_sec = bin2bcd(tm->tm_sec); - tm->tm_min = bin2bcd(tm->tm_min); - tm->tm_hour = bin2bcd(tm->tm_hour); - tm->tm_mday = bin2bcd(tm->tm_mday); - tm->tm_mon = bin2bcd(tm->tm_mon + 1); - tm->tm_year = bin2bcd(tm->tm_year); - - return 0; -} - -static void bcd2tm(struct rtc_time *tm) -{ - tm->tm_sec = bcd2bin(tm->tm_sec); - tm->tm_min = bcd2bin(tm->tm_min); - tm->tm_hour = bcd2bin(tm->tm_hour); - tm->tm_mday = bcd2bin(tm->tm_mday); - tm->tm_mon = bcd2bin(tm->tm_mon) - 1; - /* epoch == 1900 */ - tm->tm_year = bcd2bin(tm->tm_year); -} - -/* - * spear_rtc_read_time - set the time - * @dev: rtc device in use - * @tm: holds date and time - * - * This function read time and date. On success it will return 0 - * otherwise -ve error is returned. - */ -static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); - unsigned int time, date; - - /* we don't report wday/yday/isdst ... */ - rtc_wait_not_busy(config); - - time = readl(config->ioaddr + TIME_REG); - date = readl(config->ioaddr + DATE_REG); - tm->tm_sec = (time >> SECOND_SHIFT) & SECOND_MASK; - tm->tm_min = (time >> MINUTE_SHIFT) & MIN_MASK; - tm->tm_hour = (time >> HOUR_SHIFT) & HOUR_MASK; - tm->tm_mday = (date >> MDAY_SHIFT) & DAY_MASK; - tm->tm_mon = (date >> MONTH_SHIFT) & MONTH_MASK; - tm->tm_year = (date >> YEAR_SHIFT) & YEAR_MASK; - - bcd2tm(tm); - return 0; -} - -/* - * spear_rtc_set_time - set the time - * @dev: rtc device in use - * @tm: holds date and time - * - * This function set time and date. On success it will return 0 - * otherwise -ve error is returned. - */ -static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); - unsigned int time, date, err = 0; - - if (tm2bcd(tm) < 0) - return -EINVAL; - - rtc_wait_not_busy(config); - time = (tm->tm_sec << SECOND_SHIFT) | (tm->tm_min << MINUTE_SHIFT) | - (tm->tm_hour << HOUR_SHIFT); - date = (tm->tm_mday << MDAY_SHIFT) | (tm->tm_mon << MONTH_SHIFT) | - (tm->tm_year << YEAR_SHIFT); - writel(time, config->ioaddr + TIME_REG); - writel(date, config->ioaddr + DATE_REG); - err = is_write_complete(config); - if (err < 0) - return err; - - return 0; -} - -/* - * spear_rtc_read_alarm - read the alarm time - * @dev: rtc device in use - * @alm: holds alarm date and time - * - * This function read alarm time and date. On success it will return 0 - * otherwise -ve error is returned. - */ -static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); - unsigned int time, date; - - rtc_wait_not_busy(config); - - time = readl(config->ioaddr + ALARM_TIME_REG); - date = readl(config->ioaddr + ALARM_DATE_REG); - alm->time.tm_sec = (time >> SECOND_SHIFT) & SECOND_MASK; - alm->time.tm_min = (time >> MINUTE_SHIFT) & MIN_MASK; - alm->time.tm_hour = (time >> HOUR_SHIFT) & HOUR_MASK; - alm->time.tm_mday = (date >> MDAY_SHIFT) & DAY_MASK; - alm->time.tm_mon = (date >> MONTH_SHIFT) & MONTH_MASK; - alm->time.tm_year = (date >> YEAR_SHIFT) & YEAR_MASK; - - bcd2tm(&alm->time); - alm->enabled = readl(config->ioaddr + CTRL_REG) & INT_ENABLE; - - return 0; -} - -/* - * spear_rtc_set_alarm - set the alarm time - * @dev: rtc device in use - * @alm: holds alarm date and time - * - * This function set alarm time and date. On success it will return 0 - * otherwise -ve error is returned. - */ -static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); - unsigned int time, date, err = 0; - - if (tm2bcd(&alm->time) < 0) - return -EINVAL; - - rtc_wait_not_busy(config); - - time = (alm->time.tm_sec << SECOND_SHIFT) | (alm->time.tm_min << - MINUTE_SHIFT) | (alm->time.tm_hour << HOUR_SHIFT); - date = (alm->time.tm_mday << MDAY_SHIFT) | (alm->time.tm_mon << - MONTH_SHIFT) | (alm->time.tm_year << YEAR_SHIFT); - - writel(time, config->ioaddr + ALARM_TIME_REG); - writel(date, config->ioaddr + ALARM_DATE_REG); - err = is_write_complete(config); - if (err < 0) - return err; - - if (alm->enabled) - spear_rtc_enable_interrupt(config); - else - spear_rtc_disable_interrupt(config); - - return 0; -} -static struct rtc_class_ops spear_rtc_ops = { - .read_time = spear_rtc_read_time, - .set_time = spear_rtc_set_time, - .read_alarm = spear_rtc_read_alarm, - .set_alarm = spear_rtc_set_alarm, -}; - -static int __devinit spear_rtc_probe(struct platform_device *pdev) -{ - struct resource *res; - struct rtc_device *rtc; - struct spear_rtc_config *config; - unsigned int status = 0; - int irq; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no resource defined\n"); - return -EBUSY; - } - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "rtc region already claimed\n"); - return -EBUSY; - } - - config = kzalloc(sizeof(*config), GFP_KERNEL); - if (!config) { - dev_err(&pdev->dev, "out of memory\n"); - status = -ENOMEM; - goto err_release_region; - } - - config->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(config->clk)) { - status = PTR_ERR(config->clk); - goto err_kfree; - } - - status = clk_enable(config->clk); - if (status < 0) - goto err_clk_put; - - config->ioaddr = ioremap(res->start, resource_size(res)); - if (!config->ioaddr) { - dev_err(&pdev->dev, "ioremap fail\n"); - status = -ENOMEM; - goto err_disable_clock; - } - - spin_lock_init(&config->lock); - - rtc = rtc_device_register(pdev->name, &pdev->dev, &spear_rtc_ops, - THIS_MODULE); - if (IS_ERR(rtc)) { - dev_err(&pdev->dev, "can't register RTC device, err %ld\n", - PTR_ERR(rtc)); - status = PTR_ERR(rtc); - goto err_iounmap; - } - - platform_set_drvdata(pdev, rtc); - dev_set_drvdata(&rtc->dev, config); - - /* alarm irqs */ - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no update irq?\n"); - status = irq; - goto err_clear_platdata; - } - - status = request_irq(irq, spear_rtc_irq, 0, pdev->name, rtc); - if (status) { - dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \ - claimed\n", irq); - goto err_clear_platdata; - } - - if (!device_can_wakeup(&pdev->dev)) - device_init_wakeup(&pdev->dev, 1); - - return 0; - -err_clear_platdata: - platform_set_drvdata(pdev, NULL); - dev_set_drvdata(&rtc->dev, NULL); - rtc_device_unregister(rtc); -err_iounmap: - iounmap(config->ioaddr); -err_disable_clock: - clk_disable(config->clk); -err_clk_put: - clk_put(config->clk); -err_kfree: - kfree(config); -err_release_region: - release_mem_region(res->start, resource_size(res)); - - return status; -} - -static int __devexit spear_rtc_remove(struct platform_device *pdev) -{ - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); - int irq; - struct resource *res; - - /* leave rtc running, but disable irqs */ - spear_rtc_disable_interrupt(config); - device_init_wakeup(&pdev->dev, 0); - irq = platform_get_irq(pdev, 0); - if (irq) - free_irq(irq, pdev); - clk_disable(config->clk); - clk_put(config->clk); - iounmap(config->ioaddr); - kfree(config); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res) - release_mem_region(res->start, resource_size(res)); - platform_set_drvdata(pdev, NULL); - dev_set_drvdata(&rtc->dev, NULL); - rtc_device_unregister(rtc); - - return 0; -} - -#ifdef CONFIG_PM - -static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); - int irq; - - irq = platform_get_irq(pdev, 0); - if (device_may_wakeup(&pdev->dev)) - enable_irq_wake(irq); - else { - spear_rtc_disable_interrupt(config); - clk_disable(config->clk); - } - - return 0; -} - -static int spear_rtc_resume(struct platform_device *pdev) -{ - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); - int irq; - - irq = platform_get_irq(pdev, 0); - - if (device_may_wakeup(&pdev->dev)) - disable_irq_wake(irq); - else { - clk_enable(config->clk); - spear_rtc_enable_interrupt(config); - } - - return 0; -} - -#else -#define spear_rtc_suspend NULL -#define spear_rtc_resume NULL -#endif - -static void spear_rtc_shutdown(struct platform_device *pdev) -{ - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); - - spear_rtc_disable_interrupt(config); - clk_disable(config->clk); -} - -static struct platform_driver spear_rtc_driver = { - .probe = spear_rtc_probe, - .remove = __devexit_p(spear_rtc_remove), - .suspend = spear_rtc_suspend, - .resume = spear_rtc_resume, - .shutdown = spear_rtc_shutdown, - .driver = { - .name = "rtc-spear", - }, -}; - -static int __init rtc_init(void) -{ - return platform_driver_register(&spear_rtc_driver); -} -module_init(rtc_init); - -static void __exit rtc_exit(void) -{ - platform_driver_unregister(&spear_rtc_driver); -} -module_exit(rtc_exit); - -MODULE_ALIAS("platform:rtc-spear"); -MODULE_AUTHOR("Rajeev Kumar "); -MODULE_DESCRIPTION("ST SPEAr Realtime Clock Driver (RTC)"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/rtc/rtc-vt8500.c b/trunk/drivers/rtc/rtc-vt8500.c deleted file mode 100644 index b8bc862903ae..000000000000 --- a/trunk/drivers/rtc/rtc-vt8500.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * drivers/rtc/rtc-vt8500.c - * - * Copyright (C) 2010 Alexey Charkov - * - * Based on rtc-pxa.c - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Register definitions - */ -#define VT8500_RTC_TS 0x00 /* Time set */ -#define VT8500_RTC_DS 0x04 /* Date set */ -#define VT8500_RTC_AS 0x08 /* Alarm set */ -#define VT8500_RTC_CR 0x0c /* Control */ -#define VT8500_RTC_TR 0x10 /* Time read */ -#define VT8500_RTC_DR 0x14 /* Date read */ -#define VT8500_RTC_WS 0x18 /* Write status */ -#define VT8500_RTC_CL 0x20 /* Calibration */ -#define VT8500_RTC_IS 0x24 /* Interrupt status */ -#define VT8500_RTC_ST 0x28 /* Status */ - -#define INVALID_TIME_BIT (1 << 31) - -#define DATE_CENTURY_S 19 -#define DATE_YEAR_S 11 -#define DATE_YEAR_MASK (0xff << DATE_YEAR_S) -#define DATE_MONTH_S 6 -#define DATE_MONTH_MASK (0x1f << DATE_MONTH_S) -#define DATE_DAY_MASK 0x3f - -#define TIME_DOW_S 20 -#define TIME_DOW_MASK (0x07 << TIME_DOW_S) -#define TIME_HOUR_S 14 -#define TIME_HOUR_MASK (0x3f << TIME_HOUR_S) -#define TIME_MIN_S 7 -#define TIME_MIN_MASK (0x7f << TIME_MIN_S) -#define TIME_SEC_MASK 0x7f - -#define ALARM_DAY_S 20 -#define ALARM_DAY_MASK (0x3f << ALARM_DAY_S) - -#define ALARM_DAY_BIT (1 << 29) -#define ALARM_HOUR_BIT (1 << 28) -#define ALARM_MIN_BIT (1 << 27) -#define ALARM_SEC_BIT (1 << 26) - -#define ALARM_ENABLE_MASK (ALARM_DAY_BIT \ - | ALARM_HOUR_BIT \ - | ALARM_MIN_BIT \ - | ALARM_SEC_BIT) - -#define VT8500_RTC_CR_ENABLE (1 << 0) /* Enable RTC */ -#define VT8500_RTC_CR_24H (1 << 1) /* 24h time format */ -#define VT8500_RTC_CR_SM_ENABLE (1 << 2) /* Enable periodic irqs */ -#define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */ -#define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */ - -struct vt8500_rtc { - void __iomem *regbase; - struct resource *res; - int irq_alarm; - int irq_hz; - struct rtc_device *rtc; - spinlock_t lock; /* Protects this structure */ -}; - -static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id) -{ - struct vt8500_rtc *vt8500_rtc = dev_id; - u32 isr; - unsigned long events = 0; - - spin_lock(&vt8500_rtc->lock); - - /* clear interrupt sources */ - isr = readl(vt8500_rtc->regbase + VT8500_RTC_IS); - writel(isr, vt8500_rtc->regbase + VT8500_RTC_IS); - - spin_unlock(&vt8500_rtc->lock); - - if (isr & 1) - events |= RTC_AF | RTC_IRQF; - - /* Only second/minute interrupts are supported */ - if (isr & 2) - events |= RTC_UF | RTC_IRQF; - - rtc_update_irq(vt8500_rtc->rtc, 1, events); - - return IRQ_HANDLED; -} - -static int vt8500_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); - u32 date, time; - - date = readl(vt8500_rtc->regbase + VT8500_RTC_DR); - time = readl(vt8500_rtc->regbase + VT8500_RTC_TR); - - tm->tm_sec = bcd2bin(time & TIME_SEC_MASK); - tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S); - tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S); - tm->tm_mday = bcd2bin(date & DATE_DAY_MASK); - tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S); - tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S) - + ((date >> DATE_CENTURY_S) & 1 ? 200 : 100); - tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S; - - return 0; -} - -static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); - - if (tm->tm_year < 100) { - dev_warn(dev, "Only years 2000-2199 are supported by the " - "hardware!\n"); - return -EINVAL; - } - - writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S) - | (bin2bcd(tm->tm_mon) << DATE_MONTH_S) - | (bin2bcd(tm->tm_mday)), - vt8500_rtc->regbase + VT8500_RTC_DS); - writel((bin2bcd(tm->tm_wday) << TIME_DOW_S) - | (bin2bcd(tm->tm_hour) << TIME_HOUR_S) - | (bin2bcd(tm->tm_min) << TIME_MIN_S) - | (bin2bcd(tm->tm_sec)), - vt8500_rtc->regbase + VT8500_RTC_TS); - - return 0; -} - -static int vt8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); - u32 isr, alarm; - - alarm = readl(vt8500_rtc->regbase + VT8500_RTC_AS); - isr = readl(vt8500_rtc->regbase + VT8500_RTC_IS); - - alrm->time.tm_mday = bcd2bin((alarm & ALARM_DAY_MASK) >> ALARM_DAY_S); - alrm->time.tm_hour = bcd2bin((alarm & TIME_HOUR_MASK) >> TIME_HOUR_S); - alrm->time.tm_min = bcd2bin((alarm & TIME_MIN_MASK) >> TIME_MIN_S); - alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK)); - - alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0; - - alrm->pending = (isr & 1) ? 1 : 0; - return rtc_valid_tm(&alrm->time); -} - -static int vt8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); - - writel((alrm->enabled ? ALARM_ENABLE_MASK : 0) - | (bin2bcd(alrm->time.tm_mday) << ALARM_DAY_S) - | (bin2bcd(alrm->time.tm_hour) << TIME_HOUR_S) - | (bin2bcd(alrm->time.tm_min) << TIME_MIN_S) - | (bin2bcd(alrm->time.tm_sec)), - vt8500_rtc->regbase + VT8500_RTC_AS); - - return 0; -} - -static int vt8500_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); - unsigned long tmp = readl(vt8500_rtc->regbase + VT8500_RTC_AS); - - if (enabled) - tmp |= ALARM_ENABLE_MASK; - else - tmp &= ~ALARM_ENABLE_MASK; - - writel(tmp, vt8500_rtc->regbase + VT8500_RTC_AS); - return 0; -} - -static int vt8500_update_irq_enable(struct device *dev, unsigned int enabled) -{ - struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); - unsigned long tmp = readl(vt8500_rtc->regbase + VT8500_RTC_CR); - - if (enabled) - tmp |= VT8500_RTC_CR_SM_SEC | VT8500_RTC_CR_SM_ENABLE; - else - tmp &= ~VT8500_RTC_CR_SM_ENABLE; - - writel(tmp, vt8500_rtc->regbase + VT8500_RTC_CR); - return 0; -} - -static const struct rtc_class_ops vt8500_rtc_ops = { - .read_time = vt8500_rtc_read_time, - .set_time = vt8500_rtc_set_time, - .read_alarm = vt8500_rtc_read_alarm, - .set_alarm = vt8500_rtc_set_alarm, - .alarm_irq_enable = vt8500_alarm_irq_enable, - .update_irq_enable = vt8500_update_irq_enable, -}; - -static int __devinit vt8500_rtc_probe(struct platform_device *pdev) -{ - struct vt8500_rtc *vt8500_rtc; - int ret; - - vt8500_rtc = kzalloc(sizeof(struct vt8500_rtc), GFP_KERNEL); - if (!vt8500_rtc) - return -ENOMEM; - - spin_lock_init(&vt8500_rtc->lock); - platform_set_drvdata(pdev, vt8500_rtc); - - vt8500_rtc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!vt8500_rtc->res) { - dev_err(&pdev->dev, "No I/O memory resource defined\n"); - ret = -ENXIO; - goto err_free; - } - - vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0); - if (vt8500_rtc->irq_alarm < 0) { - dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); - ret = -ENXIO; - goto err_free; - } - - vt8500_rtc->irq_hz = platform_get_irq(pdev, 1); - if (vt8500_rtc->irq_hz < 0) { - dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n"); - ret = -ENXIO; - goto err_free; - } - - vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start, - resource_size(vt8500_rtc->res), - "vt8500-rtc"); - if (vt8500_rtc->res == NULL) { - dev_err(&pdev->dev, "failed to request I/O memory\n"); - ret = -EBUSY; - goto err_free; - } - - vt8500_rtc->regbase = ioremap(vt8500_rtc->res->start, - resource_size(vt8500_rtc->res)); - if (!vt8500_rtc->regbase) { - dev_err(&pdev->dev, "Unable to map RTC I/O memory\n"); - ret = -EBUSY; - goto err_release; - } - - /* Enable the second/minute interrupt generation and enable RTC */ - writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H - | VT8500_RTC_CR_SM_ENABLE | VT8500_RTC_CR_SM_SEC, - vt8500_rtc->regbase + VT8500_RTC_CR); - - vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev, - &vt8500_rtc_ops, THIS_MODULE); - if (IS_ERR(vt8500_rtc->rtc)) { - ret = PTR_ERR(vt8500_rtc->rtc); - dev_err(&pdev->dev, - "Failed to register RTC device -> %d\n", ret); - goto err_unmap; - } - - ret = request_irq(vt8500_rtc->irq_hz, vt8500_rtc_irq, 0, - "rtc 1Hz", vt8500_rtc); - if (ret < 0) { - dev_err(&pdev->dev, "can't get irq %i, err %d\n", - vt8500_rtc->irq_hz, ret); - goto err_unreg; - } - - ret = request_irq(vt8500_rtc->irq_alarm, vt8500_rtc_irq, 0, - "rtc alarm", vt8500_rtc); - if (ret < 0) { - dev_err(&pdev->dev, "can't get irq %i, err %d\n", - vt8500_rtc->irq_alarm, ret); - goto err_free_hz; - } - - return 0; - -err_free_hz: - free_irq(vt8500_rtc->irq_hz, vt8500_rtc); -err_unreg: - rtc_device_unregister(vt8500_rtc->rtc); -err_unmap: - iounmap(vt8500_rtc->regbase); -err_release: - release_mem_region(vt8500_rtc->res->start, - resource_size(vt8500_rtc->res)); -err_free: - kfree(vt8500_rtc); - return ret; -} - -static int __devexit vt8500_rtc_remove(struct platform_device *pdev) -{ - struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev); - - free_irq(vt8500_rtc->irq_alarm, vt8500_rtc); - free_irq(vt8500_rtc->irq_hz, vt8500_rtc); - - rtc_device_unregister(vt8500_rtc->rtc); - - /* Disable alarm matching */ - writel(0, vt8500_rtc->regbase + VT8500_RTC_IS); - iounmap(vt8500_rtc->regbase); - release_mem_region(vt8500_rtc->res->start, - resource_size(vt8500_rtc->res)); - - kfree(vt8500_rtc); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver vt8500_rtc_driver = { - .probe = vt8500_rtc_probe, - .remove = __devexit_p(vt8500_rtc_remove), - .driver = { - .name = "vt8500-rtc", - .owner = THIS_MODULE, - }, -}; - -static int __init vt8500_rtc_init(void) -{ - return platform_driver_register(&vt8500_rtc_driver); -} -module_init(vt8500_rtc_init); - -static void __exit vt8500_rtc_exit(void) -{ - platform_driver_unregister(&vt8500_rtc_driver); -} -module_exit(vt8500_rtc_exit); - -MODULE_AUTHOR("Alexey Charkov "); -MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:vt8500-rtc"); diff --git a/trunk/drivers/scsi/aacraid/linit.c b/trunk/drivers/scsi/aacraid/linit.c index 3382475dc22d..4ff26521d75f 100644 --- a/trunk/drivers/scsi/aacraid/linit.c +++ b/trunk/drivers/scsi/aacraid/linit.c @@ -59,6 +59,7 @@ #ifndef AAC_DRIVER_BRANCH #define AAC_DRIVER_BRANCH "" #endif +#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__ #define AAC_DRIVERNAME "aacraid" #ifdef AAC_DRIVER_BUILD @@ -66,7 +67,7 @@ #define str(x) _str(x) #define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH #else -#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH +#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH " " AAC_DRIVER_BUILD_DATE #endif MODULE_AUTHOR("Red Hat Inc and Adaptec"); diff --git a/trunk/drivers/scsi/in2000.c b/trunk/drivers/scsi/in2000.c index 112f1bec7756..92109b126391 100644 --- a/trunk/drivers/scsi/in2000.c +++ b/trunk/drivers/scsi/in2000.c @@ -2227,7 +2227,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, bp = buf; *bp = '\0'; if (hd->proc & PR_VERSION) { - sprintf(tbuf, "\nVersion %s - %s.", IN2000_VERSION, IN2000_DATE); + sprintf(tbuf, "\nVersion %s - %s. Compiled %s %s", IN2000_VERSION, IN2000_DATE, __DATE__, __TIME__); strcat(bp, tbuf); } if (hd->proc & PR_INFO) { diff --git a/trunk/drivers/scsi/pmcraid.c b/trunk/drivers/scsi/pmcraid.c index fca6a8953070..7f636b118287 100644 --- a/trunk/drivers/scsi/pmcraid.c +++ b/trunk/drivers/scsi/pmcraid.c @@ -4252,8 +4252,8 @@ static ssize_t pmcraid_show_drv_version( char *buf ) { - return snprintf(buf, PAGE_SIZE, "version: %s\n", - PMCRAID_DRIVER_VERSION); + return snprintf(buf, PAGE_SIZE, "version: %s, build date: %s\n", + PMCRAID_DRIVER_VERSION, PMCRAID_DRIVER_DATE); } static struct device_attribute pmcraid_driver_version_attr = { @@ -6096,8 +6096,9 @@ static int __init pmcraid_init(void) dev_t dev; int error; - pmcraid_info("%s Device Driver version: %s\n", - PMCRAID_DRIVER_NAME, PMCRAID_DRIVER_VERSION); + pmcraid_info("%s Device Driver version: %s %s\n", + PMCRAID_DRIVER_NAME, + PMCRAID_DRIVER_VERSION, PMCRAID_DRIVER_DATE); error = alloc_chrdev_region(&dev, 0, PMCRAID_MAX_ADAPTERS, diff --git a/trunk/drivers/scsi/pmcraid.h b/trunk/drivers/scsi/pmcraid.h index f920baf3ff24..34e4c915002e 100644 --- a/trunk/drivers/scsi/pmcraid.h +++ b/trunk/drivers/scsi/pmcraid.h @@ -43,6 +43,7 @@ #define PMCRAID_DRIVER_NAME "PMC MaxRAID" #define PMCRAID_DEVFILE "pmcsas" #define PMCRAID_DRIVER_VERSION "1.0.3" +#define PMCRAID_DRIVER_DATE __DATE__ #define PMCRAID_FW_VERSION_1 0x002 diff --git a/trunk/drivers/scsi/wd33c93.c b/trunk/drivers/scsi/wd33c93.c index c0ee4ea28a19..97ae716134d0 100644 --- a/trunk/drivers/scsi/wd33c93.c +++ b/trunk/drivers/scsi/wd33c93.c @@ -2051,7 +2051,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, for (i = 0; i < MAX_SETUP_ARGS; i++) printk("%s,", setup_args[i]); printk("\n"); - printk(" Version %s - %s\n", WD33C93_VERSION, WD33C93_DATE); + printk(" Version %s - %s, Compiled %s at %s\n", + WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__); } int @@ -2131,8 +2132,8 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off bp = buf; *bp = '\0'; if (hd->proc & PR_VERSION) { - sprintf(tbuf, "\nVersion %s - %s.", - WD33C93_VERSION, WD33C93_DATE); + sprintf(tbuf, "\nVersion %s - %s. Compiled %s %s", + WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__); strcat(bp, tbuf); } if (hd->proc & PR_INFO) { diff --git a/trunk/drivers/spi/Kconfig b/trunk/drivers/spi/Kconfig index fbd96b29530d..fc14b8dea0d7 100644 --- a/trunk/drivers/spi/Kconfig +++ b/trunk/drivers/spi/Kconfig @@ -271,8 +271,8 @@ config SPI_ORION This enables using the SPI master controller on the Orion chips. config SPI_PL022 - tristate "ARM AMBA PL022 SSP controller" - depends on ARM_AMBA + tristate "ARM AMBA PL022 SSP controller (EXPERIMENTAL)" + depends on ARM_AMBA && EXPERIMENTAL default y if MACH_U300 default y if ARCH_REALVIEW default y if INTEGRATOR_IMPD1 diff --git a/trunk/drivers/spi/amba-pl022.c b/trunk/drivers/spi/amba-pl022.c index 6a9e58dd36c7..08de58e7f59f 100644 --- a/trunk/drivers/spi/amba-pl022.c +++ b/trunk/drivers/spi/amba-pl022.c @@ -24,6 +24,11 @@ * GNU General Public License for more details. */ +/* + * TODO: + * - add timeout on polled transfers + */ + #include #include #include @@ -282,8 +287,6 @@ #define CLEAR_ALL_INTERRUPTS 0x3 -#define SPI_POLLING_TIMEOUT 1000 - /* * The type of reading going on on this chip @@ -1060,7 +1063,7 @@ static int __init pl022_dma_probe(struct pl022 *pl022) pl022->master_info->dma_filter, pl022->master_info->dma_rx_param); if (!pl022->dma_rx_channel) { - dev_dbg(&pl022->adev->dev, "no RX DMA channel!\n"); + dev_err(&pl022->adev->dev, "no RX DMA channel!\n"); goto err_no_rxchan; } @@ -1068,13 +1071,13 @@ static int __init pl022_dma_probe(struct pl022 *pl022) pl022->master_info->dma_filter, pl022->master_info->dma_tx_param); if (!pl022->dma_tx_channel) { - dev_dbg(&pl022->adev->dev, "no TX DMA channel!\n"); + dev_err(&pl022->adev->dev, "no TX DMA channel!\n"); goto err_no_txchan; } pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!pl022->dummypage) { - dev_dbg(&pl022->adev->dev, "no DMA dummypage!\n"); + dev_err(&pl022->adev->dev, "no DMA dummypage!\n"); goto err_no_dummypage; } @@ -1090,8 +1093,6 @@ static int __init pl022_dma_probe(struct pl022 *pl022) dma_release_channel(pl022->dma_rx_channel); pl022->dma_rx_channel = NULL; err_no_rxchan: - dev_err(&pl022->adev->dev, - "Failed to work in dma mode, work without dma!\n"); return -ENODEV; } @@ -1377,7 +1378,6 @@ static void do_polling_transfer(struct pl022 *pl022) struct spi_transfer *transfer = NULL; struct spi_transfer *previous = NULL; struct chip_data *chip; - unsigned long time, timeout; chip = pl022->cur_chip; message = pl022->cur_msg; @@ -1415,19 +1415,9 @@ static void do_polling_transfer(struct pl022 *pl022) SSP_CR1(pl022->virtbase)); dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n"); - - timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT); - while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) { - time = jiffies; + /* FIXME: insert a timeout so we don't hang here indefinitely */ + while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) readwriter(pl022); - if (time_after(time, timeout)) { - dev_warn(&pl022->adev->dev, - "%s: timeout!\n", __func__); - message->state = STATE_ERROR; - goto out; - } - cpu_relax(); - } /* Update total byte transferred */ message->actual_length += pl022->cur_transfer->len; @@ -1436,7 +1426,7 @@ static void do_polling_transfer(struct pl022 *pl022) /* Move to next transfer */ message->state = next_transfer(pl022); } -out: + /* Handle end of message */ if (message->state == STATE_DONE) message->status = 0; @@ -2117,7 +2107,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) if (platform_info->enable_dma) { status = pl022_dma_probe(pl022); if (status != 0) - platform_info->enable_dma = 0; + goto err_no_dma; } /* Initialize and start queue */ @@ -2153,6 +2143,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) err_init_queue: destroy_queue(pl022); pl022_dma_remove(pl022); + err_no_dma: free_irq(adev->irq[0], pl022); err_no_irq: clk_put(pl022->clk); diff --git a/trunk/drivers/spi/dw_spi.c b/trunk/drivers/spi/dw_spi.c index 919fa9d9e16b..871e337c917f 100644 --- a/trunk/drivers/spi/dw_spi.c +++ b/trunk/drivers/spi/dw_spi.c @@ -58,6 +58,8 @@ struct chip_data { u8 bits_per_word; u16 clk_div; /* baud rate divider */ u32 speed_hz; /* baud rate */ + int (*write)(struct dw_spi *dws); + int (*read)(struct dw_spi *dws); void (*cs_control)(u32 command); }; @@ -160,70 +162,107 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi *dws) } #endif /* CONFIG_DEBUG_FS */ -/* Return the max entries we can fill into tx fifo */ -static inline u32 tx_max(struct dw_spi *dws) +static void wait_till_not_busy(struct dw_spi *dws) { - u32 tx_left, tx_room, rxtx_gap; + unsigned long end = jiffies + 1 + usecs_to_jiffies(5000); - tx_left = (dws->tx_end - dws->tx) / dws->n_bytes; - tx_room = dws->fifo_len - dw_readw(dws, txflr); + while (time_before(jiffies, end)) { + if (!(dw_readw(dws, sr) & SR_BUSY)) + return; + cpu_relax(); + } + dev_err(&dws->master->dev, + "DW SPI: Status keeps busy for 5000us after a read/write!\n"); +} - /* - * Another concern is about the tx/rx mismatch, we - * though to use (dws->fifo_len - rxflr - txflr) as - * one maximum value for tx, but it doesn't cover the - * data which is out of tx/rx fifo and inside the - * shift registers. So a control from sw point of - * view is taken. - */ - rxtx_gap = ((dws->rx_end - dws->rx) - (dws->tx_end - dws->tx)) - / dws->n_bytes; +static void flush(struct dw_spi *dws) +{ + while (dw_readw(dws, sr) & SR_RF_NOT_EMPT) { + dw_readw(dws, dr); + cpu_relax(); + } - return min3(tx_left, tx_room, (u32) (dws->fifo_len - rxtx_gap)); + wait_till_not_busy(dws); } -/* Return the max entries we should read out of rx fifo */ -static inline u32 rx_max(struct dw_spi *dws) +static int null_writer(struct dw_spi *dws) { - u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes; + u8 n_bytes = dws->n_bytes; - return min(rx_left, (u32)dw_readw(dws, rxflr)); + if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) + || (dws->tx == dws->tx_end)) + return 0; + dw_writew(dws, dr, 0); + dws->tx += n_bytes; + + wait_till_not_busy(dws); + return 1; } -static void dw_writer(struct dw_spi *dws) +static int null_reader(struct dw_spi *dws) { - u32 max = tx_max(dws); - u16 txw = 0; + u8 n_bytes = dws->n_bytes; - while (max--) { - /* Set the tx word if the transfer's original "tx" is not null */ - if (dws->tx_end - dws->len) { - if (dws->n_bytes == 1) - txw = *(u8 *)(dws->tx); - else - txw = *(u16 *)(dws->tx); - } - dw_writew(dws, dr, txw); - dws->tx += dws->n_bytes; + while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) + && (dws->rx < dws->rx_end)) { + dw_readw(dws, dr); + dws->rx += n_bytes; } + wait_till_not_busy(dws); + return dws->rx == dws->rx_end; } -static void dw_reader(struct dw_spi *dws) +static int u8_writer(struct dw_spi *dws) { - u32 max = rx_max(dws); - u16 rxw; + if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) + || (dws->tx == dws->tx_end)) + return 0; - while (max--) { - rxw = dw_readw(dws, dr); - /* Care rx only if the transfer's original "rx" is not null */ - if (dws->rx_end - dws->len) { - if (dws->n_bytes == 1) - *(u8 *)(dws->rx) = rxw; - else - *(u16 *)(dws->rx) = rxw; - } - dws->rx += dws->n_bytes; + dw_writew(dws, dr, *(u8 *)(dws->tx)); + ++dws->tx; + + wait_till_not_busy(dws); + return 1; +} + +static int u8_reader(struct dw_spi *dws) +{ + while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) + && (dws->rx < dws->rx_end)) { + *(u8 *)(dws->rx) = dw_readw(dws, dr); + ++dws->rx; + } + + wait_till_not_busy(dws); + return dws->rx == dws->rx_end; +} + +static int u16_writer(struct dw_spi *dws) +{ + if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) + || (dws->tx == dws->tx_end)) + return 0; + + dw_writew(dws, dr, *(u16 *)(dws->tx)); + dws->tx += 2; + + wait_till_not_busy(dws); + return 1; +} + +static int u16_reader(struct dw_spi *dws) +{ + u16 temp; + + while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) + && (dws->rx < dws->rx_end)) { + temp = dw_readw(dws, dr); + *(u16 *)(dws->rx) = temp; + dws->rx += 2; } + + wait_till_not_busy(dws); + return dws->rx == dws->rx_end; } static void *next_transfer(struct dw_spi *dws) @@ -295,7 +334,8 @@ static void giveback(struct dw_spi *dws) static void int_error_stop(struct dw_spi *dws, const char *msg) { - /* Stop the hw */ + /* Stop and reset hw */ + flush(dws); spi_enable_chip(dws, 0); dev_err(&dws->master->dev, "%s\n", msg); @@ -322,28 +362,35 @@ EXPORT_SYMBOL_GPL(dw_spi_xfer_done); static irqreturn_t interrupt_transfer(struct dw_spi *dws) { - u16 irq_status = dw_readw(dws, isr); + u16 irq_status, irq_mask = 0x3f; + u32 int_level = dws->fifo_len / 2; + u32 left; + irq_status = dw_readw(dws, isr) & irq_mask; /* Error handling */ if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { dw_readw(dws, txoicr); dw_readw(dws, rxoicr); dw_readw(dws, rxuicr); - int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun"); + int_error_stop(dws, "interrupt_transfer: fifo overrun"); return IRQ_HANDLED; } - dw_reader(dws); - if (dws->rx_end == dws->rx) { - spi_mask_intr(dws, SPI_INT_TXEI); - dw_spi_xfer_done(dws); - return IRQ_HANDLED; - } if (irq_status & SPI_INT_TXEI) { spi_mask_intr(dws, SPI_INT_TXEI); - dw_writer(dws); - /* Enable TX irq always, it will be disabled when RX finished */ - spi_umask_intr(dws, SPI_INT_TXEI); + + left = (dws->tx_end - dws->tx) / dws->n_bytes; + left = (left > int_level) ? int_level : left; + + while (left--) + dws->write(dws); + dws->read(dws); + + /* Re-enable the IRQ if there is still data left to tx */ + if (dws->tx_end > dws->tx) + spi_umask_intr(dws, SPI_INT_TXEI); + else + dw_spi_xfer_done(dws); } return IRQ_HANDLED; @@ -352,13 +399,15 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) static irqreturn_t dw_spi_irq(int irq, void *dev_id) { struct dw_spi *dws = dev_id; - u16 irq_status = dw_readw(dws, isr) & 0x3f; + u16 irq_status, irq_mask = 0x3f; + irq_status = dw_readw(dws, isr) & irq_mask; if (!irq_status) return IRQ_NONE; if (!dws->cur_msg) { spi_mask_intr(dws, SPI_INT_TXEI); + /* Never fail */ return IRQ_HANDLED; } @@ -368,11 +417,13 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id) /* Must be called inside pump_transfers() */ static void poll_transfer(struct dw_spi *dws) { - do { - dw_writer(dws); - dw_reader(dws); - cpu_relax(); - } while (dws->rx_end > dws->rx); + while (dws->write(dws)) + dws->read(dws); + /* + * There is a possibility that the last word of a transaction + * will be lost if data is not ready. Re-read to solve this issue. + */ + dws->read(dws); dw_spi_xfer_done(dws); } @@ -432,6 +483,8 @@ static void pump_transfers(unsigned long data) dws->tx_end = dws->tx + transfer->len; dws->rx = transfer->rx_buf; dws->rx_end = dws->rx + transfer->len; + dws->write = dws->tx ? chip->write : null_writer; + dws->read = dws->rx ? chip->read : null_reader; dws->cs_change = transfer->cs_change; dws->len = dws->cur_transfer->len; if (chip != dws->prev_chip) @@ -465,8 +518,20 @@ static void pump_transfers(unsigned long data) switch (bits) { case 8: + dws->n_bytes = 1; + dws->dma_width = 1; + dws->read = (dws->read != null_reader) ? + u8_reader : null_reader; + dws->write = (dws->write != null_writer) ? + u8_writer : null_writer; + break; case 16: - dws->n_bytes = dws->dma_width = bits >> 3; + dws->n_bytes = 2; + dws->dma_width = 2; + dws->read = (dws->read != null_reader) ? + u16_reader : null_reader; + dws->write = (dws->write != null_writer) ? + u16_writer : null_writer; break; default: printk(KERN_ERR "MRST SPI0: unsupported bits:" @@ -510,7 +575,7 @@ static void pump_transfers(unsigned long data) txint_level = dws->fifo_len / 2; txint_level = (templen > txint_level) ? txint_level : templen; - imask |= SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI; + imask |= SPI_INT_TXEI; dws->transfer_handler = interrupt_transfer; } @@ -668,9 +733,13 @@ static int dw_spi_setup(struct spi_device *spi) if (spi->bits_per_word <= 8) { chip->n_bytes = 1; chip->dma_width = 1; + chip->read = u8_reader; + chip->write = u8_writer; } else if (spi->bits_per_word <= 16) { chip->n_bytes = 2; chip->dma_width = 2; + chip->read = u16_reader; + chip->write = u16_writer; } else { /* Never take >16b case for MRST SPIC */ dev_err(&spi->dev, "invalid wordsize\n"); @@ -782,6 +851,7 @@ static void spi_hw_init(struct dw_spi *dws) spi_enable_chip(dws, 0); spi_mask_intr(dws, 0xff); spi_enable_chip(dws, 1); + flush(dws); /* * Try to detect the FIFO depth if not set by interface driver, diff --git a/trunk/drivers/spi/dw_spi.h b/trunk/drivers/spi/dw_spi.h index 7a5e78d2a5cb..b23e452adaf7 100644 --- a/trunk/drivers/spi/dw_spi.h +++ b/trunk/drivers/spi/dw_spi.h @@ -137,6 +137,8 @@ struct dw_spi { u8 max_bits_per_word; /* maxim is 16b */ u32 dma_width; int cs_change; + int (*write)(struct dw_spi *dws); + int (*read)(struct dw_spi *dws); irqreturn_t (*transfer_handler)(struct dw_spi *dws); void (*cs_control)(u32 command); diff --git a/trunk/drivers/spi/spi.c b/trunk/drivers/spi/spi.c index 2e13a14bba3f..82b9a428c323 100644 --- a/trunk/drivers/spi/spi.c +++ b/trunk/drivers/spi/spi.c @@ -1047,8 +1047,8 @@ static u8 *buf; * spi_{async,sync}() calls with dma-safe buffers. */ int spi_write_then_read(struct spi_device *spi, - const void *txbuf, unsigned n_tx, - void *rxbuf, unsigned n_rx) + const u8 *txbuf, unsigned n_tx, + u8 *rxbuf, unsigned n_rx) { static DEFINE_MUTEX(lock); diff --git a/trunk/drivers/spi/spi_nuc900.c b/trunk/drivers/spi/spi_nuc900.c index 3cd15f690f16..d5be18b3078c 100644 --- a/trunk/drivers/spi/spi_nuc900.c +++ b/trunk/drivers/spi/spi_nuc900.c @@ -463,7 +463,7 @@ static int __devexit nuc900_spi_remove(struct platform_device *dev) platform_set_drvdata(dev, NULL); - spi_bitbang_stop(&hw->bitbang); + spi_unregister_master(hw->master); clk_disable(hw->clk); clk_put(hw->clk); diff --git a/trunk/drivers/spi/spi_s3c24xx.c b/trunk/drivers/spi/spi_s3c24xx.c index 1a5fcabfd565..151a95e40653 100644 --- a/trunk/drivers/spi/spi_s3c24xx.c +++ b/trunk/drivers/spi/spi_s3c24xx.c @@ -668,7 +668,7 @@ static int __exit s3c24xx_spi_remove(struct platform_device *dev) platform_set_drvdata(dev, NULL); - spi_bitbang_stop(&hw->bitbang); + spi_unregister_master(hw->master); clk_disable(hw->clk); clk_put(hw->clk); diff --git a/trunk/drivers/spi/spi_sh.c b/trunk/drivers/spi/spi_sh.c index 9eedd71ad898..869a07d375d6 100644 --- a/trunk/drivers/spi/spi_sh.c +++ b/trunk/drivers/spi/spi_sh.c @@ -427,10 +427,10 @@ static int __devexit spi_sh_remove(struct platform_device *pdev) { struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev); - spi_unregister_master(ss->master); destroy_workqueue(ss->workqueue); free_irq(ss->irq, ss); iounmap(ss->addr); + spi_master_put(ss->master); return 0; } diff --git a/trunk/drivers/spi/spi_tegra.c b/trunk/drivers/spi/spi_tegra.c index 6c3aa6ecaade..891e5909038c 100644 --- a/trunk/drivers/spi/spi_tegra.c +++ b/trunk/drivers/spi/spi_tegra.c @@ -578,7 +578,6 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev) master = dev_get_drvdata(&pdev->dev); tspi = spi_master_get_devdata(master); - spi_unregister_master(master); tegra_dma_free_channel(tspi->rx_dma); dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, @@ -587,6 +586,7 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev) clk_put(tspi->clk); iounmap(tspi->base); + spi_master_put(master); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(r->start, (r->end - r->start) + 1); diff --git a/trunk/drivers/spi/xilinx_spi.c b/trunk/drivers/spi/xilinx_spi.c index 4d2c75df886c..c69c6f2c2c5c 100644 --- a/trunk/drivers/spi/xilinx_spi.c +++ b/trunk/drivers/spi/xilinx_spi.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -470,7 +471,7 @@ static int __devinit xilinx_spi_probe(struct platform_device *dev) struct spi_master *master; u8 i; - pdata = dev->dev.platform_data; + pdata = mfd_get_data(dev); if (pdata) { num_cs = pdata->num_chipselect; little_endian = pdata->little_endian; diff --git a/trunk/drivers/staging/generic_serial/rio/rioinit.c b/trunk/drivers/staging/generic_serial/rio/rioinit.c index fb62b383f1de..24a282bb89d4 100644 --- a/trunk/drivers/staging/generic_serial/rio/rioinit.c +++ b/trunk/drivers/staging/generic_serial/rio/rioinit.c @@ -381,7 +381,7 @@ struct rioVersion *RIOVersid(void) { strlcpy(stVersion.version, "RIO driver for linux V1.0", sizeof(stVersion.version)); - strlcpy(stVersion.buildDate, "Aug 15 2010", + strlcpy(stVersion.buildDate, __DATE__, sizeof(stVersion.buildDate)); return &stVersion; diff --git a/trunk/drivers/tty/cyclades.c b/trunk/drivers/tty/cyclades.c index c0e8f2eeb886..bfa05e801823 100644 --- a/trunk/drivers/tty/cyclades.c +++ b/trunk/drivers/tty/cyclades.c @@ -4096,7 +4096,8 @@ static int __init cy_init(void) if (!cy_serial_driver) goto err; - printk(KERN_INFO "Cyclades driver " CY_VERSION "\n"); + printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n", + __DATE__, __TIME__); /* Initialize the tty_driver structure */ diff --git a/trunk/drivers/tty/nozomi.c b/trunk/drivers/tty/nozomi.c index fd347ff34d07..b1aecc7bb32a 100644 --- a/trunk/drivers/tty/nozomi.c +++ b/trunk/drivers/tty/nozomi.c @@ -61,7 +61,8 @@ #include -#define VERSION_STRING DRIVER_DESC " 2.1d" +#define VERSION_STRING DRIVER_DESC " 2.1d (build date: " \ + __DATE__ " " __TIME__ ")" /* Macros definitions */ diff --git a/trunk/drivers/tty/serial/m32r_sio.c b/trunk/drivers/tty/serial/m32r_sio.c index 84db7321cce8..bea5c215460c 100644 --- a/trunk/drivers/tty/serial/m32r_sio.c +++ b/trunk/drivers/tty/serial/m32r_sio.c @@ -907,10 +907,9 @@ static int m32r_sio_request_port(struct uart_port *port) return ret; } -static void m32r_sio_config_port(struct uart_port *port, int unused) +static void m32r_sio_config_port(struct uart_port *port, int flags) { struct uart_sio_port *up = (struct uart_sio_port *)port; - unsigned long flags; spin_lock_irqsave(&up->port.lock, flags); diff --git a/trunk/drivers/usb/otg/twl6030-usb.c b/trunk/drivers/usb/otg/twl6030-usb.c index cfb5aa72b196..3f2e07011a48 100644 --- a/trunk/drivers/usb/otg/twl6030-usb.c +++ b/trunk/drivers/usb/otg/twl6030-usb.c @@ -100,7 +100,6 @@ struct twl6030_usb { u8 linkstat; u8 asleep; bool irq_enabled; - unsigned long features; }; #define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg) @@ -205,12 +204,6 @@ static int twl6030_start_srp(struct otg_transceiver *x) static int twl6030_usb_ldo_init(struct twl6030_usb *twl) { - char *regulator_name; - - if (twl->features & TWL6025_SUBCLASS) - regulator_name = "ldousb"; - else - regulator_name = "vusb"; /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); @@ -221,7 +214,7 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl) /* Program MISC2 register and set bit VUSB_IN_VBAT */ twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); - twl->usb3v3 = regulator_get(twl->dev, regulator_name); + twl->usb3v3 = regulator_get(twl->dev, "vusb"); if (IS_ERR(twl->usb3v3)) return -ENODEV; @@ -416,7 +409,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) twl->dev = &pdev->dev; twl->irq1 = platform_get_irq(pdev, 0); twl->irq2 = platform_get_irq(pdev, 1); - twl->features = pdata->features; twl->otg.dev = twl->dev; twl->otg.label = "twl6030"; twl->otg.set_host = twl6030_set_host; diff --git a/trunk/drivers/video/backlight/88pm860x_bl.c b/trunk/drivers/video/backlight/88pm860x_bl.c index c04b94da81f7..c8b520e9a11a 100644 --- a/trunk/drivers/video/backlight/88pm860x_bl.c +++ b/trunk/drivers/video/backlight/88pm860x_bl.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #define MAX_BRIGHTNESS (0xFF) @@ -167,6 +168,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) struct pm860x_backlight_pdata *pdata = NULL; struct pm860x_backlight_data *data; struct backlight_device *bl; + struct mfd_cell *cell; struct resource *res; struct backlight_properties props; unsigned char value; @@ -179,7 +181,10 @@ static int pm860x_backlight_probe(struct platform_device *pdev) return -EINVAL; } - pdata = pdev->dev.platform_data; + cell = pdev->dev.platform_data; + if (cell == NULL) + return -ENODEV; + pdata = cell->mfd_data; if (pdata == NULL) { dev_err(&pdev->dev, "platform data isn't assigned to " "backlight\n"); diff --git a/trunk/drivers/video/mb862xx/mb862xxfbdrv.c b/trunk/drivers/video/mb862xx/mb862xxfbdrv.c index f70bd63b0187..ea39336addfb 100644 --- a/trunk/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/trunk/drivers/video/mb862xx/mb862xxfbdrv.c @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/trunk/drivers/video/omap/Makefile b/trunk/drivers/video/omap/Makefile index 25db55696e14..49226a1b909e 100644 --- a/trunk/drivers/video/omap/Makefile +++ b/trunk/drivers/video/omap/Makefile @@ -30,6 +30,7 @@ objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o +objs-y$(CONFIG_MACH_OMAP2EVM) += lcd_omap2evm.o objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o diff --git a/trunk/drivers/video/omap/lcd_omap2evm.c b/trunk/drivers/video/omap/lcd_omap2evm.c new file mode 100644 index 000000000000..7e7a65c08452 --- /dev/null +++ b/trunk/drivers/video/omap/lcd_omap2evm.c @@ -0,0 +1,192 @@ +/* + * LCD panel support for the MISTRAL OMAP2EVM board + * + * Author: Arun C + * + * Derived from drivers/video/omap/lcd_omap3evm.c + * Derived from drivers/video/omap/lcd-apollon.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include +#include + +#include "omapfb.h" + +#define LCD_PANEL_ENABLE_GPIO 154 +#define LCD_PANEL_LR 128 +#define LCD_PANEL_UD 129 +#define LCD_PANEL_INI 152 +#define LCD_PANEL_QVGA 148 +#define LCD_PANEL_RESB 153 + +#define TWL_LED_LEDEN 0x00 +#define TWL_PWMA_PWMAON 0x00 +#define TWL_PWMA_PWMAOFF 0x01 + +static unsigned int bklight_level; + +static int omap2evm_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable"); + gpio_request(LCD_PANEL_LR, "LCD lr"); + gpio_request(LCD_PANEL_UD, "LCD ud"); + gpio_request(LCD_PANEL_INI, "LCD ini"); + gpio_request(LCD_PANEL_QVGA, "LCD qvga"); + gpio_request(LCD_PANEL_RESB, "LCD resb"); + + gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1); + gpio_direction_output(LCD_PANEL_RESB, 1); + gpio_direction_output(LCD_PANEL_INI, 1); + gpio_direction_output(LCD_PANEL_QVGA, 0); + gpio_direction_output(LCD_PANEL_LR, 1); + gpio_direction_output(LCD_PANEL_UD, 1); + + twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN); + twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON); + twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF); + bklight_level = 100; + + return 0; +} + +static void omap2evm_panel_cleanup(struct lcd_panel *panel) +{ + gpio_free(LCD_PANEL_RESB); + gpio_free(LCD_PANEL_QVGA); + gpio_free(LCD_PANEL_INI); + gpio_free(LCD_PANEL_UD); + gpio_free(LCD_PANEL_LR); + gpio_free(LCD_PANEL_ENABLE_GPIO); +} + +static int omap2evm_panel_enable(struct lcd_panel *panel) +{ + gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0); + return 0; +} + +static void omap2evm_panel_disable(struct lcd_panel *panel) +{ + gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1); +} + +static unsigned long omap2evm_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +static int omap2evm_bklight_setlevel(struct lcd_panel *panel, + unsigned int level) +{ + u8 c; + if ((level >= 0) && (level <= 100)) { + c = (125 * (100 - level)) / 100 + 2; + twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF); + bklight_level = level; + } + return 0; +} + +static unsigned int omap2evm_bklight_getlevel(struct lcd_panel *panel) +{ + return bklight_level; +} + +static unsigned int omap2evm_bklight_getmaxlevel(struct lcd_panel *panel) +{ + return 100; +} + +struct lcd_panel omap2evm_panel = { + .name = "omap2evm", + .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | + OMAP_LCDC_INV_HSYNC, + + .bpp = 16, + .data_lines = 18, + .x_res = 480, + .y_res = 640, + .hsw = 3, + .hfp = 0, + .hbp = 28, + .vsw = 2, + .vfp = 1, + .vbp = 0, + + .pixel_clock = 20000, + + .init = omap2evm_panel_init, + .cleanup = omap2evm_panel_cleanup, + .enable = omap2evm_panel_enable, + .disable = omap2evm_panel_disable, + .get_caps = omap2evm_panel_get_caps, + .set_bklight_level = omap2evm_bklight_setlevel, + .get_bklight_level = omap2evm_bklight_getlevel, + .get_bklight_max = omap2evm_bklight_getmaxlevel, +}; + +static int omap2evm_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&omap2evm_panel); + return 0; +} + +static int omap2evm_panel_remove(struct platform_device *pdev) +{ + return 0; +} + +static int omap2evm_panel_suspend(struct platform_device *pdev, + pm_message_t mesg) +{ + return 0; +} + +static int omap2evm_panel_resume(struct platform_device *pdev) +{ + return 0; +} + +struct platform_driver omap2evm_panel_driver = { + .probe = omap2evm_panel_probe, + .remove = omap2evm_panel_remove, + .suspend = omap2evm_panel_suspend, + .resume = omap2evm_panel_resume, + .driver = { + .name = "omap2evm_lcd", + .owner = THIS_MODULE, + }, +}; + +static int __init omap2evm_panel_drv_init(void) +{ + return platform_driver_register(&omap2evm_panel_driver); +} + +static void __exit omap2evm_panel_drv_exit(void) +{ + platform_driver_unregister(&omap2evm_panel_driver); +} + +module_init(omap2evm_panel_drv_init); +module_exit(omap2evm_panel_drv_exit); diff --git a/trunk/drivers/video/tmiofb.c b/trunk/drivers/video/tmiofb.c index cd1c4dcef8fd..0c341d739604 100644 --- a/trunk/drivers/video/tmiofb.c +++ b/trunk/drivers/video/tmiofb.c @@ -250,7 +250,7 @@ static irqreturn_t tmiofb_irq(int irq, void *__info) */ static int tmiofb_hw_stop(struct platform_device *dev) { - struct tmio_fb_data *data = dev->dev.platform_data; + struct tmio_fb_data *data = mfd_get_data(dev); struct fb_info *info = platform_get_drvdata(dev); struct tmiofb_par *par = info->par; @@ -311,7 +311,7 @@ static int tmiofb_hw_init(struct platform_device *dev) */ static void tmiofb_hw_mode(struct platform_device *dev) { - struct tmio_fb_data *data = dev->dev.platform_data; + struct tmio_fb_data *data = mfd_get_data(dev); struct fb_info *info = platform_get_drvdata(dev); struct fb_videomode *mode = info->mode; struct tmiofb_par *par = info->par; @@ -557,7 +557,8 @@ static int tmiofb_ioctl(struct fb_info *fbi, static struct fb_videomode * tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var) { - struct tmio_fb_data *data = info->device->platform_data; + struct tmio_fb_data *data = + mfd_get_data(to_platform_device(info->device)); struct fb_videomode *best = NULL; int i; @@ -577,7 +578,8 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct fb_videomode *mode; - struct tmio_fb_data *data = info->device->platform_data; + struct tmio_fb_data *data = + mfd_get_data(to_platform_device(info->device)); mode = tmiofb_find_mode(info, var); if (!mode || var->bits_per_pixel > 16) @@ -678,7 +680,7 @@ static struct fb_ops tmiofb_ops = { static int __devinit tmiofb_probe(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); - struct tmio_fb_data *data = dev->dev.platform_data; + struct tmio_fb_data *data = mfd_get_data(dev); struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1); struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0); struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2); diff --git a/trunk/drivers/video/via/via-gpio.c b/trunk/drivers/video/via/via-gpio.c index ab5341814c74..c2a0a1cfd3b3 100644 --- a/trunk/drivers/video/via/via-gpio.c +++ b/trunk/drivers/video/via/via-gpio.c @@ -145,7 +145,7 @@ static int via_gpio_get(struct gpio_chip *chip, unsigned int nr) } -static struct viafb_gpio_cfg viafb_gpio_config = { +static struct viafb_gpio_cfg gpio_config = { .gpio_chip = { .label = "VIAFB onboard GPIO", .owner = THIS_MODULE, @@ -183,8 +183,8 @@ static int viafb_gpio_resume(void *private) { int i; - for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2) - viafb_gpio_enable(viafb_gpio_config.active_gpios[i]); + for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2) + viafb_gpio_enable(gpio_config.active_gpios[i]); return 0; } @@ -201,9 +201,9 @@ int viafb_gpio_lookup(const char *name) { int i; - for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i++) - if (!strcmp(name, viafb_gpio_config.active_gpios[i]->vg_name)) - return viafb_gpio_config.gpio_chip.base + i; + for (i = 0; i < gpio_config.gpio_chip.ngpio; i++) + if (!strcmp(name, gpio_config.active_gpios[i]->vg_name)) + return gpio_config.gpio_chip.base + i; return -1; } EXPORT_SYMBOL_GPL(viafb_gpio_lookup); @@ -229,15 +229,14 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev) for (gpio = viafb_all_gpios; gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++) if (gpio->vg_port_index == port_cfg[i].ioport_index) { - viafb_gpio_config.active_gpios[ngpio] = gpio; - viafb_gpio_config.gpio_names[ngpio] = - gpio->vg_name; + gpio_config.active_gpios[ngpio] = gpio; + gpio_config.gpio_names[ngpio] = gpio->vg_name; ngpio++; } } - viafb_gpio_config.gpio_chip.ngpio = ngpio; - viafb_gpio_config.gpio_chip.names = viafb_gpio_config.gpio_names; - viafb_gpio_config.vdev = vdev; + gpio_config.gpio_chip.ngpio = ngpio; + gpio_config.gpio_chip.names = gpio_config.gpio_names; + gpio_config.vdev = vdev; if (ngpio == 0) { printk(KERN_INFO "viafb: no GPIOs configured\n"); return 0; @@ -246,18 +245,18 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev) * Enable the ports. They come in pairs, with a single * enable bit for both. */ - spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags); + spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); for (i = 0; i < ngpio; i += 2) - viafb_gpio_enable(viafb_gpio_config.active_gpios[i]); - spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags); + viafb_gpio_enable(gpio_config.active_gpios[i]); + spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); /* * Get registered. */ - viafb_gpio_config.gpio_chip.base = -1; /* Dynamic */ - ret = gpiochip_add(&viafb_gpio_config.gpio_chip); + gpio_config.gpio_chip.base = -1; /* Dynamic */ + ret = gpiochip_add(&gpio_config.gpio_chip); if (ret) { printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret); - viafb_gpio_config.gpio_chip.ngpio = 0; + gpio_config.gpio_chip.ngpio = 0; } #ifdef CONFIG_PM viafb_pm_register(&viafb_gpio_pm_hooks); @@ -278,8 +277,8 @@ static int viafb_gpio_remove(struct platform_device *platdev) /* * Get unregistered. */ - if (viafb_gpio_config.gpio_chip.ngpio > 0) { - ret = gpiochip_remove(&viafb_gpio_config.gpio_chip); + if (gpio_config.gpio_chip.ngpio > 0) { + ret = gpiochip_remove(&gpio_config.gpio_chip); if (ret) { /* Somebody still using it? */ printk(KERN_ERR "Viafb: GPIO remove failed\n"); return ret; @@ -288,11 +287,11 @@ static int viafb_gpio_remove(struct platform_device *platdev) /* * Disable the ports. */ - spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags); - for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2) - viafb_gpio_disable(viafb_gpio_config.active_gpios[i]); - viafb_gpio_config.gpio_chip.ngpio = 0; - spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags); + spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); + for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2) + viafb_gpio_disable(gpio_config.active_gpios[i]); + gpio_config.gpio_chip.ngpio = 0; + spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); return ret; } diff --git a/trunk/drivers/w1/masters/Kconfig b/trunk/drivers/w1/masters/Kconfig index 00d615d7aa21..7c608c5ccf84 100644 --- a/trunk/drivers/w1/masters/Kconfig +++ b/trunk/drivers/w1/masters/Kconfig @@ -42,7 +42,7 @@ config W1_MASTER_MXC config W1_MASTER_DS1WM tristate "Maxim DS1WM 1-wire busmaster" - depends on W1 + depends on W1 && ARM && HAVE_CLK help Say Y here to enable the DS1WM 1-wire driver, such as that in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like diff --git a/trunk/drivers/w1/masters/ds1wm.c b/trunk/drivers/w1/masters/ds1wm.c index ad57593d224a..2f4fa02744a5 100644 --- a/trunk/drivers/w1/masters/ds1wm.c +++ b/trunk/drivers/w1/masters/ds1wm.c @@ -33,7 +33,6 @@ #define DS1WM_INT 0x02 /* R/W interrupt status */ #define DS1WM_INT_EN 0x03 /* R/W interrupt enable */ #define DS1WM_CLKDIV 0x04 /* R/W 5 bits of divisor and pre-scale */ -#define DS1WM_CNTRL 0x05 /* R/W master control register (not used yet) */ #define DS1WM_CMD_1W_RESET (1 << 0) /* force reset on 1-wire bus */ #define DS1WM_CMD_SRA (1 << 1) /* enable Search ROM accelerator mode */ @@ -57,7 +56,6 @@ #define DS1WM_INTEN_ERSRF (1 << 5) /* enable rx shift register full int */ #define DS1WM_INTEN_DQO (1 << 6) /* enable direct bus driving ops */ -#define DS1WM_INTEN_NOT_IAS (~DS1WM_INTEN_IAS) /* all but INTR active state */ #define DS1WM_TIMEOUT (HZ * 5) @@ -65,50 +63,41 @@ static struct { unsigned long freq; unsigned long divisor; } freq[] = { - { 1000000, 0x80 }, - { 2000000, 0x84 }, - { 3000000, 0x81 }, - { 4000000, 0x88 }, - { 5000000, 0x82 }, - { 6000000, 0x85 }, - { 7000000, 0x83 }, - { 8000000, 0x8c }, - { 10000000, 0x86 }, - { 12000000, 0x89 }, - { 14000000, 0x87 }, - { 16000000, 0x90 }, - { 20000000, 0x8a }, - { 24000000, 0x8d }, - { 28000000, 0x8b }, - { 32000000, 0x94 }, - { 40000000, 0x8e }, - { 48000000, 0x91 }, - { 56000000, 0x8f }, - { 64000000, 0x98 }, - { 80000000, 0x92 }, - { 96000000, 0x95 }, - { 112000000, 0x93 }, - { 128000000, 0x9c }, -/* you can continue this table, consult the OPERATION - CLOCK DIVISOR - section of the ds1wm spec sheet. */ + { 4000000, 0x8 }, + { 5000000, 0x2 }, + { 6000000, 0x5 }, + { 7000000, 0x3 }, + { 8000000, 0xc }, + { 10000000, 0x6 }, + { 12000000, 0x9 }, + { 14000000, 0x7 }, + { 16000000, 0x10 }, + { 20000000, 0xa }, + { 24000000, 0xd }, + { 28000000, 0xb }, + { 32000000, 0x14 }, + { 40000000, 0xe }, + { 48000000, 0x11 }, + { 56000000, 0xf }, + { 64000000, 0x18 }, + { 80000000, 0x12 }, + { 96000000, 0x15 }, + { 112000000, 0x13 }, + { 128000000, 0x1c }, }; struct ds1wm_data { - void __iomem *map; - int bus_shift; /* # of shifts to calc register offsets */ + void __iomem *map; + int bus_shift; /* # of shifts to calc register offsets */ struct platform_device *pdev; - const struct mfd_cell *cell; - int irq; - int slave_present; - void *reset_complete; - void *read_complete; - void *write_complete; - int read_error; - /* last byte received */ - u8 read_byte; - /* byte to write that makes all intr disabled, */ - /* considering active_state (IAS) (optimization) */ - u8 int_en_reg_none; + const struct mfd_cell *cell; + int irq; + int active_high; + int slave_present; + void *reset_complete; + void *read_complete; + void *write_complete; + u8 read_byte; /* last byte received */ }; static inline void ds1wm_write_register(struct ds1wm_data *ds1wm_data, u32 reg, @@ -126,39 +115,23 @@ static inline u8 ds1wm_read_register(struct ds1wm_data *ds1wm_data, u32 reg) static irqreturn_t ds1wm_isr(int isr, void *data) { struct ds1wm_data *ds1wm_data = data; - u8 intr; - u8 inten = ds1wm_read_register(ds1wm_data, DS1WM_INT_EN); - /* if no bits are set in int enable register (except the IAS) - than go no further, reading the regs below has side effects */ - if (!(inten & DS1WM_INTEN_NOT_IAS)) - return IRQ_NONE; - - ds1wm_write_register(ds1wm_data, - DS1WM_INT_EN, ds1wm_data->int_en_reg_none); - - /* this read action clears the INTR and certain flags in ds1wm */ - intr = ds1wm_read_register(ds1wm_data, DS1WM_INT); + u8 intr = ds1wm_read_register(ds1wm_data, DS1WM_INT); ds1wm_data->slave_present = (intr & DS1WM_INT_PDR) ? 0 : 1; - if ((intr & DS1WM_INT_TSRE) && ds1wm_data->write_complete) { - inten &= ~DS1WM_INTEN_ETMT; + if ((intr & DS1WM_INT_PD) && ds1wm_data->reset_complete) + complete(ds1wm_data->reset_complete); + + if ((intr & DS1WM_INT_TSRE) && ds1wm_data->write_complete) complete(ds1wm_data->write_complete); - } + if (intr & DS1WM_INT_RBF) { - /* this read clears the RBF flag */ ds1wm_data->read_byte = ds1wm_read_register(ds1wm_data, - DS1WM_DATA); - inten &= ~DS1WM_INTEN_ERBF; + DS1WM_DATA); if (ds1wm_data->read_complete) complete(ds1wm_data->read_complete); } - if ((intr & DS1WM_INT_PD) && ds1wm_data->reset_complete) { - inten &= ~DS1WM_INTEN_EPD; - complete(ds1wm_data->reset_complete); - } - ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, inten); return IRQ_HANDLED; } @@ -169,19 +142,33 @@ static int ds1wm_reset(struct ds1wm_data *ds1wm_data) ds1wm_data->reset_complete = &reset_done; - /* enable Presence detect only */ ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, DS1WM_INTEN_EPD | - ds1wm_data->int_en_reg_none); + (ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0)); ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_1W_RESET); timeleft = wait_for_completion_timeout(&reset_done, DS1WM_TIMEOUT); ds1wm_data->reset_complete = NULL; if (!timeleft) { - dev_err(&ds1wm_data->pdev->dev, "reset failed, timed out\n"); + dev_err(&ds1wm_data->pdev->dev, "reset failed\n"); return 1; } + /* Wait for the end of the reset. According to the specs, the time + * from when the interrupt is asserted to the end of the reset is: + * tRSTH - tPDH - tPDL - tPDI + * 625 us - 60 us - 240 us - 100 ns = 324.9 us + * + * We'll wait a bit longer just to be sure. + * Was udelay(500), but if it is going to busywait the cpu that long, + * might as well come back later. + */ + msleep(1); + + ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, + DS1WM_INTEN_ERBF | DS1WM_INTEN_ETMT | DS1WM_INTEN_EPD | + (ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0)); + if (!ds1wm_data->slave_present) { dev_dbg(&ds1wm_data->pdev->dev, "reset: no devices found\n"); return 1; @@ -192,47 +179,26 @@ static int ds1wm_reset(struct ds1wm_data *ds1wm_data) static int ds1wm_write(struct ds1wm_data *ds1wm_data, u8 data) { - unsigned long timeleft; DECLARE_COMPLETION_ONSTACK(write_done); ds1wm_data->write_complete = &write_done; - ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, - ds1wm_data->int_en_reg_none | DS1WM_INTEN_ETMT); - ds1wm_write_register(ds1wm_data, DS1WM_DATA, data); - timeleft = wait_for_completion_timeout(&write_done, DS1WM_TIMEOUT); - + wait_for_completion_timeout(&write_done, DS1WM_TIMEOUT); ds1wm_data->write_complete = NULL; - if (!timeleft) { - dev_err(&ds1wm_data->pdev->dev, "write failed, timed out\n"); - return -ETIMEDOUT; - } return 0; } -static u8 ds1wm_read(struct ds1wm_data *ds1wm_data, unsigned char write_data) +static int ds1wm_read(struct ds1wm_data *ds1wm_data, unsigned char write_data) { - unsigned long timeleft; - u8 intEnable = DS1WM_INTEN_ERBF | ds1wm_data->int_en_reg_none; DECLARE_COMPLETION_ONSTACK(read_done); - - ds1wm_read_register(ds1wm_data, DS1WM_DATA); - ds1wm_data->read_complete = &read_done; - ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, intEnable); - - ds1wm_write_register(ds1wm_data, DS1WM_DATA, write_data); - timeleft = wait_for_completion_timeout(&read_done, DS1WM_TIMEOUT); + ds1wm_write(ds1wm_data, write_data); + wait_for_completion_timeout(&read_done, DS1WM_TIMEOUT); ds1wm_data->read_complete = NULL; - if (!timeleft) { - dev_err(&ds1wm_data->pdev->dev, "read failed, timed out\n"); - ds1wm_data->read_error = -ETIMEDOUT; - return 0xFF; - } - ds1wm_data->read_error = 0; + return ds1wm_data->read_byte; } @@ -240,8 +206,8 @@ static int ds1wm_find_divisor(int gclk) { int i; - for (i = ARRAY_SIZE(freq)-1; i >= 0; --i) - if (gclk >= freq[i].freq) + for (i = 0; i < ARRAY_SIZE(freq); i++) + if (gclk <= freq[i].freq) return freq[i].divisor; return 0; @@ -250,14 +216,12 @@ static int ds1wm_find_divisor(int gclk) static void ds1wm_up(struct ds1wm_data *ds1wm_data) { int divisor; - struct ds1wm_driver_data *plat = ds1wm_data->pdev->dev.platform_data; + struct ds1wm_driver_data *plat = mfd_get_data(ds1wm_data->pdev); if (ds1wm_data->cell->enable) ds1wm_data->cell->enable(ds1wm_data->pdev); divisor = ds1wm_find_divisor(plat->clock_rate); - dev_dbg(&ds1wm_data->pdev->dev, - "found divisor 0x%x for clock %d\n", divisor, plat->clock_rate); if (divisor == 0) { dev_err(&ds1wm_data->pdev->dev, "no suitable divisor for %dHz clock\n", @@ -278,7 +242,7 @@ static void ds1wm_down(struct ds1wm_data *ds1wm_data) /* Disable interrupts. */ ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, - ds1wm_data->int_en_reg_none); + ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0); if (ds1wm_data->cell->disable) ds1wm_data->cell->disable(ds1wm_data->pdev); @@ -315,121 +279,41 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, { struct ds1wm_data *ds1wm_data = data; int i; - int ms_discrep_bit = -1; - u64 r = 0; /* holds the progress of the search */ - u64 r_prime, d; - unsigned slaves_found = 0; - unsigned int pass = 0; - - dev_dbg(&ds1wm_data->pdev->dev, "search begin\n"); - while (true) { - ++pass; - if (pass > 100) { - dev_dbg(&ds1wm_data->pdev->dev, - "too many attempts (100), search aborted\n"); - return; - } - - if (ds1wm_reset(ds1wm_data)) { - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d reset error (or no slaves)\n", pass); - break; - } - - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d r : %0#18llx writing SEARCH_ROM\n", pass, r); - ds1wm_write(ds1wm_data, search_type); - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d entering ASM\n", pass); - ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_SRA); - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d begining nibble loop\n", pass); - - r_prime = 0; - d = 0; - /* we work one nibble at a time */ - /* each nibble is interleaved to form a byte */ - for (i = 0; i < 16; i++) { - - unsigned char resp, _r, _r_prime, _d; - - _r = (r >> (4*i)) & 0xf; - _r = ((_r & 0x1) << 1) | - ((_r & 0x2) << 2) | - ((_r & 0x4) << 3) | - ((_r & 0x8) << 4); - - /* writes _r, then reads back: */ - resp = ds1wm_read(ds1wm_data, _r); - - if (ds1wm_data->read_error) { - dev_err(&ds1wm_data->pdev->dev, - "pass: %d nibble: %d read error\n", pass, i); - break; - } - - _r_prime = ((resp & 0x02) >> 1) | - ((resp & 0x08) >> 2) | - ((resp & 0x20) >> 3) | - ((resp & 0x80) >> 4); - - _d = ((resp & 0x01) >> 0) | - ((resp & 0x04) >> 1) | - ((resp & 0x10) >> 2) | - ((resp & 0x40) >> 3); - - r_prime |= (unsigned long long) _r_prime << (i * 4); - d |= (unsigned long long) _d << (i * 4); - - } - if (ds1wm_data->read_error) { - dev_err(&ds1wm_data->pdev->dev, - "pass: %d read error, retrying\n", pass); - break; - } - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d r\': %0#18llx d:%0#18llx\n", - pass, r_prime, d); - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d nibble loop complete, exiting ASM\n", pass); - ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA); - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d resetting bus\n", pass); - ds1wm_reset(ds1wm_data); - if ((r_prime & ((u64)1 << 63)) && (d & ((u64)1 << 63))) { - dev_err(&ds1wm_data->pdev->dev, - "pass: %d bus error, retrying\n", pass); - continue; /* start over */ - } - - - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d found %0#18llx\n", pass, r_prime); - slave_found(master_dev, r_prime); - ++slaves_found; - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d complete, preparing next pass\n", pass); - - /* any discrepency found which we already choose the - '1' branch is now is now irrelevant we reveal the - next branch with this: */ - d &= ~r; - /* find last bit set, i.e. the most signif. bit set */ - ms_discrep_bit = fls64(d) - 1; - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d new d:%0#18llx MS discrep bit:%d\n", - pass, d, ms_discrep_bit); - - /* prev_ms_discrep_bit = ms_discrep_bit; - prepare for next ROM search: */ - if (ms_discrep_bit == -1) - break; - - r = (r & ~(~0ull << (ms_discrep_bit))) | 1 << ms_discrep_bit; - } /* end while true */ - dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d total: %d search done ms d bit pos: %d\n", pass, - slaves_found, ms_discrep_bit); + unsigned long long rom_id; + + /* XXX We need to iterate for multiple devices per the DS1WM docs. + * See http://www.maxim-ic.com/appnotes.cfm/appnote_number/120. */ + if (ds1wm_reset(ds1wm_data)) + return; + + ds1wm_write(ds1wm_data, search_type); + ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_SRA); + + for (rom_id = 0, i = 0; i < 16; i++) { + + unsigned char resp, r, d; + + resp = ds1wm_read(ds1wm_data, 0x00); + + r = ((resp & 0x02) >> 1) | + ((resp & 0x08) >> 2) | + ((resp & 0x20) >> 3) | + ((resp & 0x80) >> 4); + + d = ((resp & 0x01) >> 0) | + ((resp & 0x04) >> 1) | + ((resp & 0x10) >> 2) | + ((resp & 0x40) >> 3); + + rom_id |= (unsigned long long) r << (i * 4); + + } + dev_dbg(&ds1wm_data->pdev->dev, "found 0x%08llX\n", rom_id); + + ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA); + ds1wm_reset(ds1wm_data); + + slave_found(master_dev, rom_id); } /* --------------------------------------------------------------------- */ @@ -467,21 +351,13 @@ static int ds1wm_probe(struct platform_device *pdev) ret = -ENOMEM; goto err0; } + plat = mfd_get_data(pdev); /* calculate bus shift from mem resource */ ds1wm_data->bus_shift = resource_size(res) >> 3; ds1wm_data->pdev = pdev; ds1wm_data->cell = mfd_get_cell(pdev); - if (!ds1wm_data->cell) { - ret = -ENODEV; - goto err1; - } - plat = pdev->dev.platform_data; - if (!plat) { - ret = -ENODEV; - goto err1; - } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { @@ -489,15 +365,15 @@ static int ds1wm_probe(struct platform_device *pdev) goto err1; } ds1wm_data->irq = res->start; - ds1wm_data->int_en_reg_none = (plat->active_high ? DS1WM_INTEN_IAS : 0); + ds1wm_data->active_high = plat->active_high; if (res->flags & IORESOURCE_IRQ_HIGHEDGE) irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING); if (res->flags & IORESOURCE_IRQ_LOWEDGE) irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING); - ret = request_irq(ds1wm_data->irq, ds1wm_isr, - IRQF_DISABLED | IRQF_SHARED, "ds1wm", ds1wm_data); + ret = request_irq(ds1wm_data->irq, ds1wm_isr, IRQF_DISABLED, + "ds1wm", ds1wm_data); if (ret) goto err1; @@ -584,6 +460,5 @@ module_exit(ds1wm_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Szabolcs Gyurko , " - "Matt Reimer ," - "Jean-Francois Dagenais "); + "Matt Reimer "); MODULE_DESCRIPTION("DS1WM w1 busmaster driver"); diff --git a/trunk/drivers/w1/slaves/Kconfig b/trunk/drivers/w1/slaves/Kconfig index d0cb01b42012..f0c909625bd1 100644 --- a/trunk/drivers/w1/slaves/Kconfig +++ b/trunk/drivers/w1/slaves/Kconfig @@ -16,13 +16,6 @@ config W1_SLAVE_SMEM Say Y here if you want to connect 1-wire simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. -config W1_SLAVE_DS2408 - tristate "8-Channel Addressable Switch (IO Expander) 0x29 family support (DS2408)" - help - Say Y here if you want to use a 1-wire - - DS2408 8-Channel Addressable Switch device support - config W1_SLAVE_DS2423 tristate "Counter 1-wire device (DS2423)" select CRC16 @@ -68,19 +61,6 @@ config W1_SLAVE_DS2760 If you are unsure, say N. -config W1_SLAVE_DS2780 - tristate "Dallas 2780 battery monitor chip" - depends on W1 - help - If you enable this you will have the DS2780 battery monitor - chip support. - - The battery monitor chip is used in many batteries/devices - as the one who is responsible for charging/discharging/monitoring - Li+ batteries. - - If you are unsure, say N. - config W1_SLAVE_BQ27000 tristate "BQ27000 slave support" depends on W1 diff --git a/trunk/drivers/w1/slaves/Makefile b/trunk/drivers/w1/slaves/Makefile index 1f31e9fb0b25..3c76350a24f7 100644 --- a/trunk/drivers/w1/slaves/Makefile +++ b/trunk/drivers/w1/slaves/Makefile @@ -4,10 +4,8 @@ obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o -obj-$(CONFIG_W1_SLAVE_DS2408) += w1_ds2408.o obj-$(CONFIG_W1_SLAVE_DS2423) += w1_ds2423.o obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o -obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o diff --git a/trunk/drivers/w1/slaves/w1_ds2408.c b/trunk/drivers/w1/slaves/w1_ds2408.c deleted file mode 100644 index c37781899d90..000000000000 --- a/trunk/drivers/w1/slaves/w1_ds2408.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * w1_ds2408.c - w1 family 29 (DS2408) driver - * - * Copyright (c) 2010 Jean-Francois Dagenais - * - * This source code is licensed under the GNU General Public License, - * Version 2. See the file COPYING for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "../w1.h" -#include "../w1_int.h" -#include "../w1_family.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jean-Francois Dagenais "); -MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO"); - - -#define W1_F29_RETRIES 3 - -#define W1_F29_REG_LOGIG_STATE 0x88 /* R */ -#define W1_F29_REG_OUTPUT_LATCH_STATE 0x89 /* R */ -#define W1_F29_REG_ACTIVITY_LATCH_STATE 0x8A /* R */ -#define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */ -#define W1_F29_REG_COND_SEARCH_POL_SELECT 0x8C /* RW */ -#define W1_F29_REG_CONTROL_AND_STATUS 0x8D /* RW */ - -#define W1_F29_FUNC_READ_PIO_REGS 0xF0 -#define W1_F29_FUNC_CHANN_ACCESS_READ 0xF5 -#define W1_F29_FUNC_CHANN_ACCESS_WRITE 0x5A -/* also used to write the control/status reg (0x8D): */ -#define W1_F29_FUNC_WRITE_COND_SEARCH_REG 0xCC -#define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3 - -#define W1_F29_SUCCESS_CONFIRM_BYTE 0xAA - -static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf) -{ - u8 wrbuf[3]; - dev_dbg(&sl->dev, - "Reading with slave: %p, reg addr: %0#4x, buff addr: %p", - sl, (unsigned int)address, buf); - - if (!buf) - return -EINVAL; - - mutex_lock(&sl->master->mutex); - dev_dbg(&sl->dev, "mutex locked"); - - if (w1_reset_select_slave(sl)) { - mutex_unlock(&sl->master->mutex); - return -EIO; - } - - wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS; - wrbuf[1] = address; - wrbuf[2] = 0; - w1_write_block(sl->master, wrbuf, 3); - *buf = w1_read_8(sl->master); - - mutex_unlock(&sl->master->mutex); - dev_dbg(&sl->dev, "mutex unlocked"); - return 1; -} - -static ssize_t w1_f29_read_state( - struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - dev_dbg(&kobj_to_w1_slave(kobj)->dev, - "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", - bin_attr->attr.name, kobj, (unsigned int)off, count, buf); - if (count != 1 || off != 0) - return -EFAULT; - return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf); -} - -static ssize_t w1_f29_read_output( - struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - dev_dbg(&kobj_to_w1_slave(kobj)->dev, - "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", - bin_attr->attr.name, kobj, (unsigned int)off, count, buf); - if (count != 1 || off != 0) - return -EFAULT; - return _read_reg(kobj_to_w1_slave(kobj), - W1_F29_REG_OUTPUT_LATCH_STATE, buf); -} - -static ssize_t w1_f29_read_activity( - struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - dev_dbg(&kobj_to_w1_slave(kobj)->dev, - "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", - bin_attr->attr.name, kobj, (unsigned int)off, count, buf); - if (count != 1 || off != 0) - return -EFAULT; - return _read_reg(kobj_to_w1_slave(kobj), - W1_F29_REG_ACTIVITY_LATCH_STATE, buf); -} - -static ssize_t w1_f29_read_cond_search_mask( - struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - dev_dbg(&kobj_to_w1_slave(kobj)->dev, - "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", - bin_attr->attr.name, kobj, (unsigned int)off, count, buf); - if (count != 1 || off != 0) - return -EFAULT; - return _read_reg(kobj_to_w1_slave(kobj), - W1_F29_REG_COND_SEARCH_SELECT_MASK, buf); -} - -static ssize_t w1_f29_read_cond_search_polarity( - struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - if (count != 1 || off != 0) - return -EFAULT; - return _read_reg(kobj_to_w1_slave(kobj), - W1_F29_REG_COND_SEARCH_POL_SELECT, buf); -} - -static ssize_t w1_f29_read_status_control( - struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - if (count != 1 || off != 0) - return -EFAULT; - return _read_reg(kobj_to_w1_slave(kobj), - W1_F29_REG_CONTROL_AND_STATUS, buf); -} - - - - -static ssize_t w1_f29_write_output( - struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct w1_slave *sl = kobj_to_w1_slave(kobj); - u8 w1_buf[3]; - u8 readBack; - unsigned int retries = W1_F29_RETRIES; - - if (count != 1 || off != 0) - return -EFAULT; - - dev_dbg(&sl->dev, "locking mutex for write_output"); - mutex_lock(&sl->master->mutex); - dev_dbg(&sl->dev, "mutex locked"); - - if (w1_reset_select_slave(sl)) - goto error; - - while (retries--) { - w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE; - w1_buf[1] = *buf; - w1_buf[2] = ~(*buf); - w1_write_block(sl->master, w1_buf, 3); - - readBack = w1_read_8(sl->master); - /* here the master could read another byte which - would be the PIO reg (the actual pin logic state) - since in this driver we don't know which pins are - in and outs, there's no value to read the state and - compare. with (*buf) so end this command abruptly: */ - if (w1_reset_resume_command(sl->master)) - goto error; - - if (readBack != 0xAA) { - /* try again, the slave is ready for a command */ - continue; - } - - /* go read back the output latches */ - /* (the direct effect of the write above) */ - w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; - w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE; - w1_buf[2] = 0; - w1_write_block(sl->master, w1_buf, 3); - /* read the result of the READ_PIO_REGS command */ - if (w1_read_8(sl->master) == *buf) { - /* success! */ - mutex_unlock(&sl->master->mutex); - dev_dbg(&sl->dev, - "mutex unlocked, retries:%d", retries); - return 1; - } - } -error: - mutex_unlock(&sl->master->mutex); - dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); - - return -EIO; -} - - -/** - * Writing to the activity file resets the activity latches. - */ -static ssize_t w1_f29_write_activity( - struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct w1_slave *sl = kobj_to_w1_slave(kobj); - unsigned int retries = W1_F29_RETRIES; - - if (count != 1 || off != 0) - return -EFAULT; - - mutex_lock(&sl->master->mutex); - - if (w1_reset_select_slave(sl)) - goto error; - - while (retries--) { - w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES); - if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) { - mutex_unlock(&sl->master->mutex); - return 1; - } - if (w1_reset_resume_command(sl->master)) - goto error; - } - -error: - mutex_unlock(&sl->master->mutex); - return -EIO; -} - -static ssize_t w1_f29_write_status_control( - struct file *filp, - struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, - loff_t off, - size_t count) -{ - struct w1_slave *sl = kobj_to_w1_slave(kobj); - u8 w1_buf[4]; - unsigned int retries = W1_F29_RETRIES; - - if (count != 1 || off != 0) - return -EFAULT; - - mutex_lock(&sl->master->mutex); - - if (w1_reset_select_slave(sl)) - goto error; - - while (retries--) { - w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG; - w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS; - w1_buf[2] = 0; - w1_buf[3] = *buf; - - w1_write_block(sl->master, w1_buf, 4); - if (w1_reset_resume_command(sl->master)) - goto error; - - w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; - w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS; - w1_buf[2] = 0; - - w1_write_block(sl->master, w1_buf, 3); - if (w1_read_8(sl->master) == *buf) { - /* success! */ - mutex_unlock(&sl->master->mutex); - return 1; - } - } -error: - mutex_unlock(&sl->master->mutex); - - return -EIO; -} - - - -#define NB_SYSFS_BIN_FILES 6 -static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = { - { - .attr = { - .name = "state", - .mode = S_IRUGO, - }, - .size = 1, - .read = w1_f29_read_state, - }, - { - .attr = { - .name = "output", - .mode = S_IRUGO | S_IWUSR | S_IWGRP, - }, - .size = 1, - .read = w1_f29_read_output, - .write = w1_f29_write_output, - }, - { - .attr = { - .name = "activity", - .mode = S_IRUGO, - }, - .size = 1, - .read = w1_f29_read_activity, - .write = w1_f29_write_activity, - }, - { - .attr = { - .name = "cond_search_mask", - .mode = S_IRUGO, - }, - .size = 1, - .read = w1_f29_read_cond_search_mask, - .write = 0, - }, - { - .attr = { - .name = "cond_search_polarity", - .mode = S_IRUGO, - }, - .size = 1, - .read = w1_f29_read_cond_search_polarity, - .write = 0, - }, - { - .attr = { - .name = "status_control", - .mode = S_IRUGO | S_IWUSR | S_IWGRP, - }, - .size = 1, - .read = w1_f29_read_status_control, - .write = w1_f29_write_status_control, - } -}; - -static int w1_f29_add_slave(struct w1_slave *sl) -{ - int err = 0; - int i; - - for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i) - err = sysfs_create_bin_file( - &sl->dev.kobj, - &(w1_f29_sysfs_bin_files[i])); - if (err) - while (--i >= 0) - sysfs_remove_bin_file(&sl->dev.kobj, - &(w1_f29_sysfs_bin_files[i])); - return err; -} - -static void w1_f29_remove_slave(struct w1_slave *sl) -{ - int i; - for (i = NB_SYSFS_BIN_FILES; i <= 0; --i) - sysfs_remove_bin_file(&sl->dev.kobj, - &(w1_f29_sysfs_bin_files[i])); -} - -static struct w1_family_ops w1_f29_fops = { - .add_slave = w1_f29_add_slave, - .remove_slave = w1_f29_remove_slave, -}; - -static struct w1_family w1_family_29 = { - .fid = W1_FAMILY_DS2408, - .fops = &w1_f29_fops, -}; - -static int __init w1_f29_init(void) -{ - return w1_register_family(&w1_family_29); -} - -static void __exit w1_f29_exit(void) -{ - w1_unregister_family(&w1_family_29); -} - -module_init(w1_f29_init); -module_exit(w1_f29_exit); diff --git a/trunk/drivers/w1/slaves/w1_ds2780.c b/trunk/drivers/w1/slaves/w1_ds2780.c deleted file mode 100644 index 274c8f38303f..000000000000 --- a/trunk/drivers/w1/slaves/w1_ds2780.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * 1-Wire implementation for the ds2780 chip - * - * Copyright (C) 2010 Indesign, LLC - * - * Author: Clifton Barnes - * - * Based on w1-ds2760 driver - * - * 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 "../w1.h" -#include "../w1_int.h" -#include "../w1_family.h" -#include "w1_ds2780.h" - -int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, - int io) -{ - struct w1_slave *sl = container_of(dev, struct w1_slave, dev); - - if (!dev) - return -ENODEV; - - mutex_lock(&sl->master->mutex); - - if (addr > DS2780_DATA_SIZE || addr < 0) { - count = 0; - goto out; - } - count = min_t(int, count, DS2780_DATA_SIZE - addr); - - if (w1_reset_select_slave(sl) == 0) { - if (io) { - w1_write_8(sl->master, W1_DS2780_WRITE_DATA); - w1_write_8(sl->master, addr); - w1_write_block(sl->master, buf, count); - /* XXX w1_write_block returns void, not n_written */ - } else { - w1_write_8(sl->master, W1_DS2780_READ_DATA); - w1_write_8(sl->master, addr); - count = w1_read_block(sl->master, buf, count); - } - } - -out: - mutex_unlock(&sl->master->mutex); - - return count; -} -EXPORT_SYMBOL(w1_ds2780_io); - -int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) -{ - struct w1_slave *sl = container_of(dev, struct w1_slave, dev); - - if (!dev) - return -EINVAL; - - mutex_lock(&sl->master->mutex); - - if (w1_reset_select_slave(sl) == 0) { - w1_write_8(sl->master, cmd); - w1_write_8(sl->master, addr); - } - - mutex_unlock(&sl->master->mutex); - return 0; -} -EXPORT_SYMBOL(w1_ds2780_eeprom_cmd); - -static ssize_t w1_ds2780_read_bin(struct file *filp, - struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - return w1_ds2780_io(dev, buf, off, count, 0); -} - -static struct bin_attribute w1_ds2780_bin_attr = { - .attr = { - .name = "w1_slave", - .mode = S_IRUGO, - }, - .size = DS2780_DATA_SIZE, - .read = w1_ds2780_read_bin, -}; - -static DEFINE_IDR(bat_idr); -static DEFINE_MUTEX(bat_idr_lock); - -static int new_bat_id(void) -{ - int ret; - - while (1) { - int id; - - ret = idr_pre_get(&bat_idr, GFP_KERNEL); - if (ret == 0) - return -ENOMEM; - - mutex_lock(&bat_idr_lock); - ret = idr_get_new(&bat_idr, NULL, &id); - mutex_unlock(&bat_idr_lock); - - if (ret == 0) { - ret = id & MAX_ID_MASK; - break; - } else if (ret == -EAGAIN) { - continue; - } else { - break; - } - } - - return ret; -} - -static void release_bat_id(int id) -{ - mutex_lock(&bat_idr_lock); - idr_remove(&bat_idr, id); - mutex_unlock(&bat_idr_lock); -} - -static int w1_ds2780_add_slave(struct w1_slave *sl) -{ - int ret; - int id; - struct platform_device *pdev; - - id = new_bat_id(); - if (id < 0) { - ret = id; - goto noid; - } - - pdev = platform_device_alloc("ds2780-battery", id); - if (!pdev) { - ret = -ENOMEM; - goto pdev_alloc_failed; - } - pdev->dev.parent = &sl->dev; - - ret = platform_device_add(pdev); - if (ret) - goto pdev_add_failed; - - ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr); - if (ret) - goto bin_attr_failed; - - dev_set_drvdata(&sl->dev, pdev); - - return 0; - -bin_attr_failed: -pdev_add_failed: - platform_device_unregister(pdev); -pdev_alloc_failed: - release_bat_id(id); -noid: - return ret; -} - -static void w1_ds2780_remove_slave(struct w1_slave *sl) -{ - struct platform_device *pdev = dev_get_drvdata(&sl->dev); - int id = pdev->id; - - platform_device_unregister(pdev); - release_bat_id(id); - sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr); -} - -static struct w1_family_ops w1_ds2780_fops = { - .add_slave = w1_ds2780_add_slave, - .remove_slave = w1_ds2780_remove_slave, -}; - -static struct w1_family w1_ds2780_family = { - .fid = W1_FAMILY_DS2780, - .fops = &w1_ds2780_fops, -}; - -static int __init w1_ds2780_init(void) -{ - idr_init(&bat_idr); - return w1_register_family(&w1_ds2780_family); -} - -static void __exit w1_ds2780_exit(void) -{ - w1_unregister_family(&w1_ds2780_family); - idr_destroy(&bat_idr); -} - -module_init(w1_ds2780_init); -module_exit(w1_ds2780_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Clifton Barnes "); -MODULE_DESCRIPTION("1-wire Driver for Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC"); diff --git a/trunk/drivers/w1/slaves/w1_ds2780.h b/trunk/drivers/w1/slaves/w1_ds2780.h deleted file mode 100644 index a1fba79eb1b5..000000000000 --- a/trunk/drivers/w1/slaves/w1_ds2780.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 1-Wire implementation for the ds2780 chip - * - * Copyright (C) 2010 Indesign, LLC - * - * Author: Clifton Barnes - * - * Based on w1-ds2760 driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef _W1_DS2780_H -#define _W1_DS2780_H - -/* Function commands */ -#define W1_DS2780_READ_DATA 0x69 -#define W1_DS2780_WRITE_DATA 0x6C -#define W1_DS2780_COPY_DATA 0x48 -#define W1_DS2780_RECALL_DATA 0xB8 -#define W1_DS2780_LOCK 0x6A - -/* Register map */ -/* Register 0x00 Reserved */ -#define DS2780_STATUS_REG 0x01 -#define DS2780_RAAC_MSB_REG 0x02 -#define DS2780_RAAC_LSB_REG 0x03 -#define DS2780_RSAC_MSB_REG 0x04 -#define DS2780_RSAC_LSB_REG 0x05 -#define DS2780_RARC_REG 0x06 -#define DS2780_RSRC_REG 0x07 -#define DS2780_IAVG_MSB_REG 0x08 -#define DS2780_IAVG_LSB_REG 0x09 -#define DS2780_TEMP_MSB_REG 0x0A -#define DS2780_TEMP_LSB_REG 0x0B -#define DS2780_VOLT_MSB_REG 0x0C -#define DS2780_VOLT_LSB_REG 0x0D -#define DS2780_CURRENT_MSB_REG 0x0E -#define DS2780_CURRENT_LSB_REG 0x0F -#define DS2780_ACR_MSB_REG 0x10 -#define DS2780_ACR_LSB_REG 0x11 -#define DS2780_ACRL_MSB_REG 0x12 -#define DS2780_ACRL_LSB_REG 0x13 -#define DS2780_AS_REG 0x14 -#define DS2780_SFR_REG 0x15 -#define DS2780_FULL_MSB_REG 0x16 -#define DS2780_FULL_LSB_REG 0x17 -#define DS2780_AE_MSB_REG 0x18 -#define DS2780_AE_LSB_REG 0x19 -#define DS2780_SE_MSB_REG 0x1A -#define DS2780_SE_LSB_REG 0x1B -/* Register 0x1C - 0x1E Reserved */ -#define DS2780_EEPROM_REG 0x1F -#define DS2780_EEPROM_BLOCK0_START 0x20 -/* Register 0x20 - 0x2F User EEPROM */ -#define DS2780_EEPROM_BLOCK0_END 0x2F -/* Register 0x30 - 0x5F Reserved */ -#define DS2780_EEPROM_BLOCK1_START 0x60 -#define DS2780_CONTROL_REG 0x60 -#define DS2780_AB_REG 0x61 -#define DS2780_AC_MSB_REG 0x62 -#define DS2780_AC_LSB_REG 0x63 -#define DS2780_VCHG_REG 0x64 -#define DS2780_IMIN_REG 0x65 -#define DS2780_VAE_REG 0x66 -#define DS2780_IAE_REG 0x67 -#define DS2780_AE_40_REG 0x68 -#define DS2780_RSNSP_REG 0x69 -#define DS2780_FULL_40_MSB_REG 0x6A -#define DS2780_FULL_40_LSB_REG 0x6B -#define DS2780_FULL_3040_SLOPE_REG 0x6C -#define DS2780_FULL_2030_SLOPE_REG 0x6D -#define DS2780_FULL_1020_SLOPE_REG 0x6E -#define DS2780_FULL_0010_SLOPE_REG 0x6F -#define DS2780_AE_3040_SLOPE_REG 0x70 -#define DS2780_AE_2030_SLOPE_REG 0x71 -#define DS2780_AE_1020_SLOPE_REG 0x72 -#define DS2780_AE_0010_SLOPE_REG 0x73 -#define DS2780_SE_3040_SLOPE_REG 0x74 -#define DS2780_SE_2030_SLOPE_REG 0x75 -#define DS2780_SE_1020_SLOPE_REG 0x76 -#define DS2780_SE_0010_SLOPE_REG 0x77 -#define DS2780_RSGAIN_MSB_REG 0x78 -#define DS2780_RSGAIN_LSB_REG 0x79 -#define DS2780_RSTC_REG 0x7A -#define DS2780_FRSGAIN_MSB_REG 0x7B -#define DS2780_FRSGAIN_LSB_REG 0x7C -#define DS2780_EEPROM_BLOCK1_END 0x7C -/* Register 0x7D - 0xFF Reserved */ - -/* Number of valid register addresses */ -#define DS2780_DATA_SIZE 0x80 - -/* Status register bits */ -#define DS2780_STATUS_REG_CHGTF (1 << 7) -#define DS2780_STATUS_REG_AEF (1 << 6) -#define DS2780_STATUS_REG_SEF (1 << 5) -#define DS2780_STATUS_REG_LEARNF (1 << 4) -/* Bit 3 Reserved */ -#define DS2780_STATUS_REG_UVF (1 << 2) -#define DS2780_STATUS_REG_PORF (1 << 1) -/* Bit 0 Reserved */ - -/* Control register bits */ -/* Bit 7 Reserved */ -#define DS2780_CONTROL_REG_UVEN (1 << 6) -#define DS2780_CONTROL_REG_PMOD (1 << 5) -#define DS2780_CONTROL_REG_RNAOP (1 << 4) -/* Bit 0 - 3 Reserved */ - -/* Special feature register bits */ -/* Bit 1 - 7 Reserved */ -#define DS2780_SFR_REG_PIOSC (1 << 0) - -/* EEPROM register bits */ -#define DS2780_EEPROM_REG_EEC (1 << 7) -#define DS2780_EEPROM_REG_LOCK (1 << 6) -/* Bit 2 - 6 Reserved */ -#define DS2780_EEPROM_REG_BL1 (1 << 1) -#define DS2780_EEPROM_REG_BL0 (1 << 0) - -extern int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, - int io); -extern int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd); - -#endif /* !_W1_DS2780_H */ diff --git a/trunk/drivers/w1/w1.c b/trunk/drivers/w1/w1.c index 10606c822756..b7b5014ff714 100644 --- a/trunk/drivers/w1/w1.c +++ b/trunk/drivers/w1/w1.c @@ -827,7 +827,7 @@ void w1_reconnect_slaves(struct w1_family *f, int attach) mutex_unlock(&w1_mlock); } -void w1_slave_found(struct w1_master *dev, u64 rn) +static void w1_slave_found(struct w1_master *dev, u64 rn) { struct w1_slave *sl; struct w1_reg_num *tmp; @@ -933,15 +933,14 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb } } -void w1_search_process_cb(struct w1_master *dev, u8 search_type, - w1_slave_found_callback cb) +void w1_search_process(struct w1_master *dev, u8 search_type) { struct w1_slave *sl, *sln; list_for_each_entry(sl, &dev->slist, w1_slave_entry) clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); - w1_search_devices(dev, search_type, cb); + w1_search_devices(dev, search_type, w1_slave_found); list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) @@ -954,11 +953,6 @@ void w1_search_process_cb(struct w1_master *dev, u8 search_type, dev->search_count--; } -static void w1_search_process(struct w1_master *dev, u8 search_type) -{ - w1_search_process_cb(dev, search_type, w1_slave_found); -} - int w1_process(void *data) { struct w1_master *dev = (struct w1_master *) data; diff --git a/trunk/drivers/w1/w1.h b/trunk/drivers/w1/w1.h index 1ce23fc6186c..d8a9709f3449 100644 --- a/trunk/drivers/w1/w1.h +++ b/trunk/drivers/w1/w1.h @@ -55,7 +55,6 @@ struct w1_reg_num #define W1_READ_ROM 0x33 #define W1_READ_PSUPPLY 0xB4 #define W1_MATCH_ROM 0x55 -#define W1_RESUME_CMD 0xA5 #define W1_SLAVE_ACTIVE 0 @@ -194,9 +193,7 @@ void w1_destroy_master_attributes(struct w1_master *master); void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); struct w1_slave *w1_search_slave(struct w1_reg_num *id); -void w1_slave_found(struct w1_master *dev, u64 rn); -void w1_search_process_cb(struct w1_master *dev, u8 search_type, - w1_slave_found_callback cb); +void w1_search_process(struct w1_master *dev, u8 search_type); struct w1_master *w1_search_master_id(u32 id); /* Disconnect and reconnect devices in the given family. Used for finding @@ -216,7 +213,6 @@ void w1_write_block(struct w1_master *, const u8 *, int); void w1_touch_block(struct w1_master *, u8 *, int); u8 w1_read_block(struct w1_master *, u8 *, int); int w1_reset_select_slave(struct w1_slave *sl); -int w1_reset_resume_command(struct w1_master *); void w1_next_pullup(struct w1_master *, int); static inline struct w1_slave* dev_to_w1_slave(struct device *dev) diff --git a/trunk/drivers/w1/w1_family.h b/trunk/drivers/w1/w1_family.h index 97479ae70b9c..f3b636d7cafe 100644 --- a/trunk/drivers/w1/w1_family.h +++ b/trunk/drivers/w1/w1_family.h @@ -34,10 +34,8 @@ #define W1_THERM_DS1822 0x22 #define W1_EEPROM_DS2433 0x23 #define W1_THERM_DS18B20 0x28 -#define W1_FAMILY_DS2408 0x29 #define W1_EEPROM_DS2431 0x2D #define W1_FAMILY_DS2760 0x30 -#define W1_FAMILY_DS2780 0x32 #define MAXNAMELEN 32 diff --git a/trunk/drivers/w1/w1_io.c b/trunk/drivers/w1/w1_io.c index 8e8b64cfafb6..3ebe9726a9e5 100644 --- a/trunk/drivers/w1/w1_io.c +++ b/trunk/drivers/w1/w1_io.c @@ -389,32 +389,6 @@ int w1_reset_select_slave(struct w1_slave *sl) } EXPORT_SYMBOL_GPL(w1_reset_select_slave); -/** - * When the workflow with a slave amongst many requires several - * successive commands a reset between each, this function is similar - * to doing a reset then a match ROM for the last matched ROM. The - * advantage being that the matched ROM step is skipped in favor of the - * resume command. The slave must support the command of course. - * - * If the bus has only one slave, traditionnaly the match ROM is skipped - * and a "SKIP ROM" is done for efficiency. On multi-slave busses, this - * doesn't work of course, but the resume command is the next best thing. - * - * The w1 master lock must be held. - * - * @param dev the master device - */ -int w1_reset_resume_command(struct w1_master *dev) -{ - if (w1_reset_bus(dev)) - return -1; - - /* This will make only the last matched slave perform a skip ROM. */ - w1_write_8(dev, W1_RESUME_CMD); - return 0; -} -EXPORT_SYMBOL_GPL(w1_reset_resume_command); - /** * Put out a strong pull-up of the specified duration after the next write * operation. Not all hardware supports strong pullups. Hardware that diff --git a/trunk/drivers/w1/w1_netlink.c b/trunk/drivers/w1/w1_netlink.c index 55aabd927c60..7e667bc77ef2 100644 --- a/trunk/drivers/w1/w1_netlink.c +++ b/trunk/drivers/w1/w1_netlink.c @@ -55,9 +55,6 @@ static void w1_send_slave(struct w1_master *dev, u64 rn) struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1); int avail; - /* update kernel slave list */ - w1_slave_found(dev, rn); - avail = dev->priv_size - cmd->len; if (avail > 8) { @@ -88,7 +85,7 @@ static int w1_process_search_command(struct w1_master *dev, struct cn_msg *msg, dev->priv = msg; dev->priv_size = avail; - w1_search_process_cb(dev, search_type, w1_send_slave); + w1_search_devices(dev, search_type, w1_send_slave); msg->ack = 0; cn_netlink_send(msg, 0, GFP_KERNEL); diff --git a/trunk/drivers/watchdog/rdc321x_wdt.c b/trunk/drivers/watchdog/rdc321x_wdt.c index 428f8a1583e8..d8e725082fdc 100644 --- a/trunk/drivers/watchdog/rdc321x_wdt.c +++ b/trunk/drivers/watchdog/rdc321x_wdt.c @@ -37,6 +37,7 @@ #include #include #include +#include #define RDC_WDT_MASK 0x80000000 /* Mask */ #define RDC_WDT_EN 0x00800000 /* Enable bit */ @@ -231,7 +232,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) struct resource *r; struct rdc321x_wdt_pdata *pdata; - pdata = pdev->dev.platform_data; + pdata = mfd_get_data(pdev); if (!pdata) { dev_err(&pdev->dev, "no platform data supplied\n"); return -ENODEV; diff --git a/trunk/drivers/xen/Makefile b/trunk/drivers/xen/Makefile index bbc18258ecc5..4781f806701d 100644 --- a/trunk/drivers/xen/Makefile +++ b/trunk/drivers/xen/Makefile @@ -1,6 +1,5 @@ obj-y += grant-table.o features.o events.o manage.o balloon.o obj-y += xenbus/ -obj-y += tmem.o nostackp := $(call cc-option, -fno-stack-protector) CFLAGS_features.o := $(nostackp) diff --git a/trunk/drivers/xen/tmem.c b/trunk/drivers/xen/tmem.c deleted file mode 100644 index 816a44959ef0..000000000000 --- a/trunk/drivers/xen/tmem.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Xen implementation for transcendent memory (tmem) - * - * Copyright (C) 2009-2010 Oracle Corp. All rights reserved. - * Author: Dan Magenheimer - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define TMEM_CONTROL 0 -#define TMEM_NEW_POOL 1 -#define TMEM_DESTROY_POOL 2 -#define TMEM_NEW_PAGE 3 -#define TMEM_PUT_PAGE 4 -#define TMEM_GET_PAGE 5 -#define TMEM_FLUSH_PAGE 6 -#define TMEM_FLUSH_OBJECT 7 -#define TMEM_READ 8 -#define TMEM_WRITE 9 -#define TMEM_XCHG 10 - -/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */ -#define TMEM_POOL_PERSIST 1 -#define TMEM_POOL_SHARED 2 -#define TMEM_POOL_PAGESIZE_SHIFT 4 -#define TMEM_VERSION_SHIFT 24 - - -struct tmem_pool_uuid { - u64 uuid_lo; - u64 uuid_hi; -}; - -struct tmem_oid { - u64 oid[3]; -}; - -#define TMEM_POOL_PRIVATE_UUID { 0, 0 } - -/* flags for tmem_ops.new_pool */ -#define TMEM_POOL_PERSIST 1 -#define TMEM_POOL_SHARED 2 - -/* xen tmem foundation ops/hypercalls */ - -static inline int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, struct tmem_oid oid, - u32 index, unsigned long gmfn, u32 tmem_offset, u32 pfn_offset, u32 len) -{ - struct tmem_op op; - int rc = 0; - - op.cmd = tmem_cmd; - op.pool_id = tmem_pool; - op.u.gen.oid[0] = oid.oid[0]; - op.u.gen.oid[1] = oid.oid[1]; - op.u.gen.oid[2] = oid.oid[2]; - op.u.gen.index = index; - op.u.gen.tmem_offset = tmem_offset; - op.u.gen.pfn_offset = pfn_offset; - op.u.gen.len = len; - set_xen_guest_handle(op.u.gen.gmfn, (void *)gmfn); - rc = HYPERVISOR_tmem_op(&op); - return rc; -} - -static int xen_tmem_new_pool(struct tmem_pool_uuid uuid, - u32 flags, unsigned long pagesize) -{ - struct tmem_op op; - int rc = 0, pageshift; - - for (pageshift = 0; pagesize != 1; pageshift++) - pagesize >>= 1; - flags |= (pageshift - 12) << TMEM_POOL_PAGESIZE_SHIFT; - flags |= TMEM_SPEC_VERSION << TMEM_VERSION_SHIFT; - op.cmd = TMEM_NEW_POOL; - op.u.new.uuid[0] = uuid.uuid_lo; - op.u.new.uuid[1] = uuid.uuid_hi; - op.u.new.flags = flags; - rc = HYPERVISOR_tmem_op(&op); - return rc; -} - -/* xen generic tmem ops */ - -static int xen_tmem_put_page(u32 pool_id, struct tmem_oid oid, - u32 index, unsigned long pfn) -{ - unsigned long gmfn = xen_pv_domain() ? pfn_to_mfn(pfn) : pfn; - - return xen_tmem_op(TMEM_PUT_PAGE, pool_id, oid, index, - gmfn, 0, 0, 0); -} - -static int xen_tmem_get_page(u32 pool_id, struct tmem_oid oid, - u32 index, unsigned long pfn) -{ - unsigned long gmfn = xen_pv_domain() ? pfn_to_mfn(pfn) : pfn; - - return xen_tmem_op(TMEM_GET_PAGE, pool_id, oid, index, - gmfn, 0, 0, 0); -} - -static int xen_tmem_flush_page(u32 pool_id, struct tmem_oid oid, u32 index) -{ - return xen_tmem_op(TMEM_FLUSH_PAGE, pool_id, oid, index, - 0, 0, 0, 0); -} - -static int xen_tmem_flush_object(u32 pool_id, struct tmem_oid oid) -{ - return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, oid, 0, 0, 0, 0, 0); -} - -static int xen_tmem_destroy_pool(u32 pool_id) -{ - struct tmem_oid oid = { { 0 } }; - - return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, oid, 0, 0, 0, 0, 0); -} - -int tmem_enabled; - -static int __init enable_tmem(char *s) -{ - tmem_enabled = 1; - return 1; -} - -__setup("tmem", enable_tmem); - -/* cleancache ops */ - -static void tmem_cleancache_put_page(int pool, struct cleancache_filekey key, - pgoff_t index, struct page *page) -{ - u32 ind = (u32) index; - struct tmem_oid oid = *(struct tmem_oid *)&key; - unsigned long pfn = page_to_pfn(page); - - if (pool < 0) - return; - if (ind != index) - return; - mb(); /* ensure page is quiescent; tmem may address it with an alias */ - (void)xen_tmem_put_page((u32)pool, oid, ind, pfn); -} - -static int tmem_cleancache_get_page(int pool, struct cleancache_filekey key, - pgoff_t index, struct page *page) -{ - u32 ind = (u32) index; - struct tmem_oid oid = *(struct tmem_oid *)&key; - unsigned long pfn = page_to_pfn(page); - int ret; - - /* translate return values to linux semantics */ - if (pool < 0) - return -1; - if (ind != index) - return -1; - ret = xen_tmem_get_page((u32)pool, oid, ind, pfn); - if (ret == 1) - return 0; - else - return -1; -} - -static void tmem_cleancache_flush_page(int pool, struct cleancache_filekey key, - pgoff_t index) -{ - u32 ind = (u32) index; - struct tmem_oid oid = *(struct tmem_oid *)&key; - - if (pool < 0) - return; - if (ind != index) - return; - (void)xen_tmem_flush_page((u32)pool, oid, ind); -} - -static void tmem_cleancache_flush_inode(int pool, struct cleancache_filekey key) -{ - struct tmem_oid oid = *(struct tmem_oid *)&key; - - if (pool < 0) - return; - (void)xen_tmem_flush_object((u32)pool, oid); -} - -static void tmem_cleancache_flush_fs(int pool) -{ - if (pool < 0) - return; - (void)xen_tmem_destroy_pool((u32)pool); -} - -static int tmem_cleancache_init_fs(size_t pagesize) -{ - struct tmem_pool_uuid uuid_private = TMEM_POOL_PRIVATE_UUID; - - return xen_tmem_new_pool(uuid_private, 0, pagesize); -} - -static int tmem_cleancache_init_shared_fs(char *uuid, size_t pagesize) -{ - struct tmem_pool_uuid shared_uuid; - - shared_uuid.uuid_lo = *(u64 *)uuid; - shared_uuid.uuid_hi = *(u64 *)(&uuid[8]); - return xen_tmem_new_pool(shared_uuid, TMEM_POOL_SHARED, pagesize); -} - -static int use_cleancache = 1; - -static int __init no_cleancache(char *s) -{ - use_cleancache = 0; - return 1; -} - -__setup("nocleancache", no_cleancache); - -static struct cleancache_ops tmem_cleancache_ops = { - .put_page = tmem_cleancache_put_page, - .get_page = tmem_cleancache_get_page, - .flush_page = tmem_cleancache_flush_page, - .flush_inode = tmem_cleancache_flush_inode, - .flush_fs = tmem_cleancache_flush_fs, - .init_shared_fs = tmem_cleancache_init_shared_fs, - .init_fs = tmem_cleancache_init_fs -}; - -static int __init xen_tmem_init(void) -{ - struct cleancache_ops old_ops; - - if (!xen_domain()) - return 0; -#ifdef CONFIG_CLEANCACHE - BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid)); - if (tmem_enabled && use_cleancache) { - char *s = ""; - old_ops = cleancache_register_ops(&tmem_cleancache_ops); - if (old_ops.init_fs != NULL) - s = " (WARNING: cleancache_ops overridden)"; - printk(KERN_INFO "cleancache enabled, RAM provided by " - "Xen Transcendent Memory%s\n", s); - } -#endif - return 0; -} - -module_init(xen_tmem_init) diff --git a/trunk/fs/9p/vfs_inode.c b/trunk/fs/9p/vfs_inode.c index 8d7f3e69ae29..7f6c67703195 100644 --- a/trunk/fs/9p/vfs_inode.c +++ b/trunk/fs/9p/vfs_inode.c @@ -814,7 +814,6 @@ int v9fs_vfs_unlink(struct inode *i, struct dentry *d) int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) { - dentry_unhash(d); return v9fs_remove(i, d, 1); } @@ -840,9 +839,6 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct p9_fid *newdirfid; struct p9_wstat wstat; - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - P9_DPRINTK(P9_DEBUG_VFS, "\n"); retval = 0; old_inode = old_dentry->d_inode; diff --git a/trunk/fs/Kconfig b/trunk/fs/Kconfig index 19891aab9c6e..f6edba2e069f 100644 --- a/trunk/fs/Kconfig +++ b/trunk/fs/Kconfig @@ -47,7 +47,7 @@ config FS_POSIX_ACL def_bool n config EXPORTFS - tristate + bool config FILE_LOCKING bool "Enable POSIX file locking API" if EXPERT diff --git a/trunk/fs/affs/namei.c b/trunk/fs/affs/namei.c index 03330e2e390c..e3e9efc1fdd8 100644 --- a/trunk/fs/affs/namei.c +++ b/trunk/fs/affs/namei.c @@ -320,8 +320,6 @@ affs_rmdir(struct inode *dir, struct dentry *dentry) dentry->d_inode->i_ino, (int)dentry->d_name.len, dentry->d_name.name); - dentry_unhash(dentry); - return affs_remove_header(dentry); } @@ -419,9 +417,6 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry, struct buffer_head *bh = NULL; int retval; - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n", (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name, (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name); diff --git a/trunk/fs/afs/dir.c b/trunk/fs/afs/dir.c index 2c4e05160042..20c106f24927 100644 --- a/trunk/fs/afs/dir.c +++ b/trunk/fs/afs/dir.c @@ -845,8 +845,6 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry) _enter("{%x:%u},{%s}", dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name); - dentry_unhash(dentry); - ret = -ENAMETOOLONG; if (dentry->d_name.len >= AFSNAMEMAX) goto error; @@ -1148,9 +1146,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, struct key *key; int ret; - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - vnode = AFS_FS_I(old_dentry->d_inode); orig_dvnode = AFS_FS_I(old_dir); new_dvnode = AFS_FS_I(new_dir); diff --git a/trunk/fs/autofs4/root.c b/trunk/fs/autofs4/root.c index 87d95a8cddbc..f55ae23b137e 100644 --- a/trunk/fs/autofs4/root.c +++ b/trunk/fs/autofs4/root.c @@ -583,8 +583,6 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) return -EACCES; - dentry_unhash(dentry); - if (atomic_dec_and_test(&ino->count)) { p_ino = autofs4_dentry_ino(dentry->d_parent); if (p_ino && dentry->d_parent != dentry) diff --git a/trunk/fs/bfs/dir.c b/trunk/fs/bfs/dir.c index c7d1d06b0483..b14cebfd9047 100644 --- a/trunk/fs/bfs/dir.c +++ b/trunk/fs/bfs/dir.c @@ -224,9 +224,6 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct bfs_sb_info *info; int error = -ENOENT; - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - old_bh = new_bh = NULL; old_inode = old_dentry->d_inode; if (S_ISDIR(old_inode->i_mode)) diff --git a/trunk/fs/btrfs/extent_io.c b/trunk/fs/btrfs/extent_io.c index 4f9893243dae..96fcfa522dab 100644 --- a/trunk/fs/btrfs/extent_io.c +++ b/trunk/fs/btrfs/extent_io.c @@ -11,7 +11,6 @@ #include #include #include -#include #include "extent_io.h" #include "extent_map.h" #include "compat.h" @@ -2017,13 +2016,6 @@ static int __extent_read_full_page(struct extent_io_tree *tree, set_page_extent_mapped(page); - if (!PageUptodate(page)) { - if (cleancache_get_page(page) == 0) { - BUG_ON(blocksize != PAGE_SIZE); - goto out; - } - } - end = page_end; while (1) { lock_extent(tree, start, end, GFP_NOFS); @@ -2157,7 +2149,6 @@ static int __extent_read_full_page(struct extent_io_tree *tree, cur = cur + iosize; page_offset += iosize; } -out: if (!nr) { if (!PageError(page)) SetPageUptodate(page); diff --git a/trunk/fs/btrfs/super.c b/trunk/fs/btrfs/super.c index be4ffa12f3ef..0ac712efcdf2 100644 --- a/trunk/fs/btrfs/super.c +++ b/trunk/fs/btrfs/super.c @@ -39,7 +39,6 @@ #include #include #include -#include #include "compat.h" #include "ctree.h" #include "disk-io.h" @@ -625,7 +624,6 @@ static int btrfs_fill_super(struct super_block *sb, sb->s_root = root_dentry; save_mount_options(sb, data); - cleancache_init_fs(sb); return 0; fail_close: diff --git a/trunk/fs/buffer.c b/trunk/fs/buffer.c index 698c6b2cc462..a08bb8e61c6f 100644 --- a/trunk/fs/buffer.c +++ b/trunk/fs/buffer.c @@ -41,7 +41,6 @@ #include #include #include -#include static int fsync_buffers_list(spinlock_t *lock, struct list_head *list); @@ -270,10 +269,6 @@ void invalidate_bdev(struct block_device *bdev) invalidate_bh_lrus(); lru_add_drain_all(); /* make sure all lru add caches are flushed */ invalidate_mapping_pages(mapping, 0, -1); - /* 99% of the time, we don't need to flush the cleancache on the bdev. - * But, for the strange corners, lets be cautious - */ - cleancache_flush_inode(mapping); } EXPORT_SYMBOL(invalidate_bdev); @@ -2336,26 +2331,24 @@ EXPORT_SYMBOL(block_commit_write); * page lock we can determine safely if the page is beyond EOF. If it is not * beyond EOF, then the page is guaranteed safe against truncation until we * unlock the page. - * - * Direct callers of this function should call vfs_check_frozen() so that page - * fault does not busyloop until the fs is thawed. */ -int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, - get_block_t get_block) +int +block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, + get_block_t get_block) { struct page *page = vmf->page; struct inode *inode = vma->vm_file->f_path.dentry->d_inode; unsigned long end; loff_t size; - int ret; + int ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */ lock_page(page); size = i_size_read(inode); if ((page->mapping != inode->i_mapping) || (page_offset(page) > size)) { - /* We overload EFAULT to mean page got truncated */ - ret = -EFAULT; - goto out_unlock; + /* page got truncated out from underneath us */ + unlock_page(page); + goto out; } /* page is wholly or partially inside EOF */ @@ -2368,40 +2361,17 @@ int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, if (!ret) ret = block_commit_write(page, 0, end); - if (unlikely(ret < 0)) - goto out_unlock; - /* - * Freezing in progress? We check after the page is marked dirty and - * with page lock held so if the test here fails, we are sure freezing - * code will wait during syncing until the page fault is done - at that - * point page will be dirty and unlocked so freezing code will write it - * and writeprotect it again. - */ - set_page_dirty(page); - if (inode->i_sb->s_frozen != SB_UNFROZEN) { - ret = -EAGAIN; - goto out_unlock; - } - return 0; -out_unlock: - unlock_page(page); - return ret; -} -EXPORT_SYMBOL(__block_page_mkwrite); - -int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, - get_block_t get_block) -{ - int ret; - struct super_block *sb = vma->vm_file->f_path.dentry->d_inode->i_sb; + if (unlikely(ret)) { + unlock_page(page); + if (ret == -ENOMEM) + ret = VM_FAULT_OOM; + else /* -ENOSPC, -EIO, etc */ + ret = VM_FAULT_SIGBUS; + } else + ret = VM_FAULT_LOCKED; - /* - * This check is racy but catches the common case. The check in - * __block_page_mkwrite() is reliable. - */ - vfs_check_frozen(sb, SB_FREEZE_WRITE); - ret = __block_page_mkwrite(vma, vmf, get_block); - return block_page_mkwrite_return(ret); +out: + return ret; } EXPORT_SYMBOL(block_page_mkwrite); diff --git a/trunk/fs/coda/dir.c b/trunk/fs/coda/dir.c index a46126fd5735..2b8dae4d121e 100644 --- a/trunk/fs/coda/dir.c +++ b/trunk/fs/coda/dir.c @@ -336,8 +336,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de) int len = de->d_name.len; int error; - dentry_unhash(de); - error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); if (!error) { /* VFS may delete the child */ @@ -361,9 +359,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, int new_length = new_dentry->d_name.len; int error; - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), coda_i2f(new_dir), old_length, new_length, (const char *) old_name, (const char *)new_name); diff --git a/trunk/fs/configfs/dir.c b/trunk/fs/configfs/dir.c index 9d17d350abc5..9a37a9b6de3a 100644 --- a/trunk/fs/configfs/dir.c +++ b/trunk/fs/configfs/dir.c @@ -1359,8 +1359,6 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) struct module *subsys_owner = NULL, *dead_item_owner = NULL; int ret; - dentry_unhash(dentry); - if (dentry->d_parent == configfs_sb->s_root) return -EPERM; diff --git a/trunk/fs/dlm/main.c b/trunk/fs/dlm/main.c index 5a59efa0bb46..b80e0aa3cfa5 100644 --- a/trunk/fs/dlm/main.c +++ b/trunk/fs/dlm/main.c @@ -50,7 +50,7 @@ static int __init init_dlm(void) if (error) goto out_netlink; - printk("DLM installed\n"); + printk("DLM (built %s %s) installed\n", __DATE__, __TIME__); return 0; diff --git a/trunk/fs/ecryptfs/inode.c b/trunk/fs/ecryptfs/inode.c index 227b409b8406..4d4cc6a90cd5 100644 --- a/trunk/fs/ecryptfs/inode.c +++ b/trunk/fs/ecryptfs/inode.c @@ -521,8 +521,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) struct dentry *lower_dir_dentry; int rc; - dentry_unhash(dentry); - lower_dentry = ecryptfs_dentry_to_lower(dentry); dget(dentry); lower_dir_dentry = lock_parent(lower_dentry); @@ -573,9 +571,6 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct dentry *lower_new_dir_dentry; struct dentry *trap = NULL; - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); dget(lower_old_dentry); diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index ea5f748906a8..936f5776655c 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1623,41 +1624,6 @@ static int cn_printf(struct core_name *cn, const char *fmt, ...) return ret; } -static int cn_print_exe_file(struct core_name *cn) -{ - struct file *exe_file; - char *pathbuf, *path, *p; - int ret; - - exe_file = get_mm_exe_file(current->mm); - if (!exe_file) - return cn_printf(cn, "(unknown)"); - - pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY); - if (!pathbuf) { - ret = -ENOMEM; - goto put_exe_file; - } - - path = d_path(&exe_file->f_path, pathbuf, PATH_MAX); - if (IS_ERR(path)) { - ret = PTR_ERR(path); - goto free_buf; - } - - for (p = path; *p; p++) - if (*p == '/') - *p = '!'; - - ret = cn_printf(cn, "%s", path); - -free_buf: - kfree(pathbuf); -put_exe_file: - fput(exe_file); - return ret; -} - /* format_corename will inspect the pattern parameter, and output a * name into corename, which must have space for at least * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. @@ -1729,9 +1695,6 @@ static int format_corename(struct core_name *cn, long signr) case 'e': err = cn_printf(cn, "%s", current->comm); break; - case 'E': - err = cn_print_exe_file(cn); - break; /* core limit size */ case 'c': err = cn_printf(cn, "%lu", diff --git a/trunk/fs/ext3/super.c b/trunk/fs/ext3/super.c index aad153ef6b78..3c6a9e0eadc1 100644 --- a/trunk/fs/ext3/super.c +++ b/trunk/fs/ext3/super.c @@ -36,7 +36,6 @@ #include #include #include -#include #include @@ -1368,7 +1367,6 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, } else { ext3_msg(sb, KERN_INFO, "using internal journal"); } - cleancache_init_fs(sb); return res; } diff --git a/trunk/fs/ext4/Makefile b/trunk/fs/ext4/Makefile index 04109460ba9e..c947e36eda6c 100644 --- a/trunk/fs/ext4/Makefile +++ b/trunk/fs/ext4/Makefile @@ -6,8 +6,7 @@ obj-$(CONFIG_EXT4_FS) += ext4.o ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \ ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ - ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \ - mmp.o + ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o diff --git a/trunk/fs/ext4/balloc.c b/trunk/fs/ext4/balloc.c index 264f6949511e..1c67139ad4b4 100644 --- a/trunk/fs/ext4/balloc.c +++ b/trunk/fs/ext4/balloc.c @@ -361,6 +361,130 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) return bh; } +/** + * ext4_add_groupblocks() -- Add given blocks to an existing group + * @handle: handle to this transaction + * @sb: super block + * @block: start physcial block to add to the block group + * @count: number of blocks to free + * + * This marks the blocks as free in the bitmap. We ask the + * mballoc to reload the buddy after this by setting group + * EXT4_GROUP_INFO_NEED_INIT_BIT flag + */ +void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, + ext4_fsblk_t block, unsigned long count) +{ + struct buffer_head *bitmap_bh = NULL; + struct buffer_head *gd_bh; + ext4_group_t block_group; + ext4_grpblk_t bit; + unsigned int i; + struct ext4_group_desc *desc; + struct ext4_sb_info *sbi = EXT4_SB(sb); + int err = 0, ret, blk_free_count; + ext4_grpblk_t blocks_freed; + struct ext4_group_info *grp; + + ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1); + + ext4_get_group_no_and_offset(sb, block, &block_group, &bit); + grp = ext4_get_group_info(sb, block_group); + /* + * Check to see if we are freeing blocks across a group + * boundary. + */ + if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) { + goto error_return; + } + bitmap_bh = ext4_read_block_bitmap(sb, block_group); + if (!bitmap_bh) + goto error_return; + desc = ext4_get_group_desc(sb, block_group, &gd_bh); + if (!desc) + goto error_return; + + if (in_range(ext4_block_bitmap(sb, desc), block, count) || + in_range(ext4_inode_bitmap(sb, desc), block, count) || + in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) || + in_range(block + count - 1, ext4_inode_table(sb, desc), + sbi->s_itb_per_group)) { + ext4_error(sb, "Adding blocks in system zones - " + "Block = %llu, count = %lu", + block, count); + goto error_return; + } + + /* + * We are about to add blocks to the bitmap, + * so we need undo access. + */ + BUFFER_TRACE(bitmap_bh, "getting undo access"); + err = ext4_journal_get_undo_access(handle, bitmap_bh); + if (err) + goto error_return; + + /* + * We are about to modify some metadata. Call the journal APIs + * to unshare ->b_data if a currently-committing transaction is + * using it + */ + BUFFER_TRACE(gd_bh, "get_write_access"); + err = ext4_journal_get_write_access(handle, gd_bh); + if (err) + goto error_return; + /* + * make sure we don't allow a parallel init on other groups in the + * same buddy cache + */ + down_write(&grp->alloc_sem); + for (i = 0, blocks_freed = 0; i < count; i++) { + BUFFER_TRACE(bitmap_bh, "clear bit"); + if (!ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group), + bit + i, bitmap_bh->b_data)) { + ext4_error(sb, "bit already cleared for block %llu", + (ext4_fsblk_t)(block + i)); + BUFFER_TRACE(bitmap_bh, "bit already cleared"); + } else { + blocks_freed++; + } + } + ext4_lock_group(sb, block_group); + blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc); + ext4_free_blks_set(sb, desc, blk_free_count); + desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc); + ext4_unlock_group(sb, block_group); + percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed); + + if (sbi->s_log_groups_per_flex) { + ext4_group_t flex_group = ext4_flex_group(sbi, block_group); + atomic_add(blocks_freed, + &sbi->s_flex_groups[flex_group].free_blocks); + } + /* + * request to reload the buddy with the + * new bitmap information + */ + set_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &(grp->bb_state)); + grp->bb_free += blocks_freed; + up_write(&grp->alloc_sem); + + /* We dirtied the bitmap block */ + BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); + err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); + + /* And the group descriptor block */ + BUFFER_TRACE(gd_bh, "dirtied group descriptor block"); + ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh); + if (!err) + err = ret; + +error_return: + brelse(bitmap_bh); + ext4_std_error(sb, err); + return; +} + /** * ext4_has_free_blocks() * @sbi: in-core super block structure. @@ -369,8 +493,7 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) * Check if filesystem has nblocks free & available for allocation. * On success return 1, return 0 on failure. */ -static int ext4_has_free_blocks(struct ext4_sb_info *sbi, - s64 nblocks, unsigned int flags) +static int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) { s64 free_blocks, dirty_blocks, root_blocks; struct percpu_counter *fbc = &sbi->s_freeblocks_counter; @@ -384,6 +507,11 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi, EXT4_FREEBLOCKS_WATERMARK) { free_blocks = percpu_counter_sum_positive(fbc); dirty_blocks = percpu_counter_sum_positive(dbc); + if (dirty_blocks < 0) { + printk(KERN_CRIT "Dirty block accounting " + "went wrong %lld\n", + (long long)dirty_blocks); + } } /* Check whether we have space after * accounting for current dirty blocks & root reserved blocks. @@ -394,9 +522,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi, /* Hm, nope. Are (enough) root reserved blocks available? */ if (sbi->s_resuid == current_fsuid() || ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) || - capable(CAP_SYS_RESOURCE) || - (flags & EXT4_MB_USE_ROOT_BLOCKS)) { - + capable(CAP_SYS_RESOURCE)) { if (free_blocks >= (nblocks + dirty_blocks)) return 1; } @@ -405,9 +531,9 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi, } int ext4_claim_free_blocks(struct ext4_sb_info *sbi, - s64 nblocks, unsigned int flags) + s64 nblocks) { - if (ext4_has_free_blocks(sbi, nblocks, flags)) { + if (ext4_has_free_blocks(sbi, nblocks)) { percpu_counter_add(&sbi->s_dirtyblocks_counter, nblocks); return 0; } else @@ -428,7 +554,7 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi, */ int ext4_should_retry_alloc(struct super_block *sb, int *retries) { - if (!ext4_has_free_blocks(EXT4_SB(sb), 1, 0) || + if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || (*retries)++ > 3 || !EXT4_SB(sb)->s_journal) return 0; @@ -451,8 +577,7 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries) * error stores in errp pointer */ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, - ext4_fsblk_t goal, unsigned int flags, - unsigned long *count, int *errp) + ext4_fsblk_t goal, unsigned long *count, int *errp) { struct ext4_allocation_request ar; ext4_fsblk_t ret; @@ -462,7 +587,6 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, ar.inode = inode; ar.goal = goal; ar.len = count ? *count : 1; - ar.flags = flags; ret = ext4_mb_new_blocks(handle, &ar, errp); if (count) diff --git a/trunk/fs/ext4/ext4.h b/trunk/fs/ext4/ext4.h index a74b89c09f90..4daaf2b753f4 100644 --- a/trunk/fs/ext4/ext4.h +++ b/trunk/fs/ext4/ext4.h @@ -108,8 +108,7 @@ typedef unsigned int ext4_group_t; #define EXT4_MB_DELALLOC_RESERVED 0x0400 /* We are doing stream allocation */ #define EXT4_MB_STREAM_ALLOC 0x0800 -/* Use reserved root blocks if needed */ -#define EXT4_MB_USE_ROOT_BLOCKS 0x1000 + struct ext4_allocation_request { /* target inode for block we're allocating */ @@ -210,8 +209,6 @@ struct ext4_io_submit { */ #define EXT4_BAD_INO 1 /* Bad blocks inode */ #define EXT4_ROOT_INO 2 /* Root inode */ -#define EXT4_USR_QUOTA_INO 3 /* User quota inode */ -#define EXT4_GRP_QUOTA_INO 4 /* Group quota inode */ #define EXT4_BOOT_LOADER_INO 5 /* Boot loader inode */ #define EXT4_UNDEL_DIR_INO 6 /* Undelete directory inode */ #define EXT4_RESIZE_INO 7 /* Reserved group descriptors inode */ @@ -515,10 +512,6 @@ struct ext4_new_group_data { /* Convert extent to initialized after IO complete */ #define EXT4_GET_BLOCKS_IO_CONVERT_EXT (EXT4_GET_BLOCKS_CONVERT|\ EXT4_GET_BLOCKS_CREATE_UNINIT_EXT) - /* Punch out blocks of an extent */ -#define EXT4_GET_BLOCKS_PUNCH_OUT_EXT 0x0020 - /* Don't normalize allocation size (used for fallocate) */ -#define EXT4_GET_BLOCKS_NO_NORMALIZE 0x0040 /* * Flags used by ext4_free_blocks @@ -1035,7 +1028,7 @@ struct ext4_super_block { __le16 s_want_extra_isize; /* New inodes should reserve # bytes */ __le32 s_flags; /* Miscellaneous flags */ __le16 s_raid_stride; /* RAID stride */ - __le16 s_mmp_update_interval; /* # seconds to wait in MMP checking */ + __le16 s_mmp_interval; /* # seconds to wait in MMP checking */ __le64 s_mmp_block; /* Block for multi-mount protection */ __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ __u8 s_log_groups_per_flex; /* FLEX_BG group size */ @@ -1151,9 +1144,6 @@ struct ext4_sb_info { unsigned long s_ext_blocks; unsigned long s_ext_extents; #endif - /* ext4 extent cache stats */ - unsigned long extent_cache_hits; - unsigned long extent_cache_misses; /* for buddy allocator */ struct ext4_group_info ***s_group_info; @@ -1211,9 +1201,6 @@ struct ext4_sb_info { struct ext4_li_request *s_li_request; /* Wait multiplier for lazy initialization thread */ unsigned int s_li_wait_mult; - - /* Kernel thread for multiple mount protection */ - struct task_struct *s_mmp_tsk; }; static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) @@ -1351,7 +1338,6 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 -#define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100 #define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 #define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002 @@ -1365,29 +1351,13 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) #define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400 /* EA in inode */ #define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 /* data in dirent */ -#define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR -#define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ - EXT4_FEATURE_INCOMPAT_META_BG) -#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ - EXT4_FEATURE_RO_COMPAT_BTREE_DIR) - -#define EXT3_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR -#define EXT3_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ - EXT4_FEATURE_INCOMPAT_RECOVER| \ - EXT4_FEATURE_INCOMPAT_META_BG) -#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ - EXT4_FEATURE_RO_COMPAT_BTREE_DIR) - #define EXT4_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR #define EXT4_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ EXT4_FEATURE_INCOMPAT_RECOVER| \ EXT4_FEATURE_INCOMPAT_META_BG| \ EXT4_FEATURE_INCOMPAT_EXTENTS| \ EXT4_FEATURE_INCOMPAT_64BIT| \ - EXT4_FEATURE_INCOMPAT_FLEX_BG| \ - EXT4_FEATURE_INCOMPAT_MMP) + EXT4_FEATURE_INCOMPAT_FLEX_BG) #define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \ @@ -1620,6 +1590,12 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, */ struct ext4_lazy_init { unsigned long li_state; + + wait_queue_head_t li_wait_daemon; + wait_queue_head_t li_wait_task; + struct timer_list li_timer; + struct task_struct *li_task; + struct list_head li_request_list; struct mutex li_list_mtx; }; @@ -1638,67 +1614,6 @@ struct ext4_features { struct completion f_kobj_unregister; }; -/* - * This structure will be used for multiple mount protection. It will be - * written into the block number saved in the s_mmp_block field in the - * superblock. Programs that check MMP should assume that if - * SEQ_FSCK (or any unknown code above SEQ_MAX) is present then it is NOT safe - * to use the filesystem, regardless of how old the timestamp is. - */ -#define EXT4_MMP_MAGIC 0x004D4D50U /* ASCII for MMP */ -#define EXT4_MMP_SEQ_CLEAN 0xFF4D4D50U /* mmp_seq value for clean unmount */ -#define EXT4_MMP_SEQ_FSCK 0xE24D4D50U /* mmp_seq value when being fscked */ -#define EXT4_MMP_SEQ_MAX 0xE24D4D4FU /* maximum valid mmp_seq value */ - -struct mmp_struct { - __le32 mmp_magic; /* Magic number for MMP */ - __le32 mmp_seq; /* Sequence no. updated periodically */ - - /* - * mmp_time, mmp_nodename & mmp_bdevname are only used for information - * purposes and do not affect the correctness of the algorithm - */ - __le64 mmp_time; /* Time last updated */ - char mmp_nodename[64]; /* Node which last updated MMP block */ - char mmp_bdevname[32]; /* Bdev which last updated MMP block */ - - /* - * mmp_check_interval is used to verify if the MMP block has been - * updated on the block device. The value is updated based on the - * maximum time to write the MMP block during an update cycle. - */ - __le16 mmp_check_interval; - - __le16 mmp_pad1; - __le32 mmp_pad2[227]; -}; - -/* arguments passed to the mmp thread */ -struct mmpd_data { - struct buffer_head *bh; /* bh from initial read_mmp_block() */ - struct super_block *sb; /* super block of the fs */ -}; - -/* - * Check interval multiplier - * The MMP block is written every update interval and initially checked every - * update interval x the multiplier (the value is then adapted based on the - * write latency). The reason is that writes can be delayed under load and we - * don't want readers to incorrectly assume that the filesystem is no longer - * in use. - */ -#define EXT4_MMP_CHECK_MULT 2UL - -/* - * Minimum interval for MMP checking in seconds. - */ -#define EXT4_MMP_MIN_CHECK_INTERVAL 5UL - -/* - * Maximum interval for MMP checking in seconds. - */ -#define EXT4_MMP_MAX_CHECK_INTERVAL 300UL - /* * Function prototypes */ @@ -1723,12 +1638,10 @@ extern int ext4_bg_has_super(struct super_block *sb, ext4_group_t group); extern unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group); extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, - ext4_fsblk_t goal, - unsigned int flags, - unsigned long *count, - int *errp); -extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, - s64 nblocks, unsigned int flags); + ext4_fsblk_t goal, unsigned long *count, int *errp); +extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); +extern void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, + ext4_fsblk_t block, unsigned long count); extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *); extern void ext4_check_blocks_bitmap(struct super_block *); extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, @@ -1793,8 +1706,6 @@ extern void ext4_free_blocks(handle_t *handle, struct inode *inode, unsigned long count, int flags); extern int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t i, struct ext4_group_desc *desc); -extern void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, - ext4_fsblk_t block, unsigned long count); extern int ext4_trim_fs(struct super_block *, struct fstrim_range *); /* inode.c */ @@ -1818,7 +1729,6 @@ extern int ext4_change_inode_journal_flag(struct inode *, int); extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *); extern int ext4_can_truncate(struct inode *inode); extern void ext4_truncate(struct inode *); -extern int ext4_punch_hole(struct file *file, loff_t offset, loff_t length); extern int ext4_truncate_restart_trans(handle_t *, struct inode *, int nblocks); extern void ext4_set_inode_flags(struct inode *); extern void ext4_get_inode_flags(struct ext4_inode_info *); @@ -1828,8 +1738,6 @@ extern int ext4_writepage_trans_blocks(struct inode *); extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); extern int ext4_block_truncate_page(handle_t *handle, struct address_space *mapping, loff_t from); -extern int ext4_block_zero_page_range(handle_t *handle, - struct address_space *mapping, loff_t from, loff_t length); extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); extern qsize_t *ext4_get_reserved_space(struct inode *inode); extern void ext4_da_update_reserve_space(struct inode *inode, @@ -1880,10 +1788,6 @@ extern void __ext4_warning(struct super_block *, const char *, unsigned int, __LINE__, ## message) extern void ext4_msg(struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); -extern void __dump_mmp_msg(struct super_block *, struct mmp_struct *mmp, - const char *, unsigned int, const char *); -#define dump_mmp_msg(sb, mmp, msg) __dump_mmp_msg(sb, mmp, __func__, \ - __LINE__, msg) extern void __ext4_grp_locked_error(const char *, unsigned int, \ struct super_block *, ext4_group_t, \ unsigned long, ext4_fsblk_t, \ @@ -2160,8 +2064,6 @@ extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, struct ext4_map_blocks *map, int flags); extern void ext4_ext_truncate(struct inode *); -extern int ext4_ext_punch_hole(struct file *file, loff_t offset, - loff_t length); extern void ext4_ext_init(struct super_block *); extern void ext4_ext_release(struct super_block *); extern long ext4_fallocate(struct file *file, int mode, loff_t offset, @@ -2190,9 +2092,6 @@ extern int ext4_bio_write_page(struct ext4_io_submit *io, int len, struct writeback_control *wbc); -/* mmp.c */ -extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t); - /* BH_Uninit flag: blocks are allocated but uninitialized on disk */ enum ext4_state_bits { BH_Uninit /* blocks are allocated but uninitialized on disk */ diff --git a/trunk/fs/ext4/ext4_jbd2.c b/trunk/fs/ext4/ext4_jbd2.c index f5240aa15601..6e272ef6ba96 100644 --- a/trunk/fs/ext4/ext4_jbd2.c +++ b/trunk/fs/ext4/ext4_jbd2.c @@ -6,6 +6,20 @@ #include +int __ext4_journal_get_undo_access(const char *where, unsigned int line, + handle_t *handle, struct buffer_head *bh) +{ + int err = 0; + + if (ext4_handle_valid(handle)) { + err = jbd2_journal_get_undo_access(handle, bh); + if (err) + ext4_journal_abort_handle(where, line, __func__, bh, + handle, err); + } + return err; +} + int __ext4_journal_get_write_access(const char *where, unsigned int line, handle_t *handle, struct buffer_head *bh) { diff --git a/trunk/fs/ext4/ext4_jbd2.h b/trunk/fs/ext4/ext4_jbd2.h index bb85757689b6..d0f53538a57f 100644 --- a/trunk/fs/ext4/ext4_jbd2.h +++ b/trunk/fs/ext4/ext4_jbd2.h @@ -126,6 +126,9 @@ void ext4_journal_abort_handle(const char *caller, unsigned int line, const char *err_fn, struct buffer_head *bh, handle_t *handle, int err); +int __ext4_journal_get_undo_access(const char *where, unsigned int line, + handle_t *handle, struct buffer_head *bh); + int __ext4_journal_get_write_access(const char *where, unsigned int line, handle_t *handle, struct buffer_head *bh); @@ -143,6 +146,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, int __ext4_handle_dirty_super(const char *where, unsigned int line, handle_t *handle, struct super_block *sb); +#define ext4_journal_get_undo_access(handle, bh) \ + __ext4_journal_get_undo_access(__func__, __LINE__, (handle), (bh)) #define ext4_journal_get_write_access(handle, bh) \ __ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh)) #define ext4_forget(handle, is_metadata, inode, bh, block_nr) \ diff --git a/trunk/fs/ext4/extents.c b/trunk/fs/ext4/extents.c index 5199bac7fc62..4890d6f3ad15 100644 --- a/trunk/fs/ext4/extents.c +++ b/trunk/fs/ext4/extents.c @@ -46,13 +46,6 @@ #include -static int ext4_split_extent(handle_t *handle, - struct inode *inode, - struct ext4_ext_path *path, - struct ext4_map_blocks *map, - int split_flag, - int flags); - static int ext4_ext_truncate_extend_restart(handle_t *handle, struct inode *inode, int needed) @@ -199,13 +192,12 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode, static ext4_fsblk_t ext4_ext_new_meta_block(handle_t *handle, struct inode *inode, struct ext4_ext_path *path, - struct ext4_extent *ex, int *err, unsigned int flags) + struct ext4_extent *ex, int *err) { ext4_fsblk_t goal, newblock; goal = ext4_ext_find_goal(inode, path, le32_to_cpu(ex->ee_block)); - newblock = ext4_new_meta_blocks(handle, inode, goal, flags, - NULL, err); + newblock = ext4_new_meta_blocks(handle, inode, goal, NULL, err); return newblock; } @@ -482,43 +474,9 @@ static void ext4_ext_show_leaf(struct inode *inode, struct ext4_ext_path *path) } ext_debug("\n"); } - -static void ext4_ext_show_move(struct inode *inode, struct ext4_ext_path *path, - ext4_fsblk_t newblock, int level) -{ - int depth = ext_depth(inode); - struct ext4_extent *ex; - - if (depth != level) { - struct ext4_extent_idx *idx; - idx = path[level].p_idx; - while (idx <= EXT_MAX_INDEX(path[level].p_hdr)) { - ext_debug("%d: move %d:%llu in new index %llu\n", level, - le32_to_cpu(idx->ei_block), - ext4_idx_pblock(idx), - newblock); - idx++; - } - - return; - } - - ex = path[depth].p_ext; - while (ex <= EXT_MAX_EXTENT(path[depth].p_hdr)) { - ext_debug("move %d:%llu:[%d]%d in new leaf %llu\n", - le32_to_cpu(ex->ee_block), - ext4_ext_pblock(ex), - ext4_ext_is_uninitialized(ex), - ext4_ext_get_actual_len(ex), - newblock); - ex++; - } -} - #else #define ext4_ext_show_path(inode, path) #define ext4_ext_show_leaf(inode, path) -#define ext4_ext_show_move(inode, path, newblock, level) #endif void ext4_ext_drop_refs(struct ext4_ext_path *path) @@ -834,14 +792,14 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, * - initializes subtree */ static int ext4_ext_split(handle_t *handle, struct inode *inode, - unsigned int flags, - struct ext4_ext_path *path, - struct ext4_extent *newext, int at) + struct ext4_ext_path *path, + struct ext4_extent *newext, int at) { struct buffer_head *bh = NULL; int depth = ext_depth(inode); struct ext4_extent_header *neh; struct ext4_extent_idx *fidx; + struct ext4_extent *ex; int i = at, k, m, a; ext4_fsblk_t newblock, oldblock; __le32 border; @@ -889,7 +847,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, ext_debug("allocate %d blocks for indexes/leaf\n", depth - at); for (a = 0; a < depth - at; a++) { newblock = ext4_ext_new_meta_block(handle, inode, path, - newext, &err, flags); + newext, &err); if (newblock == 0) goto cleanup; ablocks[a] = newblock; @@ -918,6 +876,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0)); neh->eh_magic = EXT4_EXT_MAGIC; neh->eh_depth = 0; + ex = EXT_FIRST_EXTENT(neh); /* move remainder of path[depth] to the new leaf */ if (unlikely(path[depth].p_hdr->eh_entries != @@ -929,12 +888,25 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, goto cleanup; } /* start copy from next extent */ - m = EXT_MAX_EXTENT(path[depth].p_hdr) - path[depth].p_ext++; - ext4_ext_show_move(inode, path, newblock, depth); + /* TODO: we could do it by single memmove */ + m = 0; + path[depth].p_ext++; + while (path[depth].p_ext <= + EXT_MAX_EXTENT(path[depth].p_hdr)) { + ext_debug("move %d:%llu:[%d]%d in new leaf %llu\n", + le32_to_cpu(path[depth].p_ext->ee_block), + ext4_ext_pblock(path[depth].p_ext), + ext4_ext_is_uninitialized(path[depth].p_ext), + ext4_ext_get_actual_len(path[depth].p_ext), + newblock); + /*memmove(ex++, path[depth].p_ext++, + sizeof(struct ext4_extent)); + neh->eh_entries++;*/ + path[depth].p_ext++; + m++; + } if (m) { - struct ext4_extent *ex; - ex = EXT_FIRST_EXTENT(neh); - memmove(ex, path[depth].p_ext, sizeof(struct ext4_extent) * m); + memmove(ex, path[depth].p_ext-m, sizeof(struct ext4_extent)*m); le16_add_cpu(&neh->eh_entries, m); } @@ -996,8 +968,12 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, ext_debug("int.index at %d (block %llu): %u -> %llu\n", i, newblock, le32_to_cpu(border), oldblock); + /* copy indexes */ + m = 0; + path[i].p_idx++; - /* move remainder of path[i] to the new index block */ + ext_debug("cur 0x%p, last 0x%p\n", path[i].p_idx, + EXT_MAX_INDEX(path[i].p_hdr)); if (unlikely(EXT_MAX_INDEX(path[i].p_hdr) != EXT_LAST_INDEX(path[i].p_hdr))) { EXT4_ERROR_INODE(inode, @@ -1006,13 +982,20 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, err = -EIO; goto cleanup; } - /* start copy indexes */ - m = EXT_MAX_INDEX(path[i].p_hdr) - path[i].p_idx++; - ext_debug("cur 0x%p, last 0x%p\n", path[i].p_idx, - EXT_MAX_INDEX(path[i].p_hdr)); - ext4_ext_show_move(inode, path, newblock, i); + while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { + ext_debug("%d: move %d:%llu in new index %llu\n", i, + le32_to_cpu(path[i].p_idx->ei_block), + ext4_idx_pblock(path[i].p_idx), + newblock); + /*memmove(++fidx, path[i].p_idx++, + sizeof(struct ext4_extent_idx)); + neh->eh_entries++; + BUG_ON(neh->eh_entries > neh->eh_max);*/ + path[i].p_idx++; + m++; + } if (m) { - memmove(++fidx, path[i].p_idx, + memmove(++fidx, path[i].p_idx - m, sizeof(struct ext4_extent_idx) * m); le16_add_cpu(&neh->eh_entries, m); } @@ -1073,9 +1056,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, * just created block */ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, - unsigned int flags, - struct ext4_ext_path *path, - struct ext4_extent *newext) + struct ext4_ext_path *path, + struct ext4_extent *newext) { struct ext4_ext_path *curp = path; struct ext4_extent_header *neh; @@ -1083,8 +1065,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, ext4_fsblk_t newblock; int err = 0; - newblock = ext4_ext_new_meta_block(handle, inode, path, - newext, &err, flags); + newblock = ext4_ext_new_meta_block(handle, inode, path, newext, &err); if (newblock == 0) return err; @@ -1159,9 +1140,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, * if no free index is found, then it requests in-depth growing. */ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode, - unsigned int flags, - struct ext4_ext_path *path, - struct ext4_extent *newext) + struct ext4_ext_path *path, + struct ext4_extent *newext) { struct ext4_ext_path *curp; int depth, i, err = 0; @@ -1181,7 +1161,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode, if (EXT_HAS_FREE_INDEX(curp)) { /* if we found index with free entry, then use that * entry: create all needed subtree and add new leaf */ - err = ext4_ext_split(handle, inode, flags, path, newext, i); + err = ext4_ext_split(handle, inode, path, newext, i); if (err) goto out; @@ -1194,8 +1174,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode, err = PTR_ERR(path); } else { /* tree is full, time to grow in depth */ - err = ext4_ext_grow_indepth(handle, inode, flags, - path, newext); + err = ext4_ext_grow_indepth(handle, inode, path, newext); if (err) goto out; @@ -1584,7 +1563,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, * Returns 0 if the extents (ex and ex+1) were _not_ merged and returns * 1 if they got merged. */ -static int ext4_ext_try_to_merge_right(struct inode *inode, +static int ext4_ext_try_to_merge(struct inode *inode, struct ext4_ext_path *path, struct ext4_extent *ex) { @@ -1623,31 +1602,6 @@ static int ext4_ext_try_to_merge_right(struct inode *inode, return merge_done; } -/* - * This function tries to merge the @ex extent to neighbours in the tree. - * return 1 if merge left else 0. - */ -static int ext4_ext_try_to_merge(struct inode *inode, - struct ext4_ext_path *path, - struct ext4_extent *ex) { - struct ext4_extent_header *eh; - unsigned int depth; - int merge_done = 0; - int ret = 0; - - depth = ext_depth(inode); - BUG_ON(path[depth].p_hdr == NULL); - eh = path[depth].p_hdr; - - if (ex > EXT_FIRST_EXTENT(eh)) - merge_done = ext4_ext_try_to_merge_right(inode, path, ex - 1); - - if (!merge_done) - ret = ext4_ext_try_to_merge_right(inode, path, ex); - - return ret; -} - /* * check if a portion of the "newext" extent overlaps with an * existing extent. @@ -1714,7 +1668,6 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, int depth, len, err; ext4_lblk_t next; unsigned uninitialized = 0; - int flags = 0; if (unlikely(ext4_ext_get_actual_len(newext) == 0)) { EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0"); @@ -1789,9 +1742,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, * There is no free space in the found leaf. * We're gonna add a new leaf in the tree. */ - if (flag & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) - flags = EXT4_MB_USE_ROOT_BLOCKS; - err = ext4_ext_create_new_leaf(handle, inode, flags, path, newext); + err = ext4_ext_create_new_leaf(handle, inode, path, newext); if (err) goto cleanup; depth = ext_depth(inode); @@ -2052,25 +2003,13 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, } /* - * ext4_ext_in_cache() - * Checks to see if the given block is in the cache. - * If it is, the cached extent is stored in the given - * cache extent pointer. If the cached extent is a hole, - * this routine should be used instead of - * ext4_ext_in_cache if the calling function needs to - * know the size of the hole. - * - * @inode: The files inode - * @block: The block to look for in the cache - * @ex: Pointer where the cached extent will be stored - * if it contains block - * * Return 0 if cache is invalid; 1 if the cache is valid */ -static int ext4_ext_check_cache(struct inode *inode, ext4_lblk_t block, - struct ext4_ext_cache *ex){ +static int +ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block, + struct ext4_extent *ex) +{ struct ext4_ext_cache *cex; - struct ext4_sb_info *sbi; int ret = 0; /* @@ -2078,59 +2017,25 @@ static int ext4_ext_check_cache(struct inode *inode, ext4_lblk_t block, */ spin_lock(&EXT4_I(inode)->i_block_reservation_lock); cex = &EXT4_I(inode)->i_cached_extent; - sbi = EXT4_SB(inode->i_sb); /* has cache valid data? */ if (cex->ec_len == 0) goto errout; if (in_range(block, cex->ec_block, cex->ec_len)) { - memcpy(ex, cex, sizeof(struct ext4_ext_cache)); + ex->ee_block = cpu_to_le32(cex->ec_block); + ext4_ext_store_pblock(ex, cex->ec_start); + ex->ee_len = cpu_to_le16(cex->ec_len); ext_debug("%u cached by %u:%u:%llu\n", block, cex->ec_block, cex->ec_len, cex->ec_start); ret = 1; } errout: - if (!ret) - sbi->extent_cache_misses++; - else - sbi->extent_cache_hits++; spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); return ret; } -/* - * ext4_ext_in_cache() - * Checks to see if the given block is in the cache. - * If it is, the cached extent is stored in the given - * extent pointer. - * - * @inode: The files inode - * @block: The block to look for in the cache - * @ex: Pointer where the cached extent will be stored - * if it contains block - * - * Return 0 if cache is invalid; 1 if the cache is valid - */ -static int -ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block, - struct ext4_extent *ex) -{ - struct ext4_ext_cache cex; - int ret = 0; - - if (ext4_ext_check_cache(inode, block, &cex)) { - ex->ee_block = cpu_to_le32(cex.ec_block); - ext4_ext_store_pblock(ex, cex.ec_start); - ex->ee_len = cpu_to_le16(cex.ec_len); - ret = 1; - } - - return ret; -} - - /* * ext4_ext_rm_idx: * removes index from the index block. @@ -2258,16 +2163,8 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, ext4_free_blocks(handle, inode, NULL, start, num, flags); } else if (from == le32_to_cpu(ex->ee_block) && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { - /* head removal */ - ext4_lblk_t num; - ext4_fsblk_t start; - - num = to - from; - start = ext4_ext_pblock(ex); - - ext_debug("free first %u blocks starting %llu\n", num, start); - ext4_free_blocks(handle, inode, 0, start, num, flags); - + printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", + from, to, le32_to_cpu(ex->ee_block), ee_len); } else { printk(KERN_INFO "strange request: removal(2) " "%u-%u from %u:%u\n", @@ -2276,22 +2173,9 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, return 0; } - -/* - * ext4_ext_rm_leaf() Removes the extents associated with the - * blocks appearing between "start" and "end", and splits the extents - * if "start" and "end" appear in the same extent - * - * @handle: The journal handle - * @inode: The files inode - * @path: The path to the leaf - * @start: The first block to remove - * @end: The last block to remove - */ static int ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, - struct ext4_ext_path *path, ext4_lblk_t start, - ext4_lblk_t end) + struct ext4_ext_path *path, ext4_lblk_t start) { int err = 0, correct_index = 0; int depth = ext_depth(inode), credits; @@ -2302,7 +2186,6 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, unsigned short ex_ee_len; unsigned uninitialized = 0; struct ext4_extent *ex; - struct ext4_map_blocks map; /* the header must be checked already in ext4_ext_remove_space() */ ext_debug("truncate since %u in leaf\n", start); @@ -2332,95 +2215,31 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, path[depth].p_ext = ex; a = ex_ee_block > start ? ex_ee_block : start; - b = ex_ee_block+ex_ee_len - 1 < end ? - ex_ee_block+ex_ee_len - 1 : end; + b = ex_ee_block + ex_ee_len - 1 < EXT_MAX_BLOCK ? + ex_ee_block + ex_ee_len - 1 : EXT_MAX_BLOCK; ext_debug(" border %u:%u\n", a, b); - /* If this extent is beyond the end of the hole, skip it */ - if (end <= ex_ee_block) { - ex--; - ex_ee_block = le32_to_cpu(ex->ee_block); - ex_ee_len = ext4_ext_get_actual_len(ex); - continue; - } else if (a != ex_ee_block && - b != ex_ee_block + ex_ee_len - 1) { - /* - * If this is a truncate, then this condition should - * never happen because at least one of the end points - * needs to be on the edge of the extent. - */ - if (end == EXT_MAX_BLOCK) { - ext_debug(" bad truncate %u:%u\n", - start, end); - block = 0; - num = 0; - err = -EIO; - goto out; - } - /* - * else this is a hole punch, so the extent needs to - * be split since neither edge of the hole is on the - * extent edge - */ - else{ - map.m_pblk = ext4_ext_pblock(ex); - map.m_lblk = ex_ee_block; - map.m_len = b - ex_ee_block; - - err = ext4_split_extent(handle, - inode, path, &map, 0, - EXT4_GET_BLOCKS_PUNCH_OUT_EXT | - EXT4_GET_BLOCKS_PRE_IO); - - if (err < 0) - goto out; - - ex_ee_len = ext4_ext_get_actual_len(ex); - - b = ex_ee_block+ex_ee_len - 1 < end ? - ex_ee_block+ex_ee_len - 1 : end; - - /* Then remove tail of this extent */ - block = ex_ee_block; - num = a - block; - } + if (a != ex_ee_block && b != ex_ee_block + ex_ee_len - 1) { + block = 0; + num = 0; + BUG(); } else if (a != ex_ee_block) { /* remove tail of the extent */ block = ex_ee_block; num = a - block; } else if (b != ex_ee_block + ex_ee_len - 1) { /* remove head of the extent */ - block = b; - num = ex_ee_block + ex_ee_len - b; - - /* - * If this is a truncate, this condition - * should never happen - */ - if (end == EXT_MAX_BLOCK) { - ext_debug(" bad truncate %u:%u\n", - start, end); - err = -EIO; - goto out; - } + block = a; + num = b - a; + /* there is no "make a hole" API yet */ + BUG(); } else { /* remove whole extent: excellent! */ block = ex_ee_block; num = 0; - if (a != ex_ee_block) { - ext_debug(" bad truncate %u:%u\n", - start, end); - err = -EIO; - goto out; - } - - if (b != ex_ee_block + ex_ee_len - 1) { - ext_debug(" bad truncate %u:%u\n", - start, end); - err = -EIO; - goto out; - } + BUG_ON(a != ex_ee_block); + BUG_ON(b != ex_ee_block + ex_ee_len - 1); } /* @@ -2451,13 +2270,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, if (num == 0) { /* this extent is removed; mark slot entirely unused */ ext4_ext_store_pblock(ex, 0); - } else if (block != ex_ee_block) { - /* - * If this was a head removal, then we need to update - * the physical block since it is now at a different - * location - */ - ext4_ext_store_pblock(ex, ext4_ext_pblock(ex) + (b-a)); + le16_add_cpu(&eh->eh_entries, -1); } ex->ee_block = cpu_to_le32(block); @@ -2473,27 +2286,6 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, if (err) goto out; - /* - * If the extent was completely released, - * we need to remove it from the leaf - */ - if (num == 0) { - if (end != EXT_MAX_BLOCK) { - /* - * For hole punching, we need to scoot all the - * extents up when an extent is removed so that - * we dont have blank extents in the middle - */ - memmove(ex, ex+1, (EXT_LAST_EXTENT(eh) - ex) * - sizeof(struct ext4_extent)); - - /* Now get rid of the one at the end */ - memset(EXT_LAST_EXTENT(eh), 0, - sizeof(struct ext4_extent)); - } - le16_add_cpu(&eh->eh_entries, -1); - } - ext_debug("new extent: %u:%u:%llu\n", block, num, ext4_ext_pblock(ex)); ex--; @@ -2534,8 +2326,7 @@ ext4_ext_more_to_rm(struct ext4_ext_path *path) return 1; } -static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, - ext4_lblk_t end) +static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start) { struct super_block *sb = inode->i_sb; int depth = ext_depth(inode); @@ -2574,8 +2365,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, while (i >= 0 && err == 0) { if (i == depth) { /* this is leaf block */ - err = ext4_ext_rm_leaf(handle, inode, path, - start, end); + err = ext4_ext_rm_leaf(handle, inode, path, start); /* root level has p_bh == NULL, brelse() eats this */ brelse(path[i].p_bh); path[i].p_bh = NULL; @@ -2739,195 +2529,6 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex) return ret; } -/* - * used by extent splitting. - */ -#define EXT4_EXT_MAY_ZEROOUT 0x1 /* safe to zeroout if split fails \ - due to ENOSPC */ -#define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ -#define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ - -/* - * ext4_split_extent_at() splits an extent at given block. - * - * @handle: the journal handle - * @inode: the file inode - * @path: the path to the extent - * @split: the logical block where the extent is splitted. - * @split_flags: indicates if the extent could be zeroout if split fails, and - * the states(init or uninit) of new extents. - * @flags: flags used to insert new extent to extent tree. - * - * - * Splits extent [a, b] into two extents [a, @split) and [@split, b], states - * of which are deterimined by split_flag. - * - * There are two cases: - * a> the extent are splitted into two extent. - * b> split is not needed, and just mark the extent. - * - * return 0 on success. - */ -static int ext4_split_extent_at(handle_t *handle, - struct inode *inode, - struct ext4_ext_path *path, - ext4_lblk_t split, - int split_flag, - int flags) -{ - ext4_fsblk_t newblock; - ext4_lblk_t ee_block; - struct ext4_extent *ex, newex, orig_ex; - struct ext4_extent *ex2 = NULL; - unsigned int ee_len, depth; - int err = 0; - - ext_debug("ext4_split_extents_at: inode %lu, logical" - "block %llu\n", inode->i_ino, (unsigned long long)split); - - ext4_ext_show_leaf(inode, path); - - depth = ext_depth(inode); - ex = path[depth].p_ext; - ee_block = le32_to_cpu(ex->ee_block); - ee_len = ext4_ext_get_actual_len(ex); - newblock = split - ee_block + ext4_ext_pblock(ex); - - BUG_ON(split < ee_block || split >= (ee_block + ee_len)); - - err = ext4_ext_get_access(handle, inode, path + depth); - if (err) - goto out; - - if (split == ee_block) { - /* - * case b: block @split is the block that the extent begins with - * then we just change the state of the extent, and splitting - * is not needed. - */ - if (split_flag & EXT4_EXT_MARK_UNINIT2) - ext4_ext_mark_uninitialized(ex); - else - ext4_ext_mark_initialized(ex); - - if (!(flags & EXT4_GET_BLOCKS_PRE_IO)) - ext4_ext_try_to_merge(inode, path, ex); - - err = ext4_ext_dirty(handle, inode, path + depth); - goto out; - } - - /* case a */ - memcpy(&orig_ex, ex, sizeof(orig_ex)); - ex->ee_len = cpu_to_le16(split - ee_block); - if (split_flag & EXT4_EXT_MARK_UNINIT1) - ext4_ext_mark_uninitialized(ex); - - /* - * path may lead to new leaf, not to original leaf any more - * after ext4_ext_insert_extent() returns, - */ - err = ext4_ext_dirty(handle, inode, path + depth); - if (err) - goto fix_extent_len; - - ex2 = &newex; - ex2->ee_block = cpu_to_le32(split); - ex2->ee_len = cpu_to_le16(ee_len - (split - ee_block)); - ext4_ext_store_pblock(ex2, newblock); - if (split_flag & EXT4_EXT_MARK_UNINIT2) - ext4_ext_mark_uninitialized(ex2); - - err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); - if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { - err = ext4_ext_zeroout(inode, &orig_ex); - if (err) - goto fix_extent_len; - /* update the extent length and mark as initialized */ - ex->ee_len = cpu_to_le32(ee_len); - ext4_ext_try_to_merge(inode, path, ex); - err = ext4_ext_dirty(handle, inode, path + depth); - goto out; - } else if (err) - goto fix_extent_len; - -out: - ext4_ext_show_leaf(inode, path); - return err; - -fix_extent_len: - ex->ee_len = orig_ex.ee_len; - ext4_ext_dirty(handle, inode, path + depth); - return err; -} - -/* - * ext4_split_extents() splits an extent and mark extent which is covered - * by @map as split_flags indicates - * - * It may result in splitting the extent into multiple extents (upto three) - * There are three possibilities: - * a> There is no split required - * b> Splits in two extents: Split is happening at either end of the extent - * c> Splits in three extents: Somone is splitting in middle of the extent - * - */ -static int ext4_split_extent(handle_t *handle, - struct inode *inode, - struct ext4_ext_path *path, - struct ext4_map_blocks *map, - int split_flag, - int flags) -{ - ext4_lblk_t ee_block; - struct ext4_extent *ex; - unsigned int ee_len, depth; - int err = 0; - int uninitialized; - int split_flag1, flags1; - - depth = ext_depth(inode); - ex = path[depth].p_ext; - ee_block = le32_to_cpu(ex->ee_block); - ee_len = ext4_ext_get_actual_len(ex); - uninitialized = ext4_ext_is_uninitialized(ex); - - if (map->m_lblk + map->m_len < ee_block + ee_len) { - split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? - EXT4_EXT_MAY_ZEROOUT : 0; - flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; - if (uninitialized) - split_flag1 |= EXT4_EXT_MARK_UNINIT1 | - EXT4_EXT_MARK_UNINIT2; - err = ext4_split_extent_at(handle, inode, path, - map->m_lblk + map->m_len, split_flag1, flags1); - if (err) - goto out; - } - - ext4_ext_drop_refs(path); - path = ext4_ext_find_extent(inode, map->m_lblk, path); - if (IS_ERR(path)) - return PTR_ERR(path); - - if (map->m_lblk >= ee_block) { - split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? - EXT4_EXT_MAY_ZEROOUT : 0; - if (uninitialized) - split_flag1 |= EXT4_EXT_MARK_UNINIT1; - if (split_flag & EXT4_EXT_MARK_UNINIT2) - split_flag1 |= EXT4_EXT_MARK_UNINIT2; - err = ext4_split_extent_at(handle, inode, path, - map->m_lblk, split_flag1, flags); - if (err) - goto out; - } - - ext4_ext_show_leaf(inode, path); -out: - return err ? err : map->m_len; -} - #define EXT4_EXT_ZERO_LEN 7 /* * This function is called by ext4_ext_map_blocks() if someone tries to write @@ -2944,13 +2545,17 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, struct ext4_map_blocks *map, struct ext4_ext_path *path) { - struct ext4_map_blocks split_map; - struct ext4_extent zero_ex; - struct ext4_extent *ex; + struct ext4_extent *ex, newex, orig_ex; + struct ext4_extent *ex1 = NULL; + struct ext4_extent *ex2 = NULL; + struct ext4_extent *ex3 = NULL; + struct ext4_extent_header *eh; ext4_lblk_t ee_block, eof_block; unsigned int allocated, ee_len, depth; + ext4_fsblk_t newblock; int err = 0; - int split_flag = 0; + int ret = 0; + int may_zeroout; ext_debug("ext4_ext_convert_to_initialized: inode %lu, logical" "block %llu, max_blocks %u\n", inode->i_ino, @@ -2962,86 +2567,280 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, eof_block = map->m_lblk + map->m_len; depth = ext_depth(inode); + eh = path[depth].p_hdr; ex = path[depth].p_ext; ee_block = le32_to_cpu(ex->ee_block); ee_len = ext4_ext_get_actual_len(ex); allocated = ee_len - (map->m_lblk - ee_block); + newblock = map->m_lblk - ee_block + ext4_ext_pblock(ex); + + ex2 = ex; + orig_ex.ee_block = ex->ee_block; + orig_ex.ee_len = cpu_to_le16(ee_len); + ext4_ext_store_pblock(&orig_ex, ext4_ext_pblock(ex)); - WARN_ON(map->m_lblk < ee_block); /* * It is safe to convert extent to initialized via explicit * zeroout only if extent is fully insde i_size or new_size. */ - split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; + may_zeroout = ee_block + ee_len <= eof_block; + err = ext4_ext_get_access(handle, inode, path + depth); + if (err) + goto out; /* If extent has less than 2*EXT4_EXT_ZERO_LEN zerout directly */ - if (ee_len <= 2*EXT4_EXT_ZERO_LEN && - (EXT4_EXT_MAY_ZEROOUT & split_flag)) { - err = ext4_ext_zeroout(inode, ex); - if (err) - goto out; - - err = ext4_ext_get_access(handle, inode, path + depth); + if (ee_len <= 2*EXT4_EXT_ZERO_LEN && may_zeroout) { + err = ext4_ext_zeroout(inode, &orig_ex); if (err) - goto out; - ext4_ext_mark_initialized(ex); - ext4_ext_try_to_merge(inode, path, ex); - err = ext4_ext_dirty(handle, inode, path + depth); - goto out; + goto fix_extent_len; + /* update the extent length and mark as initialized */ + ex->ee_block = orig_ex.ee_block; + ex->ee_len = orig_ex.ee_len; + ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex)); + ext4_ext_dirty(handle, inode, path + depth); + /* zeroed the full extent */ + return allocated; } + /* ex1: ee_block to map->m_lblk - 1 : uninitialized */ + if (map->m_lblk > ee_block) { + ex1 = ex; + ex1->ee_len = cpu_to_le16(map->m_lblk - ee_block); + ext4_ext_mark_uninitialized(ex1); + ex2 = &newex; + } /* - * four cases: - * 1. split the extent into three extents. - * 2. split the extent into two extents, zeroout the first half. - * 3. split the extent into two extents, zeroout the second half. - * 4. split the extent into two extents with out zeroout. + * for sanity, update the length of the ex2 extent before + * we insert ex3, if ex1 is NULL. This is to avoid temporary + * overlap of blocks. */ - split_map.m_lblk = map->m_lblk; - split_map.m_len = map->m_len; - + if (!ex1 && allocated > map->m_len) + ex2->ee_len = cpu_to_le16(map->m_len); + /* ex3: to ee_block + ee_len : uninitialised */ if (allocated > map->m_len) { - if (allocated <= EXT4_EXT_ZERO_LEN && - (EXT4_EXT_MAY_ZEROOUT & split_flag)) { - /* case 3 */ - zero_ex.ee_block = - cpu_to_le32(map->m_lblk); - zero_ex.ee_len = cpu_to_le16(allocated); - ext4_ext_store_pblock(&zero_ex, - ext4_ext_pblock(ex) + map->m_lblk - ee_block); - err = ext4_ext_zeroout(inode, &zero_ex); - if (err) - goto out; - split_map.m_lblk = map->m_lblk; - split_map.m_len = allocated; - } else if ((map->m_lblk - ee_block + map->m_len < - EXT4_EXT_ZERO_LEN) && - (EXT4_EXT_MAY_ZEROOUT & split_flag)) { - /* case 2 */ - if (map->m_lblk != ee_block) { - zero_ex.ee_block = ex->ee_block; - zero_ex.ee_len = cpu_to_le16(map->m_lblk - - ee_block); - ext4_ext_store_pblock(&zero_ex, - ext4_ext_pblock(ex)); - err = ext4_ext_zeroout(inode, &zero_ex); - if (err) - goto out; - } + unsigned int newdepth; + /* If extent has less than EXT4_EXT_ZERO_LEN zerout directly */ + if (allocated <= EXT4_EXT_ZERO_LEN && may_zeroout) { + /* + * map->m_lblk == ee_block is handled by the zerouout + * at the beginning. + * Mark first half uninitialized. + * Mark second half initialized and zero out the + * initialized extent + */ + ex->ee_block = orig_ex.ee_block; + ex->ee_len = cpu_to_le16(ee_len - allocated); + ext4_ext_mark_uninitialized(ex); + ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex)); + ext4_ext_dirty(handle, inode, path + depth); + + ex3 = &newex; + ex3->ee_block = cpu_to_le32(map->m_lblk); + ext4_ext_store_pblock(ex3, newblock); + ex3->ee_len = cpu_to_le16(allocated); + err = ext4_ext_insert_extent(handle, inode, path, + ex3, 0); + if (err == -ENOSPC) { + err = ext4_ext_zeroout(inode, &orig_ex); + if (err) + goto fix_extent_len; + ex->ee_block = orig_ex.ee_block; + ex->ee_len = orig_ex.ee_len; + ext4_ext_store_pblock(ex, + ext4_ext_pblock(&orig_ex)); + ext4_ext_dirty(handle, inode, path + depth); + /* blocks available from map->m_lblk */ + return allocated; + + } else if (err) + goto fix_extent_len; + + /* + * We need to zero out the second half because + * an fallocate request can update file size and + * converting the second half to initialized extent + * implies that we can leak some junk data to user + * space. + */ + err = ext4_ext_zeroout(inode, ex3); + if (err) { + /* + * We should actually mark the + * second half as uninit and return error + * Insert would have changed the extent + */ + depth = ext_depth(inode); + ext4_ext_drop_refs(path); + path = ext4_ext_find_extent(inode, map->m_lblk, + path); + if (IS_ERR(path)) { + err = PTR_ERR(path); + return err; + } + /* get the second half extent details */ + ex = path[depth].p_ext; + err = ext4_ext_get_access(handle, inode, + path + depth); + if (err) + return err; + ext4_ext_mark_uninitialized(ex); + ext4_ext_dirty(handle, inode, path + depth); + return err; + } - split_map.m_lblk = ee_block; - split_map.m_len = map->m_lblk - ee_block + map->m_len; - allocated = map->m_len; + /* zeroed the second half */ + return allocated; } - } + ex3 = &newex; + ex3->ee_block = cpu_to_le32(map->m_lblk + map->m_len); + ext4_ext_store_pblock(ex3, newblock + map->m_len); + ex3->ee_len = cpu_to_le16(allocated - map->m_len); + ext4_ext_mark_uninitialized(ex3); + err = ext4_ext_insert_extent(handle, inode, path, ex3, 0); + if (err == -ENOSPC && may_zeroout) { + err = ext4_ext_zeroout(inode, &orig_ex); + if (err) + goto fix_extent_len; + /* update the extent length and mark as initialized */ + ex->ee_block = orig_ex.ee_block; + ex->ee_len = orig_ex.ee_len; + ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex)); + ext4_ext_dirty(handle, inode, path + depth); + /* zeroed the full extent */ + /* blocks available from map->m_lblk */ + return allocated; + + } else if (err) + goto fix_extent_len; + /* + * The depth, and hence eh & ex might change + * as part of the insert above. + */ + newdepth = ext_depth(inode); + /* + * update the extent length after successful insert of the + * split extent + */ + ee_len -= ext4_ext_get_actual_len(ex3); + orig_ex.ee_len = cpu_to_le16(ee_len); + may_zeroout = ee_block + ee_len <= eof_block; + + depth = newdepth; + ext4_ext_drop_refs(path); + path = ext4_ext_find_extent(inode, map->m_lblk, path); + if (IS_ERR(path)) { + err = PTR_ERR(path); + goto out; + } + eh = path[depth].p_hdr; + ex = path[depth].p_ext; + if (ex2 != &newex) + ex2 = ex; + + err = ext4_ext_get_access(handle, inode, path + depth); + if (err) + goto out; - allocated = ext4_split_extent(handle, inode, path, - &split_map, split_flag, 0); - if (allocated < 0) - err = allocated; + allocated = map->m_len; + /* If extent has less than EXT4_EXT_ZERO_LEN and we are trying + * to insert a extent in the middle zerout directly + * otherwise give the extent a chance to merge to left + */ + if (le16_to_cpu(orig_ex.ee_len) <= EXT4_EXT_ZERO_LEN && + map->m_lblk != ee_block && may_zeroout) { + err = ext4_ext_zeroout(inode, &orig_ex); + if (err) + goto fix_extent_len; + /* update the extent length and mark as initialized */ + ex->ee_block = orig_ex.ee_block; + ex->ee_len = orig_ex.ee_len; + ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex)); + ext4_ext_dirty(handle, inode, path + depth); + /* zero out the first half */ + /* blocks available from map->m_lblk */ + return allocated; + } + } + /* + * If there was a change of depth as part of the + * insertion of ex3 above, we need to update the length + * of the ex1 extent again here + */ + if (ex1 && ex1 != ex) { + ex1 = ex; + ex1->ee_len = cpu_to_le16(map->m_lblk - ee_block); + ext4_ext_mark_uninitialized(ex1); + ex2 = &newex; + } + /* ex2: map->m_lblk to map->m_lblk + maxblocks-1 : initialised */ + ex2->ee_block = cpu_to_le32(map->m_lblk); + ext4_ext_store_pblock(ex2, newblock); + ex2->ee_len = cpu_to_le16(allocated); + if (ex2 != ex) + goto insert; + /* + * New (initialized) extent starts from the first block + * in the current extent. i.e., ex2 == ex + * We have to see if it can be merged with the extent + * on the left. + */ + if (ex2 > EXT_FIRST_EXTENT(eh)) { + /* + * To merge left, pass "ex2 - 1" to try_to_merge(), + * since it merges towards right _only_. + */ + ret = ext4_ext_try_to_merge(inode, path, ex2 - 1); + if (ret) { + err = ext4_ext_correct_indexes(handle, inode, path); + if (err) + goto out; + depth = ext_depth(inode); + ex2--; + } + } + /* + * Try to Merge towards right. This might be required + * only when the whole extent is being written to. + * i.e. ex2 == ex and ex3 == NULL. + */ + if (!ex3) { + ret = ext4_ext_try_to_merge(inode, path, ex2); + if (ret) { + err = ext4_ext_correct_indexes(handle, inode, path); + if (err) + goto out; + } + } + /* Mark modified extent as dirty */ + err = ext4_ext_dirty(handle, inode, path + depth); + goto out; +insert: + err = ext4_ext_insert_extent(handle, inode, path, &newex, 0); + if (err == -ENOSPC && may_zeroout) { + err = ext4_ext_zeroout(inode, &orig_ex); + if (err) + goto fix_extent_len; + /* update the extent length and mark as initialized */ + ex->ee_block = orig_ex.ee_block; + ex->ee_len = orig_ex.ee_len; + ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex)); + ext4_ext_dirty(handle, inode, path + depth); + /* zero out the first half */ + return allocated; + } else if (err) + goto fix_extent_len; out: + ext4_ext_show_leaf(inode, path); return err ? err : allocated; + +fix_extent_len: + ex->ee_block = orig_ex.ee_block; + ex->ee_len = orig_ex.ee_len; + ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex)); + ext4_ext_mark_uninitialized(ex); + ext4_ext_dirty(handle, inode, path + depth); + return err; } /* @@ -3072,11 +2871,15 @@ static int ext4_split_unwritten_extents(handle_t *handle, struct ext4_ext_path *path, int flags) { - ext4_lblk_t eof_block; - ext4_lblk_t ee_block; - struct ext4_extent *ex; - unsigned int ee_len; - int split_flag = 0, depth; + struct ext4_extent *ex, newex, orig_ex; + struct ext4_extent *ex1 = NULL; + struct ext4_extent *ex2 = NULL; + struct ext4_extent *ex3 = NULL; + ext4_lblk_t ee_block, eof_block; + unsigned int allocated, ee_len, depth; + ext4_fsblk_t newblock; + int err = 0; + int may_zeroout; ext_debug("ext4_split_unwritten_extents: inode %lu, logical" "block %llu, max_blocks %u\n", inode->i_ino, @@ -3086,22 +2889,156 @@ static int ext4_split_unwritten_extents(handle_t *handle, inode->i_sb->s_blocksize_bits; if (eof_block < map->m_lblk + map->m_len) eof_block = map->m_lblk + map->m_len; - /* - * It is safe to convert extent to initialized via explicit - * zeroout only if extent is fully insde i_size or new_size. - */ + depth = ext_depth(inode); ex = path[depth].p_ext; ee_block = le32_to_cpu(ex->ee_block); ee_len = ext4_ext_get_actual_len(ex); + allocated = ee_len - (map->m_lblk - ee_block); + newblock = map->m_lblk - ee_block + ext4_ext_pblock(ex); - split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; - split_flag |= EXT4_EXT_MARK_UNINIT2; + ex2 = ex; + orig_ex.ee_block = ex->ee_block; + orig_ex.ee_len = cpu_to_le16(ee_len); + ext4_ext_store_pblock(&orig_ex, ext4_ext_pblock(ex)); - flags |= EXT4_GET_BLOCKS_PRE_IO; - return ext4_split_extent(handle, inode, path, map, split_flag, flags); -} + /* + * It is safe to convert extent to initialized via explicit + * zeroout only if extent is fully insde i_size or new_size. + */ + may_zeroout = ee_block + ee_len <= eof_block; + + /* + * If the uninitialized extent begins at the same logical + * block where the write begins, and the write completely + * covers the extent, then we don't need to split it. + */ + if ((map->m_lblk == ee_block) && (allocated <= map->m_len)) + return allocated; + + err = ext4_ext_get_access(handle, inode, path + depth); + if (err) + goto out; + /* ex1: ee_block to map->m_lblk - 1 : uninitialized */ + if (map->m_lblk > ee_block) { + ex1 = ex; + ex1->ee_len = cpu_to_le16(map->m_lblk - ee_block); + ext4_ext_mark_uninitialized(ex1); + ex2 = &newex; + } + /* + * for sanity, update the length of the ex2 extent before + * we insert ex3, if ex1 is NULL. This is to avoid temporary + * overlap of blocks. + */ + if (!ex1 && allocated > map->m_len) + ex2->ee_len = cpu_to_le16(map->m_len); + /* ex3: to ee_block + ee_len : uninitialised */ + if (allocated > map->m_len) { + unsigned int newdepth; + ex3 = &newex; + ex3->ee_block = cpu_to_le32(map->m_lblk + map->m_len); + ext4_ext_store_pblock(ex3, newblock + map->m_len); + ex3->ee_len = cpu_to_le16(allocated - map->m_len); + ext4_ext_mark_uninitialized(ex3); + err = ext4_ext_insert_extent(handle, inode, path, ex3, flags); + if (err == -ENOSPC && may_zeroout) { + err = ext4_ext_zeroout(inode, &orig_ex); + if (err) + goto fix_extent_len; + /* update the extent length and mark as initialized */ + ex->ee_block = orig_ex.ee_block; + ex->ee_len = orig_ex.ee_len; + ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex)); + ext4_ext_dirty(handle, inode, path + depth); + /* zeroed the full extent */ + /* blocks available from map->m_lblk */ + return allocated; + + } else if (err) + goto fix_extent_len; + /* + * The depth, and hence eh & ex might change + * as part of the insert above. + */ + newdepth = ext_depth(inode); + /* + * update the extent length after successful insert of the + * split extent + */ + ee_len -= ext4_ext_get_actual_len(ex3); + orig_ex.ee_len = cpu_to_le16(ee_len); + may_zeroout = ee_block + ee_len <= eof_block; + + depth = newdepth; + ext4_ext_drop_refs(path); + path = ext4_ext_find_extent(inode, map->m_lblk, path); + if (IS_ERR(path)) { + err = PTR_ERR(path); + goto out; + } + ex = path[depth].p_ext; + if (ex2 != &newex) + ex2 = ex; + + err = ext4_ext_get_access(handle, inode, path + depth); + if (err) + goto out; + + allocated = map->m_len; + } + /* + * If there was a change of depth as part of the + * insertion of ex3 above, we need to update the length + * of the ex1 extent again here + */ + if (ex1 && ex1 != ex) { + ex1 = ex; + ex1->ee_len = cpu_to_le16(map->m_lblk - ee_block); + ext4_ext_mark_uninitialized(ex1); + ex2 = &newex; + } + /* + * ex2: map->m_lblk to map->m_lblk + map->m_len-1 : to be written + * using direct I/O, uninitialised still. + */ + ex2->ee_block = cpu_to_le32(map->m_lblk); + ext4_ext_store_pblock(ex2, newblock); + ex2->ee_len = cpu_to_le16(allocated); + ext4_ext_mark_uninitialized(ex2); + if (ex2 != ex) + goto insert; + /* Mark modified extent as dirty */ + err = ext4_ext_dirty(handle, inode, path + depth); + ext_debug("out here\n"); + goto out; +insert: + err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); + if (err == -ENOSPC && may_zeroout) { + err = ext4_ext_zeroout(inode, &orig_ex); + if (err) + goto fix_extent_len; + /* update the extent length and mark as initialized */ + ex->ee_block = orig_ex.ee_block; + ex->ee_len = orig_ex.ee_len; + ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex)); + ext4_ext_dirty(handle, inode, path + depth); + /* zero out the first half */ + return allocated; + } else if (err) + goto fix_extent_len; +out: + ext4_ext_show_leaf(inode, path); + return err ? err : allocated; +fix_extent_len: + ex->ee_block = orig_ex.ee_block; + ex->ee_len = orig_ex.ee_len; + ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex)); + ext4_ext_mark_uninitialized(ex); + ext4_ext_dirty(handle, inode, path + depth); + return err; +} static int ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode, struct ext4_ext_path *path) @@ -3110,27 +3047,46 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle, struct ext4_extent_header *eh; int depth; int err = 0; + int ret = 0; depth = ext_depth(inode); eh = path[depth].p_hdr; ex = path[depth].p_ext; - ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" - "block %llu, max_blocks %u\n", inode->i_ino, - (unsigned long long)le32_to_cpu(ex->ee_block), - ext4_ext_get_actual_len(ex)); - err = ext4_ext_get_access(handle, inode, path + depth); if (err) goto out; /* first mark the extent as initialized */ ext4_ext_mark_initialized(ex); - /* note: ext4_ext_correct_indexes() isn't needed here because - * borders are not changed + /* + * We have to see if it can be merged with the extent + * on the left. */ - ext4_ext_try_to_merge(inode, path, ex); - + if (ex > EXT_FIRST_EXTENT(eh)) { + /* + * To merge left, pass "ex - 1" to try_to_merge(), + * since it merges towards right _only_. + */ + ret = ext4_ext_try_to_merge(inode, path, ex - 1); + if (ret) { + err = ext4_ext_correct_indexes(handle, inode, path); + if (err) + goto out; + depth = ext_depth(inode); + ex--; + } + } + /* + * Try to Merge towards right. + */ + ret = ext4_ext_try_to_merge(inode, path, ex); + if (ret) { + err = ext4_ext_correct_indexes(handle, inode, path); + if (err) + goto out; + depth = ext_depth(inode); + } /* Mark modified extent as dirty */ err = ext4_ext_dirty(handle, inode, path + depth); out: @@ -3346,19 +3302,15 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, ext4_fsblk_t newblock = 0; int err = 0, depth, ret; unsigned int allocated = 0; - unsigned int punched_out = 0; - unsigned int result = 0; struct ext4_allocation_request ar; ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio; - struct ext4_map_blocks punch_map; ext_debug("blocks %u/%u requested for inode %lu\n", map->m_lblk, map->m_len, inode->i_ino); trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags); /* check in cache */ - if (ext4_ext_in_cache(inode, map->m_lblk, &newex) && - ((flags & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) == 0)) { + if (ext4_ext_in_cache(inode, map->m_lblk, &newex)) { if (!newex.ee_start_lo && !newex.ee_start_hi) { if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) { /* @@ -3423,84 +3375,16 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, ext_debug("%u fit into %u:%d -> %llu\n", map->m_lblk, ee_block, ee_len, newblock); - if ((flags & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) == 0) { - /* - * Do not put uninitialized extent - * in the cache - */ - if (!ext4_ext_is_uninitialized(ex)) { - ext4_ext_put_in_cache(inode, ee_block, - ee_len, ee_start); - goto out; - } - ret = ext4_ext_handle_uninitialized_extents( - handle, inode, map, path, flags, - allocated, newblock); - return ret; - } - - /* - * Punch out the map length, but only to the - * end of the extent - */ - punched_out = allocated < map->m_len ? - allocated : map->m_len; - - /* - * Sense extents need to be converted to - * uninitialized, they must fit in an - * uninitialized extent - */ - if (punched_out > EXT_UNINIT_MAX_LEN) - punched_out = EXT_UNINIT_MAX_LEN; - - punch_map.m_lblk = map->m_lblk; - punch_map.m_pblk = newblock; - punch_map.m_len = punched_out; - punch_map.m_flags = 0; - - /* Check to see if the extent needs to be split */ - if (punch_map.m_len != ee_len || - punch_map.m_lblk != ee_block) { - - ret = ext4_split_extent(handle, inode, - path, &punch_map, 0, - EXT4_GET_BLOCKS_PUNCH_OUT_EXT | - EXT4_GET_BLOCKS_PRE_IO); - - if (ret < 0) { - err = ret; - goto out2; - } - /* - * find extent for the block at - * the start of the hole - */ - ext4_ext_drop_refs(path); - kfree(path); - - path = ext4_ext_find_extent(inode, - map->m_lblk, NULL); - if (IS_ERR(path)) { - err = PTR_ERR(path); - path = NULL; - goto out2; - } - - depth = ext_depth(inode); - ex = path[depth].p_ext; - ee_len = ext4_ext_get_actual_len(ex); - ee_block = le32_to_cpu(ex->ee_block); - ee_start = ext4_ext_pblock(ex); - + /* Do not put uninitialized extent in the cache */ + if (!ext4_ext_is_uninitialized(ex)) { + ext4_ext_put_in_cache(inode, ee_block, + ee_len, ee_start); + goto out; } - - ext4_ext_mark_uninitialized(ex); - - err = ext4_ext_remove_space(inode, map->m_lblk, - map->m_lblk + punched_out); - - goto out2; + ret = ext4_ext_handle_uninitialized_extents(handle, + inode, map, path, flags, allocated, + newblock); + return ret; } } @@ -3562,8 +3446,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, else /* disable in-core preallocation for non-regular files */ ar.flags = 0; - if (flags & EXT4_GET_BLOCKS_NO_NORMALIZE) - ar.flags |= EXT4_MB_HINT_NOPREALLOC; newblock = ext4_mb_new_blocks(handle, &ar, &err); if (!newblock) goto out2; @@ -3647,11 +3529,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, } trace_ext4_ext_map_blocks_exit(inode, map->m_lblk, newblock, map->m_len, err ? err : allocated); - - result = (flags & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) ? - punched_out : allocated; - - return err ? err : result; + return err ? err : allocated; } void ext4_ext_truncate(struct inode *inode) @@ -3699,7 +3577,7 @@ void ext4_ext_truncate(struct inode *inode) last_block = (inode->i_size + sb->s_blocksize - 1) >> EXT4_BLOCK_SIZE_BITS(sb); - err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCK); + err = ext4_ext_remove_space(inode, last_block); /* In a multi-transaction truncate, we only make the final * transaction synchronous. @@ -3707,9 +3585,8 @@ void ext4_ext_truncate(struct inode *inode) if (IS_SYNC(inode)) ext4_handle_sync(handle); - up_write(&EXT4_I(inode)->i_data_sem); - out_stop: + up_write(&EXT4_I(inode)->i_data_sem); /* * If this was a simple ftruncate() and the file will remain alive, * then we need to clear up the orphan record which we created above. @@ -3774,6 +3651,10 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) struct ext4_map_blocks map; unsigned int credits, blkbits = inode->i_blkbits; + /* We only support the FALLOC_FL_KEEP_SIZE mode */ + if (mode & ~FALLOC_FL_KEEP_SIZE) + return -EOPNOTSUPP; + /* * currently supporting (pre)allocate mode for extent-based * files _only_ @@ -3781,13 +3662,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) return -EOPNOTSUPP; - /* Return error if mode is not supported */ - if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) - return -EOPNOTSUPP; - - if (mode & FALLOC_FL_PUNCH_HOLE) - return ext4_punch_hole(file, offset, len); - trace_ext4_fallocate_enter(inode, offset, len, mode); map.m_lblk = offset >> blkbits; /* @@ -3817,8 +3691,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) break; } ret = ext4_map_blocks(handle, inode, &map, - EXT4_GET_BLOCKS_CREATE_UNINIT_EXT | - EXT4_GET_BLOCKS_NO_NORMALIZE); + EXT4_GET_BLOCKS_CREATE_UNINIT_EXT); if (ret <= 0) { #ifdef EXT4FS_DEBUG WARN_ON(ret <= 0); @@ -3949,7 +3822,6 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, pgoff_t last_offset; pgoff_t offset; pgoff_t index; - pgoff_t start_index = 0; struct page **pages = NULL; struct buffer_head *bh = NULL; struct buffer_head *head = NULL; @@ -3976,57 +3848,39 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, kfree(pages); return EXT_CONTINUE; } - index = 0; -next_page: /* Try to find the 1st mapped buffer. */ - end = ((__u64)pages[index]->index << PAGE_SHIFT) >> + end = ((__u64)pages[0]->index << PAGE_SHIFT) >> blksize_bits; - if (!page_has_buffers(pages[index])) + if (!page_has_buffers(pages[0])) goto out; - head = page_buffers(pages[index]); + head = page_buffers(pages[0]); if (!head) goto out; - index++; bh = head; do { - if (end >= newex->ec_block + - newex->ec_len) - /* The buffer is out of - * the request range. - */ - goto out; - - if (buffer_mapped(bh) && - end >= newex->ec_block) { - start_index = index - 1; + if (buffer_mapped(bh)) { /* get the 1st mapped buffer. */ + if (end > newex->ec_block + + newex->ec_len) + /* The buffer is out of + * the request range. + */ + goto out; goto found_mapped_buffer; } - bh = bh->b_this_page; end++; } while (bh != head); - /* No mapped buffer in the range found in this page, - * We need to look up next page. - */ - if (index >= ret) { - /* There is no page left, but we need to limit - * newex->ec_len. - */ - newex->ec_len = end - newex->ec_block; - goto out; - } - goto next_page; + /* No mapped buffer found. */ + goto out; } else { /*Find contiguous delayed buffers. */ if (ret > 0 && pages[0]->index == last_offset) head = page_buffers(pages[0]); bh = head; - index = 1; - start_index = 0; } found_mapped_buffer: @@ -4049,7 +3903,7 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, end++; } while (bh != head); - for (; index < ret; index++) { + for (index = 1; index < ret; index++) { if (!page_has_buffers(pages[index])) { bh = NULL; break; @@ -4059,10 +3913,8 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, bh = NULL; break; } - if (pages[index]->index != - pages[start_index]->index + index - - start_index) { + pages[0]->index + index) { /* Blocks are not contiguous. */ bh = NULL; break; @@ -4154,177 +4006,6 @@ static int ext4_xattr_fiemap(struct inode *inode, return (error < 0 ? error : 0); } -/* - * ext4_ext_punch_hole - * - * Punches a hole of "length" bytes in a file starting - * at byte "offset" - * - * @inode: The inode of the file to punch a hole in - * @offset: The starting byte offset of the hole - * @length: The length of the hole - * - * Returns the number of blocks removed or negative on err - */ -int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) -{ - struct inode *inode = file->f_path.dentry->d_inode; - struct super_block *sb = inode->i_sb; - struct ext4_ext_cache cache_ex; - ext4_lblk_t first_block, last_block, num_blocks, iblock, max_blocks; - struct address_space *mapping = inode->i_mapping; - struct ext4_map_blocks map; - handle_t *handle; - loff_t first_block_offset, last_block_offset, block_len; - loff_t first_page, last_page, first_page_offset, last_page_offset; - int ret, credits, blocks_released, err = 0; - - first_block = (offset + sb->s_blocksize - 1) >> - EXT4_BLOCK_SIZE_BITS(sb); - last_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb); - - first_block_offset = first_block << EXT4_BLOCK_SIZE_BITS(sb); - last_block_offset = last_block << EXT4_BLOCK_SIZE_BITS(sb); - - first_page = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - last_page = (offset + length) >> PAGE_CACHE_SHIFT; - - first_page_offset = first_page << PAGE_CACHE_SHIFT; - last_page_offset = last_page << PAGE_CACHE_SHIFT; - - /* - * Write out all dirty pages to avoid race conditions - * Then release them. - */ - if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { - err = filemap_write_and_wait_range(mapping, - first_page_offset == 0 ? 0 : first_page_offset-1, - last_page_offset); - - if (err) - return err; - } - - /* Now release the pages */ - if (last_page_offset > first_page_offset) { - truncate_inode_pages_range(mapping, first_page_offset, - last_page_offset-1); - } - - /* finish any pending end_io work */ - ext4_flush_completed_IO(inode); - - credits = ext4_writepage_trans_blocks(inode); - handle = ext4_journal_start(inode, credits); - if (IS_ERR(handle)) - return PTR_ERR(handle); - - err = ext4_orphan_add(handle, inode); - if (err) - goto out; - - /* - * Now we need to zero out the un block aligned data. - * If the file is smaller than a block, just - * zero out the middle - */ - if (first_block > last_block) - ext4_block_zero_page_range(handle, mapping, offset, length); - else { - /* zero out the head of the hole before the first block */ - block_len = first_block_offset - offset; - if (block_len > 0) - ext4_block_zero_page_range(handle, mapping, - offset, block_len); - - /* zero out the tail of the hole after the last block */ - block_len = offset + length - last_block_offset; - if (block_len > 0) { - ext4_block_zero_page_range(handle, mapping, - last_block_offset, block_len); - } - } - - /* If there are no blocks to remove, return now */ - if (first_block >= last_block) - goto out; - - down_write(&EXT4_I(inode)->i_data_sem); - ext4_ext_invalidate_cache(inode); - ext4_discard_preallocations(inode); - - /* - * Loop over all the blocks and identify blocks - * that need to be punched out - */ - iblock = first_block; - blocks_released = 0; - while (iblock < last_block) { - max_blocks = last_block - iblock; - num_blocks = 1; - memset(&map, 0, sizeof(map)); - map.m_lblk = iblock; - map.m_len = max_blocks; - ret = ext4_ext_map_blocks(handle, inode, &map, - EXT4_GET_BLOCKS_PUNCH_OUT_EXT); - - if (ret > 0) { - blocks_released += ret; - num_blocks = ret; - } else if (ret == 0) { - /* - * If map blocks could not find the block, - * then it is in a hole. If the hole was - * not already cached, then map blocks should - * put it in the cache. So we can get the hole - * out of the cache - */ - memset(&cache_ex, 0, sizeof(cache_ex)); - if ((ext4_ext_check_cache(inode, iblock, &cache_ex)) && - !cache_ex.ec_start) { - - /* The hole is cached */ - num_blocks = cache_ex.ec_block + - cache_ex.ec_len - iblock; - - } else { - /* The block could not be identified */ - err = -EIO; - break; - } - } else { - /* Map blocks error */ - err = ret; - break; - } - - if (num_blocks == 0) { - /* This condition should never happen */ - ext_debug("Block lookup failed"); - err = -EIO; - break; - } - - iblock += num_blocks; - } - - if (blocks_released > 0) { - ext4_ext_invalidate_cache(inode); - ext4_discard_preallocations(inode); - } - - if (IS_SYNC(inode)) - ext4_handle_sync(handle); - - up_write(&EXT4_I(inode)->i_data_sem); - -out: - ext4_orphan_del(handle, inode); - inode->i_mtime = inode->i_ctime = ext4_current_time(inode); - ext4_mark_inode_dirty(handle, inode); - ext4_journal_stop(handle); - return err; -} int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, __u64 start, __u64 len) { @@ -4361,3 +4042,4 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, return error; } + diff --git a/trunk/fs/ext4/file.c b/trunk/fs/ext4/file.c index 2c0972322009..7b80d543b89e 100644 --- a/trunk/fs/ext4/file.c +++ b/trunk/fs/ext4/file.c @@ -272,6 +272,7 @@ const struct file_operations ext4_file_operations = { }; const struct inode_operations ext4_file_inode_operations = { + .truncate = ext4_truncate, .setattr = ext4_setattr, .getattr = ext4_getattr, #ifdef CONFIG_EXT4_FS_XATTR diff --git a/trunk/fs/ext4/fsync.c b/trunk/fs/ext4/fsync.c index ce66d2fe826c..e9473cbe80df 100644 --- a/trunk/fs/ext4/fsync.c +++ b/trunk/fs/ext4/fsync.c @@ -36,7 +36,7 @@ static void dump_completed_IO(struct inode * inode) { -#ifdef EXT4FS_DEBUG +#ifdef EXT4_DEBUG struct list_head *cur, *before, *after; ext4_io_end_t *io, *io0, *io1; unsigned long flags; @@ -172,7 +172,6 @@ int ext4_sync_file(struct file *file, int datasync) journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; int ret; tid_t commit_tid; - bool needs_barrier = false; J_ASSERT(ext4_journal_current_handle() == NULL); @@ -212,12 +211,22 @@ int ext4_sync_file(struct file *file, int datasync) } commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; - if (journal->j_flags & JBD2_BARRIER && - !jbd2_trans_will_send_data_barrier(journal, commit_tid)) - needs_barrier = true; - jbd2_log_start_commit(journal, commit_tid); - ret = jbd2_log_wait_commit(journal, commit_tid); - if (needs_barrier) + if (jbd2_log_start_commit(journal, commit_tid)) { + /* + * When the journal is on a different device than the + * fs data disk, we need to issue the barrier in + * writeback mode. (In ordered mode, the jbd2 layer + * will take care of issuing the barrier. In + * data=journal, all of the data blocks are written to + * the journal device.) + */ + if (ext4_should_writeback_data(inode) && + (journal->j_fs_dev != journal->j_dev) && + (journal->j_flags & JBD2_BARRIER)) + blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, + NULL); + ret = jbd2_log_wait_commit(journal, commit_tid); + } else if (journal->j_flags & JBD2_BARRIER) blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); out: trace_ext4_sync_file_exit(inode, ret); diff --git a/trunk/fs/ext4/inode.c b/trunk/fs/ext4/inode.c index 50d0e9c64584..f2fa5e8a582c 100644 --- a/trunk/fs/ext4/inode.c +++ b/trunk/fs/ext4/inode.c @@ -639,8 +639,8 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode, while (target > 0) { count = target; /* allocating blocks for indirect blocks and direct blocks */ - current_block = ext4_new_meta_blocks(handle, inode, goal, - 0, &count, err); + current_block = ext4_new_meta_blocks(handle, inode, + goal, &count, err); if (*err) goto failed_out; @@ -1930,7 +1930,7 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) * We do still charge estimated metadata to the sb though; * we cannot afford to run out of free blocks. */ - if (ext4_claim_free_blocks(sbi, md_needed + 1, 0)) { + if (ext4_claim_free_blocks(sbi, md_needed + 1)) { dquot_release_reservation_block(inode, 1); if (ext4_should_retry_alloc(inode->i_sb, &retries)) { yield(); @@ -2796,7 +2796,9 @@ static int write_cache_pages_da(struct address_space *mapping, continue; } - wait_on_page_writeback(page); + if (PageWriteback(page)) + wait_on_page_writeback(page); + BUG_ON(PageWriteback(page)); if (mpd->next_page != page->index) @@ -3511,7 +3513,7 @@ static ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, loff_t end = offset + iov_length(iov, nr_segs); if (end > isize) - ext4_truncate_failed_write(inode); + vmtruncate(inode, isize); } } if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) @@ -3913,31 +3915,10 @@ void ext4_set_aops(struct inode *inode) */ int ext4_block_truncate_page(handle_t *handle, struct address_space *mapping, loff_t from) -{ - unsigned offset = from & (PAGE_CACHE_SIZE-1); - unsigned length; - unsigned blocksize; - struct inode *inode = mapping->host; - - blocksize = inode->i_sb->s_blocksize; - length = blocksize - (offset & (blocksize - 1)); - - return ext4_block_zero_page_range(handle, mapping, from, length); -} - -/* - * ext4_block_zero_page_range() zeros out a mapping of length 'length' - * starting from file offset 'from'. The range to be zero'd must - * be contained with in one block. If the specified range exceeds - * the end of the block it will be shortened to end of the block - * that cooresponds to 'from' - */ -int ext4_block_zero_page_range(handle_t *handle, - struct address_space *mapping, loff_t from, loff_t length) { ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT; unsigned offset = from & (PAGE_CACHE_SIZE-1); - unsigned blocksize, max, pos; + unsigned blocksize, length, pos; ext4_lblk_t iblock; struct inode *inode = mapping->host; struct buffer_head *bh; @@ -3950,15 +3931,7 @@ int ext4_block_zero_page_range(handle_t *handle, return -EINVAL; blocksize = inode->i_sb->s_blocksize; - max = blocksize - (offset & (blocksize - 1)); - - /* - * correct length if it does not fall between - * 'from' and the end of the block - */ - if (length > max || length < 0) - length = max; - + length = blocksize - (offset & (blocksize - 1)); iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); if (!page_has_buffers(page)) @@ -4407,6 +4380,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, int ext4_can_truncate(struct inode *inode) { + if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + return 0; if (S_ISREG(inode->i_mode)) return 1; if (S_ISDIR(inode->i_mode)) @@ -4416,31 +4391,6 @@ int ext4_can_truncate(struct inode *inode) return 0; } -/* - * ext4_punch_hole: punches a hole in a file by releaseing the blocks - * associated with the given offset and length - * - * @inode: File inode - * @offset: The offset where the hole will begin - * @len: The length of the hole - * - * Returns: 0 on sucess or negative on failure - */ - -int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) -{ - struct inode *inode = file->f_path.dentry->d_inode; - if (!S_ISREG(inode->i_mode)) - return -ENOTSUPP; - - if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { - /* TODO: Add support for non extent hole punching */ - return -ENOTSUPP; - } - - return ext4_ext_punch_hole(file, offset, length); -} - /* * ext4_truncate() * @@ -4667,7 +4617,7 @@ static int __ext4_get_inode_loc(struct inode *inode, /* * Figure out the offset within the block group inode table */ - inodes_per_block = EXT4_SB(sb)->s_inodes_per_block; + inodes_per_block = (EXT4_BLOCK_SIZE(sb) / EXT4_INODE_SIZE(sb)); inode_offset = ((inode->i_ino - 1) % EXT4_INODES_PER_GROUP(sb)); block = ext4_inode_table(sb, gdp) + (inode_offset / inodes_per_block); @@ -5361,7 +5311,8 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) if (S_ISREG(inode->i_mode) && attr->ia_valid & ATTR_SIZE && - (attr->ia_size < inode->i_size)) { + (attr->ia_size < inode->i_size || + (ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)))) { handle_t *handle; handle = ext4_journal_start(inode, 3); @@ -5395,16 +5346,15 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) goto err_out; } } - } - - if (attr->ia_valid & ATTR_SIZE) { - if (attr->ia_size != i_size_read(inode)) { - truncate_setsize(inode, attr->ia_size); - ext4_truncate(inode); - } else if (ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)) + /* ext4_truncate will clear the flag */ + if ((ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS))) ext4_truncate(inode); } + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) + rc = vmtruncate(inode, attr->ia_size); + if (!rc) { setattr_copy(inode, attr); mark_inode_dirty(inode); @@ -5861,19 +5811,15 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) goto out_unlock; } ret = 0; - - lock_page(page); - wait_on_page_writeback(page); - if (PageMappedToDisk(page)) { - up_read(&inode->i_alloc_sem); - return VM_FAULT_LOCKED; - } + if (PageMappedToDisk(page)) + goto out_unlock; if (page->index == size >> PAGE_CACHE_SHIFT) len = size & ~PAGE_CACHE_MASK; else len = PAGE_CACHE_SIZE; + lock_page(page); /* * return if we have all the buffers mapped. This avoid * the need to call write_begin/write_end which does a @@ -5883,8 +5829,8 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (page_has_buffers(page)) { if (!walk_page_buffers(NULL, page_buffers(page), 0, len, NULL, ext4_bh_unmapped)) { - up_read(&inode->i_alloc_sem); - return VM_FAULT_LOCKED; + unlock_page(page); + goto out_unlock; } } unlock_page(page); @@ -5904,16 +5850,6 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (ret < 0) goto out_unlock; ret = 0; - - /* - * write_begin/end might have created a dirty page and someone - * could wander in and start the IO. Make sure that hasn't - * happened. - */ - lock_page(page); - wait_on_page_writeback(page); - up_read(&inode->i_alloc_sem); - return VM_FAULT_LOCKED; out_unlock: if (ret) ret = VM_FAULT_SIGBUS; diff --git a/trunk/fs/ext4/mballoc.c b/trunk/fs/ext4/mballoc.c index 859f2ae8864e..d8a16eecf1d5 100644 --- a/trunk/fs/ext4/mballoc.c +++ b/trunk/fs/ext4/mballoc.c @@ -787,7 +787,6 @@ static int ext4_mb_init_cache(struct page *page, char *incore) struct inode *inode; char *data; char *bitmap; - struct ext4_group_info *grinfo; mb_debug(1, "init page %lu\n", page->index); @@ -820,18 +819,6 @@ static int ext4_mb_init_cache(struct page *page, char *incore) if (first_group + i >= ngroups) break; - grinfo = ext4_get_group_info(sb, first_group + i); - /* - * If page is uptodate then we came here after online resize - * which added some new uninitialized group info structs, so - * we must skip all initialized uptodate buddies on the page, - * which may be currently in use by an allocating task. - */ - if (PageUptodate(page) && !EXT4_MB_GRP_NEED_INIT(grinfo)) { - bh[i] = NULL; - continue; - } - err = -EIO; desc = ext4_get_group_desc(sb, first_group + i, NULL); if (desc == NULL) @@ -884,28 +871,26 @@ static int ext4_mb_init_cache(struct page *page, char *incore) } /* wait for I/O completion */ - for (i = 0; i < groups_per_page; i++) - if (bh[i]) - wait_on_buffer(bh[i]); + for (i = 0; i < groups_per_page && bh[i]; i++) + wait_on_buffer(bh[i]); err = -EIO; - for (i = 0; i < groups_per_page; i++) - if (bh[i] && !buffer_uptodate(bh[i])) + for (i = 0; i < groups_per_page && bh[i]; i++) + if (!buffer_uptodate(bh[i])) goto out; err = 0; first_block = page->index * blocks_per_page; + /* init the page */ + memset(page_address(page), 0xff, PAGE_CACHE_SIZE); for (i = 0; i < blocks_per_page; i++) { int group; + struct ext4_group_info *grinfo; group = (first_block + i) >> 1; if (group >= ngroups) break; - if (!bh[group - first_group]) - /* skip initialized uptodate buddy */ - continue; - /* * data carry information regarding this * particular group in the format specified @@ -934,8 +919,6 @@ static int ext4_mb_init_cache(struct page *page, char *incore) * incore got set to the group block bitmap below */ ext4_lock_group(sb, group); - /* init the buddy */ - memset(data, 0xff, blocksize); ext4_mb_generate_buddy(sb, data, incore, group); ext4_unlock_group(sb, group); incore = NULL; @@ -965,7 +948,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore) out: if (bh) { - for (i = 0; i < groups_per_page; i++) + for (i = 0; i < groups_per_page && bh[i]; i++) brelse(bh[i]); if (bh != &bhs) kfree(bh); @@ -974,21 +957,22 @@ static int ext4_mb_init_cache(struct page *page, char *incore) } /* - * Lock the buddy and bitmap pages. This make sure other parallel init_group - * on the same buddy page doesn't happen whild holding the buddy page lock. - * Return locked buddy and bitmap pages on e4b struct. If buddy and bitmap - * are on the same page e4b->bd_buddy_page is NULL and return value is 0. + * lock the group_info alloc_sem of all the groups + * belonging to the same buddy cache page. This + * make sure other parallel operation on the buddy + * cache doesn't happen whild holding the buddy cache + * lock */ -static int ext4_mb_get_buddy_page_lock(struct super_block *sb, - ext4_group_t group, struct ext4_buddy *e4b) +static int ext4_mb_get_buddy_cache_lock(struct super_block *sb, + ext4_group_t group) { - struct inode *inode = EXT4_SB(sb)->s_buddy_cache; - int block, pnum, poff; + int i; + int block, pnum; int blocks_per_page; - struct page *page; - - e4b->bd_buddy_page = NULL; - e4b->bd_bitmap_page = NULL; + int groups_per_page; + ext4_group_t ngroups = ext4_get_groups_count(sb); + ext4_group_t first_group; + struct ext4_group_info *grp; blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; /* @@ -998,40 +982,57 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb, */ block = group * 2; pnum = block / blocks_per_page; - poff = block % blocks_per_page; - page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS); - if (!page) - return -EIO; - BUG_ON(page->mapping != inode->i_mapping); - e4b->bd_bitmap_page = page; - e4b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize); + first_group = pnum * blocks_per_page / 2; - if (blocks_per_page >= 2) { - /* buddy and bitmap are on the same page */ - return 0; - } + groups_per_page = blocks_per_page >> 1; + if (groups_per_page == 0) + groups_per_page = 1; + /* read all groups the page covers into the cache */ + for (i = 0; i < groups_per_page; i++) { - block++; - pnum = block / blocks_per_page; - poff = block % blocks_per_page; - page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS); - if (!page) - return -EIO; - BUG_ON(page->mapping != inode->i_mapping); - e4b->bd_buddy_page = page; - return 0; + if ((first_group + i) >= ngroups) + break; + grp = ext4_get_group_info(sb, first_group + i); + /* take all groups write allocation + * semaphore. This make sure there is + * no block allocation going on in any + * of that groups + */ + down_write_nested(&grp->alloc_sem, i); + } + return i; } -static void ext4_mb_put_buddy_page_lock(struct ext4_buddy *e4b) +static void ext4_mb_put_buddy_cache_lock(struct super_block *sb, + ext4_group_t group, int locked_group) { - if (e4b->bd_bitmap_page) { - unlock_page(e4b->bd_bitmap_page); - page_cache_release(e4b->bd_bitmap_page); - } - if (e4b->bd_buddy_page) { - unlock_page(e4b->bd_buddy_page); - page_cache_release(e4b->bd_buddy_page); + int i; + int block, pnum; + int blocks_per_page; + ext4_group_t first_group; + struct ext4_group_info *grp; + + blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; + /* + * the buddy cache inode stores the block bitmap + * and buddy information in consecutive blocks. + * So for each group we need two blocks. + */ + block = group * 2; + pnum = block / blocks_per_page; + first_group = pnum * blocks_per_page / 2; + /* release locks on all the groups */ + for (i = 0; i < locked_group; i++) { + + grp = ext4_get_group_info(sb, first_group + i); + /* take all groups write allocation + * semaphore. This make sure there is + * no block allocation going on in any + * of that groups + */ + up_write(&grp->alloc_sem); } + } /* @@ -1043,60 +1044,93 @@ static noinline_for_stack int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) { - struct ext4_group_info *this_grp; - struct ext4_buddy e4b; - struct page *page; int ret = 0; + void *bitmap; + int blocks_per_page; + int block, pnum, poff; + int num_grp_locked = 0; + struct ext4_group_info *this_grp; + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct inode *inode = sbi->s_buddy_cache; + struct page *page = NULL, *bitmap_page = NULL; mb_debug(1, "init group %u\n", group); + blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; this_grp = ext4_get_group_info(sb, group); /* * This ensures that we don't reinit the buddy cache * page which map to the group from which we are already * allocating. If we are looking at the buddy cache we would * have taken a reference using ext4_mb_load_buddy and that - * would have pinned buddy page to page cache. + * would have taken the alloc_sem lock. */ - ret = ext4_mb_get_buddy_page_lock(sb, group, &e4b); - if (ret || !EXT4_MB_GRP_NEED_INIT(this_grp)) { + num_grp_locked = ext4_mb_get_buddy_cache_lock(sb, group); + if (!EXT4_MB_GRP_NEED_INIT(this_grp)) { /* * somebody initialized the group * return without doing anything */ + ret = 0; goto err; } - - page = e4b.bd_bitmap_page; - ret = ext4_mb_init_cache(page, NULL); - if (ret) - goto err; - if (!PageUptodate(page)) { + /* + * the buddy cache inode stores the block bitmap + * and buddy information in consecutive blocks. + * So for each group we need two blocks. + */ + block = group * 2; + pnum = block / blocks_per_page; + poff = block % blocks_per_page; + page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS); + if (page) { + BUG_ON(page->mapping != inode->i_mapping); + ret = ext4_mb_init_cache(page, NULL); + if (ret) { + unlock_page(page); + goto err; + } + unlock_page(page); + } + if (page == NULL || !PageUptodate(page)) { ret = -EIO; goto err; } mark_page_accessed(page); + bitmap_page = page; + bitmap = page_address(page) + (poff * sb->s_blocksize); - if (e4b.bd_buddy_page == NULL) { + /* init buddy cache */ + block++; + pnum = block / blocks_per_page; + poff = block % blocks_per_page; + page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS); + if (page == bitmap_page) { /* * If both the bitmap and buddy are in * the same page we don't need to force * init the buddy */ - ret = 0; - goto err; + unlock_page(page); + } else if (page) { + BUG_ON(page->mapping != inode->i_mapping); + ret = ext4_mb_init_cache(page, bitmap); + if (ret) { + unlock_page(page); + goto err; + } + unlock_page(page); } - /* init buddy cache */ - page = e4b.bd_buddy_page; - ret = ext4_mb_init_cache(page, e4b.bd_bitmap); - if (ret) - goto err; - if (!PageUptodate(page)) { + if (page == NULL || !PageUptodate(page)) { ret = -EIO; goto err; } mark_page_accessed(page); err: - ext4_mb_put_buddy_page_lock(&e4b); + ext4_mb_put_buddy_cache_lock(sb, group, num_grp_locked); + if (bitmap_page) + page_cache_release(bitmap_page); + if (page) + page_cache_release(page); return ret; } @@ -1130,8 +1164,24 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, e4b->bd_group = group; e4b->bd_buddy_page = NULL; e4b->bd_bitmap_page = NULL; + e4b->alloc_semp = &grp->alloc_sem; + + /* Take the read lock on the group alloc + * sem. This would make sure a parallel + * ext4_mb_init_group happening on other + * groups mapped by the page is blocked + * till we are done with allocation + */ +repeat_load_buddy: + down_read(e4b->alloc_semp); if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) { + /* we need to check for group need init flag + * with alloc_semp held so that we can be sure + * that new blocks didn't get added to the group + * when we are loading the buddy cache + */ + up_read(e4b->alloc_semp); /* * we need full data about the group * to make a good selection @@ -1139,6 +1189,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, ret = ext4_mb_init_group(sb, group); if (ret) return ret; + goto repeat_load_buddy; } /* @@ -1222,14 +1273,15 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, return 0; err: - if (page) - page_cache_release(page); if (e4b->bd_bitmap_page) page_cache_release(e4b->bd_bitmap_page); if (e4b->bd_buddy_page) page_cache_release(e4b->bd_buddy_page); e4b->bd_buddy = NULL; e4b->bd_bitmap = NULL; + + /* Done with the buddy cache */ + up_read(e4b->alloc_semp); return ret; } @@ -1239,6 +1291,9 @@ static void ext4_mb_unload_buddy(struct ext4_buddy *e4b) page_cache_release(e4b->bd_bitmap_page); if (e4b->bd_buddy_page) page_cache_release(e4b->bd_buddy_page); + /* Done with the buddy cache */ + if (e4b->alloc_semp) + up_read(e4b->alloc_semp); } @@ -1551,6 +1606,9 @@ static void ext4_mb_use_best_found(struct ext4_allocation_context *ac, get_page(ac->ac_bitmap_page); ac->ac_buddy_page = e4b->bd_buddy_page; get_page(ac->ac_buddy_page); + /* on allocation we use ac to track the held semaphore */ + ac->alloc_semp = e4b->alloc_semp; + e4b->alloc_semp = NULL; /* store last allocated for subsequent stream allocation */ if (ac->ac_flags & EXT4_MB_STREAM_ALLOC) { spin_lock(&sbi->s_md_lock); @@ -2601,7 +2659,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) struct super_block *sb = journal->j_private; struct ext4_buddy e4b; struct ext4_group_info *db; - int err, count = 0, count2 = 0; + int err, ret, count = 0, count2 = 0; struct ext4_free_data *entry; struct list_head *l, *ltmp; @@ -2611,9 +2669,15 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) mb_debug(1, "gonna free %u blocks in group %u (0x%p):", entry->count, entry->group, entry); - if (test_opt(sb, DISCARD)) - ext4_issue_discard(sb, entry->group, - entry->start_blk, entry->count); + if (test_opt(sb, DISCARD)) { + ret = ext4_issue_discard(sb, entry->group, + entry->start_blk, entry->count); + if (unlikely(ret == -EOPNOTSUPP)) { + ext4_warning(sb, "discard not supported, " + "disabling"); + clear_opt(sb, DISCARD); + } + } err = ext4_mb_load_buddy(sb, entry->group, &e4b); /* we expect to find existing buddy because it's pinned */ @@ -4162,12 +4226,15 @@ static int ext4_mb_release_context(struct ext4_allocation_context *ac) spin_unlock(&pa->pa_lock); } } + if (ac->alloc_semp) + up_read(ac->alloc_semp); if (pa) { /* * We want to add the pa to the right bucket. * Remove it from the list and while adding * make sure the list to which we are adding - * doesn't grow big. + * doesn't grow big. We need to release + * alloc_semp before calling ext4_mb_add_n_trim() */ if ((pa->pa_type == MB_GROUP_PA) && likely(pa->pa_free)) { spin_lock(pa->pa_obj_lock); @@ -4236,9 +4303,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, * there is enough free blocks to do block allocation * and verify allocation doesn't exceed the quota limits. */ - while (ar->len && - ext4_claim_free_blocks(sbi, ar->len, ar->flags)) { - + while (ar->len && ext4_claim_free_blocks(sbi, ar->len)) { /* let others to free the space */ yield(); ar->len = ar->len >> 1; @@ -4248,15 +4313,9 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, return 0; } reserv_blks = ar->len; - if (ar->flags & EXT4_MB_USE_ROOT_BLOCKS) { - dquot_alloc_block_nofail(ar->inode, ar->len); - } else { - while (ar->len && - dquot_alloc_block(ar->inode, ar->len)) { - - ar->flags |= EXT4_MB_HINT_NOPREALLOC; - ar->len--; - } + while (ar->len && dquot_alloc_block(ar->inode, ar->len)) { + ar->flags |= EXT4_MB_HINT_NOPREALLOC; + ar->len--; } inquota = ar->len; if (ar->len == 0) { @@ -4644,127 +4703,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, return; } -/** - * ext4_add_groupblocks() -- Add given blocks to an existing group - * @handle: handle to this transaction - * @sb: super block - * @block: start physcial block to add to the block group - * @count: number of blocks to free - * - * This marks the blocks as free in the bitmap and buddy. - */ -void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, - ext4_fsblk_t block, unsigned long count) -{ - struct buffer_head *bitmap_bh = NULL; - struct buffer_head *gd_bh; - ext4_group_t block_group; - ext4_grpblk_t bit; - unsigned int i; - struct ext4_group_desc *desc; - struct ext4_sb_info *sbi = EXT4_SB(sb); - struct ext4_buddy e4b; - int err = 0, ret, blk_free_count; - ext4_grpblk_t blocks_freed; - struct ext4_group_info *grp; - - ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1); - - ext4_get_group_no_and_offset(sb, block, &block_group, &bit); - grp = ext4_get_group_info(sb, block_group); - /* - * Check to see if we are freeing blocks across a group - * boundary. - */ - if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) - goto error_return; - - bitmap_bh = ext4_read_block_bitmap(sb, block_group); - if (!bitmap_bh) - goto error_return; - desc = ext4_get_group_desc(sb, block_group, &gd_bh); - if (!desc) - goto error_return; - - if (in_range(ext4_block_bitmap(sb, desc), block, count) || - in_range(ext4_inode_bitmap(sb, desc), block, count) || - in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) || - in_range(block + count - 1, ext4_inode_table(sb, desc), - sbi->s_itb_per_group)) { - ext4_error(sb, "Adding blocks in system zones - " - "Block = %llu, count = %lu", - block, count); - goto error_return; - } - - BUFFER_TRACE(bitmap_bh, "getting write access"); - err = ext4_journal_get_write_access(handle, bitmap_bh); - if (err) - goto error_return; - - /* - * We are about to modify some metadata. Call the journal APIs - * to unshare ->b_data if a currently-committing transaction is - * using it - */ - BUFFER_TRACE(gd_bh, "get_write_access"); - err = ext4_journal_get_write_access(handle, gd_bh); - if (err) - goto error_return; - - for (i = 0, blocks_freed = 0; i < count; i++) { - BUFFER_TRACE(bitmap_bh, "clear bit"); - if (!mb_test_bit(bit + i, bitmap_bh->b_data)) { - ext4_error(sb, "bit already cleared for block %llu", - (ext4_fsblk_t)(block + i)); - BUFFER_TRACE(bitmap_bh, "bit already cleared"); - } else { - blocks_freed++; - } - } - - err = ext4_mb_load_buddy(sb, block_group, &e4b); - if (err) - goto error_return; - - /* - * need to update group_info->bb_free and bitmap - * with group lock held. generate_buddy look at - * them with group lock_held - */ - ext4_lock_group(sb, block_group); - mb_clear_bits(bitmap_bh->b_data, bit, count); - mb_free_blocks(NULL, &e4b, bit, count); - blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc); - ext4_free_blks_set(sb, desc, blk_free_count); - desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc); - ext4_unlock_group(sb, block_group); - percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed); - - if (sbi->s_log_groups_per_flex) { - ext4_group_t flex_group = ext4_flex_group(sbi, block_group); - atomic_add(blocks_freed, - &sbi->s_flex_groups[flex_group].free_blocks); - } - - ext4_mb_unload_buddy(&e4b); - - /* We dirtied the bitmap block */ - BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); - err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); - - /* And the group descriptor block */ - BUFFER_TRACE(gd_bh, "dirtied group descriptor block"); - ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh); - if (!err) - err = ret; - -error_return: - brelse(bitmap_bh); - ext4_std_error(sb, err); - return; -} - /** * ext4_trim_extent -- function to TRIM one single free extent in the group * @sb: super block for the file system @@ -4777,10 +4715,11 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, * one will allocate those blocks, mark it as used in buddy bitmap. This must * be called with under the group lock. */ -static void ext4_trim_extent(struct super_block *sb, int start, int count, - ext4_group_t group, struct ext4_buddy *e4b) +static int ext4_trim_extent(struct super_block *sb, int start, int count, + ext4_group_t group, struct ext4_buddy *e4b) { struct ext4_free_extent ex; + int ret = 0; assert_spin_locked(ext4_group_lock_ptr(sb, group)); @@ -4794,9 +4733,12 @@ static void ext4_trim_extent(struct super_block *sb, int start, int count, */ mb_mark_used(e4b, &ex); ext4_unlock_group(sb, group); - ext4_issue_discard(sb, group, start, count); + + ret = ext4_issue_discard(sb, group, start, count); + ext4_lock_group(sb, group); mb_free_blocks(NULL, e4b, start, ex.fe_len); + return ret; } /** @@ -4818,26 +4760,21 @@ static void ext4_trim_extent(struct super_block *sb, int start, int count, * the group buddy bitmap. This is done until whole group is scanned. */ static ext4_grpblk_t -ext4_trim_all_free(struct super_block *sb, ext4_group_t group, - ext4_grpblk_t start, ext4_grpblk_t max, - ext4_grpblk_t minblocks) +ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b, + ext4_grpblk_t start, ext4_grpblk_t max, ext4_grpblk_t minblocks) { void *bitmap; ext4_grpblk_t next, count = 0; - struct ext4_buddy e4b; - int ret; + ext4_group_t group; + int ret = 0; - ret = ext4_mb_load_buddy(sb, group, &e4b); - if (ret) { - ext4_error(sb, "Error in loading buddy " - "information for %u", group); - return ret; - } - bitmap = e4b.bd_bitmap; + BUG_ON(e4b == NULL); + bitmap = e4b->bd_bitmap; + group = e4b->bd_group; + start = (e4b->bd_info->bb_first_free > start) ? + e4b->bd_info->bb_first_free : start; ext4_lock_group(sb, group); - start = (e4b.bd_info->bb_first_free > start) ? - e4b.bd_info->bb_first_free : start; while (start < max) { start = mb_find_next_zero_bit(bitmap, max, start); @@ -4846,8 +4783,10 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, next = mb_find_next_bit(bitmap, max, start); if ((next - start) >= minblocks) { - ext4_trim_extent(sb, start, - next - start, group, &e4b); + ret = ext4_trim_extent(sb, start, + next - start, group, e4b); + if (ret < 0) + break; count += next - start; } start = next + 1; @@ -4863,15 +4802,17 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, ext4_lock_group(sb, group); } - if ((e4b.bd_info->bb_free - count) < minblocks) + if ((e4b->bd_info->bb_free - count) < minblocks) break; } ext4_unlock_group(sb, group); - ext4_mb_unload_buddy(&e4b); ext4_debug("trimmed %d blocks in the group %d\n", count, group); + if (ret < 0) + count = ret; + return count; } @@ -4889,11 +4830,11 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, */ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) { - struct ext4_group_info *grp; + struct ext4_buddy e4b; ext4_group_t first_group, last_group; ext4_group_t group, ngroups = ext4_get_groups_count(sb); ext4_grpblk_t cnt = 0, first_block, last_block; - uint64_t start, len, minlen, trimmed = 0; + uint64_t start, len, minlen, trimmed; ext4_fsblk_t first_data_blk = le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); int ret = 0; @@ -4901,6 +4842,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) start = range->start >> sb->s_blocksize_bits; len = range->len >> sb->s_blocksize_bits; minlen = range->minlen >> sb->s_blocksize_bits; + trimmed = 0; if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb))) return -EINVAL; @@ -4921,12 +4863,11 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) return -EINVAL; for (group = first_group; group <= last_group; group++) { - grp = ext4_get_group_info(sb, group); - /* We only do this if the grp has never been initialized */ - if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) { - ret = ext4_mb_init_group(sb, group); - if (ret) - break; + ret = ext4_mb_load_buddy(sb, group, &e4b); + if (ret) { + ext4_error(sb, "Error in loading buddy " + "information for %u", group); + break; } /* @@ -4939,14 +4880,16 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) last_block = first_block + len; len -= last_block - first_block; - if (grp->bb_free >= minlen) { - cnt = ext4_trim_all_free(sb, group, first_block, + if (e4b.bd_info->bb_free >= minlen) { + cnt = ext4_trim_all_free(sb, &e4b, first_block, last_block, minlen); if (cnt < 0) { ret = cnt; + ext4_mb_unload_buddy(&e4b); break; } } + ext4_mb_unload_buddy(&e4b); trimmed += cnt; first_block = 0; } diff --git a/trunk/fs/ext4/mballoc.h b/trunk/fs/ext4/mballoc.h index 20b5e7bfebd1..22bd4d7f289b 100644 --- a/trunk/fs/ext4/mballoc.h +++ b/trunk/fs/ext4/mballoc.h @@ -193,6 +193,11 @@ struct ext4_allocation_context { __u8 ac_op; /* operation, for history only */ struct page *ac_bitmap_page; struct page *ac_buddy_page; + /* + * pointer to the held semaphore upon successful + * block allocation + */ + struct rw_semaphore *alloc_semp; struct ext4_prealloc_space *ac_pa; struct ext4_locality_group *ac_lg; }; @@ -210,6 +215,7 @@ struct ext4_buddy { struct super_block *bd_sb; __u16 bd_blkbits; ext4_group_t bd_group; + struct rw_semaphore *alloc_semp; }; #define EXT4_MB_BITMAP(e4b) ((e4b)->bd_bitmap) #define EXT4_MB_BUDDY(e4b) ((e4b)->bd_buddy) diff --git a/trunk/fs/ext4/migrate.c b/trunk/fs/ext4/migrate.c index b57b98fb44d1..92816b4e0f16 100644 --- a/trunk/fs/ext4/migrate.c +++ b/trunk/fs/ext4/migrate.c @@ -376,7 +376,7 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode, * We have the extent map build with the tmp inode. * Now copy the i_data across */ - ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS); + ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS); memcpy(ei->i_data, tmp_ei->i_data, sizeof(ei->i_data)); /* diff --git a/trunk/fs/ext4/mmp.c b/trunk/fs/ext4/mmp.c deleted file mode 100644 index 9bdef3f537c5..000000000000 --- a/trunk/fs/ext4/mmp.c +++ /dev/null @@ -1,351 +0,0 @@ -#include -#include -#include -#include -#include - -#include "ext4.h" - -/* - * Write the MMP block using WRITE_SYNC to try to get the block on-disk - * faster. - */ -static int write_mmp_block(struct buffer_head *bh) -{ - mark_buffer_dirty(bh); - lock_buffer(bh); - bh->b_end_io = end_buffer_write_sync; - get_bh(bh); - submit_bh(WRITE_SYNC, bh); - wait_on_buffer(bh); - if (unlikely(!buffer_uptodate(bh))) - return 1; - - return 0; -} - -/* - * Read the MMP block. It _must_ be read from disk and hence we clear the - * uptodate flag on the buffer. - */ -static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, - ext4_fsblk_t mmp_block) -{ - struct mmp_struct *mmp; - - if (*bh) - clear_buffer_uptodate(*bh); - - /* This would be sb_bread(sb, mmp_block), except we need to be sure - * that the MD RAID device cache has been bypassed, and that the read - * is not blocked in the elevator. */ - if (!*bh) - *bh = sb_getblk(sb, mmp_block); - if (*bh) { - get_bh(*bh); - lock_buffer(*bh); - (*bh)->b_end_io = end_buffer_read_sync; - submit_bh(READ_SYNC, *bh); - wait_on_buffer(*bh); - if (!buffer_uptodate(*bh)) { - brelse(*bh); - *bh = NULL; - } - } - if (!*bh) { - ext4_warning(sb, "Error while reading MMP block %llu", - mmp_block); - return -EIO; - } - - mmp = (struct mmp_struct *)((*bh)->b_data); - if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC) - return -EINVAL; - - return 0; -} - -/* - * Dump as much information as possible to help the admin. - */ -void __dump_mmp_msg(struct super_block *sb, struct mmp_struct *mmp, - const char *function, unsigned int line, const char *msg) -{ - __ext4_warning(sb, function, line, msg); - __ext4_warning(sb, function, line, - "MMP failure info: last update time: %llu, last update " - "node: %s, last update device: %s\n", - (long long unsigned int) le64_to_cpu(mmp->mmp_time), - mmp->mmp_nodename, mmp->mmp_bdevname); -} - -/* - * kmmpd will update the MMP sequence every s_mmp_update_interval seconds - */ -static int kmmpd(void *data) -{ - struct super_block *sb = ((struct mmpd_data *) data)->sb; - struct buffer_head *bh = ((struct mmpd_data *) data)->bh; - struct ext4_super_block *es = EXT4_SB(sb)->s_es; - struct mmp_struct *mmp; - ext4_fsblk_t mmp_block; - u32 seq = 0; - unsigned long failed_writes = 0; - int mmp_update_interval = le16_to_cpu(es->s_mmp_update_interval); - unsigned mmp_check_interval; - unsigned long last_update_time; - unsigned long diff; - int retval; - - mmp_block = le64_to_cpu(es->s_mmp_block); - mmp = (struct mmp_struct *)(bh->b_data); - mmp->mmp_time = cpu_to_le64(get_seconds()); - /* - * Start with the higher mmp_check_interval and reduce it if - * the MMP block is being updated on time. - */ - mmp_check_interval = max(EXT4_MMP_CHECK_MULT * mmp_update_interval, - EXT4_MMP_MIN_CHECK_INTERVAL); - mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval); - bdevname(bh->b_bdev, mmp->mmp_bdevname); - - memcpy(mmp->mmp_nodename, init_utsname()->sysname, - sizeof(mmp->mmp_nodename)); - - while (!kthread_should_stop()) { - if (++seq > EXT4_MMP_SEQ_MAX) - seq = 1; - - mmp->mmp_seq = cpu_to_le32(seq); - mmp->mmp_time = cpu_to_le64(get_seconds()); - last_update_time = jiffies; - - retval = write_mmp_block(bh); - /* - * Don't spew too many error messages. Print one every - * (s_mmp_update_interval * 60) seconds. - */ - if (retval && (failed_writes % 60) == 0) { - ext4_error(sb, "Error writing to MMP block"); - failed_writes++; - } - - if (!(le32_to_cpu(es->s_feature_incompat) & - EXT4_FEATURE_INCOMPAT_MMP)) { - ext4_warning(sb, "kmmpd being stopped since MMP feature" - " has been disabled."); - EXT4_SB(sb)->s_mmp_tsk = NULL; - goto failed; - } - - if (sb->s_flags & MS_RDONLY) { - ext4_warning(sb, "kmmpd being stopped since filesystem " - "has been remounted as readonly."); - EXT4_SB(sb)->s_mmp_tsk = NULL; - goto failed; - } - - diff = jiffies - last_update_time; - if (diff < mmp_update_interval * HZ) - schedule_timeout_interruptible(mmp_update_interval * - HZ - diff); - - /* - * We need to make sure that more than mmp_check_interval - * seconds have not passed since writing. If that has happened - * we need to check if the MMP block is as we left it. - */ - diff = jiffies - last_update_time; - if (diff > mmp_check_interval * HZ) { - struct buffer_head *bh_check = NULL; - struct mmp_struct *mmp_check; - - retval = read_mmp_block(sb, &bh_check, mmp_block); - if (retval) { - ext4_error(sb, "error reading MMP data: %d", - retval); - - EXT4_SB(sb)->s_mmp_tsk = NULL; - goto failed; - } - - mmp_check = (struct mmp_struct *)(bh_check->b_data); - if (mmp->mmp_seq != mmp_check->mmp_seq || - memcmp(mmp->mmp_nodename, mmp_check->mmp_nodename, - sizeof(mmp->mmp_nodename))) { - dump_mmp_msg(sb, mmp_check, - "Error while updating MMP info. " - "The filesystem seems to have been" - " multiply mounted."); - ext4_error(sb, "abort"); - goto failed; - } - put_bh(bh_check); - } - - /* - * Adjust the mmp_check_interval depending on how much time - * it took for the MMP block to be written. - */ - mmp_check_interval = max(min(EXT4_MMP_CHECK_MULT * diff / HZ, - EXT4_MMP_MAX_CHECK_INTERVAL), - EXT4_MMP_MIN_CHECK_INTERVAL); - mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval); - } - - /* - * Unmount seems to be clean. - */ - mmp->mmp_seq = cpu_to_le32(EXT4_MMP_SEQ_CLEAN); - mmp->mmp_time = cpu_to_le64(get_seconds()); - - retval = write_mmp_block(bh); - -failed: - kfree(data); - brelse(bh); - return retval; -} - -/* - * Get a random new sequence number but make sure it is not greater than - * EXT4_MMP_SEQ_MAX. - */ -static unsigned int mmp_new_seq(void) -{ - u32 new_seq; - - do { - get_random_bytes(&new_seq, sizeof(u32)); - } while (new_seq > EXT4_MMP_SEQ_MAX); - - return new_seq; -} - -/* - * Protect the filesystem from being mounted more than once. - */ -int ext4_multi_mount_protect(struct super_block *sb, - ext4_fsblk_t mmp_block) -{ - struct ext4_super_block *es = EXT4_SB(sb)->s_es; - struct buffer_head *bh = NULL; - struct mmp_struct *mmp = NULL; - struct mmpd_data *mmpd_data; - u32 seq; - unsigned int mmp_check_interval = le16_to_cpu(es->s_mmp_update_interval); - unsigned int wait_time = 0; - int retval; - - if (mmp_block < le32_to_cpu(es->s_first_data_block) || - mmp_block >= ext4_blocks_count(es)) { - ext4_warning(sb, "Invalid MMP block in superblock"); - goto failed; - } - - retval = read_mmp_block(sb, &bh, mmp_block); - if (retval) - goto failed; - - mmp = (struct mmp_struct *)(bh->b_data); - - if (mmp_check_interval < EXT4_MMP_MIN_CHECK_INTERVAL) - mmp_check_interval = EXT4_MMP_MIN_CHECK_INTERVAL; - - /* - * If check_interval in MMP block is larger, use that instead of - * update_interval from the superblock. - */ - if (mmp->mmp_check_interval > mmp_check_interval) - mmp_check_interval = mmp->mmp_check_interval; - - seq = le32_to_cpu(mmp->mmp_seq); - if (seq == EXT4_MMP_SEQ_CLEAN) - goto skip; - - if (seq == EXT4_MMP_SEQ_FSCK) { - dump_mmp_msg(sb, mmp, "fsck is running on the filesystem"); - goto failed; - } - - wait_time = min(mmp_check_interval * 2 + 1, - mmp_check_interval + 60); - - /* Print MMP interval if more than 20 secs. */ - if (wait_time > EXT4_MMP_MIN_CHECK_INTERVAL * 4) - ext4_warning(sb, "MMP interval %u higher than expected, please" - " wait.\n", wait_time * 2); - - if (schedule_timeout_interruptible(HZ * wait_time) != 0) { - ext4_warning(sb, "MMP startup interrupted, failing mount\n"); - goto failed; - } - - retval = read_mmp_block(sb, &bh, mmp_block); - if (retval) - goto failed; - mmp = (struct mmp_struct *)(bh->b_data); - if (seq != le32_to_cpu(mmp->mmp_seq)) { - dump_mmp_msg(sb, mmp, - "Device is already active on another node."); - goto failed; - } - -skip: - /* - * write a new random sequence number. - */ - mmp->mmp_seq = seq = cpu_to_le32(mmp_new_seq()); - - retval = write_mmp_block(bh); - if (retval) - goto failed; - - /* - * wait for MMP interval and check mmp_seq. - */ - if (schedule_timeout_interruptible(HZ * wait_time) != 0) { - ext4_warning(sb, "MMP startup interrupted, failing mount\n"); - goto failed; - } - - retval = read_mmp_block(sb, &bh, mmp_block); - if (retval) - goto failed; - mmp = (struct mmp_struct *)(bh->b_data); - if (seq != le32_to_cpu(mmp->mmp_seq)) { - dump_mmp_msg(sb, mmp, - "Device is already active on another node."); - goto failed; - } - - mmpd_data = kmalloc(sizeof(struct mmpd_data), GFP_KERNEL); - if (!mmpd_data) { - ext4_warning(sb, "not enough memory for mmpd_data"); - goto failed; - } - mmpd_data->sb = sb; - mmpd_data->bh = bh; - - /* - * Start a kernel thread to update the MMP block periodically. - */ - EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%s", - bdevname(bh->b_bdev, - mmp->mmp_bdevname)); - if (IS_ERR(EXT4_SB(sb)->s_mmp_tsk)) { - EXT4_SB(sb)->s_mmp_tsk = NULL; - kfree(mmpd_data); - ext4_warning(sb, "Unable to create kmmpd thread for %s.", - sb->s_id); - goto failed; - } - - return 0; - -failed: - brelse(bh); - return 1; -} - - diff --git a/trunk/fs/ext4/move_extent.c b/trunk/fs/ext4/move_extent.c index 2b8304bf3c50..b9f3e7862f13 100644 --- a/trunk/fs/ext4/move_extent.c +++ b/trunk/fs/ext4/move_extent.c @@ -876,7 +876,8 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, * It needs to call wait_on_page_writeback() to wait for the * writeback of the page. */ - wait_on_page_writeback(page); + if (PageWriteback(page)) + wait_on_page_writeback(page); /* Release old bh and drop refs */ try_to_release_page(page, 0); diff --git a/trunk/fs/ext4/namei.c b/trunk/fs/ext4/namei.c index b754b7721f51..67fd0b025858 100644 --- a/trunk/fs/ext4/namei.c +++ b/trunk/fs/ext4/namei.c @@ -1413,22 +1413,10 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, frame->at = entries; frame->bh = bh; bh = bh2; - - ext4_handle_dirty_metadata(handle, dir, frame->bh); - ext4_handle_dirty_metadata(handle, dir, bh); - de = do_split(handle,dir, &bh, frame, &hinfo, &retval); - if (!de) { - /* - * Even if the block split failed, we have to properly write - * out all the changes we did so far. Otherwise we can end up - * with corrupted filesystem. - */ - ext4_mark_inode_dirty(handle, dir); - dx_release(frames); + dx_release (frames); + if (!(de)) return retval; - } - dx_release(frames); retval = add_dirent_to_buf(handle, dentry, inode, de, bh); brelse(bh); @@ -2252,7 +2240,6 @@ static int ext4_symlink(struct inode *dir, handle_t *handle; struct inode *inode; int l, err, retries = 0; - int credits; l = strlen(symname)+1; if (l > dir->i_sb->s_blocksize) @@ -2260,26 +2247,10 @@ static int ext4_symlink(struct inode *dir, dquot_initialize(dir); - if (l > EXT4_N_BLOCKS * 4) { - /* - * For non-fast symlinks, we just allocate inode and put it on - * orphan list in the first transaction => we need bitmap, - * group descriptor, sb, inode block, quota blocks. - */ - credits = 4 + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb); - } else { - /* - * Fast symlink. We have to add entry to directory - * (EXT4_DATA_TRANS_BLOCKS + EXT4_INDEX_EXTRA_TRANS_BLOCKS), - * allocate new inode (bitmap, group descriptor, inode block, - * quota blocks, sb is already counted in previous macros). - */ - credits = EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + - EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + - EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb); - } retry: - handle = ext4_journal_start(dir, credits); + handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 5 + + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2292,44 +2263,21 @@ static int ext4_symlink(struct inode *dir, if (IS_ERR(inode)) goto out_stop; - if (l > EXT4_N_BLOCKS * 4) { + if (l > sizeof(EXT4_I(inode)->i_data)) { inode->i_op = &ext4_symlink_inode_operations; ext4_set_aops(inode); /* - * We cannot call page_symlink() with transaction started - * because it calls into ext4_write_begin() which can wait - * for transaction commit if we are running out of space - * and thus we deadlock. So we have to stop transaction now - * and restart it when symlink contents is written. - * - * To keep fs consistent in case of crash, we have to put inode - * to orphan list in the mean time. + * page_symlink() calls into ext4_prepare/commit_write. + * We have a transaction open. All is sweetness. It also sets + * i_size in generic_commit_write(). */ - drop_nlink(inode); - err = ext4_orphan_add(handle, inode); - ext4_journal_stop(handle); - if (err) - goto err_drop_inode; err = __page_symlink(inode, symname, l, 1); - if (err) - goto err_drop_inode; - /* - * Now inode is being linked into dir (EXT4_DATA_TRANS_BLOCKS - * + EXT4_INDEX_EXTRA_TRANS_BLOCKS), inode is also modified - */ - handle = ext4_journal_start(dir, - EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + - EXT4_INDEX_EXTRA_TRANS_BLOCKS + 1); - if (IS_ERR(handle)) { - err = PTR_ERR(handle); - goto err_drop_inode; - } - inc_nlink(inode); - err = ext4_orphan_del(handle, inode); if (err) { - ext4_journal_stop(handle); clear_nlink(inode); - goto err_drop_inode; + unlock_new_inode(inode); + ext4_mark_inode_dirty(handle, inode); + iput(inode); + goto out_stop; } } else { /* clear the extent format for fast symlink */ @@ -2345,10 +2293,6 @@ static int ext4_symlink(struct inode *dir, if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) goto retry; return err; -err_drop_inode: - unlock_new_inode(inode); - iput(inode); - return err; } static int ext4_link(struct dentry *old_dentry, diff --git a/trunk/fs/ext4/page-io.c b/trunk/fs/ext4/page-io.c index 7bb8f76d470a..b6dbd056fcb1 100644 --- a/trunk/fs/ext4/page-io.c +++ b/trunk/fs/ext4/page-io.c @@ -203,29 +203,46 @@ static void ext4_end_bio(struct bio *bio, int error) for (i = 0; i < io_end->num_io_pages; i++) { struct page *page = io_end->pages[i]->p_page; struct buffer_head *bh, *head; - loff_t offset; - loff_t io_end_offset; + int partial_write = 0; - if (error) { + head = page_buffers(page); + if (error) SetPageError(page); - set_bit(AS_EIO, &page->mapping->flags); - head = page_buffers(page); - BUG_ON(!head); - - io_end_offset = io_end->offset + io_end->size; + BUG_ON(!head); + if (head->b_size != PAGE_CACHE_SIZE) { + loff_t offset; + loff_t io_end_offset = io_end->offset + io_end->size; offset = (sector_t) page->index << PAGE_CACHE_SHIFT; bh = head; do { if ((offset >= io_end->offset) && - (offset+bh->b_size <= io_end_offset)) - buffer_io_error(bh); - + (offset+bh->b_size <= io_end_offset)) { + if (error) + buffer_io_error(bh); + + } + if (buffer_delay(bh)) + partial_write = 1; + else if (!buffer_mapped(bh)) + clear_buffer_dirty(bh); + else if (buffer_dirty(bh)) + partial_write = 1; offset += bh->b_size; bh = bh->b_this_page; } while (bh != head); } + /* + * If this is a partial write which happened to make + * all buffers uptodate then we can optimize away a + * bogus readpage() for the next read(). Here we + * 'discover' whether the page went uptodate as a + * result of this (potentially partial) write. + */ + if (!partial_write) + SetPageUptodate(page); + put_io_page(io_end->pages[i]); } io_end->num_io_pages = 0; diff --git a/trunk/fs/ext4/super.c b/trunk/fs/ext4/super.c index cc5c157aa11d..8553dfb310af 100644 --- a/trunk/fs/ext4/super.c +++ b/trunk/fs/ext4/super.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -76,27 +75,11 @@ static void ext4_write_super(struct super_block *sb); static int ext4_freeze(struct super_block *sb); static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data); -static inline int ext2_feature_set_ok(struct super_block *sb); -static inline int ext3_feature_set_ok(struct super_block *sb); static int ext4_feature_set_ok(struct super_block *sb, int readonly); static void ext4_destroy_lazyinit_thread(void); static void ext4_unregister_li_request(struct super_block *sb); static void ext4_clear_request_list(void); -#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) -static struct file_system_type ext2_fs_type = { - .owner = THIS_MODULE, - .name = "ext2", - .mount = ext4_mount, - .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV, -}; -#define IS_EXT2_SB(sb) ((sb)->s_bdev->bd_holder == &ext2_fs_type) -#else -#define IS_EXT2_SB(sb) (0) -#endif - - #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) static struct file_system_type ext3_fs_type = { .owner = THIS_MODULE, @@ -823,8 +806,6 @@ static void ext4_put_super(struct super_block *sb) invalidate_bdev(sbi->journal_bdev); ext4_blkdev_remove(sbi); } - if (sbi->s_mmp_tsk) - kthread_stop(sbi->s_mmp_tsk); sb->s_fs_info = NULL; /* * Now that we are completely done shutting down the @@ -1115,7 +1096,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) if (!test_opt(sb, INIT_INODE_TABLE)) seq_puts(seq, ",noinit_inode_table"); - else if (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT) + else if (sbi->s_li_wait_mult) seq_printf(seq, ",init_inode_table=%u", (unsigned) sbi->s_li_wait_mult); @@ -1206,7 +1187,9 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off); static const struct dquot_operations ext4_quota_operations = { +#ifdef CONFIG_QUOTA .get_reserved_space = ext4_get_reserved_space, +#endif .write_dquot = ext4_write_dquot, .acquire_dquot = ext4_acquire_dquot, .release_dquot = ext4_release_dquot, @@ -1917,7 +1900,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, ext4_msg(sb, KERN_WARNING, "warning: mounting fs with errors, " "running e2fsck is recommended"); - else if ((__s16) le16_to_cpu(es->s_max_mnt_count) > 0 && + else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 && le16_to_cpu(es->s_mnt_count) >= (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) ext4_msg(sb, KERN_WARNING, @@ -1949,7 +1932,6 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, EXT4_INODES_PER_GROUP(sb), sbi->s_mount_opt, sbi->s_mount_opt2); - cleancache_init_fs(sb); return res; } @@ -2443,18 +2425,6 @@ static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, EXT4_SB(sb)->s_sectors_written_start) >> 1))); } -static ssize_t extent_cache_hits_show(struct ext4_attr *a, - struct ext4_sb_info *sbi, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_hits); -} - -static ssize_t extent_cache_misses_show(struct ext4_attr *a, - struct ext4_sb_info *sbi, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_misses); -} - static ssize_t inode_readahead_blks_store(struct ext4_attr *a, struct ext4_sb_info *sbi, const char *buf, size_t count) @@ -2512,8 +2482,6 @@ static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store) EXT4_RO_ATTR(delayed_allocation_blocks); EXT4_RO_ATTR(session_write_kbytes); EXT4_RO_ATTR(lifetime_write_kbytes); -EXT4_RO_ATTR(extent_cache_hits); -EXT4_RO_ATTR(extent_cache_misses); EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, inode_readahead_blks_store, s_inode_readahead_blks); EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); @@ -2529,8 +2497,6 @@ static struct attribute *ext4_attrs[] = { ATTR_LIST(delayed_allocation_blocks), ATTR_LIST(session_write_kbytes), ATTR_LIST(lifetime_write_kbytes), - ATTR_LIST(extent_cache_hits), - ATTR_LIST(extent_cache_misses), ATTR_LIST(inode_readahead_blks), ATTR_LIST(inode_goal), ATTR_LIST(mb_stats), @@ -2693,6 +2659,12 @@ static void print_daily_error_info(unsigned long arg) mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ } +static void ext4_lazyinode_timeout(unsigned long data) +{ + struct task_struct *p = (struct task_struct *)data; + wake_up_process(p); +} + /* Find next suitable group and run ext4_init_inode_table */ static int ext4_run_li_request(struct ext4_li_request *elr) { @@ -2724,8 +2696,11 @@ static int ext4_run_li_request(struct ext4_li_request *elr) ret = ext4_init_inode_table(sb, group, elr->lr_timeout ? 0 : 1); if (elr->lr_timeout == 0) { - timeout = (jiffies - timeout) * - elr->lr_sbi->s_li_wait_mult; + timeout = jiffies - timeout; + if (elr->lr_sbi->s_li_wait_mult) + timeout *= elr->lr_sbi->s_li_wait_mult; + else + timeout *= 20; elr->lr_timeout = timeout; } elr->lr_next_sched = jiffies + elr->lr_timeout; @@ -2737,7 +2712,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr) /* * Remove lr_request from the list_request and free the - * request structure. Should be called with li_list_mtx held + * request tructure. Should be called with li_list_mtx held */ static void ext4_remove_li_request(struct ext4_li_request *elr) { @@ -2755,16 +2730,14 @@ static void ext4_remove_li_request(struct ext4_li_request *elr) static void ext4_unregister_li_request(struct super_block *sb) { - mutex_lock(&ext4_li_mtx); - if (!ext4_li_info) { - mutex_unlock(&ext4_li_mtx); + struct ext4_li_request *elr = EXT4_SB(sb)->s_li_request; + + if (!ext4_li_info) return; - } mutex_lock(&ext4_li_info->li_list_mtx); - ext4_remove_li_request(EXT4_SB(sb)->s_li_request); + ext4_remove_li_request(elr); mutex_unlock(&ext4_li_info->li_list_mtx); - mutex_unlock(&ext4_li_mtx); } static struct task_struct *ext4_lazyinit_task; @@ -2783,10 +2756,17 @@ static int ext4_lazyinit_thread(void *arg) struct ext4_lazy_init *eli = (struct ext4_lazy_init *)arg; struct list_head *pos, *n; struct ext4_li_request *elr; - unsigned long next_wakeup, cur; + unsigned long next_wakeup; + DEFINE_WAIT(wait); BUG_ON(NULL == eli); + eli->li_timer.data = (unsigned long)current; + eli->li_timer.function = ext4_lazyinode_timeout; + + eli->li_task = current; + wake_up(&eli->li_wait_task); + cont_thread: while (true) { next_wakeup = MAX_JIFFY_OFFSET; @@ -2817,15 +2797,19 @@ static int ext4_lazyinit_thread(void *arg) if (freezing(current)) refrigerator(); - cur = jiffies; - if ((time_after_eq(cur, next_wakeup)) || + if ((time_after_eq(jiffies, next_wakeup)) || (MAX_JIFFY_OFFSET == next_wakeup)) { cond_resched(); continue; } - schedule_timeout_interruptible(next_wakeup - cur); - + eli->li_timer.expires = next_wakeup; + add_timer(&eli->li_timer); + prepare_to_wait(&eli->li_wait_daemon, &wait, + TASK_INTERRUPTIBLE); + if (time_before(jiffies, next_wakeup)) + schedule(); + finish_wait(&eli->li_wait_daemon, &wait); if (kthread_should_stop()) { ext4_clear_request_list(); goto exit_thread; @@ -2849,7 +2833,12 @@ static int ext4_lazyinit_thread(void *arg) goto cont_thread; } mutex_unlock(&eli->li_list_mtx); + del_timer_sync(&ext4_li_info->li_timer); + eli->li_task = NULL; + wake_up(&eli->li_wait_task); + kfree(ext4_li_info); + ext4_lazyinit_task = NULL; ext4_li_info = NULL; mutex_unlock(&ext4_li_mtx); @@ -2877,6 +2866,7 @@ static int ext4_run_lazyinit_thread(void) if (IS_ERR(ext4_lazyinit_task)) { int err = PTR_ERR(ext4_lazyinit_task); ext4_clear_request_list(); + del_timer_sync(&ext4_li_info->li_timer); kfree(ext4_li_info); ext4_li_info = NULL; printk(KERN_CRIT "EXT4: error %d creating inode table " @@ -2885,6 +2875,8 @@ static int ext4_run_lazyinit_thread(void) return err; } ext4_li_info->li_state |= EXT4_LAZYINIT_RUNNING; + + wait_event(ext4_li_info->li_wait_task, ext4_li_info->li_task != NULL); return 0; } @@ -2919,9 +2911,13 @@ static int ext4_li_info_new(void) if (!eli) return -ENOMEM; + eli->li_task = NULL; INIT_LIST_HEAD(&eli->li_request_list); mutex_init(&eli->li_list_mtx); + init_waitqueue_head(&eli->li_wait_daemon); + init_waitqueue_head(&eli->li_wait_task); + init_timer(&eli->li_timer); eli->li_state |= EXT4_LAZYINIT_QUIT; ext4_li_info = eli; @@ -2964,19 +2960,20 @@ static int ext4_register_li_request(struct super_block *sb, ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; int ret = 0; - if (sbi->s_li_request != NULL) { - /* - * Reset timeout so it can be computed again, because - * s_li_wait_mult might have changed. - */ - sbi->s_li_request->lr_timeout = 0; + if (sbi->s_li_request != NULL) return 0; - } if (first_not_zeroed == ngroups || (sb->s_flags & MS_RDONLY) || - !test_opt(sb, INIT_INODE_TABLE)) + !test_opt(sb, INIT_INODE_TABLE)) { + sbi->s_li_request = NULL; return 0; + } + + if (first_not_zeroed == ngroups) { + sbi->s_li_request = NULL; + return 0; + } elr = ext4_li_request_new(sb, first_not_zeroed); if (!elr) @@ -3169,12 +3166,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ((def_mount_opts & EXT4_DEFM_NODELALLOC) == 0)) set_opt(sb, DELALLOC); - /* - * set default s_li_wait_mult for lazyinit, for the case there is - * no mount option specified. - */ - sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT; - if (!parse_options((char *) sbi->s_es->s_mount_opts, sb, &journal_devnum, &journal_ioprio, NULL, 0)) { ext4_msg(sb, KERN_WARNING, @@ -3196,28 +3187,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) "feature flags set on rev 0 fs, " "running e2fsck is recommended"); - if (IS_EXT2_SB(sb)) { - if (ext2_feature_set_ok(sb)) - ext4_msg(sb, KERN_INFO, "mounting ext2 file system " - "using the ext4 subsystem"); - else { - ext4_msg(sb, KERN_ERR, "couldn't mount as ext2 due " - "to feature incompatibilities"); - goto failed_mount; - } - } - - if (IS_EXT3_SB(sb)) { - if (ext3_feature_set_ok(sb)) - ext4_msg(sb, KERN_INFO, "mounting ext3 file system " - "using the ext4 subsystem"); - else { - ext4_msg(sb, KERN_ERR, "couldn't mount as ext3 due " - "to feature incompatibilities"); - goto failed_mount; - } - } - /* * Check feature flags regardless of the revision level, since we * previously didn't change the revision level when setting the flags, @@ -3490,11 +3459,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)); - if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_MMP) && - !(sb->s_flags & MS_RDONLY)) - if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block))) - goto failed_mount3; - /* * The first inode we look at is the journal inode. Don't try * root first: it may be modified in the journal! @@ -3510,6 +3474,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount_wq; } else { clear_opt(sb, DATA_FLAGS); + set_opt(sb, WRITEBACK_DATA); sbi->s_journal = NULL; needs_recovery = 0; goto no_journal; @@ -3742,8 +3707,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) percpu_counter_destroy(&sbi->s_freeinodes_counter); percpu_counter_destroy(&sbi->s_dirs_counter); percpu_counter_destroy(&sbi->s_dirtyblocks_counter); - if (sbi->s_mmp_tsk) - kthread_stop(sbi->s_mmp_tsk); failed_mount2: for (i = 0; i < db_count; i++) brelse(sbi->s_group_desc[i]); @@ -4279,7 +4242,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) int enable_quota = 0; ext4_group_t g; unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO; - int err = 0; + int err; #ifdef CONFIG_QUOTA int i; #endif @@ -4405,13 +4368,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) goto restore_opts; if (!ext4_setup_super(sb, es, 0)) sb->s_flags &= ~MS_RDONLY; - if (EXT4_HAS_INCOMPAT_FEATURE(sb, - EXT4_FEATURE_INCOMPAT_MMP)) - if (ext4_multi_mount_protect(sb, - le64_to_cpu(es->s_mmp_block))) { - err = -EROFS; - goto restore_opts; - } enable_quota = 1; } } @@ -4476,7 +4432,6 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; u64 fsid; - s64 bfree; if (test_opt(sb, MINIX_DF)) { sbi->s_overhead_last = 0; @@ -4520,10 +4475,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_type = EXT4_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; - bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - + buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); - /* prevent underflow in case that few free space is available */ - buf->f_bfree = max_t(s64, bfree, 0); buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); if (buf->f_bfree < ext4_r_blocks_count(es)) buf->f_bavail = 0; @@ -4699,9 +4652,6 @@ static int ext4_quota_off(struct super_block *sb, int type) if (test_opt(sb, DELALLOC)) sync_filesystem(sb); - if (!inode) - goto out; - /* Update modification times of quota files when userspace can * start looking at them */ handle = ext4_journal_start(inode, 1); @@ -4822,6 +4772,14 @@ static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, } #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) +static struct file_system_type ext2_fs_type = { + .owner = THIS_MODULE, + .name = "ext2", + .mount = ext4_mount, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, +}; + static inline void register_as_ext2(void) { int err = register_filesystem(&ext2_fs_type); @@ -4834,22 +4792,10 @@ static inline void unregister_as_ext2(void) { unregister_filesystem(&ext2_fs_type); } - -static inline int ext2_feature_set_ok(struct super_block *sb) -{ - if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP)) - return 0; - if (sb->s_flags & MS_RDONLY) - return 1; - if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP)) - return 0; - return 1; -} MODULE_ALIAS("ext2"); #else static inline void register_as_ext2(void) { } static inline void unregister_as_ext2(void) { } -static inline int ext2_feature_set_ok(struct super_block *sb) { return 0; } #endif #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) @@ -4865,24 +4811,10 @@ static inline void unregister_as_ext3(void) { unregister_filesystem(&ext3_fs_type); } - -static inline int ext3_feature_set_ok(struct super_block *sb) -{ - if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP)) - return 0; - if (!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) - return 0; - if (sb->s_flags & MS_RDONLY) - return 1; - if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP)) - return 0; - return 1; -} MODULE_ALIAS("ext3"); #else static inline void register_as_ext3(void) { } static inline void unregister_as_ext3(void) { } -static inline int ext3_feature_set_ok(struct super_block *sb) { return 0; } #endif static struct file_system_type ext4_fs_type = { @@ -4966,8 +4898,8 @@ static int __init ext4_init_fs(void) err = init_inodecache(); if (err) goto out1; - register_as_ext3(); register_as_ext2(); + register_as_ext3(); err = register_filesystem(&ext4_fs_type); if (err) goto out; diff --git a/trunk/fs/ext4/xattr.c b/trunk/fs/ext4/xattr.c index c757adc97250..b545ca1c459c 100644 --- a/trunk/fs/ext4/xattr.c +++ b/trunk/fs/ext4/xattr.c @@ -820,8 +820,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) goal = goal & EXT4_MAX_BLOCK_FILE_PHYS; - block = ext4_new_meta_blocks(handle, inode, goal, 0, - NULL, &error); + block = ext4_new_meta_blocks(handle, inode, + goal, NULL, &error); if (error) goto cleanup; diff --git a/trunk/fs/fat/namei_msdos.c b/trunk/fs/fat/namei_msdos.c index be15437c272e..3b222dafd15b 100644 --- a/trunk/fs/fat/namei_msdos.c +++ b/trunk/fs/fat/namei_msdos.c @@ -326,8 +326,6 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) struct fat_slot_info sinfo; int err; - dentry_unhash(dentry); - lock_super(sb); /* * Check whether the directory is not in use, then check @@ -459,9 +457,6 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, old_inode = old_dentry->d_inode; new_inode = new_dentry->d_inode; - if (new_inode && S_ISDIR(new_inode->i_mode)) - dentry_unhash(new_dentry); - err = fat_scan(old_dir, old_name, &old_sinfo); if (err) { err = -EIO; diff --git a/trunk/fs/fat/namei_vfat.c b/trunk/fs/fat/namei_vfat.c index c61a6789f36c..20b4ea53fdc4 100644 --- a/trunk/fs/fat/namei_vfat.c +++ b/trunk/fs/fat/namei_vfat.c @@ -824,8 +824,6 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry) struct fat_slot_info sinfo; int err; - dentry_unhash(dentry); - lock_super(sb); err = fat_dir_empty(inode); @@ -933,9 +931,6 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, int err, is_dir, update_dotdot, corrupt = 0; struct super_block *sb = old_dir->i_sb; - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; old_inode = old_dentry->d_inode; new_inode = new_dentry->d_inode; diff --git a/trunk/fs/fuse/dir.c b/trunk/fs/fuse/dir.c index 0d0e3faddcfa..b32eb29a4e6f 100644 --- a/trunk/fs/fuse/dir.c +++ b/trunk/fs/fuse/dir.c @@ -667,8 +667,6 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) if (IS_ERR(req)) return PTR_ERR(req); - dentry_unhash(entry); - req->in.h.opcode = FUSE_RMDIR; req->in.h.nodeid = get_node_id(dir); req->in.numargs = 1; @@ -693,10 +691,6 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, struct fuse_rename_in inarg; struct fuse_conn *fc = get_fuse_conn(olddir); struct fuse_req *req = fuse_get_req(fc); - - if (newent->d_inode && S_ISDIR(newent->d_inode->i_mode)) - dentry_unhash(newent); - if (IS_ERR(req)) return PTR_ERR(req); diff --git a/trunk/fs/gfs2/main.c b/trunk/fs/gfs2/main.c index c2b34cd2abe0..cfa327d33194 100644 --- a/trunk/fs/gfs2/main.c +++ b/trunk/fs/gfs2/main.c @@ -146,7 +146,7 @@ static int __init init_gfs2_fs(void) gfs2_register_debugfs(); - printk("GFS2 installed\n"); + printk("GFS2 (built %s %s) installed\n", __DATE__, __TIME__); return 0; diff --git a/trunk/fs/hfs/dir.c b/trunk/fs/hfs/dir.c index 1cb70cdba2c1..b4d70b13be92 100644 --- a/trunk/fs/hfs/dir.c +++ b/trunk/fs/hfs/dir.c @@ -253,9 +253,6 @@ static int hfs_remove(struct inode *dir, struct dentry *dentry) struct inode *inode = dentry->d_inode; int res; - if (S_ISDIR(inode->i_mode)) - dentry_unhash(dentry); - if (S_ISDIR(inode->i_mode) && inode->i_size != 2) return -ENOTEMPTY; res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name); @@ -286,9 +283,6 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry, /* Unlink destination if it already exists */ if (new_dentry->d_inode) { - if (S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - res = hfs_remove(new_dir, new_dentry); if (res) return res; diff --git a/trunk/fs/hfsplus/dir.c b/trunk/fs/hfsplus/dir.c index b28835091dd0..4df5059c25da 100644 --- a/trunk/fs/hfsplus/dir.c +++ b/trunk/fs/hfsplus/dir.c @@ -370,8 +370,6 @@ static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) struct inode *inode = dentry->d_inode; int res; - dentry_unhash(dentry); - if (inode->i_size != 2) return -ENOTEMPTY; @@ -469,12 +467,10 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, /* Unlink destination if it already exists */ if (new_dentry->d_inode) { - if (S_ISDIR(new_dentry->d_inode->i_mode)) { - dentry_unhash(new_dentry); + if (S_ISDIR(new_dentry->d_inode->i_mode)) res = hfsplus_rmdir(new_dir, new_dentry); - } else { + else res = hfsplus_unlink(new_dir, new_dentry); - } if (res) return res; } diff --git a/trunk/fs/hostfs/hostfs_kern.c b/trunk/fs/hostfs/hostfs_kern.c index e6816b9e6903..2638c834ed28 100644 --- a/trunk/fs/hostfs/hostfs_kern.c +++ b/trunk/fs/hostfs/hostfs_kern.c @@ -683,8 +683,6 @@ int hostfs_rmdir(struct inode *ino, struct dentry *dentry) char *file; int err; - dentry_unhash(dentry); - if ((file = dentry_name(dentry)) == NULL) return -ENOMEM; err = do_rmdir(file); @@ -738,9 +736,6 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from, char *from_name, *to_name; int err; - if (to->d_inode && S_ISDIR(to->d_inode->i_mode)) - dentry_unhash(to); - if ((from_name = dentry_name(from)) == NULL) return -ENOMEM; if ((to_name = dentry_name(to)) == NULL) { diff --git a/trunk/fs/hpfs/namei.c b/trunk/fs/hpfs/namei.c index ff0ce21c0867..1f05839c27a7 100644 --- a/trunk/fs/hpfs/namei.c +++ b/trunk/fs/hpfs/namei.c @@ -395,6 +395,7 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry) dentry_unhash(dentry); if (!d_unhashed(dentry)) { + dput(dentry); hpfs_unlock(dir->i_sb); return -ENOSPC; } @@ -402,6 +403,7 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry) !S_ISREG(inode->i_mode) || get_write_access(inode)) { d_rehash(dentry); + dput(dentry); } else { struct iattr newattrs; /*printk("HPFS: truncating file before delete.\n");*/ @@ -409,6 +411,7 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry) newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; err = notify_change(dentry, &newattrs); put_write_access(inode); + dput(dentry); if (!err) goto again; } @@ -439,8 +442,6 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) int err; int r; - dentry_unhash(dentry); - hpfs_adjust_length(name, &len); hpfs_lock(dir->i_sb); err = -ENOENT; @@ -534,10 +535,6 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct buffer_head *bh; struct fnode *fnode; int err; - - if (new_inode && S_ISDIR(new_inode->i_mode)) - dentry_unhash(new_dentry); - if ((err = hpfs_chk_name(new_name, &new_len))) return err; err = 0; hpfs_adjust_length(old_name, &old_len); diff --git a/trunk/fs/hugetlbfs/inode.c b/trunk/fs/hugetlbfs/inode.c index 7aafeb8fa300..e7a035781b7d 100644 --- a/trunk/fs/hugetlbfs/inode.c +++ b/trunk/fs/hugetlbfs/inode.c @@ -921,8 +921,7 @@ static int can_do_hugetlb_shm(void) return capable(CAP_IPC_LOCK) || in_group_p(sysctl_hugetlb_shm_group); } -struct file *hugetlb_file_setup(const char *name, size_t size, - vm_flags_t acctflag, +struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, struct user_struct **user, int creat_flags) { int error = -ENOMEM; diff --git a/trunk/fs/jbd2/commit.c b/trunk/fs/jbd2/commit.c index 7f21cf3aaf92..29148a81c783 100644 --- a/trunk/fs/jbd2/commit.c +++ b/trunk/fs/jbd2/commit.c @@ -219,6 +219,7 @@ static int journal_submit_data_buffers(journal_t *journal, ret = err; spin_lock(&journal->j_list_lock); J_ASSERT(jinode->i_transaction == commit_transaction); + commit_transaction->t_flushed_data_blocks = 1; clear_bit(__JI_COMMIT_RUNNING, &jinode->i_flags); smp_mb__after_clear_bit(); wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); @@ -671,16 +672,12 @@ void jbd2_journal_commit_transaction(journal_t *journal) err = 0; } - write_lock(&journal->j_state_lock); - J_ASSERT(commit_transaction->t_state == T_COMMIT); - commit_transaction->t_state = T_COMMIT_DFLUSH; - write_unlock(&journal->j_state_lock); /* * If the journal is not located on the file system device, * then we must flush the file system device before we issue * the commit record */ - if (commit_transaction->t_need_data_flush && + if (commit_transaction->t_flushed_data_blocks && (journal->j_fs_dev != journal->j_dev) && (journal->j_flags & JBD2_BARRIER)) blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); @@ -757,13 +754,8 @@ void jbd2_journal_commit_transaction(journal_t *journal) required. */ JBUFFER_TRACE(jh, "file as BJ_Forget"); jbd2_journal_file_buffer(jh, commit_transaction, BJ_Forget); - /* - * Wake up any transactions which were waiting for this IO to - * complete. The barrier must be here so that changes by - * jbd2_journal_file_buffer() take effect before wake_up_bit() - * does the waitqueue check. - */ - smp_mb(); + /* Wake up any transactions which were waiting for this + IO to complete */ wake_up_bit(&bh->b_state, BH_Unshadow); JBUFFER_TRACE(jh, "brelse shadowed buffer"); __brelse(bh); @@ -802,10 +794,6 @@ void jbd2_journal_commit_transaction(journal_t *journal) jbd2_journal_abort(journal, err); jbd_debug(3, "JBD: commit phase 5\n"); - write_lock(&journal->j_state_lock); - J_ASSERT(commit_transaction->t_state == T_COMMIT_DFLUSH); - commit_transaction->t_state = T_COMMIT_JFLUSH; - write_unlock(&journal->j_state_lock); if (!JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { @@ -961,7 +949,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) jbd_debug(3, "JBD: commit phase 7\n"); - J_ASSERT(commit_transaction->t_state == T_COMMIT_JFLUSH); + J_ASSERT(commit_transaction->t_state == T_COMMIT); commit_transaction->t_start = jiffies; stats.run.rs_logging = jbd2_time_diff(stats.run.rs_logging, diff --git a/trunk/fs/jbd2/journal.c b/trunk/fs/jbd2/journal.c index 9a7826990304..e0ec3db1c395 100644 --- a/trunk/fs/jbd2/journal.c +++ b/trunk/fs/jbd2/journal.c @@ -479,12 +479,9 @@ int __jbd2_log_space_left(journal_t *journal) int __jbd2_log_start_commit(journal_t *journal, tid_t target) { /* - * The only transaction we can possibly wait upon is the - * currently running transaction (if it exists). Otherwise, - * the target tid must be an old one. + * Are we already doing a recent enough commit? */ - if (journal->j_running_transaction && - journal->j_running_transaction->t_tid == target) { + if (!tid_geq(journal->j_commit_request, target)) { /* * We want a new commit: OK, mark the request and wakeup the * commit thread. We do _not_ do the commit ourselves. @@ -496,15 +493,7 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target) journal->j_commit_sequence); wake_up(&journal->j_wait_commit); return 1; - } else if (!tid_geq(journal->j_commit_request, target)) - /* This should never happen, but if it does, preserve - the evidence before kjournald goes into a loop and - increments j_commit_sequence beyond all recognition. */ - WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n", - journal->j_commit_request, - journal->j_commit_sequence, - target, journal->j_running_transaction ? - journal->j_running_transaction->t_tid : 0); + } return 0; } @@ -587,47 +576,6 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid) return ret; } -/* - * Return 1 if a given transaction has not yet sent barrier request - * connected with a transaction commit. If 0 is returned, transaction - * may or may not have sent the barrier. Used to avoid sending barrier - * twice in common cases. - */ -int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid) -{ - int ret = 0; - transaction_t *commit_trans; - - if (!(journal->j_flags & JBD2_BARRIER)) - return 0; - read_lock(&journal->j_state_lock); - /* Transaction already committed? */ - if (tid_geq(journal->j_commit_sequence, tid)) - goto out; - commit_trans = journal->j_committing_transaction; - if (!commit_trans || commit_trans->t_tid != tid) { - ret = 1; - goto out; - } - /* - * Transaction is being committed and we already proceeded to - * submitting a flush to fs partition? - */ - if (journal->j_fs_dev != journal->j_dev) { - if (!commit_trans->t_need_data_flush || - commit_trans->t_state >= T_COMMIT_DFLUSH) - goto out; - } else { - if (commit_trans->t_state >= T_COMMIT_JFLUSH) - goto out; - } - ret = 1; -out: - read_unlock(&journal->j_state_lock); - return ret; -} -EXPORT_SYMBOL(jbd2_trans_will_send_data_barrier); - /* * Wait for a specified commit to complete. * The caller may not hold the journal lock. diff --git a/trunk/fs/jbd2/transaction.c b/trunk/fs/jbd2/transaction.c index 3eec82d32fd4..05fa77a23711 100644 --- a/trunk/fs/jbd2/transaction.c +++ b/trunk/fs/jbd2/transaction.c @@ -82,7 +82,7 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) */ /* - * Update transaction's maximum wait time, if debugging is enabled. + * Update transiaction's maximum wait time, if debugging is enabled. * * In order for t_max_wait to be reliable, it must be protected by a * lock. But doing so will mean that start_this_handle() can not be @@ -91,10 +91,11 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) * means that maximum wait time reported by the jbd2_run_stats * tracepoint will always be zero. */ -static inline void update_t_max_wait(transaction_t *transaction, - unsigned long ts) +static inline void update_t_max_wait(transaction_t *transaction) { #ifdef CONFIG_JBD2_DEBUG + unsigned long ts = jiffies; + if (jbd2_journal_enable_debug && time_after(transaction->t_start, ts)) { ts = jbd2_time_diff(ts, transaction->t_start); @@ -120,7 +121,6 @@ static int start_this_handle(journal_t *journal, handle_t *handle, tid_t tid; int needed, need_to_start; int nblocks = handle->h_buffer_credits; - unsigned long ts = jiffies; if (nblocks > journal->j_max_transaction_buffers) { printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", @@ -271,7 +271,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle, /* OK, account for the buffers that this operation expects to * use and add the handle to the running transaction. */ - update_t_max_wait(transaction, ts); + update_t_max_wait(transaction); handle->h_transaction = transaction; atomic_inc(&transaction->t_updates); atomic_inc(&transaction->t_handle_count); @@ -316,8 +316,7 @@ static handle_t *new_handle(int nblocks) * This function is visible to journal users (like ext3fs), so is not * called with the journal already locked. * - * Return a pointer to a newly allocated handle, or an ERR_PTR() value - * on failure. + * Return a pointer to a newly allocated handle, or NULL on failure */ handle_t *jbd2__journal_start(journal_t *journal, int nblocks, int gfp_mask) { @@ -922,8 +921,8 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh) */ JBUFFER_TRACE(jh, "cancelling revoke"); jbd2_journal_cancel_revoke(handle, jh); -out: jbd2_journal_put_journal_head(jh); +out: return err; } @@ -2148,13 +2147,6 @@ int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode) jinode->i_next_transaction == transaction) goto done; - /* - * We only ever set this variable to 1 so the test is safe. Since - * t_need_data_flush is likely to be set, we do the test to save some - * cacheline bouncing - */ - if (!transaction->t_need_data_flush) - transaction->t_need_data_flush = 1; /* On some different transaction's list - should be * the committing one */ if (jinode->i_transaction) { diff --git a/trunk/fs/jffs2/dir.c b/trunk/fs/jffs2/dir.c index 05f73328b28b..82faddd1f321 100644 --- a/trunk/fs/jffs2/dir.c +++ b/trunk/fs/jffs2/dir.c @@ -609,8 +609,6 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) int ret; uint32_t now = get_seconds(); - dentry_unhash(dentry); - for (fd = f->dents ; fd; fd = fd->next) { if (fd->ino) return -ENOTEMPTY; @@ -786,9 +784,6 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, uint8_t type; uint32_t now; - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - /* The VFS will check for us and prevent trying to rename a * file over a directory and vice versa, but if it's a directory, * the VFS can't check whether the victim is empty. The filesystem diff --git a/trunk/fs/jfs/namei.c b/trunk/fs/jfs/namei.c index 865df16a6cf3..eaaf2b511e89 100644 --- a/trunk/fs/jfs/namei.c +++ b/trunk/fs/jfs/namei.c @@ -360,8 +360,6 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry) jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name); - dentry_unhash(dentry); - /* Init inode for quota operations. */ dquot_initialize(dip); dquot_initialize(ip); @@ -1097,9 +1095,6 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, jfs_info("jfs_rename: %s %s", old_dentry->d_name.name, new_dentry->d_name.name); - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - dquot_initialize(old_dir); dquot_initialize(new_dir); diff --git a/trunk/fs/logfs/dir.c b/trunk/fs/logfs/dir.c index f34c9cde9e94..9ed89d1663f8 100644 --- a/trunk/fs/logfs/dir.c +++ b/trunk/fs/logfs/dir.c @@ -273,8 +273,6 @@ static int logfs_rmdir(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; - dentry_unhash(dentry); - if (!logfs_empty_dir(inode)) return -ENOTEMPTY; @@ -624,9 +622,6 @@ static int logfs_rename_cross(struct inode *old_dir, struct dentry *old_dentry, loff_t pos; int err; - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - /* 1. locate source dd */ err = logfs_get_dd(old_dir, old_dentry, &dd, &pos); if (err) diff --git a/trunk/fs/minix/namei.c b/trunk/fs/minix/namei.c index f60aed8db9c4..6e6777f1b4b2 100644 --- a/trunk/fs/minix/namei.c +++ b/trunk/fs/minix/namei.c @@ -168,8 +168,6 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry) struct inode * inode = dentry->d_inode; int err = -ENOTEMPTY; - dentry_unhash(dentry); - if (minix_empty_dir(inode)) { err = minix_unlink(dir, dentry); if (!err) { @@ -192,9 +190,6 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, struct minix_dir_entry * old_de; int err = -ENOENT; - if (new_inode && S_ISDIR(new_inode->i_mode)) - dentry_unhash(new_dentry); - old_de = minix_find_entry(old_dentry, &old_page); if (!old_de) goto out; diff --git a/trunk/fs/mpage.c b/trunk/fs/mpage.c index fdfae9fa98cd..0afc809e46e0 100644 --- a/trunk/fs/mpage.c +++ b/trunk/fs/mpage.c @@ -27,7 +27,6 @@ #include #include #include -#include /* * I/O completion handler for multipage BIOs. @@ -272,12 +271,6 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages, SetPageMappedToDisk(page); } - if (fully_mapped && blocks_per_page == 1 && !PageUptodate(page) && - cleancache_get_page(page) == 0) { - SetPageUptodate(page); - goto confused; - } - /* * This page will go to BIO. Do we need to send this BIO off first? */ diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 2358b326b221..6ff858c049c0 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -391,28 +391,79 @@ void path_put(struct path *path) } EXPORT_SYMBOL(path_put); -/* +/** + * nameidata_drop_rcu - drop this nameidata out of rcu-walk + * @nd: nameidata pathwalk data to drop + * Returns: 0 on success, -ECHILD on failure + * * Path walking has 2 modes, rcu-walk and ref-walk (see - * Documentation/filesystems/path-lookup.txt). In situations when we can't - * continue in RCU mode, we attempt to drop out of rcu-walk mode and grab - * normal reference counts on dentries and vfsmounts to transition to rcu-walk - * mode. Refcounts are grabbed at the last known good point before rcu-walk - * got stuck, so ref-walk may continue from there. If this is not successful - * (eg. a seqcount has changed), then failure is returned and it's up to caller - * to restart the path walk from the beginning in ref-walk mode. + * Documentation/filesystems/path-lookup.txt). __drop_rcu* functions attempt + * to drop out of rcu-walk mode and take normal reference counts on dentries + * and vfsmounts to transition to rcu-walk mode. __drop_rcu* functions take + * refcounts at the last known good point before rcu-walk got stuck, so + * ref-walk may continue from there. If this is not successful (eg. a seqcount + * has changed), then failure is returned and path walk restarts from the + * beginning in ref-walk mode. + * + * nameidata_drop_rcu attempts to drop the current nd->path and nd->root into + * ref-walk. Must be called from rcu-walk context. */ +static int nameidata_drop_rcu(struct nameidata *nd) +{ + struct fs_struct *fs = current->fs; + struct dentry *dentry = nd->path.dentry; + int want_root = 0; + + BUG_ON(!(nd->flags & LOOKUP_RCU)); + if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) { + want_root = 1; + spin_lock(&fs->lock); + if (nd->root.mnt != fs->root.mnt || + nd->root.dentry != fs->root.dentry) + goto err_root; + } + spin_lock(&dentry->d_lock); + if (!__d_rcu_to_refcount(dentry, nd->seq)) + goto err; + BUG_ON(nd->inode != dentry->d_inode); + spin_unlock(&dentry->d_lock); + if (want_root) { + path_get(&nd->root); + spin_unlock(&fs->lock); + } + mntget(nd->path.mnt); + + rcu_read_unlock(); + br_read_unlock(vfsmount_lock); + nd->flags &= ~LOOKUP_RCU; + return 0; +err: + spin_unlock(&dentry->d_lock); +err_root: + if (want_root) + spin_unlock(&fs->lock); + return -ECHILD; +} + +/* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing. */ +static inline int nameidata_drop_rcu_maybe(struct nameidata *nd) +{ + if (nd->flags & LOOKUP_RCU) + return nameidata_drop_rcu(nd); + return 0; +} /** - * unlazy_walk - try to switch to ref-walk mode. - * @nd: nameidata pathwalk data - * @dentry: child of nd->path.dentry or NULL + * nameidata_dentry_drop_rcu - drop nameidata and dentry out of rcu-walk + * @nd: nameidata pathwalk data to drop + * @dentry: dentry to drop * Returns: 0 on success, -ECHILD on failure * - * unlazy_walk attempts to legitimize the current nd->path, nd->root and dentry - * for ref-walk mode. @dentry must be a path found by a do_lookup call on - * @nd or NULL. Must be called from rcu-walk context. + * nameidata_dentry_drop_rcu attempts to drop the current nd->path and nd->root, + * and dentry into ref-walk. @dentry must be a path found by a do_lookup call on + * @nd. Must be called from rcu-walk context. */ -static int unlazy_walk(struct nameidata *nd, struct dentry *dentry) +static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry) { struct fs_struct *fs = current->fs; struct dentry *parent = nd->path.dentry; @@ -427,25 +478,18 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry) goto err_root; } spin_lock(&parent->d_lock); - if (!dentry) { - if (!__d_rcu_to_refcount(parent, nd->seq)) - goto err_parent; - BUG_ON(nd->inode != parent->d_inode); - } else { - spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); - if (!__d_rcu_to_refcount(dentry, nd->seq)) - goto err_child; - /* - * If the sequence check on the child dentry passed, then - * the child has not been removed from its parent. This - * means the parent dentry must be valid and able to take - * a reference at this point. - */ - BUG_ON(!IS_ROOT(dentry) && dentry->d_parent != parent); - BUG_ON(!parent->d_count); - parent->d_count++; - spin_unlock(&dentry->d_lock); - } + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); + if (!__d_rcu_to_refcount(dentry, nd->seq)) + goto err; + /* + * If the sequence check on the child dentry passed, then the child has + * not been removed from its parent. This means the parent dentry must + * be valid and able to take a reference at this point. + */ + BUG_ON(!IS_ROOT(dentry) && dentry->d_parent != parent); + BUG_ON(!parent->d_count); + parent->d_count++; + spin_unlock(&dentry->d_lock); spin_unlock(&parent->d_lock); if (want_root) { path_get(&nd->root); @@ -457,10 +501,8 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry) br_read_unlock(vfsmount_lock); nd->flags &= ~LOOKUP_RCU; return 0; - -err_child: +err: spin_unlock(&dentry->d_lock); -err_parent: spin_unlock(&parent->d_lock); err_root: if (want_root) @@ -468,6 +510,59 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry) return -ECHILD; } +/* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing. */ +static inline int nameidata_dentry_drop_rcu_maybe(struct nameidata *nd, struct dentry *dentry) +{ + if (nd->flags & LOOKUP_RCU) { + if (unlikely(nameidata_dentry_drop_rcu(nd, dentry))) { + nd->flags &= ~LOOKUP_RCU; + if (!(nd->flags & LOOKUP_ROOT)) + nd->root.mnt = NULL; + rcu_read_unlock(); + br_read_unlock(vfsmount_lock); + return -ECHILD; + } + } + return 0; +} + +/** + * nameidata_drop_rcu_last - drop nameidata ending path walk out of rcu-walk + * @nd: nameidata pathwalk data to drop + * Returns: 0 on success, -ECHILD on failure + * + * nameidata_drop_rcu_last attempts to drop the current nd->path into ref-walk. + * nd->path should be the final element of the lookup, so nd->root is discarded. + * Must be called from rcu-walk context. + */ +static int nameidata_drop_rcu_last(struct nameidata *nd) +{ + struct dentry *dentry = nd->path.dentry; + + BUG_ON(!(nd->flags & LOOKUP_RCU)); + nd->flags &= ~LOOKUP_RCU; + if (!(nd->flags & LOOKUP_ROOT)) + nd->root.mnt = NULL; + spin_lock(&dentry->d_lock); + if (!__d_rcu_to_refcount(dentry, nd->seq)) + goto err_unlock; + BUG_ON(nd->inode != dentry->d_inode); + spin_unlock(&dentry->d_lock); + + mntget(nd->path.mnt); + + rcu_read_unlock(); + br_read_unlock(vfsmount_lock); + + return 0; + +err_unlock: + spin_unlock(&dentry->d_lock); + rcu_read_unlock(); + br_read_unlock(vfsmount_lock); + return -ECHILD; +} + /** * release_open_intent - free up open intent resources * @nd: pointer to nameidata @@ -511,39 +606,26 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd) return dentry; } -/** - * complete_walk - successful completion of path walk - * @nd: pointer nameidata +/* + * handle_reval_path - force revalidation of a dentry + * + * In some situations the path walking code will trust dentries without + * revalidating them. This causes problems for filesystems that depend on + * d_revalidate to handle file opens (e.g. NFSv4). When FS_REVAL_DOT is set + * (which indicates that it's possible for the dentry to go stale), force + * a d_revalidate call before proceeding. * - * If we had been in RCU mode, drop out of it and legitimize nd->path. - * Revalidate the final result, unless we'd already done that during - * the path walk or the filesystem doesn't ask for it. Return 0 on - * success, -error on failure. In case of failure caller does not - * need to drop nd->path. + * Returns 0 if the revalidation was successful. If the revalidation fails, + * either return the error returned by d_revalidate or -ESTALE if the + * revalidation it just returned 0. If d_revalidate returns 0, we attempt to + * invalidate the dentry. It's up to the caller to handle putting references + * to the path if necessary. */ -static int complete_walk(struct nameidata *nd) +static inline int handle_reval_path(struct nameidata *nd) { struct dentry *dentry = nd->path.dentry; int status; - if (nd->flags & LOOKUP_RCU) { - nd->flags &= ~LOOKUP_RCU; - if (!(nd->flags & LOOKUP_ROOT)) - nd->root.mnt = NULL; - spin_lock(&dentry->d_lock); - if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) { - spin_unlock(&dentry->d_lock); - rcu_read_unlock(); - br_read_unlock(vfsmount_lock); - return -ECHILD; - } - BUG_ON(nd->inode != dentry->d_inode); - spin_unlock(&dentry->d_lock); - mntget(nd->path.mnt); - rcu_read_unlock(); - br_read_unlock(vfsmount_lock); - } - if (likely(!(nd->flags & LOOKUP_JUMPED))) return 0; @@ -561,7 +643,6 @@ static int complete_walk(struct nameidata *nd) if (!status) status = -ESTALE; - path_put(&nd->path); return status; } @@ -1160,8 +1241,13 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, if (likely(__follow_mount_rcu(nd, path, inode, false))) return 0; unlazy: - if (unlazy_walk(nd, dentry)) - return -ECHILD; + if (dentry) { + if (nameidata_dentry_drop_rcu(nd, dentry)) + return -ECHILD; + } else { + if (nameidata_drop_rcu(nd)) + return -ECHILD; + } } else { dentry = __d_lookup(parent, name); } @@ -1217,7 +1303,7 @@ static inline int may_lookup(struct nameidata *nd) int err = exec_permission(nd->inode, IPERM_FLAG_RCU); if (err != -ECHILD) return err; - if (unlazy_walk(nd, NULL)) + if (nameidata_drop_rcu(nd)) return -ECHILD; } return exec_permission(nd->inode, 0); @@ -1271,12 +1357,8 @@ static inline int walk_component(struct nameidata *nd, struct path *path, return -ENOENT; } if (unlikely(inode->i_op->follow_link) && follow) { - if (nd->flags & LOOKUP_RCU) { - if (unlikely(unlazy_walk(nd, path->dentry))) { - terminate_walk(nd); - return -ECHILD; - } - } + if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry)) + return -ECHILD; BUG_ON(inode != path->dentry->d_inode); return 1; } @@ -1575,8 +1657,18 @@ static int path_lookupat(int dfd, const char *name, } } - if (!err) - err = complete_walk(nd); + if (nd->flags & LOOKUP_RCU) { + /* went all way through without dropping RCU */ + BUG_ON(err); + if (nameidata_drop_rcu_last(nd)) + err = -ECHILD; + } + + if (!err) { + err = handle_reval_path(nd); + if (err) + path_put(&nd->path); + } if (!err && nd->flags & LOOKUP_DIRECTORY) { if (!nd->inode->i_op->lookup) { @@ -2042,9 +2134,13 @@ static struct file *do_last(struct nameidata *nd, struct path *path, return ERR_PTR(error); /* fallthrough */ case LAST_ROOT: - error = complete_walk(nd); + if (nd->flags & LOOKUP_RCU) { + if (nameidata_drop_rcu_last(nd)) + return ERR_PTR(-ECHILD); + } + error = handle_reval_path(nd); if (error) - return ERR_PTR(error); + goto exit; audit_inode(pathname, nd->path.dentry); if (open_flag & O_CREAT) { error = -EISDIR; @@ -2052,9 +2148,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path, } goto ok; case LAST_BIND: - error = complete_walk(nd); + /* can't be RCU mode here */ + error = handle_reval_path(nd); if (error) - return ERR_PTR(error); + goto exit; audit_inode(pathname, dir); goto ok; } @@ -2073,9 +2170,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path, if (error) /* symlink */ return NULL; /* sayonara */ - error = complete_walk(nd); - if (error) - return ERR_PTR(-ECHILD); + if (nd->flags & LOOKUP_RCU) { + if (nameidata_drop_rcu_last(nd)) + return ERR_PTR(-ECHILD); + } error = -ENOTDIR; if (nd->flags & LOOKUP_DIRECTORY) { @@ -2087,9 +2185,11 @@ static struct file *do_last(struct nameidata *nd, struct path *path, } /* create side of things */ - error = complete_walk(nd); - if (error) - return ERR_PTR(error); + + if (nd->flags & LOOKUP_RCU) { + if (nameidata_drop_rcu_last(nd)) + return ERR_PTR(-ECHILD); + } audit_inode(pathname, dir); error = -EISDIR; @@ -2529,10 +2629,10 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode) } /* - * The dentry_unhash() helper will try to drop the dentry early: we - * should have a usage count of 2 if we're the only user of this - * dentry, and if that is true (possibly after pruning the dcache), - * then we drop the dentry now. + * We try to drop the dentry early: we should have + * a usage count of 2 if we're the only user of this + * dentry, and if that is true (possibly after pruning + * the dcache), then we drop the dentry now. * * A low-level filesystem can, if it choses, legally * do a @@ -2545,9 +2645,10 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode) */ void dentry_unhash(struct dentry *dentry) { + dget(dentry); shrink_dcache_parent(dentry); spin_lock(&dentry->d_lock); - if (dentry->d_count == 1) + if (dentry->d_count == 2) __d_drop(dentry); spin_unlock(&dentry->d_lock); } @@ -2563,26 +2664,25 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) return -EPERM; mutex_lock(&dentry->d_inode->i_mutex); - - error = -EBUSY; + dentry_unhash(dentry); if (d_mountpoint(dentry)) - goto out; - - error = security_inode_rmdir(dir, dentry); - if (error) - goto out; - - error = dir->i_op->rmdir(dir, dentry); - if (error) - goto out; - - dentry->d_inode->i_flags |= S_DEAD; - dont_mount(dentry); - -out: + error = -EBUSY; + else { + error = security_inode_rmdir(dir, dentry); + if (!error) { + error = dir->i_op->rmdir(dir, dentry); + if (!error) { + dentry->d_inode->i_flags |= S_DEAD; + dont_mount(dentry); + } + } + } mutex_unlock(&dentry->d_inode->i_mutex); - if (!error) + if (!error) { d_delete(dentry); + } + dput(dentry); + return error; } @@ -2953,7 +3053,12 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname * HOWEVER, it relies on the assumption that any object with ->lookup() * has no more than 1 dentry. If "hybrid" objects will ever appear, * we'd better make sure that there's no link(2) for them. - * d) conversion from fhandle to dentry may come in the wrong moment - when + * d) some filesystems don't support opened-but-unlinked directories, + * either because of layout or because they are not ready to deal with + * all cases correctly. The latter will be fixed (taking this sort of + * stuff into VFS), but the former is not going away. Solution: the same + * trick as in rmdir(). + * e) conversion from fhandle to dentry may come in the wrong moment - when * we are removing the target. Solution: we will have to grab ->i_mutex * in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on * ->i_mutex on parents, which works but leads to some truly excessive @@ -2963,7 +3068,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { int error = 0; - struct inode *target = new_dentry->d_inode; + struct inode *target; /* * If we are going to change the parent - check write permissions, @@ -2979,24 +3084,26 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, if (error) return error; + target = new_dentry->d_inode; if (target) mutex_lock(&target->i_mutex); - - error = -EBUSY; - if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry)) - goto out; - - error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); - if (error) - goto out; - - if (target) { - target->i_flags |= S_DEAD; - dont_mount(new_dentry); + if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) + error = -EBUSY; + else { + if (target) + dentry_unhash(new_dentry); + error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); } -out: - if (target) + if (target) { + if (!error) { + target->i_flags |= S_DEAD; + dont_mount(new_dentry); + } mutex_unlock(&target->i_mutex); + if (d_unhashed(new_dentry)) + d_rehash(new_dentry); + dput(new_dentry); + } if (!error) if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) d_move(old_dentry,new_dentry); @@ -3006,7 +3113,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { - struct inode *target = new_dentry->d_inode; + struct inode *target; int error; error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry); @@ -3014,22 +3121,19 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, return error; dget(new_dentry); + target = new_dentry->d_inode; if (target) mutex_lock(&target->i_mutex); - - error = -EBUSY; if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) - goto out; - - error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); - if (error) - goto out; - - if (target) - dont_mount(new_dentry); - if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) - d_move(old_dentry, new_dentry); -out: + error = -EBUSY; + else + error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); + if (!error) { + if (target) + dont_mount(new_dentry); + if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) + d_move(old_dentry, new_dentry); + } if (target) mutex_unlock(&target->i_mutex); dput(new_dentry); diff --git a/trunk/fs/namespace.c b/trunk/fs/namespace.c index fe59bd145d21..d99bcf59e4c2 100644 --- a/trunk/fs/namespace.c +++ b/trunk/fs/namespace.c @@ -1695,7 +1695,7 @@ static int graft_tree(struct vfsmount *mnt, struct path *path) static int flags_to_propagation_type(int flags) { - int type = flags & ~(MS_REC | MS_SILENT); + int type = flags & ~MS_REC; /* Fail if any non-propagation flags are set */ if (type & ~(MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) diff --git a/trunk/fs/ncpfs/dir.c b/trunk/fs/ncpfs/dir.c index e3e646b06404..f6946bb5cb55 100644 --- a/trunk/fs/ncpfs/dir.c +++ b/trunk/fs/ncpfs/dir.c @@ -1033,8 +1033,6 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry) DPRINTK("ncp_rmdir: removing %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); - dentry_unhash(dentry); - error = -EBUSY; if (!d_unhashed(dentry)) goto out; @@ -1141,9 +1139,6 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, old_dentry->d_parent->d_name.name, old_dentry->d_name.name, new_dentry->d_parent->d_name.name, new_dentry->d_name.name); - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - ncp_age_dentry(server, old_dentry); ncp_age_dentry(server, new_dentry); diff --git a/trunk/fs/ncpfs/mmap.c b/trunk/fs/ncpfs/mmap.c index e5d71b27a5b0..a7c07b44b100 100644 --- a/trunk/fs/ncpfs/mmap.c +++ b/trunk/fs/ncpfs/mmap.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -93,7 +92,6 @@ static int ncp_file_mmap_fault(struct vm_area_struct *area, * -- wli */ count_vm_event(PGMAJFAULT); - mem_cgroup_count_vm_event(area->vm_mm, PGMAJFAULT); return VM_FAULT_MAJOR; } diff --git a/trunk/fs/nilfs2/namei.c b/trunk/fs/nilfs2/namei.c index 1102a5fbb744..546849b3e88f 100644 --- a/trunk/fs/nilfs2/namei.c +++ b/trunk/fs/nilfs2/namei.c @@ -334,8 +334,6 @@ static int nilfs_rmdir(struct inode *dir, struct dentry *dentry) struct nilfs_transaction_info ti; int err; - dentry_unhash(dentry); - err = nilfs_transaction_begin(dir->i_sb, &ti, 0); if (err) return err; @@ -371,9 +369,6 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct nilfs_transaction_info ti; int err; - if (new_inode && S_ISDIR(new_inode->i_mode)) - dentry_unhash(new_dentry); - err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1); if (unlikely(err)) return err; diff --git a/trunk/fs/ocfs2/Makefile b/trunk/fs/ocfs2/Makefile index f17e58b32989..d8a0313e99e6 100644 --- a/trunk/fs/ocfs2/Makefile +++ b/trunk/fs/ocfs2/Makefile @@ -30,7 +30,6 @@ ocfs2-objs := \ namei.o \ refcounttree.o \ reservations.o \ - move_extents.o \ resize.o \ slot_map.o \ suballoc.o \ diff --git a/trunk/fs/ocfs2/alloc.c b/trunk/fs/ocfs2/alloc.c index ed553c60de82..48aa9c7401c7 100644 --- a/trunk/fs/ocfs2/alloc.c +++ b/trunk/fs/ocfs2/alloc.c @@ -29,7 +29,6 @@ #include #include #include -#include #include @@ -7185,168 +7184,3 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh, out: return ret; } - -static int ocfs2_trim_extent(struct super_block *sb, - struct ocfs2_group_desc *gd, - u32 start, u32 count) -{ - u64 discard, bcount; - - bcount = ocfs2_clusters_to_blocks(sb, count); - discard = le64_to_cpu(gd->bg_blkno) + - ocfs2_clusters_to_blocks(sb, start); - - trace_ocfs2_trim_extent(sb, (unsigned long long)discard, bcount); - - return sb_issue_discard(sb, discard, bcount, GFP_NOFS, 0); -} - -static int ocfs2_trim_group(struct super_block *sb, - struct ocfs2_group_desc *gd, - u32 start, u32 max, u32 minbits) -{ - int ret = 0, count = 0, next; - void *bitmap = gd->bg_bitmap; - - if (le16_to_cpu(gd->bg_free_bits_count) < minbits) - return 0; - - trace_ocfs2_trim_group((unsigned long long)le64_to_cpu(gd->bg_blkno), - start, max, minbits); - - while (start < max) { - start = ocfs2_find_next_zero_bit(bitmap, max, start); - if (start >= max) - break; - next = ocfs2_find_next_bit(bitmap, max, start); - - if ((next - start) >= minbits) { - ret = ocfs2_trim_extent(sb, gd, - start, next - start); - if (ret < 0) { - mlog_errno(ret); - break; - } - count += next - start; - } - start = next + 1; - - if (fatal_signal_pending(current)) { - count = -ERESTARTSYS; - break; - } - - if ((le16_to_cpu(gd->bg_free_bits_count) - count) < minbits) - break; - } - - if (ret < 0) - count = ret; - - return count; -} - -int ocfs2_trim_fs(struct super_block *sb, struct fstrim_range *range) -{ - struct ocfs2_super *osb = OCFS2_SB(sb); - u64 start, len, trimmed, first_group, last_group, group; - int ret, cnt; - u32 first_bit, last_bit, minlen; - struct buffer_head *main_bm_bh = NULL; - struct inode *main_bm_inode = NULL; - struct buffer_head *gd_bh = NULL; - struct ocfs2_dinode *main_bm; - struct ocfs2_group_desc *gd = NULL; - - start = range->start >> osb->s_clustersize_bits; - len = range->len >> osb->s_clustersize_bits; - minlen = range->minlen >> osb->s_clustersize_bits; - trimmed = 0; - - if (!len) { - range->len = 0; - return 0; - } - - if (minlen >= osb->bitmap_cpg) - return -EINVAL; - - main_bm_inode = ocfs2_get_system_file_inode(osb, - GLOBAL_BITMAP_SYSTEM_INODE, - OCFS2_INVALID_SLOT); - if (!main_bm_inode) { - ret = -EIO; - mlog_errno(ret); - goto out; - } - - mutex_lock(&main_bm_inode->i_mutex); - - ret = ocfs2_inode_lock(main_bm_inode, &main_bm_bh, 0); - if (ret < 0) { - mlog_errno(ret); - goto out_mutex; - } - main_bm = (struct ocfs2_dinode *)main_bm_bh->b_data; - - if (start >= le32_to_cpu(main_bm->i_clusters)) { - ret = -EINVAL; - goto out_unlock; - } - - if (start + len > le32_to_cpu(main_bm->i_clusters)) - len = le32_to_cpu(main_bm->i_clusters) - start; - - trace_ocfs2_trim_fs(start, len, minlen); - - /* Determine first and last group to examine based on start and len */ - first_group = ocfs2_which_cluster_group(main_bm_inode, start); - if (first_group == osb->first_cluster_group_blkno) - first_bit = start; - else - first_bit = start - ocfs2_blocks_to_clusters(sb, first_group); - last_group = ocfs2_which_cluster_group(main_bm_inode, start + len - 1); - last_bit = osb->bitmap_cpg; - - for (group = first_group; group <= last_group;) { - if (first_bit + len >= osb->bitmap_cpg) - last_bit = osb->bitmap_cpg; - else - last_bit = first_bit + len; - - ret = ocfs2_read_group_descriptor(main_bm_inode, - main_bm, group, - &gd_bh); - if (ret < 0) { - mlog_errno(ret); - break; - } - - gd = (struct ocfs2_group_desc *)gd_bh->b_data; - cnt = ocfs2_trim_group(sb, gd, first_bit, last_bit, minlen); - brelse(gd_bh); - gd_bh = NULL; - if (cnt < 0) { - ret = cnt; - mlog_errno(ret); - break; - } - - trimmed += cnt; - len -= osb->bitmap_cpg - first_bit; - first_bit = 0; - if (group == osb->first_cluster_group_blkno) - group = ocfs2_clusters_to_blocks(sb, osb->bitmap_cpg); - else - group += ocfs2_clusters_to_blocks(sb, osb->bitmap_cpg); - } - range->len = trimmed * sb->s_blocksize; -out_unlock: - ocfs2_inode_unlock(main_bm_inode, 0); - brelse(main_bm_bh); -out_mutex: - mutex_unlock(&main_bm_inode->i_mutex); - iput(main_bm_inode); -out: - return ret; -} diff --git a/trunk/fs/ocfs2/alloc.h b/trunk/fs/ocfs2/alloc.h index ca381c584127..3bd08a03251c 100644 --- a/trunk/fs/ocfs2/alloc.h +++ b/trunk/fs/ocfs2/alloc.h @@ -239,7 +239,6 @@ int ocfs2_find_leaf(struct ocfs2_caching_info *ci, struct buffer_head **leaf_bh); int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster); -int ocfs2_trim_fs(struct super_block *sb, struct fstrim_range *range); /* * Helper function to look at the # of clusters in an extent record. */ diff --git a/trunk/fs/ocfs2/cluster/sys.c b/trunk/fs/ocfs2/cluster/sys.c index a4b07730b2e1..bc702dab5d1f 100644 --- a/trunk/fs/ocfs2/cluster/sys.c +++ b/trunk/fs/ocfs2/cluster/sys.c @@ -57,6 +57,7 @@ static struct kset *o2cb_kset; void o2cb_sys_shutdown(void) { mlog_sys_shutdown(); + sysfs_remove_link(NULL, "o2cb"); kset_unregister(o2cb_kset); } @@ -68,6 +69,14 @@ int o2cb_sys_init(void) if (!o2cb_kset) return -ENOMEM; + /* + * Create this symlink for backwards compatibility with old + * versions of ocfs2-tools which look for things in /sys/o2cb. + */ + ret = sysfs_create_link(NULL, &o2cb_kset->kobj, "o2cb"); + if (ret) + goto error; + ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group); if (ret) goto error; diff --git a/trunk/fs/ocfs2/dlm/dlmcommon.h b/trunk/fs/ocfs2/dlm/dlmcommon.h index d602abb51b61..4bdf7baee344 100644 --- a/trunk/fs/ocfs2/dlm/dlmcommon.h +++ b/trunk/fs/ocfs2/dlm/dlmcommon.h @@ -144,7 +144,6 @@ struct dlm_ctxt wait_queue_head_t dlm_join_events; unsigned long live_nodes_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; unsigned long domain_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; - unsigned long exit_domain_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; unsigned long recovery_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; struct dlm_recovery_ctxt reco; spinlock_t master_lock; @@ -402,18 +401,6 @@ static inline int dlm_lvb_is_empty(char *lvb) return 1; } -static inline char *dlm_list_in_text(enum dlm_lockres_list idx) -{ - if (idx == DLM_GRANTED_LIST) - return "granted"; - else if (idx == DLM_CONVERTING_LIST) - return "converting"; - else if (idx == DLM_BLOCKED_LIST) - return "blocked"; - else - return "unknown"; -} - static inline struct list_head * dlm_list_idx_to_ptr(struct dlm_lock_resource *res, enum dlm_lockres_list idx) { @@ -461,7 +448,6 @@ enum { DLM_FINALIZE_RECO_MSG = 518, DLM_QUERY_REGION = 519, DLM_QUERY_NODEINFO = 520, - DLM_BEGIN_EXIT_DOMAIN_MSG = 521, }; struct dlm_reco_node_data diff --git a/trunk/fs/ocfs2/dlm/dlmdebug.c b/trunk/fs/ocfs2/dlm/dlmdebug.c index 56f82cb912e3..04a32be0aeb9 100644 --- a/trunk/fs/ocfs2/dlm/dlmdebug.c +++ b/trunk/fs/ocfs2/dlm/dlmdebug.c @@ -756,12 +756,6 @@ static int debug_state_print(struct dlm_ctxt *dlm, char *buf, int len) buf + out, len - out); out += snprintf(buf + out, len - out, "\n"); - /* Exit Domain Map: xx xx xx */ - out += snprintf(buf + out, len - out, "Exit Domain Map: "); - out += stringify_nodemap(dlm->exit_domain_map, O2NM_MAX_NODES, - buf + out, len - out); - out += snprintf(buf + out, len - out, "\n"); - /* Live Map: xx xx xx */ out += snprintf(buf + out, len - out, "Live Map: "); out += stringify_nodemap(dlm->live_nodes_map, O2NM_MAX_NODES, diff --git a/trunk/fs/ocfs2/dlm/dlmdomain.c b/trunk/fs/ocfs2/dlm/dlmdomain.c index 6ed6b95dcf93..3b179d6cbde0 100644 --- a/trunk/fs/ocfs2/dlm/dlmdomain.c +++ b/trunk/fs/ocfs2/dlm/dlmdomain.c @@ -132,12 +132,10 @@ static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events); * New in version 1.1: * - Message DLM_QUERY_REGION added to support global heartbeat * - Message DLM_QUERY_NODEINFO added to allow online node removes - * New in version 1.2: - * - Message DLM_BEGIN_EXIT_DOMAIN_MSG added to mark start of exit domain */ static const struct dlm_protocol_version dlm_protocol = { .pv_major = 1, - .pv_minor = 2, + .pv_minor = 1, }; #define DLM_DOMAIN_BACKOFF_MS 200 @@ -451,18 +449,14 @@ static int dlm_migrate_all_locks(struct dlm_ctxt *dlm) dropped = dlm_empty_lockres(dlm, res); spin_lock(&res->spinlock); - if (dropped) - __dlm_lockres_calc_usage(dlm, res); - else - iter = res->hash_node.next; + __dlm_lockres_calc_usage(dlm, res); + iter = res->hash_node.next; spin_unlock(&res->spinlock); dlm_lockres_put(res); - if (dropped) { - cond_resched_lock(&dlm->spinlock); + if (dropped) goto redo_bucket; - } } cond_resched_lock(&dlm->spinlock); num += n; @@ -492,28 +486,6 @@ static int dlm_no_joining_node(struct dlm_ctxt *dlm) return ret; } -static int dlm_begin_exit_domain_handler(struct o2net_msg *msg, u32 len, - void *data, void **ret_data) -{ - struct dlm_ctxt *dlm = data; - unsigned int node; - struct dlm_exit_domain *exit_msg = (struct dlm_exit_domain *) msg->buf; - - if (!dlm_grab(dlm)) - return 0; - - node = exit_msg->node_idx; - mlog(0, "%s: Node %u sent a begin exit domain message\n", dlm->name, node); - - spin_lock(&dlm->spinlock); - set_bit(node, dlm->exit_domain_map); - spin_unlock(&dlm->spinlock); - - dlm_put(dlm); - - return 0; -} - static void dlm_mark_domain_leaving(struct dlm_ctxt *dlm) { /* Yikes, a double spinlock! I need domain_lock for the dlm @@ -570,7 +542,6 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, spin_lock(&dlm->spinlock); clear_bit(node, dlm->domain_map); - clear_bit(node, dlm->exit_domain_map); __dlm_print_nodes(dlm); /* notify anything attached to the heartbeat events */ @@ -583,56 +554,29 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, return 0; } -static int dlm_send_one_domain_exit(struct dlm_ctxt *dlm, u32 msg_type, +static int dlm_send_one_domain_exit(struct dlm_ctxt *dlm, unsigned int node) { int status; struct dlm_exit_domain leave_msg; - mlog(0, "%s: Sending domain exit message %u to node %u\n", dlm->name, - msg_type, node); + mlog(0, "Asking node %u if we can leave the domain %s me = %u\n", + node, dlm->name, dlm->node_num); memset(&leave_msg, 0, sizeof(leave_msg)); leave_msg.node_idx = dlm->node_num; - status = o2net_send_message(msg_type, dlm->key, &leave_msg, - sizeof(leave_msg), node, NULL); + status = o2net_send_message(DLM_EXIT_DOMAIN_MSG, dlm->key, + &leave_msg, sizeof(leave_msg), node, + NULL); if (status < 0) - mlog(ML_ERROR, "Error %d sending domain exit message %u " - "to node %u on domain %s\n", status, msg_type, node, - dlm->name); + mlog(ML_ERROR, "Error %d when sending message %u (key 0x%x) to " + "node %u\n", status, DLM_EXIT_DOMAIN_MSG, dlm->key, node); + mlog(0, "status return %d from o2net_send_message\n", status); return status; } -static void dlm_begin_exit_domain(struct dlm_ctxt *dlm) -{ - int node = -1; - - /* Support for begin exit domain was added in 1.2 */ - if (dlm->dlm_locking_proto.pv_major == 1 && - dlm->dlm_locking_proto.pv_minor < 2) - return; - - /* - * Unlike DLM_EXIT_DOMAIN_MSG, DLM_BEGIN_EXIT_DOMAIN_MSG is purely - * informational. Meaning if a node does not receive the message, - * so be it. - */ - spin_lock(&dlm->spinlock); - while (1) { - node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES, node + 1); - if (node >= O2NM_MAX_NODES) - break; - if (node == dlm->node_num) - continue; - - spin_unlock(&dlm->spinlock); - dlm_send_one_domain_exit(dlm, DLM_BEGIN_EXIT_DOMAIN_MSG, node); - spin_lock(&dlm->spinlock); - } - spin_unlock(&dlm->spinlock); -} static void dlm_leave_domain(struct dlm_ctxt *dlm) { @@ -658,8 +602,7 @@ static void dlm_leave_domain(struct dlm_ctxt *dlm) clear_node = 1; - status = dlm_send_one_domain_exit(dlm, DLM_EXIT_DOMAIN_MSG, - node); + status = dlm_send_one_domain_exit(dlm, node); if (status < 0 && status != -ENOPROTOOPT && status != -ENOTCONN) { @@ -734,7 +677,6 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm) if (leave) { mlog(0, "shutting down domain %s\n", dlm->name); - dlm_begin_exit_domain(dlm); /* We changed dlm state, notify the thread */ dlm_kick_thread(dlm, NULL); @@ -967,7 +909,6 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, * leftover join state. */ BUG_ON(dlm->joining_node != assert->node_idx); set_bit(assert->node_idx, dlm->domain_map); - clear_bit(assert->node_idx, dlm->exit_domain_map); __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN); printk(KERN_NOTICE "o2dlm: Node %u joins domain %s\n", @@ -1852,13 +1793,6 @@ static int dlm_register_domain_handlers(struct dlm_ctxt *dlm) if (status) goto bail; - status = o2net_register_handler(DLM_BEGIN_EXIT_DOMAIN_MSG, dlm->key, - sizeof(struct dlm_exit_domain), - dlm_begin_exit_domain_handler, - dlm, NULL, &dlm->dlm_domain_handlers); - if (status) - goto bail; - bail: if (status) dlm_unregister_domain_handlers(dlm); diff --git a/trunk/fs/ocfs2/dlm/dlmmaster.c b/trunk/fs/ocfs2/dlm/dlmmaster.c index 11eefb8c12e9..84d166328cf7 100644 --- a/trunk/fs/ocfs2/dlm/dlmmaster.c +++ b/trunk/fs/ocfs2/dlm/dlmmaster.c @@ -2339,55 +2339,65 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data) dlm_lockres_put(res); } -/* - * A migrateable resource is one that is : - * 1. locally mastered, and, - * 2. zero local locks, and, - * 3. one or more non-local locks, or, one or more references - * Returns 1 if yes, 0 if not. +/* Checks whether the lockres can be migrated. Returns 0 if yes, < 0 + * if not. If 0, numlocks is set to the number of locks in the lockres. */ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm, - struct dlm_lock_resource *res) + struct dlm_lock_resource *res, + int *numlocks, + int *hasrefs) { - enum dlm_lockres_list idx; - int nonlocal = 0, node_ref; + int ret; + int i; + int count = 0; struct list_head *queue; struct dlm_lock *lock; - u64 cookie; assert_spin_locked(&res->spinlock); - if (res->owner != dlm->node_num) - return 0; + *numlocks = 0; + *hasrefs = 0; - for (idx = DLM_GRANTED_LIST; idx <= DLM_BLOCKED_LIST; idx++) { - queue = dlm_list_idx_to_ptr(res, idx); + ret = -EINVAL; + if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { + mlog(0, "cannot migrate lockres with unknown owner!\n"); + goto leave; + } + + if (res->owner != dlm->node_num) { + mlog(0, "cannot migrate lockres this node doesn't own!\n"); + goto leave; + } + + ret = 0; + queue = &res->granted; + for (i = 0; i < 3; i++) { list_for_each_entry(lock, queue, list) { - if (lock->ml.node != dlm->node_num) { - nonlocal++; - continue; + ++count; + if (lock->ml.node == dlm->node_num) { + mlog(0, "found a lock owned by this node still " + "on the %s queue! will not migrate this " + "lockres\n", (i == 0 ? "granted" : + (i == 1 ? "converting" : + "blocked"))); + ret = -ENOTEMPTY; + goto leave; } - cookie = be64_to_cpu(lock->ml.cookie); - mlog(0, "%s: Not migrateable res %.*s, lock %u:%llu on " - "%s list\n", dlm->name, res->lockname.len, - res->lockname.name, - dlm_get_lock_cookie_node(cookie), - dlm_get_lock_cookie_seq(cookie), - dlm_list_in_text(idx)); - return 0; } + queue++; } - if (!nonlocal) { - node_ref = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); - if (node_ref >= O2NM_MAX_NODES) - return 0; - } + *numlocks = count; - mlog(0, "%s: res %.*s, Migrateable\n", dlm->name, res->lockname.len, - res->lockname.name); + count = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); + if (count < O2NM_MAX_NODES) + *hasrefs = 1; - return 1; + mlog(0, "%s: res %.*s, Migrateable, locks %d, refs %d\n", dlm->name, + res->lockname.len, res->lockname.name, *numlocks, *hasrefs); + +leave: + return ret; } /* @@ -2396,7 +2406,8 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm, static int dlm_migrate_lockres(struct dlm_ctxt *dlm, - struct dlm_lock_resource *res, u8 target) + struct dlm_lock_resource *res, + u8 target) { struct dlm_master_list_entry *mle = NULL; struct dlm_master_list_entry *oldmle = NULL; @@ -2405,20 +2416,37 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, const char *name; unsigned int namelen; int mle_added = 0; + int numlocks, hasrefs; int wake = 0; if (!dlm_grab(dlm)) return -EINVAL; - BUG_ON(target == O2NM_MAX_NODES); - name = res->lockname.name; namelen = res->lockname.len; - mlog(0, "%s: Migrating %.*s to node %u\n", dlm->name, namelen, name, - target); + mlog(0, "%s: Migrating %.*s to %u\n", dlm->name, namelen, name, target); + + /* + * ensure this lockres is a proper candidate for migration + */ + spin_lock(&res->spinlock); + ret = dlm_is_lockres_migrateable(dlm, res, &numlocks, &hasrefs); + if (ret < 0) { + spin_unlock(&res->spinlock); + goto leave; + } + spin_unlock(&res->spinlock); + + /* no work to do */ + if (numlocks == 0 && !hasrefs) + goto leave; + + /* + * preallocate up front + * if this fails, abort + */ - /* preallocate up front. if this fails, abort */ ret = -ENOMEM; mres = (struct dlm_migratable_lockres *) __get_free_page(GFP_NOFS); if (!mres) { @@ -2433,11 +2461,36 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, } ret = 0; + /* + * find a node to migrate the lockres to + */ + + spin_lock(&dlm->spinlock); + /* pick a new node */ + if (!test_bit(target, dlm->domain_map) || + target >= O2NM_MAX_NODES) { + target = dlm_pick_migration_target(dlm, res); + } + mlog(0, "%s: res %.*s, Node %u chosen for migration\n", dlm->name, + namelen, name, target); + + if (target >= O2NM_MAX_NODES || + !test_bit(target, dlm->domain_map)) { + /* target chosen is not alive */ + ret = -EINVAL; + } + + if (ret) { + spin_unlock(&dlm->spinlock); + goto fail; + } + + mlog(0, "continuing with target = %u\n", target); + /* * clear any existing master requests and * add the migration mle to the list */ - spin_lock(&dlm->spinlock); spin_lock(&dlm->master_lock); ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, name, namelen, target, dlm->node_num); @@ -2478,7 +2531,6 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, dlm_put_mle(mle); } else if (mle) { kmem_cache_free(dlm_mle_cache, mle); - mle = NULL; } goto leave; } @@ -2600,52 +2652,69 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, if (wake) wake_up(&res->wq); + /* TODO: cleanup */ if (mres) free_page((unsigned long)mres); dlm_put(dlm); - mlog(0, "%s: Migrating %.*s to %u, returns %d\n", dlm->name, namelen, - name, target, ret); + mlog(0, "returning %d\n", ret); return ret; } #define DLM_MIGRATION_RETRY_MS 100 -/* - * Should be called only after beginning the domain leave process. +/* Should be called only after beginning the domain leave process. * There should not be any remaining locks on nonlocal lock resources, * and there should be no local locks left on locally mastered resources. * * Called with the dlm spinlock held, may drop it to do migration, but * will re-acquire before exit. * - * Returns: 1 if dlm->spinlock was dropped/retaken, 0 if never dropped - */ + * Returns: 1 if dlm->spinlock was dropped/retaken, 0 if never dropped */ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) { int ret; int lock_dropped = 0; - u8 target = O2NM_MAX_NODES; - - assert_spin_locked(&dlm->spinlock); + int numlocks, hasrefs; spin_lock(&res->spinlock); - if (dlm_is_lockres_migrateable(dlm, res)) - target = dlm_pick_migration_target(dlm, res); - spin_unlock(&res->spinlock); + if (res->owner != dlm->node_num) { + if (!__dlm_lockres_unused(res)) { + mlog(ML_ERROR, "%s:%.*s: this node is not master, " + "trying to free this but locks remain\n", + dlm->name, res->lockname.len, res->lockname.name); + } + spin_unlock(&res->spinlock); + goto leave; + } - if (target == O2NM_MAX_NODES) + /* No need to migrate a lockres having no locks */ + ret = dlm_is_lockres_migrateable(dlm, res, &numlocks, &hasrefs); + if (ret >= 0 && numlocks == 0 && !hasrefs) { + spin_unlock(&res->spinlock); goto leave; + } + spin_unlock(&res->spinlock); /* Wheee! Migrate lockres here! Will sleep so drop spinlock. */ spin_unlock(&dlm->spinlock); lock_dropped = 1; - ret = dlm_migrate_lockres(dlm, res, target); - if (ret) - mlog(0, "%s: res %.*s, Migrate to node %u failed with %d\n", - dlm->name, res->lockname.len, res->lockname.name, - target, ret); + while (1) { + ret = dlm_migrate_lockres(dlm, res, O2NM_MAX_NODES); + if (ret >= 0) + break; + if (ret == -ENOTEMPTY) { + mlog(ML_ERROR, "lockres %.*s still has local locks!\n", + res->lockname.len, res->lockname.name); + BUG(); + } + + mlog(0, "lockres %.*s: migrate failed, " + "retrying\n", res->lockname.len, + res->lockname.name); + msleep(DLM_MIGRATION_RETRY_MS); + } spin_lock(&dlm->spinlock); leave: return lock_dropped; @@ -2829,55 +2898,61 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm, } } -/* - * Pick a node to migrate the lock resource to. This function selects a - * potential target based first on the locks and then on refmap. It skips - * nodes that are in the process of exiting the domain. - */ +/* for now this is not too intelligent. we will + * need stats to make this do the right thing. + * this just finds the first lock on one of the + * queues and uses that node as the target. */ static u8 dlm_pick_migration_target(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) { - enum dlm_lockres_list idx; + int i; struct list_head *queue = &res->granted; struct dlm_lock *lock; - int noderef; - u8 nodenum = O2NM_MAX_NODES; + int nodenum; assert_spin_locked(&dlm->spinlock); - assert_spin_locked(&res->spinlock); - /* Go through all the locks */ - for (idx = DLM_GRANTED_LIST; idx <= DLM_BLOCKED_LIST; idx++) { - queue = dlm_list_idx_to_ptr(res, idx); + spin_lock(&res->spinlock); + for (i=0; i<3; i++) { list_for_each_entry(lock, queue, list) { - if (lock->ml.node == dlm->node_num) - continue; - if (test_bit(lock->ml.node, dlm->exit_domain_map)) - continue; - nodenum = lock->ml.node; - goto bail; + /* up to the caller to make sure this node + * is alive */ + if (lock->ml.node != dlm->node_num) { + spin_unlock(&res->spinlock); + return lock->ml.node; + } } + queue++; + } + + nodenum = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); + if (nodenum < O2NM_MAX_NODES) { + spin_unlock(&res->spinlock); + return nodenum; } + spin_unlock(&res->spinlock); + mlog(0, "have not found a suitable target yet! checking domain map\n"); - /* Go thru the refmap */ - noderef = -1; + /* ok now we're getting desperate. pick anyone alive. */ + nodenum = -1; while (1) { - noderef = find_next_bit(res->refmap, O2NM_MAX_NODES, - noderef + 1); - if (noderef >= O2NM_MAX_NODES) + nodenum = find_next_bit(dlm->domain_map, + O2NM_MAX_NODES, nodenum+1); + mlog(0, "found %d in domain map\n", nodenum); + if (nodenum >= O2NM_MAX_NODES) break; - if (noderef == dlm->node_num) - continue; - if (test_bit(noderef, dlm->exit_domain_map)) - continue; - nodenum = noderef; - goto bail; + if (nodenum != dlm->node_num) { + mlog(0, "picking %d\n", nodenum); + return nodenum; + } } -bail: - return nodenum; + mlog(0, "giving up. no master to migrate to\n"); + return DLM_LOCK_RES_OWNER_UNKNOWN; } + + /* this is called by the new master once all lockres * data has been received */ static int dlm_do_migrate_request(struct dlm_ctxt *dlm, diff --git a/trunk/fs/ocfs2/dlm/dlmrecovery.c b/trunk/fs/ocfs2/dlm/dlmrecovery.c index 7efab6d28a21..f1beb6fc254d 100644 --- a/trunk/fs/ocfs2/dlm/dlmrecovery.c +++ b/trunk/fs/ocfs2/dlm/dlmrecovery.c @@ -2393,7 +2393,6 @@ static void __dlm_hb_node_down(struct dlm_ctxt *dlm, int idx) mlog(0, "node %u being removed from domain map!\n", idx); clear_bit(idx, dlm->domain_map); - clear_bit(idx, dlm->exit_domain_map); /* wake up migration waiters if a node goes down. * perhaps later we can genericize this for other waiters. */ wake_up(&dlm->migration_wq); diff --git a/trunk/fs/ocfs2/dlmfs/dlmfs.c b/trunk/fs/ocfs2/dlmfs/dlmfs.c index b42076797049..8c5c0eddc365 100644 --- a/trunk/fs/ocfs2/dlmfs/dlmfs.c +++ b/trunk/fs/ocfs2/dlmfs/dlmfs.c @@ -88,7 +88,7 @@ struct workqueue_struct *user_dlm_worker; * signifies a bast fired on the lock. */ #define DLMFS_CAPABILITIES "bast stackglue" -static int param_set_dlmfs_capabilities(const char *val, +extern int param_set_dlmfs_capabilities(const char *val, struct kernel_param *kp) { printk(KERN_ERR "%s: readonly parameter\n", kp->name); diff --git a/trunk/fs/ocfs2/file.c b/trunk/fs/ocfs2/file.c index b1e35a392ca5..89659d6dc206 100644 --- a/trunk/fs/ocfs2/file.c +++ b/trunk/fs/ocfs2/file.c @@ -2670,7 +2670,6 @@ const struct file_operations ocfs2_fops_no_plocks = { .flock = ocfs2_flock, .splice_read = ocfs2_file_splice_read, .splice_write = ocfs2_file_splice_write, - .fallocate = ocfs2_fallocate, }; const struct file_operations ocfs2_dops_no_plocks = { diff --git a/trunk/fs/ocfs2/ioctl.c b/trunk/fs/ocfs2/ioctl.c index bc91072b7219..8f13c5989eae 100644 --- a/trunk/fs/ocfs2/ioctl.c +++ b/trunk/fs/ocfs2/ioctl.c @@ -22,11 +22,6 @@ #include "ioctl.h" #include "resize.h" #include "refcounttree.h" -#include "sysfile.h" -#include "dir.h" -#include "buffer_head_io.h" -#include "suballoc.h" -#include "move_extents.h" #include @@ -40,27 +35,31 @@ * be -EFAULT. The error will be returned from the ioctl(2) call. It's * just a best-effort to tell userspace that this request caused the error. */ -static inline void o2info_set_request_error(struct ocfs2_info_request *kreq, +static inline void __o2info_set_request_error(struct ocfs2_info_request *kreq, struct ocfs2_info_request __user *req) { kreq->ir_flags |= OCFS2_INFO_FL_ERROR; (void)put_user(kreq->ir_flags, (__u32 __user *)&(req->ir_flags)); } -static inline void o2info_set_request_filled(struct ocfs2_info_request *req) +#define o2info_set_request_error(a, b) \ + __o2info_set_request_error((struct ocfs2_info_request *)&(a), b) + +static inline void __o2info_set_request_filled(struct ocfs2_info_request *req) { req->ir_flags |= OCFS2_INFO_FL_FILLED; } -static inline void o2info_clear_request_filled(struct ocfs2_info_request *req) +#define o2info_set_request_filled(a) \ + __o2info_set_request_filled((struct ocfs2_info_request *)&(a)) + +static inline void __o2info_clear_request_filled(struct ocfs2_info_request *req) { req->ir_flags &= ~OCFS2_INFO_FL_FILLED; } -static inline int o2info_coherent(struct ocfs2_info_request *req) -{ - return (!(req->ir_flags & OCFS2_INFO_FL_NON_COHERENT)); -} +#define o2info_clear_request_filled(a) \ + __o2info_clear_request_filled((struct ocfs2_info_request *)&(a)) static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) { @@ -154,7 +153,7 @@ int ocfs2_info_handle_blocksize(struct inode *inode, oib.ib_blocksize = inode->i_sb->s_blocksize; - o2info_set_request_filled(&oib.ib_req); + o2info_set_request_filled(oib); if (o2info_to_user(oib, req)) goto bail; @@ -162,7 +161,7 @@ int ocfs2_info_handle_blocksize(struct inode *inode, status = 0; bail: if (status) - o2info_set_request_error(&oib.ib_req, req); + o2info_set_request_error(oib, req); return status; } @@ -179,7 +178,7 @@ int ocfs2_info_handle_clustersize(struct inode *inode, oic.ic_clustersize = osb->s_clustersize; - o2info_set_request_filled(&oic.ic_req); + o2info_set_request_filled(oic); if (o2info_to_user(oic, req)) goto bail; @@ -187,7 +186,7 @@ int ocfs2_info_handle_clustersize(struct inode *inode, status = 0; bail: if (status) - o2info_set_request_error(&oic.ic_req, req); + o2info_set_request_error(oic, req); return status; } @@ -204,7 +203,7 @@ int ocfs2_info_handle_maxslots(struct inode *inode, oim.im_max_slots = osb->max_slots; - o2info_set_request_filled(&oim.im_req); + o2info_set_request_filled(oim); if (o2info_to_user(oim, req)) goto bail; @@ -212,7 +211,7 @@ int ocfs2_info_handle_maxslots(struct inode *inode, status = 0; bail: if (status) - o2info_set_request_error(&oim.im_req, req); + o2info_set_request_error(oim, req); return status; } @@ -229,7 +228,7 @@ int ocfs2_info_handle_label(struct inode *inode, memcpy(oil.il_label, osb->vol_label, OCFS2_MAX_VOL_LABEL_LEN); - o2info_set_request_filled(&oil.il_req); + o2info_set_request_filled(oil); if (o2info_to_user(oil, req)) goto bail; @@ -237,7 +236,7 @@ int ocfs2_info_handle_label(struct inode *inode, status = 0; bail: if (status) - o2info_set_request_error(&oil.il_req, req); + o2info_set_request_error(oil, req); return status; } @@ -254,7 +253,7 @@ int ocfs2_info_handle_uuid(struct inode *inode, memcpy(oiu.iu_uuid_str, osb->uuid_str, OCFS2_TEXT_UUID_LEN + 1); - o2info_set_request_filled(&oiu.iu_req); + o2info_set_request_filled(oiu); if (o2info_to_user(oiu, req)) goto bail; @@ -262,7 +261,7 @@ int ocfs2_info_handle_uuid(struct inode *inode, status = 0; bail: if (status) - o2info_set_request_error(&oiu.iu_req, req); + o2info_set_request_error(oiu, req); return status; } @@ -281,7 +280,7 @@ int ocfs2_info_handle_fs_features(struct inode *inode, oif.if_incompat_features = osb->s_feature_incompat; oif.if_ro_compat_features = osb->s_feature_ro_compat; - o2info_set_request_filled(&oif.if_req); + o2info_set_request_filled(oif); if (o2info_to_user(oif, req)) goto bail; @@ -289,7 +288,7 @@ int ocfs2_info_handle_fs_features(struct inode *inode, status = 0; bail: if (status) - o2info_set_request_error(&oif.if_req, req); + o2info_set_request_error(oif, req); return status; } @@ -306,7 +305,7 @@ int ocfs2_info_handle_journal_size(struct inode *inode, oij.ij_journal_size = osb->journal->j_inode->i_size; - o2info_set_request_filled(&oij.ij_req); + o2info_set_request_filled(oij); if (o2info_to_user(oij, req)) goto bail; @@ -314,408 +313,7 @@ int ocfs2_info_handle_journal_size(struct inode *inode, status = 0; bail: if (status) - o2info_set_request_error(&oij.ij_req, req); - - return status; -} - -int ocfs2_info_scan_inode_alloc(struct ocfs2_super *osb, - struct inode *inode_alloc, u64 blkno, - struct ocfs2_info_freeinode *fi, u32 slot) -{ - int status = 0, unlock = 0; - - struct buffer_head *bh = NULL; - struct ocfs2_dinode *dinode_alloc = NULL; - - if (inode_alloc) - mutex_lock(&inode_alloc->i_mutex); - - if (o2info_coherent(&fi->ifi_req)) { - status = ocfs2_inode_lock(inode_alloc, &bh, 0); - if (status < 0) { - mlog_errno(status); - goto bail; - } - unlock = 1; - } else { - status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh); - if (status < 0) { - mlog_errno(status); - goto bail; - } - } - - dinode_alloc = (struct ocfs2_dinode *)bh->b_data; - - fi->ifi_stat[slot].lfi_total = - le32_to_cpu(dinode_alloc->id1.bitmap1.i_total); - fi->ifi_stat[slot].lfi_free = - le32_to_cpu(dinode_alloc->id1.bitmap1.i_total) - - le32_to_cpu(dinode_alloc->id1.bitmap1.i_used); - -bail: - if (unlock) - ocfs2_inode_unlock(inode_alloc, 0); - - if (inode_alloc) - mutex_unlock(&inode_alloc->i_mutex); - - brelse(bh); - - return status; -} - -int ocfs2_info_handle_freeinode(struct inode *inode, - struct ocfs2_info_request __user *req) -{ - u32 i; - u64 blkno = -1; - char namebuf[40]; - int status = -EFAULT, type = INODE_ALLOC_SYSTEM_INODE; - struct ocfs2_info_freeinode *oifi = NULL; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct inode *inode_alloc = NULL; - - oifi = kzalloc(sizeof(struct ocfs2_info_freeinode), GFP_KERNEL); - if (!oifi) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - - if (o2info_from_user(*oifi, req)) - goto bail; - - oifi->ifi_slotnum = osb->max_slots; - - for (i = 0; i < oifi->ifi_slotnum; i++) { - if (o2info_coherent(&oifi->ifi_req)) { - inode_alloc = ocfs2_get_system_file_inode(osb, type, i); - if (!inode_alloc) { - mlog(ML_ERROR, "unable to get alloc inode in " - "slot %u\n", i); - status = -EIO; - goto bail; - } - } else { - ocfs2_sprintf_system_inode_name(namebuf, - sizeof(namebuf), - type, i); - status = ocfs2_lookup_ino_from_name(osb->sys_root_inode, - namebuf, - strlen(namebuf), - &blkno); - if (status < 0) { - status = -ENOENT; - goto bail; - } - } - - status = ocfs2_info_scan_inode_alloc(osb, inode_alloc, blkno, oifi, i); - if (status < 0) - goto bail; - - iput(inode_alloc); - inode_alloc = NULL; - } - - o2info_set_request_filled(&oifi->ifi_req); - - if (o2info_to_user(*oifi, req)) - goto bail; - - status = 0; -bail: - if (status) - o2info_set_request_error(&oifi->ifi_req, req); - - kfree(oifi); - - return status; -} - -static void o2ffg_update_histogram(struct ocfs2_info_free_chunk_list *hist, - unsigned int chunksize) -{ - int index; - - index = __ilog2_u32(chunksize); - if (index >= OCFS2_INFO_MAX_HIST) - index = OCFS2_INFO_MAX_HIST - 1; - - hist->fc_chunks[index]++; - hist->fc_clusters[index] += chunksize; -} - -static void o2ffg_update_stats(struct ocfs2_info_freefrag_stats *stats, - unsigned int chunksize) -{ - if (chunksize > stats->ffs_max) - stats->ffs_max = chunksize; - - if (chunksize < stats->ffs_min) - stats->ffs_min = chunksize; - - stats->ffs_avg += chunksize; - stats->ffs_free_chunks_real++; -} - -void ocfs2_info_update_ffg(struct ocfs2_info_freefrag *ffg, - unsigned int chunksize) -{ - o2ffg_update_histogram(&(ffg->iff_ffs.ffs_fc_hist), chunksize); - o2ffg_update_stats(&(ffg->iff_ffs), chunksize); -} - -int ocfs2_info_freefrag_scan_chain(struct ocfs2_super *osb, - struct inode *gb_inode, - struct ocfs2_dinode *gb_dinode, - struct ocfs2_chain_rec *rec, - struct ocfs2_info_freefrag *ffg, - u32 chunks_in_group) -{ - int status = 0, used; - u64 blkno; - - struct buffer_head *bh = NULL; - struct ocfs2_group_desc *bg = NULL; - - unsigned int max_bits, num_clusters; - unsigned int offset = 0, cluster, chunk; - unsigned int chunk_free, last_chunksize = 0; - - if (!le32_to_cpu(rec->c_free)) - goto bail; - - do { - if (!bg) - blkno = le64_to_cpu(rec->c_blkno); - else - blkno = le64_to_cpu(bg->bg_next_group); - - if (bh) { - brelse(bh); - bh = NULL; - } - - if (o2info_coherent(&ffg->iff_req)) - status = ocfs2_read_group_descriptor(gb_inode, - gb_dinode, - blkno, &bh); - else - status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh); - - if (status < 0) { - mlog(ML_ERROR, "Can't read the group descriptor # " - "%llu from device.", (unsigned long long)blkno); - status = -EIO; - goto bail; - } - - bg = (struct ocfs2_group_desc *)bh->b_data; - - if (!le16_to_cpu(bg->bg_free_bits_count)) - continue; - - max_bits = le16_to_cpu(bg->bg_bits); - offset = 0; - - for (chunk = 0; chunk < chunks_in_group; chunk++) { - /* - * last chunk may be not an entire one. - */ - if ((offset + ffg->iff_chunksize) > max_bits) - num_clusters = max_bits - offset; - else - num_clusters = ffg->iff_chunksize; - - chunk_free = 0; - for (cluster = 0; cluster < num_clusters; cluster++) { - used = ocfs2_test_bit(offset, - (unsigned long *)bg->bg_bitmap); - /* - * - chunk_free counts free clusters in #N chunk. - * - last_chunksize records the size(in) clusters - * for the last real free chunk being counted. - */ - if (!used) { - last_chunksize++; - chunk_free++; - } - - if (used && last_chunksize) { - ocfs2_info_update_ffg(ffg, - last_chunksize); - last_chunksize = 0; - } - - offset++; - } - - if (chunk_free == ffg->iff_chunksize) - ffg->iff_ffs.ffs_free_chunks++; - } - - /* - * need to update the info for last free chunk. - */ - if (last_chunksize) - ocfs2_info_update_ffg(ffg, last_chunksize); - - } while (le64_to_cpu(bg->bg_next_group)); - -bail: - brelse(bh); - - return status; -} - -int ocfs2_info_freefrag_scan_bitmap(struct ocfs2_super *osb, - struct inode *gb_inode, u64 blkno, - struct ocfs2_info_freefrag *ffg) -{ - u32 chunks_in_group; - int status = 0, unlock = 0, i; - - struct buffer_head *bh = NULL; - struct ocfs2_chain_list *cl = NULL; - struct ocfs2_chain_rec *rec = NULL; - struct ocfs2_dinode *gb_dinode = NULL; - - if (gb_inode) - mutex_lock(&gb_inode->i_mutex); - - if (o2info_coherent(&ffg->iff_req)) { - status = ocfs2_inode_lock(gb_inode, &bh, 0); - if (status < 0) { - mlog_errno(status); - goto bail; - } - unlock = 1; - } else { - status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh); - if (status < 0) { - mlog_errno(status); - goto bail; - } - } - - gb_dinode = (struct ocfs2_dinode *)bh->b_data; - cl = &(gb_dinode->id2.i_chain); - - /* - * Chunksize(in) clusters from userspace should be - * less than clusters in a group. - */ - if (ffg->iff_chunksize > le16_to_cpu(cl->cl_cpg)) { - status = -EINVAL; - goto bail; - } - - memset(&ffg->iff_ffs, 0, sizeof(struct ocfs2_info_freefrag_stats)); - - ffg->iff_ffs.ffs_min = ~0U; - ffg->iff_ffs.ffs_clusters = - le32_to_cpu(gb_dinode->id1.bitmap1.i_total); - ffg->iff_ffs.ffs_free_clusters = ffg->iff_ffs.ffs_clusters - - le32_to_cpu(gb_dinode->id1.bitmap1.i_used); - - chunks_in_group = le16_to_cpu(cl->cl_cpg) / ffg->iff_chunksize + 1; - - for (i = 0; i < le16_to_cpu(cl->cl_next_free_rec); i++) { - rec = &(cl->cl_recs[i]); - status = ocfs2_info_freefrag_scan_chain(osb, gb_inode, - gb_dinode, - rec, ffg, - chunks_in_group); - if (status) - goto bail; - } - - if (ffg->iff_ffs.ffs_free_chunks_real) - ffg->iff_ffs.ffs_avg = (ffg->iff_ffs.ffs_avg / - ffg->iff_ffs.ffs_free_chunks_real); -bail: - if (unlock) - ocfs2_inode_unlock(gb_inode, 0); - - if (gb_inode) - mutex_unlock(&gb_inode->i_mutex); - - if (gb_inode) - iput(gb_inode); - - brelse(bh); - - return status; -} - -int ocfs2_info_handle_freefrag(struct inode *inode, - struct ocfs2_info_request __user *req) -{ - u64 blkno = -1; - char namebuf[40]; - int status = -EFAULT, type = GLOBAL_BITMAP_SYSTEM_INODE; - - struct ocfs2_info_freefrag *oiff; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct inode *gb_inode = NULL; - - oiff = kzalloc(sizeof(struct ocfs2_info_freefrag), GFP_KERNEL); - if (!oiff) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - - if (o2info_from_user(*oiff, req)) - goto bail; - /* - * chunksize from userspace should be power of 2. - */ - if ((oiff->iff_chunksize & (oiff->iff_chunksize - 1)) || - (!oiff->iff_chunksize)) { - status = -EINVAL; - goto bail; - } - - if (o2info_coherent(&oiff->iff_req)) { - gb_inode = ocfs2_get_system_file_inode(osb, type, - OCFS2_INVALID_SLOT); - if (!gb_inode) { - mlog(ML_ERROR, "unable to get global_bitmap inode\n"); - status = -EIO; - goto bail; - } - } else { - ocfs2_sprintf_system_inode_name(namebuf, sizeof(namebuf), type, - OCFS2_INVALID_SLOT); - status = ocfs2_lookup_ino_from_name(osb->sys_root_inode, - namebuf, - strlen(namebuf), - &blkno); - if (status < 0) { - status = -ENOENT; - goto bail; - } - } - - status = ocfs2_info_freefrag_scan_bitmap(osb, gb_inode, blkno, oiff); - if (status < 0) - goto bail; - - o2info_set_request_filled(&oiff->iff_req); - - if (o2info_to_user(*oiff, req)) - goto bail; - - status = 0; -bail: - if (status) - o2info_set_request_error(&oiff->iff_req, req); - - kfree(oiff); + o2info_set_request_error(oij, req); return status; } @@ -729,7 +327,7 @@ int ocfs2_info_handle_unknown(struct inode *inode, if (o2info_from_user(oir, req)) goto bail; - o2info_clear_request_filled(&oir); + o2info_clear_request_filled(oir); if (o2info_to_user(oir, req)) goto bail; @@ -737,7 +335,7 @@ int ocfs2_info_handle_unknown(struct inode *inode, status = 0; bail: if (status) - o2info_set_request_error(&oir, req); + o2info_set_request_error(oir, req); return status; } @@ -791,14 +389,6 @@ int ocfs2_info_handle_request(struct inode *inode, if (oir.ir_size == sizeof(struct ocfs2_info_journal_size)) status = ocfs2_info_handle_journal_size(inode, req); break; - case OCFS2_INFO_FREEINODE: - if (oir.ir_size == sizeof(struct ocfs2_info_freeinode)) - status = ocfs2_info_handle_freeinode(inode, req); - break; - case OCFS2_INFO_FREEFRAG: - if (oir.ir_size == sizeof(struct ocfs2_info_freefrag)) - status = ocfs2_info_handle_freefrag(inode, req); - break; default: status = ocfs2_info_handle_unknown(inode, req); break; @@ -952,31 +542,6 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EFAULT; return ocfs2_info_handle(inode, &info, 0); - case FITRIM: - { - struct super_block *sb = inode->i_sb; - struct fstrim_range range; - int ret = 0; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (copy_from_user(&range, (struct fstrim_range *)arg, - sizeof(range))) - return -EFAULT; - - ret = ocfs2_trim_fs(sb, &range); - if (ret < 0) - return ret; - - if (copy_to_user((struct fstrim_range *)arg, &range, - sizeof(range))) - return -EFAULT; - - return 0; - } - case OCFS2_IOC_MOVE_EXT: - return ocfs2_ioctl_move_extents(filp, (void __user *)arg); default: return -ENOTTY; } @@ -1004,7 +569,6 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) case OCFS2_IOC_GROUP_EXTEND: case OCFS2_IOC_GROUP_ADD: case OCFS2_IOC_GROUP_ADD64: - case FITRIM: break; case OCFS2_IOC_REFLINK: if (copy_from_user(&args, (struct reflink_arguments *)arg, @@ -1020,8 +584,6 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) return -EFAULT; return ocfs2_info_handle(inode, &info, 1); - case OCFS2_IOC_MOVE_EXT: - break; default: return -ENOIOCTLCMD; } diff --git a/trunk/fs/ocfs2/move_extents.c b/trunk/fs/ocfs2/move_extents.c deleted file mode 100644 index 4c5488468c14..000000000000 --- a/trunk/fs/ocfs2/move_extents.c +++ /dev/null @@ -1,1153 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * move_extents.c - * - * Copyright (C) 2011 Oracle. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ -#include -#include -#include -#include - -#include - -#include "ocfs2.h" -#include "ocfs2_ioctl.h" - -#include "alloc.h" -#include "aops.h" -#include "dlmglue.h" -#include "extent_map.h" -#include "inode.h" -#include "journal.h" -#include "suballoc.h" -#include "uptodate.h" -#include "super.h" -#include "dir.h" -#include "buffer_head_io.h" -#include "sysfile.h" -#include "suballoc.h" -#include "refcounttree.h" -#include "move_extents.h" - -struct ocfs2_move_extents_context { - struct inode *inode; - struct file *file; - int auto_defrag; - int partial; - int credits; - u32 new_phys_cpos; - u32 clusters_moved; - u64 refcount_loc; - struct ocfs2_move_extents *range; - struct ocfs2_extent_tree et; - struct ocfs2_alloc_context *meta_ac; - struct ocfs2_alloc_context *data_ac; - struct ocfs2_cached_dealloc_ctxt dealloc; -}; - -static int __ocfs2_move_extent(handle_t *handle, - struct ocfs2_move_extents_context *context, - u32 cpos, u32 len, u32 p_cpos, u32 new_p_cpos, - int ext_flags) -{ - int ret = 0, index; - struct inode *inode = context->inode; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct ocfs2_extent_rec *rec, replace_rec; - struct ocfs2_path *path = NULL; - struct ocfs2_extent_list *el; - u64 ino = ocfs2_metadata_cache_owner(context->et.et_ci); - u64 old_blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cpos); - - ret = ocfs2_duplicate_clusters_by_page(handle, context->file, cpos, - p_cpos, new_p_cpos, len); - if (ret) { - mlog_errno(ret); - goto out; - } - - memset(&replace_rec, 0, sizeof(replace_rec)); - replace_rec.e_cpos = cpu_to_le32(cpos); - replace_rec.e_leaf_clusters = cpu_to_le16(len); - replace_rec.e_blkno = cpu_to_le64(ocfs2_clusters_to_blocks(inode->i_sb, - new_p_cpos)); - - path = ocfs2_new_path_from_et(&context->et); - if (!path) { - ret = -ENOMEM; - mlog_errno(ret); - goto out; - } - - ret = ocfs2_find_path(INODE_CACHE(inode), path, cpos); - if (ret) { - mlog_errno(ret); - goto out; - } - - el = path_leaf_el(path); - - index = ocfs2_search_extent_list(el, cpos); - if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) { - ocfs2_error(inode->i_sb, - "Inode %llu has an extent at cpos %u which can no " - "longer be found.\n", - (unsigned long long)ino, cpos); - ret = -EROFS; - goto out; - } - - rec = &el->l_recs[index]; - - BUG_ON(ext_flags != rec->e_flags); - /* - * after moving/defraging to new location, the extent is not going - * to be refcounted anymore. - */ - replace_rec.e_flags = ext_flags & ~OCFS2_EXT_REFCOUNTED; - - ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), - context->et.et_root_bh, - OCFS2_JOURNAL_ACCESS_WRITE); - if (ret) { - mlog_errno(ret); - goto out; - } - - ret = ocfs2_split_extent(handle, &context->et, path, index, - &replace_rec, context->meta_ac, - &context->dealloc); - if (ret) { - mlog_errno(ret); - goto out; - } - - ocfs2_journal_dirty(handle, context->et.et_root_bh); - - context->new_phys_cpos = new_p_cpos; - - /* - * need I to append truncate log for old clusters? - */ - if (old_blkno) { - if (ext_flags & OCFS2_EXT_REFCOUNTED) - ret = ocfs2_decrease_refcount(inode, handle, - ocfs2_blocks_to_clusters(osb->sb, - old_blkno), - len, context->meta_ac, - &context->dealloc, 1); - else - ret = ocfs2_truncate_log_append(osb, handle, - old_blkno, len); - } - -out: - return ret; -} - -/* - * lock allocators, and reserving appropriate number of bits for - * meta blocks and data clusters. - * - * in some cases, we don't need to reserve clusters, just let data_ac - * be NULL. - */ -static int ocfs2_lock_allocators_move_extents(struct inode *inode, - struct ocfs2_extent_tree *et, - u32 clusters_to_move, - u32 extents_to_split, - struct ocfs2_alloc_context **meta_ac, - struct ocfs2_alloc_context **data_ac, - int extra_blocks, - int *credits) -{ - int ret, num_free_extents; - unsigned int max_recs_needed = 2 * extents_to_split + clusters_to_move; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - - num_free_extents = ocfs2_num_free_extents(osb, et); - if (num_free_extents < 0) { - ret = num_free_extents; - mlog_errno(ret); - goto out; - } - - if (!num_free_extents || - (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) - extra_blocks += ocfs2_extend_meta_needed(et->et_root_el); - - ret = ocfs2_reserve_new_metadata_blocks(osb, extra_blocks, meta_ac); - if (ret) { - mlog_errno(ret); - goto out; - } - - if (data_ac) { - ret = ocfs2_reserve_clusters(osb, clusters_to_move, data_ac); - if (ret) { - mlog_errno(ret); - goto out; - } - } - - *credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el, - clusters_to_move + 2); - - mlog(0, "reserve metadata_blocks: %d, data_clusters: %u, credits: %d\n", - extra_blocks, clusters_to_move, *credits); -out: - if (ret) { - if (*meta_ac) { - ocfs2_free_alloc_context(*meta_ac); - *meta_ac = NULL; - } - } - - return ret; -} - -/* - * Using one journal handle to guarantee the data consistency in case - * crash happens anywhere. - * - * XXX: defrag can end up with finishing partial extent as requested, - * due to not enough contiguous clusters can be found in allocator. - */ -static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context, - u32 cpos, u32 phys_cpos, u32 *len, int ext_flags) -{ - int ret, credits = 0, extra_blocks = 0, partial = context->partial; - handle_t *handle; - struct inode *inode = context->inode; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct inode *tl_inode = osb->osb_tl_inode; - struct ocfs2_refcount_tree *ref_tree = NULL; - u32 new_phys_cpos, new_len; - u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos); - - if ((ext_flags & OCFS2_EXT_REFCOUNTED) && *len) { - - BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & - OCFS2_HAS_REFCOUNT_FL)); - - BUG_ON(!context->refcount_loc); - - ret = ocfs2_lock_refcount_tree(osb, context->refcount_loc, 1, - &ref_tree, NULL); - if (ret) { - mlog_errno(ret); - return ret; - } - - ret = ocfs2_prepare_refcount_change_for_del(inode, - context->refcount_loc, - phys_blkno, - *len, - &credits, - &extra_blocks); - if (ret) { - mlog_errno(ret); - goto out; - } - } - - ret = ocfs2_lock_allocators_move_extents(inode, &context->et, *len, 1, - &context->meta_ac, - &context->data_ac, - extra_blocks, &credits); - if (ret) { - mlog_errno(ret); - goto out; - } - - /* - * should be using allocation reservation strategy there? - * - * if (context->data_ac) - * context->data_ac->ac_resv = &OCFS2_I(inode)->ip_la_data_resv; - */ - - mutex_lock(&tl_inode->i_mutex); - - if (ocfs2_truncate_log_needs_flush(osb)) { - ret = __ocfs2_flush_truncate_log(osb); - if (ret < 0) { - mlog_errno(ret); - goto out_unlock_mutex; - } - } - - handle = ocfs2_start_trans(osb, credits); - if (IS_ERR(handle)) { - ret = PTR_ERR(handle); - mlog_errno(ret); - goto out_unlock_mutex; - } - - ret = __ocfs2_claim_clusters(handle, context->data_ac, 1, *len, - &new_phys_cpos, &new_len); - if (ret) { - mlog_errno(ret); - goto out_commit; - } - - /* - * allowing partial extent moving is kind of 'pros and cons', it makes - * whole defragmentation less likely to fail, on the contrary, the bad - * thing is it may make the fs even more fragmented after moving, let - * userspace make a good decision here. - */ - if (new_len != *len) { - mlog(0, "len_claimed: %u, len: %u\n", new_len, *len); - if (!partial) { - context->range->me_flags &= ~OCFS2_MOVE_EXT_FL_COMPLETE; - ret = -ENOSPC; - goto out_commit; - } - } - - mlog(0, "cpos: %u, phys_cpos: %u, new_phys_cpos: %u\n", cpos, - phys_cpos, new_phys_cpos); - - ret = __ocfs2_move_extent(handle, context, cpos, new_len, phys_cpos, - new_phys_cpos, ext_flags); - if (ret) - mlog_errno(ret); - - if (partial && (new_len != *len)) - *len = new_len; - - /* - * Here we should write the new page out first if we are - * in write-back mode. - */ - ret = ocfs2_cow_sync_writeback(inode->i_sb, context->inode, cpos, *len); - if (ret) - mlog_errno(ret); - -out_commit: - ocfs2_commit_trans(osb, handle); - -out_unlock_mutex: - mutex_unlock(&tl_inode->i_mutex); - - if (context->data_ac) { - ocfs2_free_alloc_context(context->data_ac); - context->data_ac = NULL; - } - - if (context->meta_ac) { - ocfs2_free_alloc_context(context->meta_ac); - context->meta_ac = NULL; - } - -out: - if (ref_tree) - ocfs2_unlock_refcount_tree(osb, ref_tree, 1); - - return ret; -} - -/* - * find the victim alloc group, where #blkno fits. - */ -static int ocfs2_find_victim_alloc_group(struct inode *inode, - u64 vict_blkno, - int type, int slot, - int *vict_bit, - struct buffer_head **ret_bh) -{ - int ret, i, blocks_per_unit = 1; - u64 blkno; - char namebuf[40]; - - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct buffer_head *ac_bh = NULL, *gd_bh = NULL; - struct ocfs2_chain_list *cl; - struct ocfs2_chain_rec *rec; - struct ocfs2_dinode *ac_dinode; - struct ocfs2_group_desc *bg; - - ocfs2_sprintf_system_inode_name(namebuf, sizeof(namebuf), type, slot); - ret = ocfs2_lookup_ino_from_name(osb->sys_root_inode, namebuf, - strlen(namebuf), &blkno); - if (ret) { - ret = -ENOENT; - goto out; - } - - ret = ocfs2_read_blocks_sync(osb, blkno, 1, &ac_bh); - if (ret) { - mlog_errno(ret); - goto out; - } - - ac_dinode = (struct ocfs2_dinode *)ac_bh->b_data; - cl = &(ac_dinode->id2.i_chain); - rec = &(cl->cl_recs[0]); - - if (type == GLOBAL_BITMAP_SYSTEM_INODE) - blocks_per_unit <<= (osb->s_clustersize_bits - - inode->i_sb->s_blocksize_bits); - /* - * 'vict_blkno' was out of the valid range. - */ - if ((vict_blkno < le64_to_cpu(rec->c_blkno)) || - (vict_blkno >= (le32_to_cpu(ac_dinode->id1.bitmap1.i_total) * - blocks_per_unit))) { - ret = -EINVAL; - goto out; - } - - for (i = 0; i < le16_to_cpu(cl->cl_next_free_rec); i++) { - - rec = &(cl->cl_recs[i]); - if (!rec) - continue; - - bg = NULL; - - do { - if (!bg) - blkno = le64_to_cpu(rec->c_blkno); - else - blkno = le64_to_cpu(bg->bg_next_group); - - if (gd_bh) { - brelse(gd_bh); - gd_bh = NULL; - } - - ret = ocfs2_read_blocks_sync(osb, blkno, 1, &gd_bh); - if (ret) { - mlog_errno(ret); - goto out; - } - - bg = (struct ocfs2_group_desc *)gd_bh->b_data; - - if (vict_blkno < (le64_to_cpu(bg->bg_blkno) + - le16_to_cpu(bg->bg_bits))) { - - *ret_bh = gd_bh; - *vict_bit = (vict_blkno - blkno) / - blocks_per_unit; - mlog(0, "find the victim group: #%llu, " - "total_bits: %u, vict_bit: %u\n", - blkno, le16_to_cpu(bg->bg_bits), - *vict_bit); - goto out; - } - - } while (le64_to_cpu(bg->bg_next_group)); - } - - ret = -EINVAL; -out: - brelse(ac_bh); - - /* - * caller has to release the gd_bh properly. - */ - return ret; -} - -/* - * XXX: helper to validate and adjust moving goal. - */ -static int ocfs2_validate_and_adjust_move_goal(struct inode *inode, - struct ocfs2_move_extents *range) -{ - int ret, goal_bit = 0; - - struct buffer_head *gd_bh = NULL; - struct ocfs2_group_desc *bg; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - int c_to_b = 1 << (osb->s_clustersize_bits - - inode->i_sb->s_blocksize_bits); - - /* - * validate goal sits within global_bitmap, and return the victim - * group desc - */ - ret = ocfs2_find_victim_alloc_group(inode, range->me_goal, - GLOBAL_BITMAP_SYSTEM_INODE, - OCFS2_INVALID_SLOT, - &goal_bit, &gd_bh); - if (ret) - goto out; - - bg = (struct ocfs2_group_desc *)gd_bh->b_data; - - /* - * make goal become cluster aligned. - */ - if (range->me_goal % c_to_b) - range->me_goal = range->me_goal / c_to_b * c_to_b; - - /* - * moving goal is not allowd to start with a group desc blok(#0 blk) - * let's compromise to the latter cluster. - */ - if (range->me_goal == le64_to_cpu(bg->bg_blkno)) - range->me_goal += c_to_b; - - /* - * movement is not gonna cross two groups. - */ - if ((le16_to_cpu(bg->bg_bits) - goal_bit) * osb->s_clustersize < - range->me_len) { - ret = -EINVAL; - goto out; - } - /* - * more exact validations/adjustments will be performed later during - * moving operation for each extent range. - */ - mlog(0, "extents get ready to be moved to #%llu block\n", - range->me_goal); - -out: - brelse(gd_bh); - - return ret; -} - -static void ocfs2_probe_alloc_group(struct inode *inode, struct buffer_head *bh, - int *goal_bit, u32 move_len, u32 max_hop, - u32 *phys_cpos) -{ - int i, used, last_free_bits = 0, base_bit = *goal_bit; - struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; - u32 base_cpos = ocfs2_blocks_to_clusters(inode->i_sb, - le64_to_cpu(gd->bg_blkno)); - - for (i = base_bit; i < le16_to_cpu(gd->bg_bits); i++) { - - used = ocfs2_test_bit(i, (unsigned long *)gd->bg_bitmap); - if (used) { - /* - * we even tried searching the free chunk by jumping - * a 'max_hop' distance, but still failed. - */ - if ((i - base_bit) > max_hop) { - *phys_cpos = 0; - break; - } - - if (last_free_bits) - last_free_bits = 0; - - continue; - } else - last_free_bits++; - - if (last_free_bits == move_len) { - *goal_bit = i; - *phys_cpos = base_cpos + i; - break; - } - } - - mlog(0, "found phys_cpos: %u to fit the wanted moving.\n", *phys_cpos); -} - -static int ocfs2_alloc_dinode_update_counts(struct inode *inode, - handle_t *handle, - struct buffer_head *di_bh, - u32 num_bits, - u16 chain) -{ - int ret; - u32 tmp_used; - struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data; - struct ocfs2_chain_list *cl = - (struct ocfs2_chain_list *) &di->id2.i_chain; - - ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, - OCFS2_JOURNAL_ACCESS_WRITE); - if (ret < 0) { - mlog_errno(ret); - goto out; - } - - tmp_used = le32_to_cpu(di->id1.bitmap1.i_used); - di->id1.bitmap1.i_used = cpu_to_le32(num_bits + tmp_used); - le32_add_cpu(&cl->cl_recs[chain].c_free, -num_bits); - ocfs2_journal_dirty(handle, di_bh); - -out: - return ret; -} - -static inline int ocfs2_block_group_set_bits(handle_t *handle, - struct inode *alloc_inode, - struct ocfs2_group_desc *bg, - struct buffer_head *group_bh, - unsigned int bit_off, - unsigned int num_bits) -{ - int status; - void *bitmap = bg->bg_bitmap; - int journal_type = OCFS2_JOURNAL_ACCESS_WRITE; - - /* All callers get the descriptor via - * ocfs2_read_group_descriptor(). Any corruption is a code bug. */ - BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); - BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits); - - mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off, - num_bits); - - if (ocfs2_is_cluster_bitmap(alloc_inode)) - journal_type = OCFS2_JOURNAL_ACCESS_UNDO; - - status = ocfs2_journal_access_gd(handle, - INODE_CACHE(alloc_inode), - group_bh, - journal_type); - if (status < 0) { - mlog_errno(status); - goto bail; - } - - le16_add_cpu(&bg->bg_free_bits_count, -num_bits); - if (le16_to_cpu(bg->bg_free_bits_count) > le16_to_cpu(bg->bg_bits)) { - ocfs2_error(alloc_inode->i_sb, "Group descriptor # %llu has bit" - " count %u but claims %u are freed. num_bits %d", - (unsigned long long)le64_to_cpu(bg->bg_blkno), - le16_to_cpu(bg->bg_bits), - le16_to_cpu(bg->bg_free_bits_count), num_bits); - return -EROFS; - } - while (num_bits--) - ocfs2_set_bit(bit_off++, bitmap); - - ocfs2_journal_dirty(handle, group_bh); - -bail: - return status; -} - -static int ocfs2_move_extent(struct ocfs2_move_extents_context *context, - u32 cpos, u32 phys_cpos, u32 *new_phys_cpos, - u32 len, int ext_flags) -{ - int ret, credits = 0, extra_blocks = 0, goal_bit = 0; - handle_t *handle; - struct inode *inode = context->inode; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct inode *tl_inode = osb->osb_tl_inode; - struct inode *gb_inode = NULL; - struct buffer_head *gb_bh = NULL; - struct buffer_head *gd_bh = NULL; - struct ocfs2_group_desc *gd; - struct ocfs2_refcount_tree *ref_tree = NULL; - u32 move_max_hop = ocfs2_blocks_to_clusters(inode->i_sb, - context->range->me_threshold); - u64 phys_blkno, new_phys_blkno; - - phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos); - - if ((ext_flags & OCFS2_EXT_REFCOUNTED) && len) { - - BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & - OCFS2_HAS_REFCOUNT_FL)); - - BUG_ON(!context->refcount_loc); - - ret = ocfs2_lock_refcount_tree(osb, context->refcount_loc, 1, - &ref_tree, NULL); - if (ret) { - mlog_errno(ret); - return ret; - } - - ret = ocfs2_prepare_refcount_change_for_del(inode, - context->refcount_loc, - phys_blkno, - len, - &credits, - &extra_blocks); - if (ret) { - mlog_errno(ret); - goto out; - } - } - - ret = ocfs2_lock_allocators_move_extents(inode, &context->et, len, 1, - &context->meta_ac, - NULL, extra_blocks, &credits); - if (ret) { - mlog_errno(ret); - goto out; - } - - /* - * need to count 2 extra credits for global_bitmap inode and - * group descriptor. - */ - credits += OCFS2_INODE_UPDATE_CREDITS + 1; - - /* - * ocfs2_move_extent() didn't reserve any clusters in lock_allocators() - * logic, while we still need to lock the global_bitmap. - */ - gb_inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, - OCFS2_INVALID_SLOT); - if (!gb_inode) { - mlog(ML_ERROR, "unable to get global_bitmap inode\n"); - ret = -EIO; - goto out; - } - - mutex_lock(&gb_inode->i_mutex); - - ret = ocfs2_inode_lock(gb_inode, &gb_bh, 1); - if (ret) { - mlog_errno(ret); - goto out_unlock_gb_mutex; - } - - mutex_lock(&tl_inode->i_mutex); - - handle = ocfs2_start_trans(osb, credits); - if (IS_ERR(handle)) { - ret = PTR_ERR(handle); - mlog_errno(ret); - goto out_unlock_tl_inode; - } - - new_phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, *new_phys_cpos); - ret = ocfs2_find_victim_alloc_group(inode, new_phys_blkno, - GLOBAL_BITMAP_SYSTEM_INODE, - OCFS2_INVALID_SLOT, - &goal_bit, &gd_bh); - if (ret) { - mlog_errno(ret); - goto out_commit; - } - - /* - * probe the victim cluster group to find a proper - * region to fit wanted movement, it even will perfrom - * a best-effort attempt by compromising to a threshold - * around the goal. - */ - ocfs2_probe_alloc_group(inode, gd_bh, &goal_bit, len, move_max_hop, - new_phys_cpos); - if (!new_phys_cpos) { - ret = -ENOSPC; - goto out_commit; - } - - ret = __ocfs2_move_extent(handle, context, cpos, len, phys_cpos, - *new_phys_cpos, ext_flags); - if (ret) { - mlog_errno(ret); - goto out_commit; - } - - gd = (struct ocfs2_group_desc *)gd_bh->b_data; - ret = ocfs2_alloc_dinode_update_counts(gb_inode, handle, gb_bh, len, - le16_to_cpu(gd->bg_chain)); - if (ret) { - mlog_errno(ret); - goto out_commit; - } - - ret = ocfs2_block_group_set_bits(handle, gb_inode, gd, gd_bh, - goal_bit, len); - if (ret) - mlog_errno(ret); - - /* - * Here we should write the new page out first if we are - * in write-back mode. - */ - ret = ocfs2_cow_sync_writeback(inode->i_sb, context->inode, cpos, len); - if (ret) - mlog_errno(ret); - -out_commit: - ocfs2_commit_trans(osb, handle); - brelse(gd_bh); - -out_unlock_tl_inode: - mutex_unlock(&tl_inode->i_mutex); - - ocfs2_inode_unlock(gb_inode, 1); -out_unlock_gb_mutex: - mutex_unlock(&gb_inode->i_mutex); - brelse(gb_bh); - iput(gb_inode); - -out: - if (context->meta_ac) { - ocfs2_free_alloc_context(context->meta_ac); - context->meta_ac = NULL; - } - - if (ref_tree) - ocfs2_unlock_refcount_tree(osb, ref_tree, 1); - - return ret; -} - -/* - * Helper to calculate the defraging length in one run according to threshold. - */ -static void ocfs2_calc_extent_defrag_len(u32 *alloc_size, u32 *len_defraged, - u32 threshold, int *skip) -{ - if ((*alloc_size + *len_defraged) < threshold) { - /* - * proceed defragmentation until we meet the thresh - */ - *len_defraged += *alloc_size; - } else if (*len_defraged == 0) { - /* - * XXX: skip a large extent. - */ - *skip = 1; - } else { - /* - * split this extent to coalesce with former pieces as - * to reach the threshold. - * - * we're done here with one cycle of defragmentation - * in a size of 'thresh', resetting 'len_defraged' - * forces a new defragmentation. - */ - *alloc_size = threshold - *len_defraged; - *len_defraged = 0; - } -} - -static int __ocfs2_move_extents_range(struct buffer_head *di_bh, - struct ocfs2_move_extents_context *context) -{ - int ret = 0, flags, do_defrag, skip = 0; - u32 cpos, phys_cpos, move_start, len_to_move, alloc_size; - u32 len_defraged = 0, defrag_thresh = 0, new_phys_cpos = 0; - - struct inode *inode = context->inode; - struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; - struct ocfs2_move_extents *range = context->range; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - - if ((inode->i_size == 0) || (range->me_len == 0)) - return 0; - - if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) - return 0; - - context->refcount_loc = le64_to_cpu(di->i_refcount_loc); - - ocfs2_init_dinode_extent_tree(&context->et, INODE_CACHE(inode), di_bh); - ocfs2_init_dealloc_ctxt(&context->dealloc); - - /* - * TO-DO XXX: - * - * - xattr extents. - */ - - do_defrag = context->auto_defrag; - - /* - * extents moving happens in unit of clusters, for the sake - * of simplicity, we may ignore two clusters where 'byte_start' - * and 'byte_start + len' were within. - */ - move_start = ocfs2_clusters_for_bytes(osb->sb, range->me_start); - len_to_move = (range->me_start + range->me_len) >> - osb->s_clustersize_bits; - if (len_to_move >= move_start) - len_to_move -= move_start; - else - len_to_move = 0; - - if (do_defrag) { - defrag_thresh = range->me_threshold >> osb->s_clustersize_bits; - if (defrag_thresh <= 1) - goto done; - } else - new_phys_cpos = ocfs2_blocks_to_clusters(inode->i_sb, - range->me_goal); - - mlog(0, "Inode: %llu, start: %llu, len: %llu, cstart: %u, clen: %u, " - "thresh: %u\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (unsigned long long)range->me_start, - (unsigned long long)range->me_len, - move_start, len_to_move, defrag_thresh); - - cpos = move_start; - while (len_to_move) { - ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &alloc_size, - &flags); - if (ret) { - mlog_errno(ret); - goto out; - } - - if (alloc_size > len_to_move) - alloc_size = len_to_move; - - /* - * XXX: how to deal with a hole: - * - * - skip the hole of course - * - force a new defragmentation - */ - if (!phys_cpos) { - if (do_defrag) - len_defraged = 0; - - goto next; - } - - if (do_defrag) { - ocfs2_calc_extent_defrag_len(&alloc_size, &len_defraged, - defrag_thresh, &skip); - /* - * skip large extents - */ - if (skip) { - skip = 0; - goto next; - } - - mlog(0, "#Defrag: cpos: %u, phys_cpos: %u, " - "alloc_size: %u, len_defraged: %u\n", - cpos, phys_cpos, alloc_size, len_defraged); - - ret = ocfs2_defrag_extent(context, cpos, phys_cpos, - &alloc_size, flags); - } else { - ret = ocfs2_move_extent(context, cpos, phys_cpos, - &new_phys_cpos, alloc_size, - flags); - - new_phys_cpos += alloc_size; - } - - if (ret < 0) { - mlog_errno(ret); - goto out; - } - - context->clusters_moved += alloc_size; -next: - cpos += alloc_size; - len_to_move -= alloc_size; - } - -done: - range->me_flags |= OCFS2_MOVE_EXT_FL_COMPLETE; - -out: - range->me_moved_len = ocfs2_clusters_to_bytes(osb->sb, - context->clusters_moved); - range->me_new_offset = ocfs2_clusters_to_bytes(osb->sb, - context->new_phys_cpos); - - ocfs2_schedule_truncate_log_flush(osb, 1); - ocfs2_run_deallocs(osb, &context->dealloc); - - return ret; -} - -static int ocfs2_move_extents(struct ocfs2_move_extents_context *context) -{ - int status; - handle_t *handle; - struct inode *inode = context->inode; - struct ocfs2_dinode *di; - struct buffer_head *di_bh = NULL; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - - if (!inode) - return -ENOENT; - - if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) - return -EROFS; - - mutex_lock(&inode->i_mutex); - - /* - * This prevents concurrent writes from other nodes - */ - status = ocfs2_rw_lock(inode, 1); - if (status) { - mlog_errno(status); - goto out; - } - - status = ocfs2_inode_lock(inode, &di_bh, 1); - if (status) { - mlog_errno(status); - goto out_rw_unlock; - } - - /* - * rememer ip_xattr_sem also needs to be held if necessary - */ - down_write(&OCFS2_I(inode)->ip_alloc_sem); - - status = __ocfs2_move_extents_range(di_bh, context); - - up_write(&OCFS2_I(inode)->ip_alloc_sem); - if (status) { - mlog_errno(status); - goto out_inode_unlock; - } - - /* - * We update ctime for these changes - */ - handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); - if (IS_ERR(handle)) { - status = PTR_ERR(handle); - mlog_errno(status); - goto out_inode_unlock; - } - - status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, - OCFS2_JOURNAL_ACCESS_WRITE); - if (status) { - mlog_errno(status); - goto out_commit; - } - - di = (struct ocfs2_dinode *)di_bh->b_data; - inode->i_ctime = CURRENT_TIME; - di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); - di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); - - ocfs2_journal_dirty(handle, di_bh); - -out_commit: - ocfs2_commit_trans(osb, handle); - -out_inode_unlock: - brelse(di_bh); - ocfs2_inode_unlock(inode, 1); -out_rw_unlock: - ocfs2_rw_unlock(inode, 1); -out: - mutex_unlock(&inode->i_mutex); - - return status; -} - -int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp) -{ - int status; - - struct inode *inode = filp->f_path.dentry->d_inode; - struct ocfs2_move_extents range; - struct ocfs2_move_extents_context *context = NULL; - - status = mnt_want_write(filp->f_path.mnt); - if (status) - return status; - - if ((!S_ISREG(inode->i_mode)) || !(filp->f_mode & FMODE_WRITE)) - goto out; - - if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) { - status = -EPERM; - goto out; - } - - context = kzalloc(sizeof(struct ocfs2_move_extents_context), GFP_NOFS); - if (!context) { - status = -ENOMEM; - mlog_errno(status); - goto out; - } - - context->inode = inode; - context->file = filp; - - if (argp) { - if (copy_from_user(&range, (struct ocfs2_move_extents *)argp, - sizeof(range))) { - status = -EFAULT; - goto out; - } - } else { - status = -EINVAL; - goto out; - } - - if (range.me_start > i_size_read(inode)) - goto out; - - if (range.me_start + range.me_len > i_size_read(inode)) - range.me_len = i_size_read(inode) - range.me_start; - - context->range = ⦥ - - if (range.me_flags & OCFS2_MOVE_EXT_FL_AUTO_DEFRAG) { - context->auto_defrag = 1; - /* - * ok, the default theshold for the defragmentation - * is 1M, since our maximum clustersize was 1M also. - * any thought? - */ - if (!range.me_threshold) - range.me_threshold = 1024 * 1024; - - if (range.me_threshold > i_size_read(inode)) - range.me_threshold = i_size_read(inode); - - if (range.me_flags & OCFS2_MOVE_EXT_FL_PART_DEFRAG) - context->partial = 1; - } else { - /* - * first best-effort attempt to validate and adjust the goal - * (physical address in block), while it can't guarantee later - * operation can succeed all the time since global_bitmap may - * change a bit over time. - */ - - status = ocfs2_validate_and_adjust_move_goal(inode, &range); - if (status) - goto out; - } - - status = ocfs2_move_extents(context); - if (status) - mlog_errno(status); -out: - /* - * movement/defragmentation may end up being partially completed, - * that's the reason why we need to return userspace the finished - * length and new_offset even if failure happens somewhere. - */ - if (argp) { - if (copy_to_user((struct ocfs2_move_extents *)argp, &range, - sizeof(range))) - status = -EFAULT; - } - - kfree(context); - - mnt_drop_write(filp->f_path.mnt); - - return status; -} diff --git a/trunk/fs/ocfs2/move_extents.h b/trunk/fs/ocfs2/move_extents.h deleted file mode 100644 index 4e143e811441..000000000000 --- a/trunk/fs/ocfs2/move_extents.h +++ /dev/null @@ -1,22 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * move_extents.h - * - * Copyright (C) 2011 Oracle. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ -#ifndef OCFS2_MOVE_EXTENTS_H -#define OCFS2_MOVE_EXTENTS_H - -int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp); - -#endif /* OCFS2_MOVE_EXTENTS_H */ diff --git a/trunk/fs/ocfs2/ocfs2_ioctl.h b/trunk/fs/ocfs2/ocfs2_ioctl.h index 5b27ff1fa577..b46f39bf7438 100644 --- a/trunk/fs/ocfs2/ocfs2_ioctl.h +++ b/trunk/fs/ocfs2/ocfs2_ioctl.h @@ -142,38 +142,6 @@ struct ocfs2_info_journal_size { __u64 ij_journal_size; }; -struct ocfs2_info_freeinode { - struct ocfs2_info_request ifi_req; - struct ocfs2_info_local_freeinode { - __u64 lfi_total; - __u64 lfi_free; - } ifi_stat[OCFS2_MAX_SLOTS]; - __u32 ifi_slotnum; /* out */ - __u32 ifi_pad; -}; - -#define OCFS2_INFO_MAX_HIST (32) - -struct ocfs2_info_freefrag { - struct ocfs2_info_request iff_req; - struct ocfs2_info_freefrag_stats { /* (out) */ - struct ocfs2_info_free_chunk_list { - __u32 fc_chunks[OCFS2_INFO_MAX_HIST]; - __u32 fc_clusters[OCFS2_INFO_MAX_HIST]; - } ffs_fc_hist; - __u32 ffs_clusters; - __u32 ffs_free_clusters; - __u32 ffs_free_chunks; - __u32 ffs_free_chunks_real; - __u32 ffs_min; /* Minimum free chunksize in clusters */ - __u32 ffs_max; - __u32 ffs_avg; - __u32 ffs_pad; - } iff_ffs; - __u32 iff_chunksize; /* chunksize in clusters(in) */ - __u32 iff_pad; -}; - /* Codes for ocfs2_info_request */ enum ocfs2_info_type { OCFS2_INFO_CLUSTERSIZE = 1, @@ -183,8 +151,6 @@ enum ocfs2_info_type { OCFS2_INFO_UUID, OCFS2_INFO_FS_FEATURES, OCFS2_INFO_JOURNAL_SIZE, - OCFS2_INFO_FREEINODE, - OCFS2_INFO_FREEFRAG, OCFS2_INFO_NUM_TYPES }; @@ -205,38 +171,4 @@ enum ocfs2_info_type { #define OCFS2_IOC_INFO _IOR('o', 5, struct ocfs2_info) -struct ocfs2_move_extents { -/* All values are in bytes */ - /* in */ - __u64 me_start; /* Virtual start in the file to move */ - __u64 me_len; /* Length of the extents to be moved */ - __u64 me_goal; /* Physical offset of the goal, - it's in block unit */ - __u64 me_threshold; /* Maximum distance from goal or threshold - for auto defragmentation */ - __u64 me_flags; /* Flags for the operation: - * - auto defragmentation. - * - refcount,xattr cases. - */ - /* out */ - __u64 me_moved_len; /* Moved/defraged length */ - __u64 me_new_offset; /* Resulting physical location */ - __u32 me_reserved[2]; /* Reserved for futhure */ -}; - -#define OCFS2_MOVE_EXT_FL_AUTO_DEFRAG (0x00000001) /* Kernel manages to - claim new clusters - as the goal place - for extents moving */ -#define OCFS2_MOVE_EXT_FL_PART_DEFRAG (0x00000002) /* Allow partial extent - moving, is to make - movement less likely - to fail, may make fs - even more fragmented */ -#define OCFS2_MOVE_EXT_FL_COMPLETE (0x00000004) /* Move or defragmenation - completely gets done. - */ - -#define OCFS2_IOC_MOVE_EXT _IOW('o', 6, struct ocfs2_move_extents) - #endif /* OCFS2_IOCTL_H */ diff --git a/trunk/fs/ocfs2/ocfs2_trace.h b/trunk/fs/ocfs2/ocfs2_trace.h index 3b481f490633..a1dae5bb54ac 100644 --- a/trunk/fs/ocfs2/ocfs2_trace.h +++ b/trunk/fs/ocfs2/ocfs2_trace.h @@ -688,31 +688,6 @@ TRACE_EVENT(ocfs2_cache_block_dealloc, __entry->blkno, __entry->bit) ); -TRACE_EVENT(ocfs2_trim_extent, - TP_PROTO(struct super_block *sb, unsigned long long blk, - unsigned long long count), - TP_ARGS(sb, blk, count), - TP_STRUCT__entry( - __field(int, dev_major) - __field(int, dev_minor) - __field(unsigned long long, blk) - __field(__u64, count) - ), - TP_fast_assign( - __entry->dev_major = MAJOR(sb->s_dev); - __entry->dev_minor = MINOR(sb->s_dev); - __entry->blk = blk; - __entry->count = count; - ), - TP_printk("%d %d %llu %llu", - __entry->dev_major, __entry->dev_minor, - __entry->blk, __entry->count) -); - -DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_trim_group); - -DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_trim_fs); - /* End of trace events for fs/ocfs2/alloc.c. */ /* Trace events for fs/ocfs2/localalloc.c. */ diff --git a/trunk/fs/ocfs2/refcounttree.c b/trunk/fs/ocfs2/refcounttree.c index ebfd3825f12a..3c7606cff1ab 100644 --- a/trunk/fs/ocfs2/refcounttree.c +++ b/trunk/fs/ocfs2/refcounttree.c @@ -66,7 +66,7 @@ struct ocfs2_cow_context { u32 *num_clusters, unsigned int *extent_flags); int (*cow_duplicate_clusters)(handle_t *handle, - struct file *file, + struct ocfs2_cow_context *context, u32 cpos, u32 old_cluster, u32 new_cluster, u32 new_len); }; @@ -2921,21 +2921,20 @@ static int ocfs2_clear_cow_buffer(handle_t *handle, struct buffer_head *bh) return 0; } -int ocfs2_duplicate_clusters_by_page(handle_t *handle, - struct file *file, - u32 cpos, u32 old_cluster, - u32 new_cluster, u32 new_len) +static int ocfs2_duplicate_clusters_by_page(handle_t *handle, + struct ocfs2_cow_context *context, + u32 cpos, u32 old_cluster, + u32 new_cluster, u32 new_len) { int ret = 0, partial; - struct inode *inode = file->f_path.dentry->d_inode; - struct ocfs2_caching_info *ci = INODE_CACHE(inode); + struct ocfs2_caching_info *ci = context->data_et.et_ci; struct super_block *sb = ocfs2_metadata_cache_get_super(ci); u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster); struct page *page; pgoff_t page_index; unsigned int from, to, readahead_pages; loff_t offset, end, map_end; - struct address_space *mapping = inode->i_mapping; + struct address_space *mapping = context->inode->i_mapping; trace_ocfs2_duplicate_clusters_by_page(cpos, old_cluster, new_cluster, new_len); @@ -2949,8 +2948,8 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle, * We only duplicate pages until we reach the page contains i_size - 1. * So trim 'end' to i_size. */ - if (end > i_size_read(inode)) - end = i_size_read(inode); + if (end > i_size_read(context->inode)) + end = i_size_read(context->inode); while (offset < end) { page_index = offset >> PAGE_CACHE_SHIFT; @@ -2973,9 +2972,10 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle, if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize) BUG_ON(PageDirty(page)); - if (PageReadahead(page)) { + if (PageReadahead(page) && context->file) { page_cache_async_readahead(mapping, - &file->f_ra, file, + &context->file->f_ra, + context->file, page, page_index, readahead_pages); } @@ -2999,7 +2999,8 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle, } } - ocfs2_map_and_dirty_page(inode, handle, from, to, + ocfs2_map_and_dirty_page(context->inode, + handle, from, to, page, 0, &new_block); mark_page_accessed(page); unlock: @@ -3014,15 +3015,14 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle, return ret; } -int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, - struct file *file, - u32 cpos, u32 old_cluster, - u32 new_cluster, u32 new_len) +static int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, + struct ocfs2_cow_context *context, + u32 cpos, u32 old_cluster, + u32 new_cluster, u32 new_len) { int ret = 0; - struct inode *inode = file->f_path.dentry->d_inode; - struct super_block *sb = inode->i_sb; - struct ocfs2_caching_info *ci = INODE_CACHE(inode); + struct super_block *sb = context->inode->i_sb; + struct ocfs2_caching_info *ci = context->data_et.et_ci; int i, blocks = ocfs2_clusters_to_blocks(sb, new_len); u64 old_block = ocfs2_clusters_to_blocks(sb, old_cluster); u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster); @@ -3145,8 +3145,8 @@ static int ocfs2_replace_clusters(handle_t *handle, /*If the old clusters is unwritten, no need to duplicate. */ if (!(ext_flags & OCFS2_EXT_UNWRITTEN)) { - ret = context->cow_duplicate_clusters(handle, context->file, - cpos, old, new, len); + ret = context->cow_duplicate_clusters(handle, context, cpos, + old, new, len); if (ret) { mlog_errno(ret); goto out; @@ -3162,22 +3162,22 @@ static int ocfs2_replace_clusters(handle_t *handle, return ret; } -int ocfs2_cow_sync_writeback(struct super_block *sb, - struct inode *inode, - u32 cpos, u32 num_clusters) +static int ocfs2_cow_sync_writeback(struct super_block *sb, + struct ocfs2_cow_context *context, + u32 cpos, u32 num_clusters) { int ret = 0; loff_t offset, end, map_end; pgoff_t page_index; struct page *page; - if (ocfs2_should_order_data(inode)) + if (ocfs2_should_order_data(context->inode)) return 0; offset = ((loff_t)cpos) << OCFS2_SB(sb)->s_clustersize_bits; end = offset + (num_clusters << OCFS2_SB(sb)->s_clustersize_bits); - ret = filemap_fdatawrite_range(inode->i_mapping, + ret = filemap_fdatawrite_range(context->inode->i_mapping, offset, end - 1); if (ret < 0) { mlog_errno(ret); @@ -3190,7 +3190,7 @@ int ocfs2_cow_sync_writeback(struct super_block *sb, if (map_end > end) map_end = end; - page = find_or_create_page(inode->i_mapping, + page = find_or_create_page(context->inode->i_mapping, page_index, GFP_NOFS); BUG_ON(!page); @@ -3349,7 +3349,7 @@ static int ocfs2_make_clusters_writable(struct super_block *sb, * in write-back mode. */ if (context->get_clusters == ocfs2_di_get_clusters) { - ret = ocfs2_cow_sync_writeback(sb, context->inode, cpos, + ret = ocfs2_cow_sync_writeback(sb, context, cpos, orig_num_clusters); if (ret) mlog_errno(ret); diff --git a/trunk/fs/ocfs2/refcounttree.h b/trunk/fs/ocfs2/refcounttree.h index 7754608c83a4..c8ce46f7d8e3 100644 --- a/trunk/fs/ocfs2/refcounttree.h +++ b/trunk/fs/ocfs2/refcounttree.h @@ -84,17 +84,6 @@ int ocfs2_refcount_cow_xattr(struct inode *inode, struct buffer_head *ref_root_bh, u32 cpos, u32 write_len, struct ocfs2_post_refcount *post); -int ocfs2_duplicate_clusters_by_page(handle_t *handle, - struct file *file, - u32 cpos, u32 old_cluster, - u32 new_cluster, u32 new_len); -int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, - struct file *file, - u32 cpos, u32 old_cluster, - u32 new_cluster, u32 new_len); -int ocfs2_cow_sync_writeback(struct super_block *sb, - struct inode *inode, - u32 cpos, u32 num_clusters); int ocfs2_add_refcount_flag(struct inode *inode, struct ocfs2_extent_tree *data_et, struct ocfs2_caching_info *ref_ci, diff --git a/trunk/fs/ocfs2/super.c b/trunk/fs/ocfs2/super.c index cdbaf5e97308..5a521c748859 100644 --- a/trunk/fs/ocfs2/super.c +++ b/trunk/fs/ocfs2/super.c @@ -41,7 +41,6 @@ #include #include #include -#include #define CREATE_TRACE_POINTS #include "ocfs2_trace.h" @@ -1567,7 +1566,7 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) if (osb->preferred_slot != OCFS2_INVALID_SLOT) seq_printf(s, ",preferred_slot=%d", osb->preferred_slot); - if (!(mnt->mnt_flags & MNT_NOATIME) && !(mnt->mnt_flags & MNT_RELATIME)) + if (osb->s_atime_quantum != OCFS2_DEFAULT_ATIME_QUANTUM) seq_printf(s, ",atime_quantum=%u", osb->s_atime_quantum); if (osb->osb_commit_interval) @@ -2353,7 +2352,6 @@ static int ocfs2_initialize_super(struct super_block *sb, mlog_errno(status); goto bail; } - cleancache_init_shared_fs((char *)&uuid_net_key, sb); bail: return status; diff --git a/trunk/fs/omfs/dir.c b/trunk/fs/omfs/dir.c index c368360c35a1..de4ff29f1e05 100644 --- a/trunk/fs/omfs/dir.c +++ b/trunk/fs/omfs/dir.c @@ -240,12 +240,8 @@ static int omfs_remove(struct inode *dir, struct dentry *dentry) struct inode *inode = dentry->d_inode; int ret; - - if (S_ISDIR(inode->i_mode)) { - dentry_unhash(dentry); - if (!omfs_dir_is_empty(inode)) - return -ENOTEMPTY; - } + if (S_ISDIR(inode->i_mode) && !omfs_dir_is_empty(inode)) + return -ENOTEMPTY; ret = omfs_delete_entry(dentry); if (ret) @@ -382,9 +378,6 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, int err; if (new_inode) { - if (S_ISDIR(new_inode->i_mode)) - dentry_unhash(new_dentry); - /* overwriting existing file/dir */ err = omfs_remove(new_dir, new_dentry); if (err) diff --git a/trunk/fs/partitions/efi.c b/trunk/fs/partitions/efi.c index 6296b403c67a..19d6750d1d6c 100644 --- a/trunk/fs/partitions/efi.c +++ b/trunk/fs/partitions/efi.c @@ -310,15 +310,6 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, goto fail; } - /* Check the GUID Partition Table header size */ - if (le32_to_cpu((*gpt)->header_size) > - bdev_logical_block_size(state->bdev)) { - pr_debug("GUID Partition Table Header size is wrong: %u > %u\n", - le32_to_cpu((*gpt)->header_size), - bdev_logical_block_size(state->bdev)); - goto fail; - } - /* Check the GUID Partition Table CRC */ origcrc = le32_to_cpu((*gpt)->header_crc32); (*gpt)->header_crc32 = 0; diff --git a/trunk/fs/proc/array.c b/trunk/fs/proc/array.c index 9b45ee84fbcc..5e4f776b0917 100644 --- a/trunk/fs/proc/array.c +++ b/trunk/fs/proc/array.c @@ -131,7 +131,7 @@ static inline void task_name(struct seq_file *m, struct task_struct *p) * you can test for combinations of others with * simple bit tests. */ -static const char * const task_state_array[] = { +static const char *task_state_array[] = { "R (running)", /* 0 */ "S (sleeping)", /* 1 */ "D (disk sleep)", /* 2 */ @@ -147,7 +147,7 @@ static const char * const task_state_array[] = { static inline const char *get_task_state(struct task_struct *tsk) { unsigned int state = (tsk->state & TASK_REPORT) | tsk->exit_state; - const char * const *p = &task_state_array[0]; + const char **p = &task_state_array[0]; BUILD_BUG_ON(1 + ilog2(TASK_STATE_MAX) != ARRAY_SIZE(task_state_array)); diff --git a/trunk/fs/proc/base.c b/trunk/fs/proc/base.c index 4ede550517a6..dc8bca72b002 100644 --- a/trunk/fs/proc/base.c +++ b/trunk/fs/proc/base.c @@ -894,20 +894,20 @@ static ssize_t mem_write(struct file * file, const char __user *buf, if (!task) goto out_no_task; - copied = -ENOMEM; - page = (char *)__get_free_page(GFP_TEMPORARY); - if (!page) - goto out_task; - mm = check_mem_permission(task); copied = PTR_ERR(mm); if (IS_ERR(mm)) - goto out_free; + goto out_task; copied = -EIO; if (file->private_data != (void *)((long)current->self_exec_id)) goto out_mm; + copied = -ENOMEM; + page = (char *)__get_free_page(GFP_TEMPORARY); + if (!page) + goto out_mm; + copied = 0; while (count > 0) { int this_len, retval; @@ -929,11 +929,9 @@ static ssize_t mem_write(struct file * file, const char __user *buf, count -= retval; } *ppos = dst; - + free_page((unsigned long) page); out_mm: mmput(mm); -out_free: - free_page((unsigned long) page); out_task: put_task_struct(task); out_no_task: @@ -1061,7 +1059,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, { struct task_struct *task; char buffer[PROC_NUMBUF]; - int oom_adjust; + long oom_adjust; unsigned long flags; int err; @@ -1073,7 +1071,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, goto out; } - err = kstrtoint(strstrip(buffer), 0, &oom_adjust); + err = strict_strtol(strstrip(buffer), 0, &oom_adjust); if (err) goto out; if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && @@ -1170,7 +1168,7 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, struct task_struct *task; char buffer[PROC_NUMBUF]; unsigned long flags; - int oom_score_adj; + long oom_score_adj; int err; memset(buffer, 0, sizeof(buffer)); @@ -1181,7 +1179,7 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, goto out; } - err = kstrtoint(strstrip(buffer), 0, &oom_score_adj); + err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); if (err) goto out; if (oom_score_adj < OOM_SCORE_ADJ_MIN || @@ -1470,7 +1468,7 @@ sched_autogroup_write(struct file *file, const char __user *buf, struct inode *inode = file->f_path.dentry->d_inode; struct task_struct *p; char buffer[PROC_NUMBUF]; - int nice; + long nice; int err; memset(buffer, 0, sizeof(buffer)); @@ -1479,9 +1477,9 @@ sched_autogroup_write(struct file *file, const char __user *buf, if (copy_from_user(buffer, buf, count)) return -EFAULT; - err = kstrtoint(strstrip(buffer), 0, &nice); - if (err < 0) - return err; + err = strict_strtol(strstrip(buffer), 0, &nice); + if (err) + return -EINVAL; p = get_proc_task(inode); if (!p) @@ -1578,6 +1576,57 @@ static const struct file_operations proc_pid_set_comm_operations = { .release = single_release, }; +/* + * We added or removed a vma mapping the executable. The vmas are only mapped + * during exec and are not mapped with the mmap system call. + * Callers must hold down_write() on the mm's mmap_sem for these + */ +void added_exe_file_vma(struct mm_struct *mm) +{ + mm->num_exe_file_vmas++; +} + +void removed_exe_file_vma(struct mm_struct *mm) +{ + mm->num_exe_file_vmas--; + if ((mm->num_exe_file_vmas == 0) && mm->exe_file){ + fput(mm->exe_file); + mm->exe_file = NULL; + } + +} + +void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) +{ + if (new_exe_file) + get_file(new_exe_file); + if (mm->exe_file) + fput(mm->exe_file); + mm->exe_file = new_exe_file; + mm->num_exe_file_vmas = 0; +} + +struct file *get_mm_exe_file(struct mm_struct *mm) +{ + struct file *exe_file; + + /* We need mmap_sem to protect against races with removal of + * VM_EXECUTABLE vmas */ + down_read(&mm->mmap_sem); + exe_file = mm->exe_file; + if (exe_file) + get_file(exe_file); + up_read(&mm->mmap_sem); + return exe_file; +} + +void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm) +{ + /* It's safe to write the exe_file pointer without exe_file_lock because + * this is called during fork when the task is not yet in /proc */ + newmm->exe_file = get_mm_exe_file(oldmm); +} + static int proc_exe_link(struct inode *inode, struct path *exe_path) { struct task_struct *task; diff --git a/trunk/fs/proc/stat.c b/trunk/fs/proc/stat.c index 9758b654a1bc..1cffa2b8a2fc 100644 --- a/trunk/fs/proc/stat.c +++ b/trunk/fs/proc/stat.c @@ -138,9 +138,9 @@ static int stat_open(struct inode *inode, struct file *file) struct seq_file *m; int res; - /* don't ask for more than the kmalloc() max size */ - if (size > KMALLOC_MAX_SIZE) - size = KMALLOC_MAX_SIZE; + /* don't ask for more than the kmalloc() max size, currently 128 KB */ + if (size > 128 * 1024) + size = 128 * 1024; buf = kmalloc(size, GFP_KERNEL); if (!buf) return -ENOMEM; diff --git a/trunk/fs/proc/task_mmu.c b/trunk/fs/proc/task_mmu.c index 25b6a887adb9..2c9db29ea358 100644 --- a/trunk/fs/proc/task_mmu.c +++ b/trunk/fs/proc/task_mmu.c @@ -211,7 +211,7 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) { struct mm_struct *mm = vma->vm_mm; struct file *file = vma->vm_file; - vm_flags_t flags = vma->vm_flags; + int flags = vma->vm_flags; unsigned long ino = 0; unsigned long long pgoff = 0; unsigned long start, end; @@ -536,17 +536,15 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, char buffer[PROC_NUMBUF]; struct mm_struct *mm; struct vm_area_struct *vma; - int type; - int rv; + long type; memset(buffer, 0, sizeof(buffer)); if (count > sizeof(buffer) - 1) count = sizeof(buffer) - 1; if (copy_from_user(buffer, buf, count)) return -EFAULT; - rv = kstrtoint(strstrip(buffer), 10, &type); - if (rv < 0) - return rv; + if (strict_strtol(strstrip(buffer), 10, &type)) + return -EINVAL; if (type < CLEAR_REFS_ALL || type > CLEAR_REFS_MAPPED) return -EINVAL; task = get_proc_task(file->f_path.dentry->d_inode); @@ -771,12 +769,18 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, if (!task) goto out; + mm = mm_for_maps(task); + ret = PTR_ERR(mm); + if (!mm || IS_ERR(mm)) + goto out_task; + ret = -EINVAL; /* file position must be aligned */ if ((*ppos % PM_ENTRY_BYTES) || (count % PM_ENTRY_BYTES)) goto out_task; ret = 0; + if (!count) goto out_task; @@ -784,12 +788,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, pm.buffer = kmalloc(pm.len, GFP_TEMPORARY); ret = -ENOMEM; if (!pm.buffer) - goto out_task; - - mm = mm_for_maps(task); - ret = PTR_ERR(mm); - if (!mm || IS_ERR(mm)) - goto out_free; + goto out_mm; pagemap_walk.pmd_entry = pagemap_pte_range; pagemap_walk.pte_hole = pagemap_pte_hole; @@ -832,7 +831,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, len = min(count, PM_ENTRY_BYTES * pm.pos); if (copy_to_user(buf, pm.buffer, len)) { ret = -EFAULT; - goto out_mm; + goto out_free; } copied += len; buf += len; @@ -842,10 +841,10 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, if (!ret || ret == PM_END_OF_BUFFER) ret = copied; -out_mm: - mmput(mm); out_free: kfree(pm.buffer); +out_mm: + mmput(mm); out_task: put_task_struct(task); out: diff --git a/trunk/fs/proc/vmcore.c b/trunk/fs/proc/vmcore.c index cd99bf557650..74802bc5ded9 100644 --- a/trunk/fs/proc/vmcore.c +++ b/trunk/fs/proc/vmcore.c @@ -35,46 +35,6 @@ static u64 vmcore_size; static struct proc_dir_entry *proc_vmcore = NULL; -/* - * Returns > 0 for RAM pages, 0 for non-RAM pages, < 0 on error - * The called function has to take care of module refcounting. - */ -static int (*oldmem_pfn_is_ram)(unsigned long pfn); - -int register_oldmem_pfn_is_ram(int (*fn)(unsigned long pfn)) -{ - if (oldmem_pfn_is_ram) - return -EBUSY; - oldmem_pfn_is_ram = fn; - return 0; -} -EXPORT_SYMBOL_GPL(register_oldmem_pfn_is_ram); - -void unregister_oldmem_pfn_is_ram(void) -{ - oldmem_pfn_is_ram = NULL; - wmb(); -} -EXPORT_SYMBOL_GPL(unregister_oldmem_pfn_is_ram); - -static int pfn_is_ram(unsigned long pfn) -{ - int (*fn)(unsigned long pfn); - /* pfn is ram unless fn() checks pagetype */ - int ret = 1; - - /* - * Ask hypervisor if the pfn is really ram. - * A ballooned page contains no data and reading from such a page - * will cause high load in the hypervisor. - */ - fn = oldmem_pfn_is_ram; - if (fn) - ret = fn(pfn); - - return ret; -} - /* Reads a page from the oldmem device from given offset. */ static ssize_t read_from_oldmem(char *buf, size_t count, u64 *ppos, int userbuf) @@ -95,15 +55,9 @@ static ssize_t read_from_oldmem(char *buf, size_t count, else nr_bytes = count; - /* If pfn is not ram, return zeros for sparse dump files */ - if (pfn_is_ram(pfn) == 0) - memset(buf, 0, nr_bytes); - else { - tmp = copy_oldmem_page(pfn, buf, nr_bytes, - offset, userbuf); - if (tmp < 0) - return tmp; - } + tmp = copy_oldmem_page(pfn, buf, nr_bytes, offset, userbuf); + if (tmp < 0) + return tmp; *ppos += nr_bytes; count -= nr_bytes; buf += nr_bytes; diff --git a/trunk/fs/reiserfs/namei.c b/trunk/fs/reiserfs/namei.c index 76c8164d5651..118662690cdf 100644 --- a/trunk/fs/reiserfs/namei.c +++ b/trunk/fs/reiserfs/namei.c @@ -831,8 +831,6 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry) INITIALIZE_PATH(path); struct reiserfs_dir_entry de; - dentry_unhash(dentry); - /* we will be doing 2 balancings and update 2 stat data, we change quotas * of the owner of the directory and of the owner of the parent directory. * The quota structure is possibly deleted only on last iput => outside @@ -1227,9 +1225,6 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry, unsigned long savelink = 1; struct timespec ctime; - if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) - dentry_unhash(new_dentry); - /* three balancings: (1) old name removal, (2) new name insertion and (3) maybe "save" link insertion stat data updates: (1) old directory, diff --git a/trunk/fs/reiserfs/xattr.c b/trunk/fs/reiserfs/xattr.c index 50f1abccd1cd..47d2a4498b03 100644 --- a/trunk/fs/reiserfs/xattr.c +++ b/trunk/fs/reiserfs/xattr.c @@ -105,6 +105,7 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry) mutex_unlock(&dentry->d_inode->i_mutex); if (!error) d_delete(dentry); + dput(dentry); return error; } diff --git a/trunk/fs/squashfs/block.c b/trunk/fs/squashfs/block.c index ed0eb2a921f4..8ab48bc2fa7d 100644 --- a/trunk/fs/squashfs/block.c +++ b/trunk/fs/squashfs/block.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/cache.c b/trunk/fs/squashfs/cache.c index f744be98cd5a..4b5a3fbb1f1f 100644 --- a/trunk/fs/squashfs/cache.c +++ b/trunk/fs/squashfs/cache.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -393,36 +393,19 @@ struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *sb, /* * Read a filesystem table (uncompressed sequence of bytes) from disk */ -void *squashfs_read_table(struct super_block *sb, u64 block, int length) +int squashfs_read_table(struct super_block *sb, void *buffer, u64 block, + int length) { int pages = (length + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; int i, res; - void *table, *buffer, **data; - - table = buffer = kmalloc(length, GFP_KERNEL); - if (table == NULL) - return ERR_PTR(-ENOMEM); - - data = kcalloc(pages, sizeof(void *), GFP_KERNEL); - if (data == NULL) { - res = -ENOMEM; - goto failed; - } + void **data = kcalloc(pages, sizeof(void *), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE) data[i] = buffer; - res = squashfs_read_data(sb, data, block, length | SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length, pages); - kfree(data); - - if (res < 0) - goto failed; - - return table; - -failed: - kfree(table); - return ERR_PTR(res); + return res; } diff --git a/trunk/fs/squashfs/decompressor.c b/trunk/fs/squashfs/decompressor.c index 9f1b0bb96f13..e921bd213738 100644 --- a/trunk/fs/squashfs/decompressor.c +++ b/trunk/fs/squashfs/decompressor.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/decompressor.h b/trunk/fs/squashfs/decompressor.h index 8ba70cff09a6..099745ad5691 100644 --- a/trunk/fs/squashfs/decompressor.h +++ b/trunk/fs/squashfs/decompressor.h @@ -4,7 +4,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/dir.c b/trunk/fs/squashfs/dir.c index 9dfe2ce0fb70..3f79cd1d0c19 100644 --- a/trunk/fs/squashfs/dir.c +++ b/trunk/fs/squashfs/dir.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/export.c b/trunk/fs/squashfs/export.c index 730c56248c9b..7f93d5a9ee05 100644 --- a/trunk/fs/squashfs/export.c +++ b/trunk/fs/squashfs/export.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -121,38 +121,30 @@ static struct dentry *squashfs_get_parent(struct dentry *child) * Read uncompressed inode lookup table indexes off disk into memory */ __le64 *squashfs_read_inode_lookup_table(struct super_block *sb, - u64 lookup_table_start, u64 next_table, unsigned int inodes) + u64 lookup_table_start, unsigned int inodes) { unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes); - __le64 *table; + __le64 *inode_lookup_table; + int err; TRACE("In read_inode_lookup_table, length %d\n", length); - /* Sanity check values */ - - /* there should always be at least one inode */ - if (inodes == 0) - return ERR_PTR(-EINVAL); - - /* length bytes should not extend into the next table - this check - * also traps instances where lookup_table_start is incorrectly larger - * than the next table start - */ - if (lookup_table_start + length > next_table) - return ERR_PTR(-EINVAL); - - table = squashfs_read_table(sb, lookup_table_start, length); + /* Allocate inode lookup table indexes */ + inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return ERR_PTR(-ENOMEM); + } - /* - * table[0] points to the first inode lookup table metadata block, - * this should be less than lookup_table_start - */ - if (!IS_ERR(table) && table[0] >= lookup_table_start) { - kfree(table); - return ERR_PTR(-EINVAL); + err = squashfs_read_table(sb, inode_lookup_table, lookup_table_start, + length); + if (err < 0) { + ERROR("unable to read inode lookup table\n"); + kfree(inode_lookup_table); + return ERR_PTR(err); } - return table; + return inode_lookup_table; } diff --git a/trunk/fs/squashfs/file.c b/trunk/fs/squashfs/file.c index 38bb1c640559..a25c5060bdcb 100644 --- a/trunk/fs/squashfs/file.c +++ b/trunk/fs/squashfs/file.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/fragment.c b/trunk/fs/squashfs/fragment.c index 1516a6490bfb..7eef571443c6 100644 --- a/trunk/fs/squashfs/fragment.c +++ b/trunk/fs/squashfs/fragment.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -71,29 +71,26 @@ int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment, * Read the uncompressed fragment lookup table indexes off disk into memory */ __le64 *squashfs_read_fragment_index_table(struct super_block *sb, - u64 fragment_table_start, u64 next_table, unsigned int fragments) + u64 fragment_table_start, unsigned int fragments) { unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(fragments); - __le64 *table; + __le64 *fragment_index; + int err; - /* - * Sanity check, length bytes should not extend into the next table - - * this check also traps instances where fragment_table_start is - * incorrectly larger than the next table start - */ - if (fragment_table_start + length > next_table) - return ERR_PTR(-EINVAL); - - table = squashfs_read_table(sb, fragment_table_start, length); + /* Allocate fragment lookup table indexes */ + fragment_index = kmalloc(length, GFP_KERNEL); + if (fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return ERR_PTR(-ENOMEM); + } - /* - * table[0] points to the first fragment table metadata block, this - * should be less than fragment_table_start - */ - if (!IS_ERR(table) && table[0] >= fragment_table_start) { - kfree(table); - return ERR_PTR(-EINVAL); + err = squashfs_read_table(sb, fragment_index, fragment_table_start, + length); + if (err < 0) { + ERROR("unable to read fragment index table\n"); + kfree(fragment_index); + return ERR_PTR(err); } - return table; + return fragment_index; } diff --git a/trunk/fs/squashfs/id.c b/trunk/fs/squashfs/id.c index a70858e0fb44..d8f32452638e 100644 --- a/trunk/fs/squashfs/id.c +++ b/trunk/fs/squashfs/id.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -66,37 +66,27 @@ int squashfs_get_id(struct super_block *sb, unsigned int index, * Read uncompressed id lookup table indexes from disk into memory */ __le64 *squashfs_read_id_index_table(struct super_block *sb, - u64 id_table_start, u64 next_table, unsigned short no_ids) + u64 id_table_start, unsigned short no_ids) { unsigned int length = SQUASHFS_ID_BLOCK_BYTES(no_ids); - __le64 *table; + __le64 *id_table; + int err; TRACE("In read_id_index_table, length %d\n", length); - /* Sanity check values */ - - /* there should always be at least one id */ - if (no_ids == 0) - return ERR_PTR(-EINVAL); - - /* - * length bytes should not extend into the next table - this check - * also traps instances where id_table_start is incorrectly larger - * than the next table start - */ - if (id_table_start + length > next_table) - return ERR_PTR(-EINVAL); - - table = squashfs_read_table(sb, id_table_start, length); + /* Allocate id lookup table indexes */ + id_table = kmalloc(length, GFP_KERNEL); + if (id_table == NULL) { + ERROR("Failed to allocate id index table\n"); + return ERR_PTR(-ENOMEM); + } - /* - * table[0] points to the first id lookup table metadata block, this - * should be less than id_table_start - */ - if (!IS_ERR(table) && table[0] >= id_table_start) { - kfree(table); - return ERR_PTR(-EINVAL); + err = squashfs_read_table(sb, id_table, id_table_start, length); + if (err < 0) { + ERROR("unable to read id index table\n"); + kfree(id_table); + return ERR_PTR(err); } - return table; + return id_table; } diff --git a/trunk/fs/squashfs/inode.c b/trunk/fs/squashfs/inode.c index 04bebcaa2373..62e63ad25075 100644 --- a/trunk/fs/squashfs/inode.c +++ b/trunk/fs/squashfs/inode.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/namei.c b/trunk/fs/squashfs/namei.c index 4bc63ac64bc0..5d922a6701ab 100644 --- a/trunk/fs/squashfs/namei.c +++ b/trunk/fs/squashfs/namei.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/squashfs.h b/trunk/fs/squashfs/squashfs.h index e3be6a71cfa7..1f2e608b8785 100644 --- a/trunk/fs/squashfs/squashfs.h +++ b/trunk/fs/squashfs/squashfs.h @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -44,24 +44,24 @@ extern struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *, u64, int); extern struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *, u64, int); -extern void *squashfs_read_table(struct super_block *, u64, int); +extern int squashfs_read_table(struct super_block *, void *, u64, int); /* decompressor.c */ extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int); extern void *squashfs_decompressor_init(struct super_block *, unsigned short); /* export.c */ -extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64, +extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, unsigned int); /* fragment.c */ extern int squashfs_frag_lookup(struct super_block *, unsigned int, u64 *); extern __le64 *squashfs_read_fragment_index_table(struct super_block *, - u64, u64, unsigned int); + u64, unsigned int); /* id.c */ extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *); -extern __le64 *squashfs_read_id_index_table(struct super_block *, u64, u64, +extern __le64 *squashfs_read_id_index_table(struct super_block *, u64, unsigned short); /* inode.c */ diff --git a/trunk/fs/squashfs/squashfs_fs.h b/trunk/fs/squashfs/squashfs_fs.h index b4a4e539a08c..4582c568ef4d 100644 --- a/trunk/fs/squashfs/squashfs_fs.h +++ b/trunk/fs/squashfs/squashfs_fs.h @@ -4,7 +4,7 @@ * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/squashfs_fs_i.h b/trunk/fs/squashfs/squashfs_fs_i.h index 73588e7700ed..359baefc01fc 100644 --- a/trunk/fs/squashfs/squashfs_fs_i.h +++ b/trunk/fs/squashfs/squashfs_fs_i.h @@ -4,7 +4,7 @@ * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/squashfs_fs_sb.h b/trunk/fs/squashfs/squashfs_fs_sb.h index 651f0b31d296..d9037a5215f0 100644 --- a/trunk/fs/squashfs/squashfs_fs_sb.h +++ b/trunk/fs/squashfs/squashfs_fs_sb.h @@ -4,7 +4,7 @@ * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/super.c b/trunk/fs/squashfs/super.c index 6f26abee3597..5c8184c061a4 100644 --- a/trunk/fs/squashfs/super.c +++ b/trunk/fs/squashfs/super.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -83,7 +83,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) long long root_inode; unsigned short flags; unsigned int fragments; - u64 lookup_table_start, xattr_id_table_start, next_table; + u64 lookup_table_start, xattr_id_table_start; int err; TRACE("Entered squashfs_fill_superblock\n"); @@ -95,6 +95,12 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) } msblk = sb->s_fs_info; + sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); + if (sblk == NULL) { + ERROR("Failed to allocate squashfs_super_block\n"); + goto failure; + } + msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE); msblk->devblksize_log2 = ffz(~msblk->devblksize); @@ -108,12 +114,10 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) * of bytes_used) we need to set it to an initial sensible dummy value */ msblk->bytes_used = sizeof(*sblk); - sblk = squashfs_read_table(sb, SQUASHFS_START, sizeof(*sblk)); + err = squashfs_read_table(sb, sblk, SQUASHFS_START, sizeof(*sblk)); - if (IS_ERR(sblk)) { + if (err < 0) { ERROR("unable to read squashfs_super_block\n"); - err = PTR_ERR(sblk); - sblk = NULL; goto failed_mount; } @@ -214,61 +218,18 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount; } - /* Handle xattrs */ - sb->s_xattr = squashfs_xattr_handlers; - xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start); - if (xattr_id_table_start == SQUASHFS_INVALID_BLK) { - next_table = msblk->bytes_used; - goto allocate_id_index_table; - } - - /* Allocate and read xattr id lookup table */ - msblk->xattr_id_table = squashfs_read_xattr_id_table(sb, - xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids); - if (IS_ERR(msblk->xattr_id_table)) { - ERROR("unable to read xattr id index table\n"); - err = PTR_ERR(msblk->xattr_id_table); - msblk->xattr_id_table = NULL; - if (err != -ENOTSUPP) - goto failed_mount; - } - next_table = msblk->xattr_table; - -allocate_id_index_table: /* Allocate and read id index table */ msblk->id_table = squashfs_read_id_index_table(sb, - le64_to_cpu(sblk->id_table_start), next_table, - le16_to_cpu(sblk->no_ids)); + le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids)); if (IS_ERR(msblk->id_table)) { - ERROR("unable to read id index table\n"); err = PTR_ERR(msblk->id_table); msblk->id_table = NULL; goto failed_mount; } - next_table = msblk->id_table[0]; - - /* Handle inode lookup table */ - lookup_table_start = le64_to_cpu(sblk->lookup_table_start); - if (lookup_table_start == SQUASHFS_INVALID_BLK) - goto handle_fragments; - - /* Allocate and read inode lookup table */ - msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb, - lookup_table_start, next_table, msblk->inodes); - if (IS_ERR(msblk->inode_lookup_table)) { - ERROR("unable to read inode lookup table\n"); - err = PTR_ERR(msblk->inode_lookup_table); - msblk->inode_lookup_table = NULL; - goto failed_mount; - } - next_table = msblk->inode_lookup_table[0]; - sb->s_export_op = &squashfs_export_ops; - -handle_fragments: fragments = le32_to_cpu(sblk->fragments); if (fragments == 0) - goto check_directory_table; + goto allocate_lookup_table; msblk->fragment_cache = squashfs_cache_init("fragment", SQUASHFS_CACHED_FRAGMENTS, msblk->block_size); @@ -279,29 +240,45 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) /* Allocate and read fragment index table */ msblk->fragment_index = squashfs_read_fragment_index_table(sb, - le64_to_cpu(sblk->fragment_table_start), next_table, fragments); + le64_to_cpu(sblk->fragment_table_start), fragments); if (IS_ERR(msblk->fragment_index)) { - ERROR("unable to read fragment index table\n"); err = PTR_ERR(msblk->fragment_index); msblk->fragment_index = NULL; goto failed_mount; } - next_table = msblk->fragment_index[0]; -check_directory_table: - /* Sanity check directory_table */ - if (msblk->directory_table >= next_table) { - err = -EINVAL; - goto failed_mount; - } +allocate_lookup_table: + lookup_table_start = le64_to_cpu(sblk->lookup_table_start); + if (lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_xattr_table; - /* Sanity check inode_table */ - if (msblk->inode_table >= msblk->directory_table) { - err = -EINVAL; + /* Allocate and read inode lookup table */ + msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb, + lookup_table_start, msblk->inodes); + if (IS_ERR(msblk->inode_lookup_table)) { + err = PTR_ERR(msblk->inode_lookup_table); + msblk->inode_lookup_table = NULL; goto failed_mount; } - /* allocate root */ + sb->s_export_op = &squashfs_export_ops; + +allocate_xattr_table: + sb->s_xattr = squashfs_xattr_handlers; + xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start); + if (xattr_id_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read xattr id lookup table */ + msblk->xattr_id_table = squashfs_read_xattr_id_table(sb, + xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids); + if (IS_ERR(msblk->xattr_id_table)) { + err = PTR_ERR(msblk->xattr_id_table); + msblk->xattr_id_table = NULL; + if (err != -ENOTSUPP) + goto failed_mount; + } +allocate_root: root = new_inode(sb); if (!root) { err = -ENOMEM; @@ -341,6 +318,11 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_fs_info = NULL; kfree(sblk); return err; + +failure: + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + return -ENOMEM; } @@ -493,5 +475,5 @@ static const struct super_operations squashfs_super_ops = { module_init(init_squashfs_fs); module_exit(exit_squashfs_fs); MODULE_DESCRIPTION("squashfs 4.0, a compressed read-only filesystem"); -MODULE_AUTHOR("Phillip Lougher "); +MODULE_AUTHOR("Phillip Lougher "); MODULE_LICENSE("GPL"); diff --git a/trunk/fs/squashfs/symlink.c b/trunk/fs/squashfs/symlink.c index 1191817264cc..ec86434921e1 100644 --- a/trunk/fs/squashfs/symlink.c +++ b/trunk/fs/squashfs/symlink.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/xattr.c b/trunk/fs/squashfs/xattr.c index 92fcde7b4d61..3876c36699a1 100644 --- a/trunk/fs/squashfs/xattr.c +++ b/trunk/fs/squashfs/xattr.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2010 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/xattr.h b/trunk/fs/squashfs/xattr.h index c83f5d9ec125..b634efce4bde 100644 --- a/trunk/fs/squashfs/xattr.h +++ b/trunk/fs/squashfs/xattr.h @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2010 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,7 +31,6 @@ static inline __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start, u64 *xattr_table_start, int *xattr_ids) { ERROR("Xattrs in filesystem, these will be ignored\n"); - *xattr_table_start = start; return ERR_PTR(-ENOTSUPP); } diff --git a/trunk/fs/squashfs/xattr_id.c b/trunk/fs/squashfs/xattr_id.c index c89607d690c4..05385dbe1465 100644 --- a/trunk/fs/squashfs/xattr_id.c +++ b/trunk/fs/squashfs/xattr_id.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2010 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -67,29 +67,34 @@ __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start, u64 *xattr_table_start, int *xattr_ids) { unsigned int len; - struct squashfs_xattr_id_table *id_table; - - id_table = squashfs_read_table(sb, start, sizeof(*id_table)); - if (IS_ERR(id_table)) - return (__le64 *) id_table; - - *xattr_table_start = le64_to_cpu(id_table->xattr_table_start); - *xattr_ids = le32_to_cpu(id_table->xattr_ids); - kfree(id_table); - - /* Sanity check values */ - - /* there is always at least one xattr id */ - if (*xattr_ids == 0) - return ERR_PTR(-EINVAL); - - /* xattr_table should be less than start */ - if (*xattr_table_start >= start) - return ERR_PTR(-EINVAL); + __le64 *xid_table; + struct squashfs_xattr_id_table id_table; + int err; + err = squashfs_read_table(sb, &id_table, start, sizeof(id_table)); + if (err < 0) { + ERROR("unable to read xattr id table\n"); + return ERR_PTR(err); + } + *xattr_table_start = le64_to_cpu(id_table.xattr_table_start); + *xattr_ids = le32_to_cpu(id_table.xattr_ids); len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids); TRACE("In read_xattr_index_table, length %d\n", len); - return squashfs_read_table(sb, start + sizeof(*id_table), len); + /* Allocate xattr id lookup table indexes */ + xid_table = kmalloc(len, GFP_KERNEL); + if (xid_table == NULL) { + ERROR("Failed to allocate xattr id index table\n"); + return ERR_PTR(-ENOMEM); + } + + err = squashfs_read_table(sb, xid_table, start + sizeof(id_table), len); + if (err < 0) { + ERROR("unable to read xattr id index table\n"); + kfree(xid_table); + return ERR_PTR(err); + } + + return xid_table; } diff --git a/trunk/fs/squashfs/xz_wrapper.c b/trunk/fs/squashfs/xz_wrapper.c index 1760b7d108f6..aa47a286d1f8 100644 --- a/trunk/fs/squashfs/xz_wrapper.c +++ b/trunk/fs/squashfs/xz_wrapper.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/squashfs/zlib_wrapper.c b/trunk/fs/squashfs/zlib_wrapper.c index 55d918fd2d86..517688b32ffa 100644 --- a/trunk/fs/squashfs/zlib_wrapper.c +++ b/trunk/fs/squashfs/zlib_wrapper.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - * Phillip Lougher + * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/fs/super.c b/trunk/fs/super.c index c75593953c52..c04f7e0b7ed2 100644 --- a/trunk/fs/super.c +++ b/trunk/fs/super.c @@ -31,7 +31,6 @@ #include #include #include -#include #include "internal.h" @@ -113,7 +112,6 @@ static struct super_block *alloc_super(struct file_system_type *type) s->s_maxbytes = MAX_NON_LFS; s->s_op = &default_op; s->s_time_gran = 1000000000; - s->cleancache_poolid = -1; } out: return s; @@ -179,7 +177,6 @@ void deactivate_locked_super(struct super_block *s) { struct file_system_type *fs = s->s_type; if (atomic_dec_and_test(&s->s_active)) { - cleancache_flush_fs(s); fs->kill_sb(s); /* * We need to call rcu_barrier so all the delayed rcu free diff --git a/trunk/fs/sysv/namei.c b/trunk/fs/sysv/namei.c index e2cc6756f3b1..e474fbcf8bde 100644 --- a/trunk/fs/sysv/namei.c +++ b/trunk/fs/sysv/namei.c @@ -196,8 +196,6 @@ static int sysv_rmdir(struct inode * dir, struct dentry * dentry) struct inode *inode = dentry->d_inode; int err = -ENOTEMPTY; - dentry_unhash(dentry); - if (sysv_empty_dir(inode)) { err = sysv_unlink(dir, dentry); if (!err) { @@ -224,9 +222,6 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, struct sysv_dir_entry * old_de; int err = -ENOENT; - if (new_inode && S_ISDIR(new_inode->i_mode)) - dentry_unhash(new_dentry); - old_de = sysv_find_entry(old_dentry, &old_page); if (!old_de) goto out; diff --git a/trunk/fs/ubifs/dir.c b/trunk/fs/ubifs/dir.c index c2b80943560d..ef5abd38f0bf 100644 --- a/trunk/fs/ubifs/dir.c +++ b/trunk/fs/ubifs/dir.c @@ -656,8 +656,6 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 }; - dentry_unhash(dentry); - /* * Budget request settings: deletion direntry, deletion inode and * changing the parent inode. If budgeting fails, go ahead anyway @@ -978,9 +976,6 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) }; struct timespec time; - if (new_inode && S_ISDIR(new_inode->i_mode)) - dentry_unhash(new_dentry); - /* * Budget request settings: deletion direntry, new direntry, removing * the old inode, and changing old and new parent directory inodes. diff --git a/trunk/fs/udf/namei.c b/trunk/fs/udf/namei.c index 4d76594c2a8f..f1dce848ef96 100644 --- a/trunk/fs/udf/namei.c +++ b/trunk/fs/udf/namei.c @@ -783,8 +783,6 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry) struct fileIdentDesc *fi, cfi; struct kernel_lb_addr tloc; - dentry_unhash(dentry); - retval = -ENOENT; fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi); if (!fi) @@ -1083,9 +1081,6 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, struct kernel_lb_addr tloc; struct udf_inode_info *old_iinfo = UDF_I(old_inode); - if (new_inode && S_ISDIR(new_inode->i_mode)) - dentry_unhash(new_dentry); - ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi); if (ofi) { if (ofibh.sbh != ofibh.ebh) diff --git a/trunk/fs/ufs/balloc.c b/trunk/fs/ufs/balloc.c index 42694e11c23d..46f7a807bbc1 100644 --- a/trunk/fs/ufs/balloc.c +++ b/trunk/fs/ufs/balloc.c @@ -424,7 +424,8 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, ufs_cpu_to_data_ptr(sb, p, result); *err = 0; UFS_I(inode)->i_lastfrag = - max(UFS_I(inode)->i_lastfrag, fragment + count); + max_t(u32, UFS_I(inode)->i_lastfrag, + fragment + count); ufs_clear_frags(inode, result + oldcount, newcount - oldcount, locked_page != NULL); } @@ -439,8 +440,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, result = ufs_add_fragments (inode, tmp, oldcount, newcount, err); if (result) { *err = 0; - UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag, - fragment + count); + UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); ufs_clear_frags(inode, result + oldcount, newcount - oldcount, locked_page != NULL); unlock_super(sb); @@ -479,8 +479,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, uspi->s_sbbase + result, locked_page); ufs_cpu_to_data_ptr(sb, p, result); *err = 0; - UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag, - fragment + count); + UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); unlock_super(sb); if (newcount < request) ufs_free_fragments (inode, result + newcount, request - newcount); diff --git a/trunk/fs/ufs/namei.c b/trunk/fs/ufs/namei.c index 953ebdfc5bf7..29309e25417f 100644 --- a/trunk/fs/ufs/namei.c +++ b/trunk/fs/ufs/namei.c @@ -258,8 +258,6 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry) struct inode * inode = dentry->d_inode; int err= -ENOTEMPTY; - dentry_unhash(dentry); - lock_ufs(dir->i_sb); if (ufs_empty_dir (inode)) { err = ufs_unlink(dir, dentry); @@ -284,9 +282,6 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry, struct ufs_dir_entry *old_de; int err = -ENOENT; - if (new_inode && S_ISDIR(new_inode->i_mode)) - dentry_unhash(new_dentry); - old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page); if (!old_de) goto out; diff --git a/trunk/fs/ufs/truncate.c b/trunk/fs/ufs/truncate.c index f04f89fbd4d9..5f821dbc0579 100644 --- a/trunk/fs/ufs/truncate.c +++ b/trunk/fs/ufs/truncate.c @@ -84,7 +84,7 @@ static int ufs_trunc_direct(struct inode *inode) retry = 0; frag1 = DIRECT_FRAGMENT; - frag4 = min_t(u64, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag); + frag4 = min_t(u32, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag); frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1); frag3 = frag4 & ~uspi->s_fpbmask; block1 = block2 = 0; diff --git a/trunk/fs/xfs/linux-2.6/xfs_discard.c b/trunk/fs/xfs/linux-2.6/xfs_discard.c index 244e797dae32..d61611c88012 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_discard.c +++ b/trunk/fs/xfs/linux-2.6/xfs_discard.c @@ -191,32 +191,3 @@ xfs_ioc_trim( return -XFS_ERROR(EFAULT); return 0; } - -int -xfs_discard_extents( - struct xfs_mount *mp, - struct list_head *list) -{ - struct xfs_busy_extent *busyp; - int error = 0; - - list_for_each_entry(busyp, list, list) { - trace_xfs_discard_extent(mp, busyp->agno, busyp->bno, - busyp->length); - - error = -blkdev_issue_discard(mp->m_ddev_targp->bt_bdev, - XFS_AGB_TO_DADDR(mp, busyp->agno, busyp->bno), - XFS_FSB_TO_BB(mp, busyp->length), - GFP_NOFS, 0); - if (error && error != EOPNOTSUPP) { - xfs_info(mp, - "discard failed for extent [0x%llu,%u], error %d", - (unsigned long long)busyp->bno, - busyp->length, - error); - return error; - } - } - - return 0; -} diff --git a/trunk/fs/xfs/linux-2.6/xfs_discard.h b/trunk/fs/xfs/linux-2.6/xfs_discard.h index 344879aea646..e82b6dd3e127 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_discard.h +++ b/trunk/fs/xfs/linux-2.6/xfs_discard.h @@ -2,9 +2,7 @@ #define XFS_DISCARD_H 1 struct fstrim_range; -struct list_head; extern int xfs_ioc_trim(struct xfs_mount *, struct fstrim_range __user *); -extern int xfs_discard_extents(struct xfs_mount *, struct list_head *); #endif /* XFS_DISCARD_H */ diff --git a/trunk/fs/xfs/linux-2.6/xfs_super.c b/trunk/fs/xfs/linux-2.6/xfs_super.c index 98b9c91fcdf1..b0aa59e51fd0 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_super.c +++ b/trunk/fs/xfs/linux-2.6/xfs_super.c @@ -110,10 +110,8 @@ mempool_t *xfs_ioend_pool; #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */ #define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */ #define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */ -#define MNTOPT_DELAYLOG "delaylog" /* Delayed logging enabled */ -#define MNTOPT_NODELAYLOG "nodelaylog" /* Delayed logging disabled */ -#define MNTOPT_DISCARD "discard" /* Discard unused blocks */ -#define MNTOPT_NODISCARD "nodiscard" /* Do not discard unused blocks */ +#define MNTOPT_DELAYLOG "delaylog" /* Delayed loging enabled */ +#define MNTOPT_NODELAYLOG "nodelaylog" /* Delayed loging disabled */ /* * Table driven mount option parser. @@ -357,10 +355,6 @@ xfs_parseargs( mp->m_flags |= XFS_MOUNT_DELAYLOG; } else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) { mp->m_flags &= ~XFS_MOUNT_DELAYLOG; - } else if (!strcmp(this_char, MNTOPT_DISCARD)) { - mp->m_flags |= XFS_MOUNT_DISCARD; - } else if (!strcmp(this_char, MNTOPT_NODISCARD)) { - mp->m_flags &= ~XFS_MOUNT_DISCARD; } else if (!strcmp(this_char, "ihashsize")) { xfs_warn(mp, "ihashsize no longer used, option is deprecated."); @@ -394,13 +388,6 @@ xfs_parseargs( return EINVAL; } - if ((mp->m_flags & XFS_MOUNT_DISCARD) && - !(mp->m_flags & XFS_MOUNT_DELAYLOG)) { - xfs_warn(mp, - "the discard option is incompatible with the nodelaylog option"); - return EINVAL; - } - #ifndef CONFIG_XFS_QUOTA if (XFS_IS_QUOTA_RUNNING(mp)) { xfs_warn(mp, "quota support not available in this kernel."); @@ -501,7 +488,6 @@ xfs_showargs( { XFS_MOUNT_FILESTREAMS, "," MNTOPT_FILESTREAM }, { XFS_MOUNT_GRPID, "," MNTOPT_GRPID }, { XFS_MOUNT_DELAYLOG, "," MNTOPT_DELAYLOG }, - { XFS_MOUNT_DISCARD, "," MNTOPT_DISCARD }, { 0, NULL } }; static struct proc_xfs_info xfs_info_unset[] = { diff --git a/trunk/fs/xfs/xfs_ag.h b/trunk/fs/xfs/xfs_ag.h index 6530769a999b..da0a561ffba2 100644 --- a/trunk/fs/xfs/xfs_ag.h +++ b/trunk/fs/xfs/xfs_ag.h @@ -187,9 +187,6 @@ struct xfs_busy_extent { xfs_agnumber_t agno; xfs_agblock_t bno; xfs_extlen_t length; - unsigned int flags; -#define XFS_ALLOC_BUSY_DISCARDED 0x01 /* undergoing a discard op. */ -#define XFS_ALLOC_BUSY_SKIP_DISCARD 0x02 /* do not discard */ }; /* diff --git a/trunk/fs/xfs/xfs_alloc.c b/trunk/fs/xfs/xfs_alloc.c index 95862bbff56b..acdced86413c 100644 --- a/trunk/fs/xfs/xfs_alloc.c +++ b/trunk/fs/xfs/xfs_alloc.c @@ -2469,7 +2469,7 @@ xfs_free_extent( error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); if (!error) - xfs_alloc_busy_insert(tp, args.agno, args.agbno, len, 0); + xfs_alloc_busy_insert(tp, args.agno, args.agbno, len); error0: xfs_perag_put(args.pag); return error; @@ -2480,8 +2480,7 @@ xfs_alloc_busy_insert( struct xfs_trans *tp, xfs_agnumber_t agno, xfs_agblock_t bno, - xfs_extlen_t len, - unsigned int flags) + xfs_extlen_t len) { struct xfs_busy_extent *new; struct xfs_busy_extent *busyp; @@ -2505,7 +2504,6 @@ xfs_alloc_busy_insert( new->bno = bno; new->length = len; INIT_LIST_HEAD(&new->list); - new->flags = flags; /* trace before insert to be able to see failed inserts */ trace_xfs_alloc_busy(tp->t_mountp, agno, bno, len); @@ -2610,18 +2608,6 @@ xfs_alloc_busy_update_extent( xfs_agblock_t bbno = busyp->bno; xfs_agblock_t bend = bbno + busyp->length; - /* - * This extent is currently being discarded. Give the thread - * performing the discard a chance to mark the extent unbusy - * and retry. - */ - if (busyp->flags & XFS_ALLOC_BUSY_DISCARDED) { - spin_unlock(&pag->pagb_lock); - delay(1); - spin_lock(&pag->pagb_lock); - return false; - } - /* * If there is a busy extent overlapping a user allocation, we have * no choice but to force the log and retry the search. @@ -2827,8 +2813,7 @@ xfs_alloc_busy_trim( * If this is a metadata allocation, try to reuse the busy * extent instead of trimming the allocation. */ - if (!args->userdata && - !(busyp->flags & XFS_ALLOC_BUSY_DISCARDED)) { + if (!args->userdata) { if (!xfs_alloc_busy_update_extent(args->mp, args->pag, busyp, fbno, flen, false)) @@ -2994,16 +2979,10 @@ xfs_alloc_busy_clear_one( kmem_free(busyp); } -/* - * Remove all extents on the passed in list from the busy extents tree. - * If do_discard is set skip extents that need to be discarded, and mark - * these as undergoing a discard operation instead. - */ void xfs_alloc_busy_clear( struct xfs_mount *mp, - struct list_head *list, - bool do_discard) + struct list_head *list) { struct xfs_busy_extent *busyp, *n; struct xfs_perag *pag = NULL; @@ -3020,11 +2999,7 @@ xfs_alloc_busy_clear( agno = busyp->agno; } - if (do_discard && busyp->length && - !(busyp->flags & XFS_ALLOC_BUSY_SKIP_DISCARD)) - busyp->flags = XFS_ALLOC_BUSY_DISCARDED; - else - xfs_alloc_busy_clear_one(mp, pag, busyp); + xfs_alloc_busy_clear_one(mp, pag, busyp); } if (pag) { diff --git a/trunk/fs/xfs/xfs_alloc.h b/trunk/fs/xfs/xfs_alloc.h index 2f52b924be79..240ad288f2f9 100644 --- a/trunk/fs/xfs/xfs_alloc.h +++ b/trunk/fs/xfs/xfs_alloc.h @@ -137,11 +137,10 @@ xfs_alloc_longest_free_extent(struct xfs_mount *mp, #ifdef __KERNEL__ void xfs_alloc_busy_insert(struct xfs_trans *tp, xfs_agnumber_t agno, - xfs_agblock_t bno, xfs_extlen_t len, unsigned int flags); + xfs_agblock_t bno, xfs_extlen_t len); void -xfs_alloc_busy_clear(struct xfs_mount *mp, struct list_head *list, - bool do_discard); +xfs_alloc_busy_clear(struct xfs_mount *mp, struct list_head *list); int xfs_alloc_busy_search(struct xfs_mount *mp, xfs_agnumber_t agno, diff --git a/trunk/fs/xfs/xfs_alloc_btree.c b/trunk/fs/xfs/xfs_alloc_btree.c index 2b3518826a69..8b469d53599f 100644 --- a/trunk/fs/xfs/xfs_alloc_btree.c +++ b/trunk/fs/xfs/xfs_alloc_btree.c @@ -120,8 +120,7 @@ xfs_allocbt_free_block( if (error) return error; - xfs_alloc_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1, - XFS_ALLOC_BUSY_SKIP_DISCARD); + xfs_alloc_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1); xfs_trans_agbtree_delta(cur->bc_tp, -1); return 0; } diff --git a/trunk/fs/xfs/xfs_bmap.c b/trunk/fs/xfs/xfs_bmap.c index e546a33214c9..fa00788de2f5 100644 --- a/trunk/fs/xfs/xfs_bmap.c +++ b/trunk/fs/xfs/xfs_bmap.c @@ -88,6 +88,22 @@ xfs_bmap_add_attrfork_local( xfs_bmap_free_t *flist, /* blocks to free at commit */ int *flags); /* inode logging flags */ +/* + * Called by xfs_bmapi to update file extent records and the btree + * after allocating space (or doing a delayed allocation). + */ +STATIC int /* error */ +xfs_bmap_add_extent( + xfs_inode_t *ip, /* incore inode pointer */ + xfs_extnum_t idx, /* extent number to update/insert */ + xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ + xfs_fsblock_t *first, /* pointer to firstblock variable */ + xfs_bmap_free_t *flist, /* list of extents to be freed */ + int *logflagsp, /* inode logging flags */ + int whichfork, /* data or attr fork */ + int rsvd); /* OK to allocate reserved blocks */ + /* * Called by xfs_bmap_add_extent to handle cases converting a delayed * allocation to a real allocation. @@ -95,13 +111,14 @@ xfs_bmap_add_attrfork_local( STATIC int /* error */ xfs_bmap_add_extent_delay_real( xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t *idx, /* extent number to update/insert */ + xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_filblks_t *dnew, /* new delayed-alloc indirect blocks */ xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ - int *logflagsp); /* inode logging flags */ + int *logflagsp, /* inode logging flags */ + int rsvd); /* OK to allocate reserved blocks */ /* * Called by xfs_bmap_add_extent to handle cases converting a hole @@ -110,9 +127,10 @@ xfs_bmap_add_extent_delay_real( STATIC int /* error */ xfs_bmap_add_extent_hole_delay( xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t *idx, /* extent number to update/insert */ + xfs_extnum_t idx, /* extent number to update/insert */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ - int *logflagsp); /* inode logging flags */ + int *logflagsp,/* inode logging flags */ + int rsvd); /* OK to allocate reserved blocks */ /* * Called by xfs_bmap_add_extent to handle cases converting a hole @@ -121,7 +139,7 @@ xfs_bmap_add_extent_hole_delay( STATIC int /* error */ xfs_bmap_add_extent_hole_real( xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t *idx, /* extent number to update/insert */ + xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ @@ -134,7 +152,7 @@ xfs_bmap_add_extent_hole_real( STATIC int /* error */ xfs_bmap_add_extent_unwritten_real( xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t *idx, /* extent number to update/insert */ + xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp); /* inode logging flags */ @@ -161,6 +179,22 @@ xfs_bmap_btree_to_extents( int *logflagsp, /* inode logging flags */ int whichfork); /* data or attr fork */ +/* + * Called by xfs_bmapi to update file extent records and the btree + * after removing space (or undoing a delayed allocation). + */ +STATIC int /* error */ +xfs_bmap_del_extent( + xfs_inode_t *ip, /* incore inode pointer */ + xfs_trans_t *tp, /* current trans pointer */ + xfs_extnum_t idx, /* extent number to update/insert */ + xfs_bmap_free_t *flist, /* list of extents to be freed */ + xfs_btree_cur_t *cur, /* if null, not a btree */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ + int *logflagsp,/* inode logging flags */ + int whichfork, /* data or attr fork */ + int rsvd); /* OK to allocate reserved blocks */ + /* * Remove the entry "free" from the free item list. Prev points to the * previous entry, unless "free" is the head of the list. @@ -440,13 +474,14 @@ xfs_bmap_add_attrfork_local( STATIC int /* error */ xfs_bmap_add_extent( xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t *idx, /* extent number to update/insert */ + xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ int *logflagsp, /* inode logging flags */ - int whichfork) /* data or attr fork */ + int whichfork, /* data or attr fork */ + int rsvd) /* OK to use reserved data blocks */ { xfs_btree_cur_t *cur; /* btree cursor or null */ xfs_filblks_t da_new; /* new count del alloc blocks used */ @@ -457,27 +492,23 @@ xfs_bmap_add_extent( xfs_extnum_t nextents; /* number of extents in file now */ XFS_STATS_INC(xs_add_exlist); - cur = *curp; ifp = XFS_IFORK_PTR(ip, whichfork); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); + ASSERT(idx <= nextents); da_old = da_new = 0; error = 0; - - ASSERT(*idx >= 0); - ASSERT(*idx <= nextents); - /* * This is the first extent added to a new/empty file. * Special case this one, so other routines get to assume there are * already extents in the list. */ if (nextents == 0) { - xfs_iext_insert(ip, *idx, 1, new, + xfs_iext_insert(ip, 0, 1, new, whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0); ASSERT(cur == NULL); - + ifp->if_lastex = 0; if (!isnullstartblock(new->br_startblock)) { XFS_IFORK_NEXT_SET(ip, whichfork, 1); logflags = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); @@ -491,25 +522,27 @@ xfs_bmap_add_extent( if (cur) ASSERT((cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL) == 0); - error = xfs_bmap_add_extent_hole_delay(ip, idx, new, - &logflags); + if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, new, + &logflags, rsvd))) + goto done; } /* * Real allocation off the end of the file. */ - else if (*idx == nextents) { + else if (idx == nextents) { if (cur) ASSERT((cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL) == 0); - error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new, - &logflags, whichfork); + if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new, + &logflags, whichfork))) + goto done; } else { xfs_bmbt_irec_t prev; /* old extent at offset idx */ /* * Get the record referred to by idx. */ - xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &prev); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &prev); /* * If it's a real allocation record, and the new allocation ends * after the start of the referred to record, then we're filling @@ -524,18 +557,22 @@ xfs_bmap_add_extent( if (cur) ASSERT(cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL); - error = xfs_bmap_add_extent_delay_real(ip, - idx, &cur, new, &da_new, - first, flist, &logflags); + if ((error = xfs_bmap_add_extent_delay_real(ip, + idx, &cur, new, &da_new, first, flist, + &logflags, rsvd))) + goto done; + } else if (new->br_state == XFS_EXT_NORM) { + ASSERT(new->br_state == XFS_EXT_NORM); + if ((error = xfs_bmap_add_extent_unwritten_real( + ip, idx, &cur, new, &logflags))) + goto done; } else { - ASSERT(new->br_state == XFS_EXT_NORM || - new->br_state == XFS_EXT_UNWRITTEN); - - error = xfs_bmap_add_extent_unwritten_real(ip, - idx, &cur, new, &logflags); - if (error) + ASSERT(new->br_state == XFS_EXT_UNWRITTEN); + if ((error = xfs_bmap_add_extent_unwritten_real( + ip, idx, &cur, new, &logflags))) goto done; } + ASSERT(*curp == cur || *curp == NULL); } /* * Otherwise we're filling in a hole with an allocation. @@ -544,15 +581,13 @@ xfs_bmap_add_extent( if (cur) ASSERT((cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL) == 0); - error = xfs_bmap_add_extent_hole_real(ip, idx, cur, - new, &logflags, whichfork); + if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, + new, &logflags, whichfork))) + goto done; } } - if (error) - goto done; ASSERT(*curp == cur || *curp == NULL); - /* * Convert to a btree if necessary. */ @@ -580,7 +615,7 @@ xfs_bmap_add_extent( ASSERT(nblks <= da_old); if (nblks < da_old) xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, - (int64_t)(da_old - nblks), 0); + (int64_t)(da_old - nblks), rsvd); } /* * Clear out the allocated field, done with it now in any case. @@ -605,13 +640,14 @@ xfs_bmap_add_extent( STATIC int /* error */ xfs_bmap_add_extent_delay_real( xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t *idx, /* extent number to update/insert */ + xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_filblks_t *dnew, /* new delayed-alloc indirect blocks */ xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ - int *logflagsp) /* inode logging flags */ + int *logflagsp, /* inode logging flags */ + int rsvd) /* OK to use reserved data block allocation */ { xfs_btree_cur_t *cur; /* btree cursor */ int diff; /* temp value */ @@ -637,7 +673,7 @@ xfs_bmap_add_extent_delay_real( */ cur = *curp; ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); - ep = xfs_iext_get_ext(ifp, *idx); + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_get_all(ep, &PREV); new_endoff = new->br_startoff + new->br_blockcount; ASSERT(PREV.br_startoff <= new->br_startoff); @@ -656,9 +692,9 @@ xfs_bmap_add_extent_delay_real( * Check and set flags if this segment has a left neighbor. * Don't set contiguous if the combined extent would be too large. */ - if (*idx > 0) { + if (idx > 0) { state |= BMAP_LEFT_VALID; - xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &LEFT); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT); if (isnullstartblock(LEFT.br_startblock)) state |= BMAP_LEFT_DELAY; @@ -676,9 +712,9 @@ xfs_bmap_add_extent_delay_real( * Don't set contiguous if the combined extent would be too large. * Also check for all-three-contiguous being too large. */ - if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) { + if (idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) { state |= BMAP_RIGHT_VALID; - xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx + 1), &RIGHT); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT); if (isnullstartblock(RIGHT.br_startblock)) state |= BMAP_RIGHT_DELAY; @@ -709,14 +745,14 @@ xfs_bmap_add_extent_delay_real( * Filling in all of a previously delayed allocation extent. * The left and right neighbors are both contiguous with new. */ - --*idx; - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); - xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), + trace_xfs_bmap_pre_update(ip, idx - 1, state, _THIS_IP_); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); - xfs_iext_remove(ip, *idx + 1, 2, state); + xfs_iext_remove(ip, idx, 2, state); + ip->i_df.if_lastex = idx - 1; ip->i_d.di_nextents--; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -748,14 +784,13 @@ xfs_bmap_add_extent_delay_real( * Filling in all of a previously delayed allocation extent. * The left neighbor is contiguous, the right is not. */ - --*idx; - - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); - xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), + trace_xfs_bmap_pre_update(ip, idx - 1, state, _THIS_IP_); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + PREV.br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); - xfs_iext_remove(ip, *idx + 1, 1, state); + ip->i_df.if_lastex = idx - 1; + xfs_iext_remove(ip, idx, 1, state); if (cur == NULL) rval = XFS_ILOG_DEXT; else { @@ -779,13 +814,14 @@ xfs_bmap_add_extent_delay_real( * Filling in all of a previously delayed allocation extent. * The right neighbor is contiguous, the left is not. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_startblock(ep, new->br_startblock); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount + RIGHT.br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); - xfs_iext_remove(ip, *idx + 1, 1, state); + ip->i_df.if_lastex = idx; + xfs_iext_remove(ip, idx + 1, 1, state); if (cur == NULL) rval = XFS_ILOG_DEXT; else { @@ -801,7 +837,6 @@ xfs_bmap_add_extent_delay_real( RIGHT.br_blockcount, PREV.br_state))) goto done; } - *dnew = 0; break; @@ -811,10 +846,11 @@ xfs_bmap_add_extent_delay_real( * Neither the left nor right neighbors are contiguous with * the new one. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_startblock(ep, new->br_startblock); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); + ip->i_df.if_lastex = idx; ip->i_d.di_nextents++; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -830,7 +866,6 @@ xfs_bmap_add_extent_delay_real( goto done; XFS_WANT_CORRUPTED_GOTO(i == 1, done); } - *dnew = 0; break; @@ -839,16 +874,17 @@ xfs_bmap_add_extent_delay_real( * Filling in the first part of a previous delayed allocation. * The left neighbor is contiguous. */ - trace_xfs_bmap_pre_update(ip, *idx - 1, state, _THIS_IP_); - xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx - 1), + trace_xfs_bmap_pre_update(ip, idx - 1, state, _THIS_IP_); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + new->br_blockcount); xfs_bmbt_set_startoff(ep, PREV.br_startoff + new->br_blockcount); - trace_xfs_bmap_post_update(ip, *idx - 1, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); temp = PREV.br_blockcount - new->br_blockcount; - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); + ip->i_df.if_lastex = idx - 1; if (cur == NULL) rval = XFS_ILOG_DEXT; else { @@ -868,9 +904,7 @@ xfs_bmap_add_extent_delay_real( temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), startblockval(PREV.br_startblock)); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); - - --*idx; + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); *dnew = temp; break; @@ -879,11 +913,12 @@ xfs_bmap_add_extent_delay_real( * Filling in the first part of a previous delayed allocation. * The left neighbor is not contiguous. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_startoff(ep, new_endoff); temp = PREV.br_blockcount - new->br_blockcount; xfs_bmbt_set_blockcount(ep, temp); - xfs_iext_insert(ip, *idx, 1, new, state); + xfs_iext_insert(ip, idx, 1, new, state); + ip->i_df.if_lastex = idx; ip->i_d.di_nextents++; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -911,10 +946,9 @@ xfs_bmap_add_extent_delay_real( temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), startblockval(PREV.br_startblock) - (cur ? cur->bc_private.b.allocated : 0)); - ep = xfs_iext_get_ext(ifp, *idx + 1); + ep = xfs_iext_get_ext(ifp, idx + 1); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); - trace_xfs_bmap_post_update(ip, *idx + 1, state, _THIS_IP_); - + trace_xfs_bmap_post_update(ip, idx + 1, state, _THIS_IP_); *dnew = temp; break; @@ -924,13 +958,15 @@ xfs_bmap_add_extent_delay_real( * The right neighbor is contiguous with the new allocation. */ temp = PREV.br_blockcount - new->br_blockcount; - trace_xfs_bmap_pre_update(ip, *idx + 1, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx + 1, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); - xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx + 1), + xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1), new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, RIGHT.br_state); - trace_xfs_bmap_post_update(ip, *idx + 1, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx + 1, state, _THIS_IP_); + ip->i_df.if_lastex = idx + 1; if (cur == NULL) rval = XFS_ILOG_DEXT; else { @@ -947,14 +983,10 @@ xfs_bmap_add_extent_delay_real( RIGHT.br_state))) goto done; } - temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), startblockval(PREV.br_startblock)); - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); - - ++*idx; + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); *dnew = temp; break; @@ -964,9 +996,10 @@ xfs_bmap_add_extent_delay_real( * The right neighbor is not contiguous. */ temp = PREV.br_blockcount - new->br_blockcount; - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); - xfs_iext_insert(ip, *idx + 1, 1, new, state); + xfs_iext_insert(ip, idx + 1, 1, new, state); + ip->i_df.if_lastex = idx + 1; ip->i_d.di_nextents++; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -994,11 +1027,9 @@ xfs_bmap_add_extent_delay_real( temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), startblockval(PREV.br_startblock) - (cur ? cur->bc_private.b.allocated : 0)); - ep = xfs_iext_get_ext(ifp, *idx); + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); - - ++*idx; + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); *dnew = temp; break; @@ -1025,7 +1056,7 @@ xfs_bmap_add_extent_delay_real( */ temp = new->br_startoff - PREV.br_startoff; temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; - trace_xfs_bmap_pre_update(ip, *idx, 0, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, 0, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); /* truncate PREV */ LEFT = *new; RIGHT.br_state = PREV.br_state; @@ -1034,7 +1065,8 @@ xfs_bmap_add_extent_delay_real( RIGHT.br_startoff = new_endoff; RIGHT.br_blockcount = temp2; /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ - xfs_iext_insert(ip, *idx + 1, 2, &LEFT, state); + xfs_iext_insert(ip, idx + 1, 2, &LEFT, state); + ip->i_df.if_lastex = idx + 1; ip->i_d.di_nextents++; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1065,7 +1097,7 @@ xfs_bmap_add_extent_delay_real( (cur ? cur->bc_private.b.allocated : 0)); if (diff > 0 && xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, - -((int64_t)diff), 0)) { + -((int64_t)diff), rsvd)) { /* * Ick gross gag me with a spoon. */ @@ -1077,7 +1109,7 @@ xfs_bmap_add_extent_delay_real( if (!diff || !xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, - -((int64_t)diff), 0)) + -((int64_t)diff), rsvd)) break; } if (temp2) { @@ -1086,20 +1118,18 @@ xfs_bmap_add_extent_delay_real( if (!diff || !xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, - -((int64_t)diff), 0)) + -((int64_t)diff), rsvd)) break; } } } - ep = xfs_iext_get_ext(ifp, *idx); + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); - trace_xfs_bmap_pre_update(ip, *idx + 2, state, _THIS_IP_); - xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx + 2), + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx + 2, state, _THIS_IP_); + xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx + 2), nullstartblock((int)temp2)); - trace_xfs_bmap_post_update(ip, *idx + 2, state, _THIS_IP_); - - ++*idx; + trace_xfs_bmap_post_update(ip, idx + 2, state, _THIS_IP_); *dnew = temp + temp2; break; @@ -1131,7 +1161,7 @@ xfs_bmap_add_extent_delay_real( STATIC int /* error */ xfs_bmap_add_extent_unwritten_real( xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t *idx, /* extent number to update/insert */ + xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp) /* inode logging flags */ @@ -1158,7 +1188,7 @@ xfs_bmap_add_extent_unwritten_real( error = 0; cur = *curp; ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); - ep = xfs_iext_get_ext(ifp, *idx); + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_get_all(ep, &PREV); newext = new->br_state; oldext = (newext == XFS_EXT_UNWRITTEN) ? @@ -1181,9 +1211,9 @@ xfs_bmap_add_extent_unwritten_real( * Check and set flags if this segment has a left neighbor. * Don't set contiguous if the combined extent would be too large. */ - if (*idx > 0) { + if (idx > 0) { state |= BMAP_LEFT_VALID; - xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &LEFT); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT); if (isnullstartblock(LEFT.br_startblock)) state |= BMAP_LEFT_DELAY; @@ -1201,9 +1231,9 @@ xfs_bmap_add_extent_unwritten_real( * Don't set contiguous if the combined extent would be too large. * Also check for all-three-contiguous being too large. */ - if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) { + if (idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) { state |= BMAP_RIGHT_VALID; - xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx + 1), &RIGHT); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT); if (isnullstartblock(RIGHT.br_startblock)) state |= BMAP_RIGHT_DELAY; } @@ -1232,15 +1262,14 @@ xfs_bmap_add_extent_unwritten_real( * Setting all of a previous oldext extent to newext. * The left and right neighbors are both contiguous with new. */ - --*idx; - - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); - xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), + trace_xfs_bmap_pre_update(ip, idx - 1, state, _THIS_IP_); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); - xfs_iext_remove(ip, *idx + 1, 2, state); + xfs_iext_remove(ip, idx, 2, state); + ip->i_df.if_lastex = idx - 1; ip->i_d.di_nextents -= 2; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1276,14 +1305,13 @@ xfs_bmap_add_extent_unwritten_real( * Setting all of a previous oldext extent to newext. * The left neighbor is contiguous, the right is not. */ - --*idx; - - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); - xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), + trace_xfs_bmap_pre_update(ip, idx - 1, state, _THIS_IP_); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + PREV.br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); - xfs_iext_remove(ip, *idx + 1, 1, state); + ip->i_df.if_lastex = idx - 1; + xfs_iext_remove(ip, idx, 1, state); ip->i_d.di_nextents--; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1313,12 +1341,13 @@ xfs_bmap_add_extent_unwritten_real( * Setting all of a previous oldext extent to newext. * The right neighbor is contiguous, the left is not. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount + RIGHT.br_blockcount); xfs_bmbt_set_state(ep, newext); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); - xfs_iext_remove(ip, *idx + 1, 1, state); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); + ip->i_df.if_lastex = idx; + xfs_iext_remove(ip, idx + 1, 1, state); ip->i_d.di_nextents--; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1349,10 +1378,11 @@ xfs_bmap_add_extent_unwritten_real( * Neither the left nor right neighbors are contiguous with * the new one. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_state(ep, newext); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); + ip->i_df.if_lastex = idx; if (cur == NULL) rval = XFS_ILOG_DEXT; else { @@ -1374,22 +1404,21 @@ xfs_bmap_add_extent_unwritten_real( * Setting the first part of a previous oldext extent to newext. * The left neighbor is contiguous. */ - trace_xfs_bmap_pre_update(ip, *idx - 1, state, _THIS_IP_); - xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx - 1), + trace_xfs_bmap_pre_update(ip, idx - 1, state, _THIS_IP_); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + new->br_blockcount); xfs_bmbt_set_startoff(ep, PREV.br_startoff + new->br_blockcount); - trace_xfs_bmap_post_update(ip, *idx - 1, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_startblock(ep, new->br_startblock + new->br_blockcount); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); - - --*idx; + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); + ip->i_df.if_lastex = idx - 1; if (cur == NULL) rval = XFS_ILOG_DEXT; else { @@ -1420,16 +1449,17 @@ xfs_bmap_add_extent_unwritten_real( * Setting the first part of a previous oldext extent to newext. * The left neighbor is not contiguous. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); ASSERT(ep && xfs_bmbt_get_state(ep) == oldext); xfs_bmbt_set_startoff(ep, new_endoff); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); xfs_bmbt_set_startblock(ep, new->br_startblock + new->br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); - xfs_iext_insert(ip, *idx, 1, new, state); + xfs_iext_insert(ip, idx, 1, new, state); + ip->i_df.if_lastex = idx; ip->i_d.di_nextents++; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1458,19 +1488,17 @@ xfs_bmap_add_extent_unwritten_real( * Setting the last part of a previous oldext extent to newext. * The right neighbor is contiguous with the new allocation. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx + 1, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); - - ++*idx; - - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); - xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx), + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); + xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1), new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, newext); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx + 1, state, _THIS_IP_); + ip->i_df.if_lastex = idx + 1; if (cur == NULL) rval = XFS_ILOG_DEXT; else { @@ -1500,14 +1528,13 @@ xfs_bmap_add_extent_unwritten_real( * Setting the last part of a previous oldext extent to newext. * The right neighbor is not contiguous. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); - - ++*idx; - xfs_iext_insert(ip, *idx, 1, new, state); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); + xfs_iext_insert(ip, idx + 1, 1, new, state); + ip->i_df.if_lastex = idx + 1; ip->i_d.di_nextents++; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1541,10 +1568,10 @@ xfs_bmap_add_extent_unwritten_real( * newext. Contiguity is impossible here. * One extent becomes three extents. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, new->br_startoff - PREV.br_startoff); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); r[0] = *new; r[1].br_startoff = new_endoff; @@ -1552,10 +1579,8 @@ xfs_bmap_add_extent_unwritten_real( PREV.br_startoff + PREV.br_blockcount - new_endoff; r[1].br_startblock = new->br_startblock + new->br_blockcount; r[1].br_state = oldext; - - ++*idx; - xfs_iext_insert(ip, *idx, 2, &r[0], state); - + xfs_iext_insert(ip, idx + 1, 2, &r[0], state); + ip->i_df.if_lastex = idx + 1; ip->i_d.di_nextents += 2; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1625,10 +1650,12 @@ xfs_bmap_add_extent_unwritten_real( STATIC int /* error */ xfs_bmap_add_extent_hole_delay( xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t *idx, /* extent number to update/insert */ + xfs_extnum_t idx, /* extent number to update/insert */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ - int *logflagsp) /* inode logging flags */ + int *logflagsp, /* inode logging flags */ + int rsvd) /* OK to allocate reserved blocks */ { + xfs_bmbt_rec_host_t *ep; /* extent record for idx */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_bmbt_irec_t left; /* left neighbor extent entry */ xfs_filblks_t newlen=0; /* new indirect size */ @@ -1638,15 +1665,16 @@ xfs_bmap_add_extent_hole_delay( xfs_filblks_t temp=0; /* temp for indirect calculations */ ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + ep = xfs_iext_get_ext(ifp, idx); state = 0; ASSERT(isnullstartblock(new->br_startblock)); /* * Check and set flags if this segment has a left neighbor */ - if (*idx > 0) { + if (idx > 0) { state |= BMAP_LEFT_VALID; - xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &left); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left); if (isnullstartblock(left.br_startblock)) state |= BMAP_LEFT_DELAY; @@ -1656,9 +1684,9 @@ xfs_bmap_add_extent_hole_delay( * Check and set flags if the current (right) segment exists. * If it doesn't exist, we're converting the hole at end-of-file. */ - if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { + if (idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { state |= BMAP_RIGHT_VALID; - xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &right); + xfs_bmbt_get_all(ep, &right); if (isnullstartblock(right.br_startblock)) state |= BMAP_RIGHT_DELAY; @@ -1691,21 +1719,21 @@ xfs_bmap_add_extent_hole_delay( * on the left and on the right. * Merge all three into a single extent record. */ - --*idx; temp = left.br_blockcount + new->br_blockcount + right.br_blockcount; - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); - xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), temp); + trace_xfs_bmap_pre_update(ip, idx - 1, state, _THIS_IP_); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp); oldlen = startblockval(left.br_startblock) + startblockval(new->br_startblock) + startblockval(right.br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); - xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx), + xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1), nullstartblock((int)newlen)); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); - xfs_iext_remove(ip, *idx + 1, 1, state); + xfs_iext_remove(ip, idx, 1, state); + ip->i_df.if_lastex = idx - 1; break; case BMAP_LEFT_CONTIG: @@ -1714,17 +1742,17 @@ xfs_bmap_add_extent_hole_delay( * on the left. * Merge the new allocation with the left neighbor. */ - --*idx; temp = left.br_blockcount + new->br_blockcount; - - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); - xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), temp); + trace_xfs_bmap_pre_update(ip, idx - 1, state, _THIS_IP_); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp); oldlen = startblockval(left.br_startblock) + startblockval(new->br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); - xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx), + xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1), nullstartblock((int)newlen)); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); + + ip->i_df.if_lastex = idx - 1; break; case BMAP_RIGHT_CONTIG: @@ -1733,15 +1761,16 @@ xfs_bmap_add_extent_hole_delay( * on the right. * Merge the new allocation with the right neighbor. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); temp = new->br_blockcount + right.br_blockcount; oldlen = startblockval(new->br_startblock) + startblockval(right.br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); - xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx), - new->br_startoff, + xfs_bmbt_set_allf(ep, new->br_startoff, nullstartblock((int)newlen), temp, right.br_state); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); + + ip->i_df.if_lastex = idx; break; case 0: @@ -1751,13 +1780,14 @@ xfs_bmap_add_extent_hole_delay( * Insert a new entry. */ oldlen = newlen = 0; - xfs_iext_insert(ip, *idx, 1, new, state); + xfs_iext_insert(ip, idx, 1, new, state); + ip->i_df.if_lastex = idx; break; } if (oldlen != newlen) { ASSERT(oldlen > newlen); xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, - (int64_t)(oldlen - newlen), 0); + (int64_t)(oldlen - newlen), rsvd); /* * Nothing to do for disk quota accounting here. */ @@ -1773,12 +1803,13 @@ xfs_bmap_add_extent_hole_delay( STATIC int /* error */ xfs_bmap_add_extent_hole_real( xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t *idx, /* extent number to update/insert */ + xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ int whichfork) /* data or attr fork */ { + xfs_bmbt_rec_host_t *ep; /* pointer to extent entry ins. point */ int error; /* error return value */ int i; /* temp state */ xfs_ifork_t *ifp; /* inode fork pointer */ @@ -1788,7 +1819,8 @@ xfs_bmap_add_extent_hole_real( int state; /* state bits, accessed thru macros */ ifp = XFS_IFORK_PTR(ip, whichfork); - ASSERT(*idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); + ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); + ep = xfs_iext_get_ext(ifp, idx); state = 0; if (whichfork == XFS_ATTR_FORK) @@ -1797,9 +1829,9 @@ xfs_bmap_add_extent_hole_real( /* * Check and set flags if this segment has a left neighbor. */ - if (*idx > 0) { + if (idx > 0) { state |= BMAP_LEFT_VALID; - xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &left); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left); if (isnullstartblock(left.br_startblock)) state |= BMAP_LEFT_DELAY; } @@ -1808,9 +1840,9 @@ xfs_bmap_add_extent_hole_real( * Check and set flags if this segment has a current value. * Not true if we're inserting into the "hole" at eof. */ - if (*idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { + if (idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { state |= BMAP_RIGHT_VALID; - xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &right); + xfs_bmbt_get_all(ep, &right); if (isnullstartblock(right.br_startblock)) state |= BMAP_RIGHT_DELAY; } @@ -1847,15 +1879,14 @@ xfs_bmap_add_extent_hole_real( * left and on the right. * Merge all three into a single extent record. */ - --*idx; - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); - xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), + trace_xfs_bmap_pre_update(ip, idx - 1, state, _THIS_IP_); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), left.br_blockcount + new->br_blockcount + right.br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); - - xfs_iext_remove(ip, *idx + 1, 1, state); + trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); + xfs_iext_remove(ip, idx, 1, state); + ifp->if_lastex = idx - 1; XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) - 1); if (cur == NULL) { @@ -1890,12 +1921,12 @@ xfs_bmap_add_extent_hole_real( * on the left. * Merge the new allocation with the left neighbor. */ - --*idx; - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); - xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), + trace_xfs_bmap_pre_update(ip, idx - 1, state, _THIS_IP_); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), left.br_blockcount + new->br_blockcount); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); + ifp->if_lastex = idx - 1; if (cur == NULL) { rval = xfs_ilog_fext(whichfork); } else { @@ -1921,13 +1952,13 @@ xfs_bmap_add_extent_hole_real( * on the right. * Merge the new allocation with the right neighbor. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); - xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx), - new->br_startoff, new->br_startblock, + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); + xfs_bmbt_set_allf(ep, new->br_startoff, new->br_startblock, new->br_blockcount + right.br_blockcount, right.br_state); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); + ifp->if_lastex = idx; if (cur == NULL) { rval = xfs_ilog_fext(whichfork); } else { @@ -1953,7 +1984,8 @@ xfs_bmap_add_extent_hole_real( * real allocation. * Insert a new entry. */ - xfs_iext_insert(ip, *idx, 1, new, state); + xfs_iext_insert(ip, idx, 1, new, state); + ifp->if_lastex = idx; XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); if (cur == NULL) { @@ -2801,12 +2833,13 @@ STATIC int /* error */ xfs_bmap_del_extent( xfs_inode_t *ip, /* incore inode pointer */ xfs_trans_t *tp, /* current transaction pointer */ - xfs_extnum_t *idx, /* extent number to update/delete */ + xfs_extnum_t idx, /* extent number to update/delete */ xfs_bmap_free_t *flist, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *del, /* data to remove from extents */ int *logflagsp, /* inode logging flags */ - int whichfork) /* data or attr fork */ + int whichfork, /* data or attr fork */ + int rsvd) /* OK to allocate reserved blocks */ { xfs_filblks_t da_new; /* new delay-alloc indirect blocks */ xfs_filblks_t da_old; /* old delay-alloc indirect blocks */ @@ -2837,10 +2870,10 @@ xfs_bmap_del_extent( mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); - ASSERT((*idx >= 0) && (*idx < ifp->if_bytes / + ASSERT((idx >= 0) && (idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))); ASSERT(del->br_blockcount > 0); - ep = xfs_iext_get_ext(ifp, *idx); + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_get_all(ep, &got); ASSERT(got.br_startoff <= del->br_startoff); del_endoff = del->br_startoff + del->br_blockcount; @@ -2914,12 +2947,11 @@ xfs_bmap_del_extent( /* * Matches the whole extent. Delete the entry. */ - xfs_iext_remove(ip, *idx, 1, + xfs_iext_remove(ip, idx, 1, whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0); - --*idx; + ifp->if_lastex = idx; if (delay) break; - XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) - 1); flags |= XFS_ILOG_CORE; @@ -2936,20 +2968,21 @@ xfs_bmap_del_extent( /* * Deleting the first part of the extent. */ - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_startoff(ep, del_endoff); temp = got.br_blockcount - del->br_blockcount; xfs_bmbt_set_blockcount(ep, temp); + ifp->if_lastex = idx; if (delay) { temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), da_old); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); da_new = temp; break; } xfs_bmbt_set_startblock(ep, del_endblock); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); if (!cur) { flags |= xfs_ilog_fext(whichfork); break; @@ -2965,17 +2998,18 @@ xfs_bmap_del_extent( * Deleting the last part of the extent. */ temp = got.br_blockcount - del->br_blockcount; - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); + ifp->if_lastex = idx; if (delay) { temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), da_old); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); da_new = temp; break; } - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); if (!cur) { flags |= xfs_ilog_fext(whichfork); break; @@ -2992,7 +3026,7 @@ xfs_bmap_del_extent( * Deleting the middle of the extent. */ temp = del->br_startoff - got.br_startoff; - trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); + trace_xfs_bmap_pre_update(ip, idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); new.br_startoff = del_endoff; temp2 = got_endoff - del_endoff; @@ -3079,9 +3113,9 @@ xfs_bmap_del_extent( } } } - trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); - xfs_iext_insert(ip, *idx + 1, 1, &new, state); - ++*idx; + trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); + xfs_iext_insert(ip, idx + 1, 1, &new, state); + ifp->if_lastex = idx + 1; break; } /* @@ -3108,7 +3142,7 @@ xfs_bmap_del_extent( ASSERT(da_old >= da_new); if (da_old > da_new) { xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, - (int64_t)(da_old - da_new), 0); + (int64_t)(da_old - da_new), rsvd); } done: *logflagsp = flags; @@ -4528,24 +4562,29 @@ xfs_bmapi( if (rt) { error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, - -((int64_t)extsz), 0); + -((int64_t)extsz), (flags & + XFS_BMAPI_RSVBLOCKS)); } else { error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, - -((int64_t)alen), 0); + -((int64_t)alen), (flags & + XFS_BMAPI_RSVBLOCKS)); } if (!error) { error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, - -((int64_t)indlen), 0); + -((int64_t)indlen), (flags & + XFS_BMAPI_RSVBLOCKS)); if (error && rt) xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, - (int64_t)extsz, 0); + (int64_t)extsz, (flags & + XFS_BMAPI_RSVBLOCKS)); else if (error) xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, - (int64_t)alen, 0); + (int64_t)alen, (flags & + XFS_BMAPI_RSVBLOCKS)); } if (error) { @@ -4662,12 +4701,13 @@ xfs_bmapi( if (!wasdelay && (flags & XFS_BMAPI_PREALLOC)) got.br_state = XFS_EXT_UNWRITTEN; } - error = xfs_bmap_add_extent(ip, &lastx, &cur, &got, + error = xfs_bmap_add_extent(ip, lastx, &cur, &got, firstblock, flist, &tmp_logflags, - whichfork); + whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); logflags |= tmp_logflags; if (error) goto error0; + lastx = ifp->if_lastex; ep = xfs_iext_get_ext(ifp, lastx); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); xfs_bmbt_get_all(ep, &got); @@ -4763,12 +4803,13 @@ xfs_bmapi( mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN) ? XFS_EXT_NORM : XFS_EXT_UNWRITTEN; - error = xfs_bmap_add_extent(ip, &lastx, &cur, mval, + error = xfs_bmap_add_extent(ip, lastx, &cur, mval, firstblock, flist, &tmp_logflags, - whichfork); + whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); logflags |= tmp_logflags; if (error) goto error0; + lastx = ifp->if_lastex; ep = xfs_iext_get_ext(ifp, lastx); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); xfs_bmbt_get_all(ep, &got); @@ -4827,14 +4868,14 @@ xfs_bmapi( /* * Else go on to the next record. */ + ep = xfs_iext_get_ext(ifp, ++lastx); prev = got; - if (++lastx < nextents) { - ep = xfs_iext_get_ext(ifp, lastx); - xfs_bmbt_get_all(ep, &got); - } else { + if (lastx >= nextents) eof = 1; - } + else + xfs_bmbt_get_all(ep, &got); } + ifp->if_lastex = lastx; *nmap = n; /* * Transform from btree to extents, give it cur. @@ -4943,6 +4984,7 @@ xfs_bmapi_single( ASSERT(!isnullstartblock(got.br_startblock)); ASSERT(bno < got.br_startoff + got.br_blockcount); *fsb = got.br_startblock + (bno - got.br_startoff); + ifp->if_lastex = lastx; return 0; } @@ -4984,6 +5026,7 @@ xfs_bunmapi( int tmp_logflags; /* partial logging flags */ int wasdel; /* was a delayed alloc extent */ int whichfork; /* data or attribute fork */ + int rsvd; /* OK to allocate reserved blocks */ xfs_fsblock_t sum; trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_); @@ -5001,7 +5044,7 @@ xfs_bunmapi( mp = ip->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); - + rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0; ASSERT(len > 0); ASSERT(nexts >= 0); ASSERT(ifp->if_ext_max == @@ -5117,9 +5160,9 @@ xfs_bunmapi( del.br_blockcount = mod; } del.br_state = XFS_EXT_UNWRITTEN; - error = xfs_bmap_add_extent(ip, &lastx, &cur, &del, + error = xfs_bmap_add_extent(ip, lastx, &cur, &del, firstblock, flist, &logflags, - XFS_DATA_FORK); + XFS_DATA_FORK, 0); if (error) goto error0; goto nodelete; @@ -5145,12 +5188,9 @@ xfs_bunmapi( */ ASSERT(bno >= del.br_blockcount); bno -= del.br_blockcount; - if (got.br_startoff > bno) { - if (--lastx >= 0) { - ep = xfs_iext_get_ext(ifp, - lastx); - xfs_bmbt_get_all(ep, &got); - } + if (bno < got.br_startoff) { + if (--lastx >= 0) + xfs_bmbt_get_all(--ep, &got); } continue; } else if (del.br_state == XFS_EXT_UNWRITTEN) { @@ -5174,19 +5214,18 @@ xfs_bunmapi( prev.br_startoff = start; } prev.br_state = XFS_EXT_UNWRITTEN; - lastx--; - error = xfs_bmap_add_extent(ip, &lastx, &cur, + error = xfs_bmap_add_extent(ip, lastx - 1, &cur, &prev, firstblock, flist, &logflags, - XFS_DATA_FORK); + XFS_DATA_FORK, 0); if (error) goto error0; goto nodelete; } else { ASSERT(del.br_state == XFS_EXT_NORM); del.br_state = XFS_EXT_UNWRITTEN; - error = xfs_bmap_add_extent(ip, &lastx, &cur, + error = xfs_bmap_add_extent(ip, lastx, &cur, &del, firstblock, flist, &logflags, - XFS_DATA_FORK); + XFS_DATA_FORK, 0); if (error) goto error0; goto nodelete; @@ -5201,13 +5240,13 @@ xfs_bunmapi( rtexts = XFS_FSB_TO_B(mp, del.br_blockcount); do_div(rtexts, mp->m_sb.sb_rextsize); xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, - (int64_t)rtexts, 0); + (int64_t)rtexts, rsvd); (void)xfs_trans_reserve_quota_nblks(NULL, ip, -((long)del.br_blockcount), 0, XFS_QMOPT_RES_RTBLKS); } else { xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, - (int64_t)del.br_blockcount, 0); + (int64_t)del.br_blockcount, rsvd); (void)xfs_trans_reserve_quota_nblks(NULL, ip, -((long)del.br_blockcount), 0, XFS_QMOPT_RES_REGBLKS); @@ -5238,29 +5277,31 @@ xfs_bunmapi( error = XFS_ERROR(ENOSPC); goto error0; } - error = xfs_bmap_del_extent(ip, tp, &lastx, flist, cur, &del, - &tmp_logflags, whichfork); + error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del, + &tmp_logflags, whichfork, rsvd); logflags |= tmp_logflags; if (error) goto error0; bno = del.br_startoff - 1; nodelete: + lastx = ifp->if_lastex; /* * If not done go on to the next (previous) record. + * Reset ep in case the extents array was re-alloced. */ + ep = xfs_iext_get_ext(ifp, lastx); if (bno != (xfs_fileoff_t)-1 && bno >= start) { - if (lastx >= 0) { - ep = xfs_iext_get_ext(ifp, lastx); - if (xfs_bmbt_get_startoff(ep) > bno) { - if (--lastx >= 0) - ep = xfs_iext_get_ext(ifp, - lastx); - } - xfs_bmbt_get_all(ep, &got); + if (lastx >= XFS_IFORK_NEXTENTS(ip, whichfork) || + xfs_bmbt_get_startoff(ep) > bno) { + if (--lastx >= 0) + ep = xfs_iext_get_ext(ifp, lastx); } + if (lastx >= 0) + xfs_bmbt_get_all(ep, &got); extno++; } } + ifp->if_lastex = lastx; *done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0; ASSERT(ifp->if_ext_max == XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); diff --git a/trunk/fs/xfs/xfs_bmap.h b/trunk/fs/xfs/xfs_bmap.h index c62234bde053..3651191daea1 100644 --- a/trunk/fs/xfs/xfs_bmap.h +++ b/trunk/fs/xfs/xfs_bmap.h @@ -69,6 +69,7 @@ typedef struct xfs_bmap_free #define XFS_BMAPI_ENTIRE 0x004 /* return entire extent, not trimmed */ #define XFS_BMAPI_METADATA 0x008 /* mapping metadata not user data */ #define XFS_BMAPI_ATTRFORK 0x010 /* use attribute fork not data */ +#define XFS_BMAPI_RSVBLOCKS 0x020 /* OK to alloc. reserved data blocks */ #define XFS_BMAPI_PREALLOC 0x040 /* preallocation op: unwritten space */ #define XFS_BMAPI_IGSTATE 0x080 /* Ignore state - */ /* combine contig. space */ @@ -86,6 +87,7 @@ typedef struct xfs_bmap_free { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ { XFS_BMAPI_METADATA, "METADATA" }, \ { XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \ + { XFS_BMAPI_RSVBLOCKS, "RSVBLOCKS" }, \ { XFS_BMAPI_PREALLOC, "PREALLOC" }, \ { XFS_BMAPI_IGSTATE, "IGSTATE" }, \ { XFS_BMAPI_CONTIG, "CONTIG" }, \ diff --git a/trunk/fs/xfs/xfs_inode.c b/trunk/fs/xfs/xfs_inode.c index a098a20ca63e..c8e3349c287c 100644 --- a/trunk/fs/xfs/xfs_inode.c +++ b/trunk/fs/xfs/xfs_inode.c @@ -920,6 +920,7 @@ xfs_iread_extents( /* * We know that the size is valid (it's checked in iformat_btree) */ + ifp->if_lastex = NULLEXTNUM; ifp->if_bytes = ifp->if_real_bytes = 0; ifp->if_flags |= XFS_IFEXTENTS; xfs_iext_add(ifp, 0, nextents); @@ -2557,9 +2558,12 @@ xfs_iflush_fork( case XFS_DINODE_FMT_EXTENTS: ASSERT((ifp->if_flags & XFS_IFEXTENTS) || !(iip->ili_format.ilf_fields & extflag[whichfork])); + ASSERT((xfs_iext_get_ext(ifp, 0) != NULL) || + (ifp->if_bytes == 0)); + ASSERT((xfs_iext_get_ext(ifp, 0) == NULL) || + (ifp->if_bytes > 0)); if ((iip->ili_format.ilf_fields & extflag[whichfork]) && (ifp->if_bytes > 0)) { - ASSERT(xfs_iext_get_ext(ifp, 0)); ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0); (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp, whichfork); @@ -3108,8 +3112,6 @@ xfs_iext_get_ext( xfs_extnum_t idx) /* index of target extent */ { ASSERT(idx >= 0); - ASSERT(idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)); - if ((ifp->if_flags & XFS_IFEXTIREC) && (idx == 0)) { return ifp->if_u1.if_ext_irec->er_extbuf; } else if (ifp->if_flags & XFS_IFEXTIREC) { @@ -3189,6 +3191,7 @@ xfs_iext_add( } ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; ifp->if_real_bytes = 0; + ifp->if_lastex = nextents + ext_diff; } /* * Otherwise use a linear (direct) extent list. @@ -3883,10 +3886,8 @@ xfs_iext_idx_to_irec( xfs_extnum_t page_idx = *idxp; /* extent index in target list */ ASSERT(ifp->if_flags & XFS_IFEXTIREC); - ASSERT(page_idx >= 0); - ASSERT(page_idx <= ifp->if_bytes / sizeof(xfs_bmbt_rec_t)); - ASSERT(page_idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t) || realloc); - + ASSERT(page_idx >= 0 && page_idx <= + ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; erp_idx = 0; low = 0; diff --git a/trunk/fs/xfs/xfs_inode.h b/trunk/fs/xfs/xfs_inode.h index 3ae6d58e5473..ff4e2a30227d 100644 --- a/trunk/fs/xfs/xfs_inode.h +++ b/trunk/fs/xfs/xfs_inode.h @@ -67,6 +67,7 @@ typedef struct xfs_ifork { short if_broot_bytes; /* bytes allocated for root */ unsigned char if_flags; /* per-fork flags */ unsigned char if_ext_max; /* max # of extent records */ + xfs_extnum_t if_lastex; /* last if_extents used */ union { xfs_bmbt_rec_host_t *if_extents;/* linear map file exts */ xfs_ext_irec_t *if_ext_irec; /* irec map file exts */ diff --git a/trunk/fs/xfs/xfs_log_cil.c b/trunk/fs/xfs/xfs_log_cil.c index c7755d5a5fbe..7d56e88a3f0e 100644 --- a/trunk/fs/xfs/xfs_log_cil.c +++ b/trunk/fs/xfs/xfs_log_cil.c @@ -29,7 +29,6 @@ #include "xfs_mount.h" #include "xfs_error.h" #include "xfs_alloc.h" -#include "xfs_discard.h" /* * Perform initial CIL structure initialisation. If the CIL is not @@ -362,28 +361,18 @@ xlog_cil_committed( int abort) { struct xfs_cil_ctx *ctx = args; - struct xfs_mount *mp = ctx->cil->xc_log->l_mp; xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, ctx->lv_chain, ctx->start_lsn, abort); xfs_alloc_busy_sort(&ctx->busy_extents); - xfs_alloc_busy_clear(mp, &ctx->busy_extents, - (mp->m_flags & XFS_MOUNT_DISCARD) && !abort); + xfs_alloc_busy_clear(ctx->cil->xc_log->l_mp, &ctx->busy_extents); spin_lock(&ctx->cil->xc_cil_lock); list_del(&ctx->committing); spin_unlock(&ctx->cil->xc_cil_lock); xlog_cil_free_logvec(ctx->lv_chain); - - if (!list_empty(&ctx->busy_extents)) { - ASSERT(mp->m_flags & XFS_MOUNT_DISCARD); - - xfs_discard_extents(mp, &ctx->busy_extents); - xfs_alloc_busy_clear(mp, &ctx->busy_extents, false); - } - kmem_free(ctx); } diff --git a/trunk/fs/xfs/xfs_mount.h b/trunk/fs/xfs/xfs_mount.h index 3d68bb267c5f..19af0ab0d0c6 100644 --- a/trunk/fs/xfs/xfs_mount.h +++ b/trunk/fs/xfs/xfs_mount.h @@ -224,7 +224,6 @@ typedef struct xfs_mount { #define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem operations, typically for disk errors in metadata */ -#define XFS_MOUNT_DISCARD (1ULL << 5) /* discard unused blocks */ #define XFS_MOUNT_RETERR (1ULL << 6) /* return alignment errors to user */ #define XFS_MOUNT_NOALIGN (1ULL << 7) /* turn off stripe alignment diff --git a/trunk/fs/xfs/xfs_trans.c b/trunk/fs/xfs/xfs_trans.c index 7c7bc2b786bd..d1f24858ccc4 100644 --- a/trunk/fs/xfs/xfs_trans.c +++ b/trunk/fs/xfs/xfs_trans.c @@ -609,7 +609,7 @@ xfs_trans_free( struct xfs_trans *tp) { xfs_alloc_busy_sort(&tp->t_busy); - xfs_alloc_busy_clear(tp->t_mountp, &tp->t_busy, false); + xfs_alloc_busy_clear(tp->t_mountp, &tp->t_busy); atomic_dec(&tp->t_mountp->m_active_trans); xfs_trans_free_dqinfo(tp); diff --git a/trunk/include/asm-generic/bitops/find.h b/trunk/include/asm-generic/bitops/find.h index 71c778033f57..110fa700f853 100644 --- a/trunk/include/asm-generic/bitops/find.h +++ b/trunk/include/asm-generic/bitops/find.h @@ -1,7 +1,6 @@ #ifndef _ASM_GENERIC_BITOPS_FIND_H_ #define _ASM_GENERIC_BITOPS_FIND_H_ -#ifndef find_next_bit /** * find_next_bit - find the next set bit in a memory region * @addr: The address to base the search on @@ -10,9 +9,7 @@ */ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset); -#endif -#ifndef find_next_zero_bit /** * find_next_zero_bit - find the next cleared bit in a memory region * @addr: The address to base the search on @@ -21,7 +18,6 @@ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long */ extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset); -#endif #ifdef CONFIG_GENERIC_FIND_FIRST_BIT diff --git a/trunk/include/asm-generic/bitops/le.h b/trunk/include/asm-generic/bitops/le.h index f95c663a6a41..946a21b1b5dc 100644 --- a/trunk/include/asm-generic/bitops/le.h +++ b/trunk/include/asm-generic/bitops/le.h @@ -30,20 +30,13 @@ static inline unsigned long find_first_zero_bit_le(const void *addr, #define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) -#ifndef find_next_zero_bit_le extern unsigned long find_next_zero_bit_le(const void *addr, unsigned long size, unsigned long offset); -#endif - -#ifndef find_next_bit_le extern unsigned long find_next_bit_le(const void *addr, unsigned long size, unsigned long offset); -#endif -#ifndef find_first_zero_bit_le #define find_first_zero_bit_le(addr, size) \ find_next_zero_bit_le((addr), (size), 0) -#endif #else #error "Please fix " diff --git a/trunk/include/asm-generic/ptrace.h b/trunk/include/asm-generic/ptrace.h deleted file mode 100644 index 82e674f6b337..000000000000 --- a/trunk/include/asm-generic/ptrace.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Common low level (register) ptrace helpers - * - * Copyright 2004-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef __ASM_GENERIC_PTRACE_H__ -#define __ASM_GENERIC_PTRACE_H__ - -#ifndef __ASSEMBLY__ - -/* Helpers for working with the instruction pointer */ -#ifndef GET_IP -#define GET_IP(regs) ((regs)->pc) -#endif -#ifndef SET_IP -#define SET_IP(regs, val) (GET_IP(regs) = (val)) -#endif - -static inline unsigned long instruction_pointer(struct pt_regs *regs) -{ - return GET_IP(regs); -} -static inline void instruction_pointer_set(struct pt_regs *regs, - unsigned long val) -{ - SET_IP(regs, val); -} - -#ifndef profile_pc -#define profile_pc(regs) instruction_pointer(regs) -#endif - -/* Helpers for working with the user stack pointer */ -#ifndef GET_USP -#define GET_USP(regs) ((regs)->usp) -#endif -#ifndef SET_USP -#define SET_USP(regs, val) (GET_USP(regs) = (val)) -#endif - -static inline unsigned long user_stack_pointer(struct pt_regs *regs) -{ - return GET_USP(regs); -} -static inline void user_stack_pointer_set(struct pt_regs *regs, - unsigned long val) -{ - SET_USP(regs, val); -} - -/* Helpers for working with the frame pointer */ -#ifndef GET_FP -#define GET_FP(regs) ((regs)->fp) -#endif -#ifndef SET_FP -#define SET_FP(regs, val) (GET_FP(regs) = (val)) -#endif - -static inline unsigned long frame_pointer(struct pt_regs *regs) -{ - return GET_FP(regs); -} -static inline void frame_pointer_set(struct pt_regs *regs, - unsigned long val) -{ - SET_FP(regs, val); -} - -#endif /* __ASSEMBLY__ */ - -#endif diff --git a/trunk/include/linux/basic_mmio_gpio.h b/trunk/include/linux/basic_mmio_gpio.h index 1ae12710d732..198087a16fc4 100644 --- a/trunk/include/linux/basic_mmio_gpio.h +++ b/trunk/include/linux/basic_mmio_gpio.h @@ -13,64 +13,8 @@ #ifndef __BASIC_MMIO_GPIO_H #define __BASIC_MMIO_GPIO_H -#include -#include -#include - struct bgpio_pdata { int base; - int ngpio; }; -struct device; - -struct bgpio_chip { - struct gpio_chip gc; - - unsigned long (*read_reg)(void __iomem *reg); - void (*write_reg)(void __iomem *reg, unsigned long data); - - void __iomem *reg_dat; - void __iomem *reg_set; - void __iomem *reg_clr; - void __iomem *reg_dir; - - /* Number of bits (GPIOs): * 8. */ - int bits; - - /* - * Some GPIO controllers work with the big-endian bits notation, - * e.g. in a 8-bits register, GPIO7 is the least significant bit. - */ - unsigned long (*pin2mask)(struct bgpio_chip *bgc, unsigned int pin); - - /* - * Used to lock bgpio_chip->data. Also, this is needed to keep - * shadowed and real data registers writes together. - */ - spinlock_t lock; - - /* Shadowed data register to clear/set bits safely. */ - unsigned long data; - - /* Shadowed direction registers to clear/set direction safely. */ - unsigned long dir; -}; - -static inline struct bgpio_chip *to_bgpio_chip(struct gpio_chip *gc) -{ - return container_of(gc, struct bgpio_chip, gc); -} - -int __devexit bgpio_remove(struct bgpio_chip *bgc); -int __devinit bgpio_init(struct bgpio_chip *bgc, - struct device *dev, - unsigned long sz, - void __iomem *dat, - void __iomem *set, - void __iomem *clr, - void __iomem *dirout, - void __iomem *dirin, - bool big_endian); - #endif /* __BASIC_MMIO_GPIO_H */ diff --git a/trunk/include/linux/bitops.h b/trunk/include/linux/bitops.h index a3ef66a2a083..2184c6b97aeb 100644 --- a/trunk/include/linux/bitops.h +++ b/trunk/include/linux/bitops.h @@ -148,7 +148,7 @@ static inline unsigned long __ffs64(u64 word) #ifdef __KERNEL__ -#ifndef find_last_bit +#ifdef CONFIG_GENERIC_FIND_LAST_BIT /** * find_last_bit - find the last set bit in a memory region * @addr: The address to start the search at @@ -158,7 +158,7 @@ static inline unsigned long __ffs64(u64 word) */ extern unsigned long find_last_bit(const unsigned long *addr, unsigned long size); -#endif +#endif /* CONFIG_GENERIC_FIND_LAST_BIT */ #endif /* __KERNEL__ */ #endif diff --git a/trunk/include/linux/buffer_head.h b/trunk/include/linux/buffer_head.h index 503c8a6b3079..f5df23561b96 100644 --- a/trunk/include/linux/buffer_head.h +++ b/trunk/include/linux/buffer_head.h @@ -217,24 +217,8 @@ int cont_write_begin(struct file *, struct address_space *, loff_t, get_block_t *, loff_t *); int generic_cont_expand_simple(struct inode *inode, loff_t size); int block_commit_write(struct page *page, unsigned from, unsigned to); -int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, - get_block_t get_block); int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, get_block_t get_block); -/* Convert errno to return value from ->page_mkwrite() call */ -static inline int block_page_mkwrite_return(int err) -{ - if (err == 0) - return VM_FAULT_LOCKED; - if (err == -EFAULT) - return VM_FAULT_NOPAGE; - if (err == -ENOMEM) - return VM_FAULT_OOM; - if (err == -EAGAIN) - return VM_FAULT_RETRY; - /* -ENOSPC, -EDQUOT, -EIO ... */ - return VM_FAULT_SIGBUS; -} sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); int block_truncate_page(struct address_space *, loff_t, get_block_t *); int nobh_write_begin(struct address_space *, loff_t, unsigned, unsigned, diff --git a/trunk/include/linux/cgroup.h b/trunk/include/linux/cgroup.h index ab4ac0ccb857..5ac7ebc36dbb 100644 --- a/trunk/include/linux/cgroup.h +++ b/trunk/include/linux/cgroup.h @@ -467,14 +467,12 @@ struct cgroup_subsys { int (*pre_destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, - struct task_struct *tsk); - int (*can_attach_task)(struct cgroup *cgrp, struct task_struct *tsk); + struct task_struct *tsk, bool threadgroup); void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, - struct task_struct *tsk); - void (*pre_attach)(struct cgroup *cgrp); - void (*attach_task)(struct cgroup *cgrp, struct task_struct *tsk); + struct task_struct *tsk, bool threadgroup); void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, - struct cgroup *old_cgrp, struct task_struct *tsk); + struct cgroup *old_cgrp, struct task_struct *tsk, + bool threadgroup); void (*fork)(struct cgroup_subsys *ss, struct task_struct *task); void (*exit)(struct cgroup_subsys *ss, struct cgroup *cgrp, struct cgroup *old_cgrp, struct task_struct *task); @@ -555,6 +553,9 @@ static inline struct cgroup* task_cgroup(struct task_struct *task, return task_subsys_state(task, subsys_id)->cgroup; } +int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss, + char *nodename); + /* A cgroup_iter should be treated as an opaque object */ struct cgroup_iter { struct list_head *cg_link; diff --git a/trunk/include/linux/cgroup_subsys.h b/trunk/include/linux/cgroup_subsys.h index ac663c18776c..cdbfcb8780ec 100644 --- a/trunk/include/linux/cgroup_subsys.h +++ b/trunk/include/linux/cgroup_subsys.h @@ -19,6 +19,12 @@ SUBSYS(debug) /* */ +#ifdef CONFIG_CGROUP_NS +SUBSYS(ns) +#endif + +/* */ + #ifdef CONFIG_CGROUP_SCHED SUBSYS(cpu_cgroup) #endif diff --git a/trunk/include/linux/cleancache.h b/trunk/include/linux/cleancache.h deleted file mode 100644 index 04ffb2e6c9d0..000000000000 --- a/trunk/include/linux/cleancache.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef _LINUX_CLEANCACHE_H -#define _LINUX_CLEANCACHE_H - -#include -#include -#include - -#define CLEANCACHE_KEY_MAX 6 - -/* - * cleancache requires every file with a page in cleancache to have a - * unique key unless/until the file is removed/truncated. For some - * filesystems, the inode number is unique, but for "modern" filesystems - * an exportable filehandle is required (see exportfs.h) - */ -struct cleancache_filekey { - union { - ino_t ino; - __u32 fh[CLEANCACHE_KEY_MAX]; - u32 key[CLEANCACHE_KEY_MAX]; - } u; -}; - -struct cleancache_ops { - int (*init_fs)(size_t); - int (*init_shared_fs)(char *uuid, size_t); - int (*get_page)(int, struct cleancache_filekey, - pgoff_t, struct page *); - void (*put_page)(int, struct cleancache_filekey, - pgoff_t, struct page *); - void (*flush_page)(int, struct cleancache_filekey, pgoff_t); - void (*flush_inode)(int, struct cleancache_filekey); - void (*flush_fs)(int); -}; - -extern struct cleancache_ops - cleancache_register_ops(struct cleancache_ops *ops); -extern void __cleancache_init_fs(struct super_block *); -extern void __cleancache_init_shared_fs(char *, struct super_block *); -extern int __cleancache_get_page(struct page *); -extern void __cleancache_put_page(struct page *); -extern void __cleancache_flush_page(struct address_space *, struct page *); -extern void __cleancache_flush_inode(struct address_space *); -extern void __cleancache_flush_fs(struct super_block *); -extern int cleancache_enabled; - -#ifdef CONFIG_CLEANCACHE -static inline bool cleancache_fs_enabled(struct page *page) -{ - return page->mapping->host->i_sb->cleancache_poolid >= 0; -} -static inline bool cleancache_fs_enabled_mapping(struct address_space *mapping) -{ - return mapping->host->i_sb->cleancache_poolid >= 0; -} -#else -#define cleancache_enabled (0) -#define cleancache_fs_enabled(_page) (0) -#define cleancache_fs_enabled_mapping(_page) (0) -#endif - -/* - * The shim layer provided by these inline functions allows the compiler - * to reduce all cleancache hooks to nothingness if CONFIG_CLEANCACHE - * is disabled, to a single global variable check if CONFIG_CLEANCACHE - * is enabled but no cleancache "backend" has dynamically enabled it, - * and, for the most frequent cleancache ops, to a single global variable - * check plus a superblock element comparison if CONFIG_CLEANCACHE is enabled - * and a cleancache backend has dynamically enabled cleancache, but the - * filesystem referenced by that cleancache op has not enabled cleancache. - * As a result, CONFIG_CLEANCACHE can be enabled by default with essentially - * no measurable performance impact. - */ - -static inline void cleancache_init_fs(struct super_block *sb) -{ - if (cleancache_enabled) - __cleancache_init_fs(sb); -} - -static inline void cleancache_init_shared_fs(char *uuid, struct super_block *sb) -{ - if (cleancache_enabled) - __cleancache_init_shared_fs(uuid, sb); -} - -static inline int cleancache_get_page(struct page *page) -{ - int ret = -1; - - if (cleancache_enabled && cleancache_fs_enabled(page)) - ret = __cleancache_get_page(page); - return ret; -} - -static inline void cleancache_put_page(struct page *page) -{ - if (cleancache_enabled && cleancache_fs_enabled(page)) - __cleancache_put_page(page); -} - -static inline void cleancache_flush_page(struct address_space *mapping, - struct page *page) -{ - /* careful... page->mapping is NULL sometimes when this is called */ - if (cleancache_enabled && cleancache_fs_enabled_mapping(mapping)) - __cleancache_flush_page(mapping, page); -} - -static inline void cleancache_flush_inode(struct address_space *mapping) -{ - if (cleancache_enabled && cleancache_fs_enabled_mapping(mapping)) - __cleancache_flush_inode(mapping); -} - -static inline void cleancache_flush_fs(struct super_block *sb) -{ - if (cleancache_enabled) - __cleancache_flush_fs(sb); -} - -#endif /* _LINUX_CLEANCACHE_H */ diff --git a/trunk/include/linux/crash_dump.h b/trunk/include/linux/crash_dump.h index 74054074e876..088cd4ace4ef 100644 --- a/trunk/include/linux/crash_dump.h +++ b/trunk/include/linux/crash_dump.h @@ -66,11 +66,6 @@ static inline void vmcore_unusable(void) if (is_kdump_kernel()) elfcorehdr_addr = ELFCORE_ADDR_ERR; } - -#define HAVE_OLDMEM_PFN_IS_RAM 1 -extern int register_oldmem_pfn_is_ram(int (*fn)(unsigned long pfn)); -extern void unregister_oldmem_pfn_is_ram(void); - #else /* !CONFIG_CRASH_DUMP */ static inline int is_kdump_kernel(void) { return 0; } #endif /* CONFIG_CRASH_DUMP */ diff --git a/trunk/include/linux/flex_array.h b/trunk/include/linux/flex_array.h index 6843cf193a44..ebeb2f3ad068 100644 --- a/trunk/include/linux/flex_array.h +++ b/trunk/include/linux/flex_array.h @@ -21,8 +21,6 @@ struct flex_array { struct { int element_size; int total_nr_elements; - int elems_per_part; - u32 reciprocal_elems; struct flex_array_part *parts[]; }; /* diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 241609346dfb..3f9d3251790d 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -1428,11 +1428,6 @@ struct super_block { */ char __rcu *s_options; const struct dentry_operations *s_d_op; /* default d_op for dentries */ - - /* - * Saved pool identifier for cleancache (-1 means none) - */ - int cleancache_poolid; }; extern struct timespec current_fs_time(struct super_block *sb); diff --git a/trunk/include/linux/hugetlb.h b/trunk/include/linux/hugetlb.h index 59225ef27d15..943c76b3d4bb 100644 --- a/trunk/include/linux/hugetlb.h +++ b/trunk/include/linux/hugetlb.h @@ -1,7 +1,6 @@ #ifndef _LINUX_HUGETLB_H #define _LINUX_HUGETLB_H -#include #include #include @@ -42,7 +41,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, unsigned int flags); int hugetlb_reserve_pages(struct inode *inode, long from, long to, struct vm_area_struct *vma, - vm_flags_t vm_flags); + int acctflags); void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed); int dequeue_hwpoisoned_huge_page(struct page *page); void copy_huge_page(struct page *dst, struct page *src); @@ -169,7 +168,7 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb) extern const struct file_operations hugetlbfs_file_operations; extern const struct vm_operations_struct hugetlb_vm_ops; -struct file *hugetlb_file_setup(const char *name, size_t size, vm_flags_t acct, +struct file *hugetlb_file_setup(const char *name, size_t size, int acct, struct user_struct **user, int creat_flags); int hugetlb_get_quota(struct address_space *mapping, long delta); void hugetlb_put_quota(struct address_space *mapping, long delta); @@ -193,7 +192,7 @@ static inline void set_file_hugepages(struct file *file) #define is_file_hugepages(file) 0 #define set_file_hugepages(file) BUG() static inline struct file *hugetlb_file_setup(const char *name, size_t size, - vm_flags_t acctflag, struct user_struct **user, int creat_flags) + int acctflag, struct user_struct **user, int creat_flags) { return ERR_PTR(-ENOSYS); } diff --git a/trunk/include/linux/hugetlb_inline.h b/trunk/include/linux/hugetlb_inline.h index 2bb681fbeb35..6931489a5c14 100644 --- a/trunk/include/linux/hugetlb_inline.h +++ b/trunk/include/linux/hugetlb_inline.h @@ -7,7 +7,7 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma) { - return !!(vma->vm_flags & VM_HUGETLB); + return vma->vm_flags & VM_HUGETLB; } #else diff --git a/trunk/include/linux/i2c/twl.h b/trunk/include/linux/i2c/twl.h index ba4f88624fcd..0c0d1ae79981 100644 --- a/trunk/include/linux/i2c/twl.h +++ b/trunk/include/linux/i2c/twl.h @@ -91,7 +91,6 @@ #define BCI_INTR_OFFSET 2 #define MADC_INTR_OFFSET 3 #define USB_INTR_OFFSET 4 -#define CHARGERFAULT_INTR_OFFSET 5 #define BCI_PRES_INTR_OFFSET 9 #define USB_PRES_INTR_OFFSET 10 #define RTC_INTR_OFFSET 11 @@ -151,12 +150,7 @@ #define MMC_PU (0x1 << 3) #define MMC_PD (0x1 << 2) -#define TWL_SIL_TYPE(rev) ((rev) & 0x00FFFFFF) -#define TWL_SIL_REV(rev) ((rev) >> 24) -#define TWL_SIL_5030 0x09002F -#define TWL5030_REV_1_0 0x00 -#define TWL5030_REV_1_1 0x10 -#define TWL5030_REV_1_2 0x30 + #define TWL4030_CLASS_ID 0x4030 #define TWL6030_CLASS_ID 0x6030 @@ -171,8 +165,6 @@ static inline int twl_class_is_ ##class(void) \ TWL_CLASS_IS(4030, TWL4030_CLASS_ID) TWL_CLASS_IS(6030, TWL6030_CLASS_ID) -#define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */ - /* * Read and write single 8-bit registers */ @@ -188,9 +180,6 @@ int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg); int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); -int twl_get_type(void); -int twl_get_version(void); - int twl6030_interrupt_unmask(u8 bit_mask, u8 offset); int twl6030_interrupt_mask(u8 bit_mask, u8 offset); @@ -290,12 +279,7 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) *(Use TWL_4030_MODULE_INTBR) */ -#define REG_IDCODE_7_0 0x00 -#define REG_IDCODE_15_8 0x01 -#define REG_IDCODE_16_23 0x02 -#define REG_IDCODE_31_24 0x03 #define REG_GPPUPDCTR1 0x0F -#define REG_UNLOCK_TEST_REG 0x12 /*I2C1 and I2C4(SR) SDA/SCL pull-up control bits */ @@ -304,8 +288,6 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) #define SR_I2C_SCL_CTRL_PU BIT(4) #define SR_I2C_SDA_CTRL_PU BIT(6) -#define TWL_EEPROM_R_UNLOCK 0x49 - /*----------------------------------------------------------------------*/ /* @@ -519,7 +501,7 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) #define RES_32KCLKOUT 26 #define RES_RESET 27 /* Power Reference */ -#define RES_MAIN_REF 28 +#define RES_Main_Ref 28 #define TOTAL_RESOURCES 28 /* @@ -611,7 +593,6 @@ enum twl4030_usb_mode { struct twl4030_usb_data { enum twl4030_usb_mode usb_mode; - unsigned long features; int (*phy_init)(struct device *dev); int (*phy_exit)(struct device *dev); @@ -718,20 +699,6 @@ struct twl4030_platform_data { struct regulator_init_data *vcxio; struct regulator_init_data *vusb; struct regulator_init_data *clk32kg; - /* TWL6025 LDO regulators */ - struct regulator_init_data *ldo1; - struct regulator_init_data *ldo2; - struct regulator_init_data *ldo3; - struct regulator_init_data *ldo4; - struct regulator_init_data *ldo5; - struct regulator_init_data *ldo6; - struct regulator_init_data *ldo7; - struct regulator_init_data *ldoln; - struct regulator_init_data *ldousb; - /* TWL6025 DCDC regulators */ - struct regulator_init_data *smps3; - struct regulator_init_data *smps4; - struct regulator_init_data *vio6025; }; /*----------------------------------------------------------------------*/ @@ -813,21 +780,4 @@ static inline int twl4030charger_usb_en(int enable) { return 0; } #define TWL6030_REG_VRTC 47 #define TWL6030_REG_CLK32KG 48 -/* LDOs on 6025 have different names */ -#define TWL6025_REG_LDO2 49 -#define TWL6025_REG_LDO4 50 -#define TWL6025_REG_LDO3 51 -#define TWL6025_REG_LDO5 52 -#define TWL6025_REG_LDO1 53 -#define TWL6025_REG_LDO7 54 -#define TWL6025_REG_LDO6 55 -#define TWL6025_REG_LDOLN 56 -#define TWL6025_REG_LDOUSB 57 - -/* 6025 DCDC supplies */ -#define TWL6025_REG_SMPS3 58 -#define TWL6025_REG_SMPS4 59 -#define TWL6025_REG_VIO 60 - - #endif /* End of __TWL4030_H */ diff --git a/trunk/include/linux/init_task.h b/trunk/include/linux/init_task.h index 580f70c02391..bafc58c00fc3 100644 --- a/trunk/include/linux/init_task.h +++ b/trunk/include/linux/init_task.h @@ -22,14 +22,6 @@ extern struct files_struct init_files; extern struct fs_struct init_fs; -#ifdef CONFIG_CGROUPS -#define INIT_THREADGROUP_FORK_LOCK(sig) \ - .threadgroup_fork_lock = \ - __RWSEM_INITIALIZER(sig.threadgroup_fork_lock), -#else -#define INIT_THREADGROUP_FORK_LOCK(sig) -#endif - #define INIT_SIGNALS(sig) { \ .nr_threads = 1, \ .wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\ @@ -46,7 +38,6 @@ extern struct fs_struct init_fs; }, \ .cred_guard_mutex = \ __MUTEX_INITIALIZER(sig.cred_guard_mutex), \ - INIT_THREADGROUP_FORK_LOCK(sig) \ } extern struct nsproxy init_nsproxy; diff --git a/trunk/include/linux/input/pmic8xxx-keypad.h b/trunk/include/linux/input/pmic8xxx-keypad.h deleted file mode 100644 index 5f1e2f9ad959..000000000000 --- a/trunk/include/linux/input/pmic8xxx-keypad.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (c) 2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __PMIC8XXX_KEYPAD_H__ -#define __PMIC8XXX_KEYPAD_H__ - -#include - -#define PM8XXX_KEYPAD_DEV_NAME "pm8xxx-keypad" - -/** - * struct pm8xxx_keypad_platform_data - platform data for keypad - * @keymap_data - matrix keymap data - * @input_name - input device name - * @input_phys_device - input device name - * @num_cols - number of columns of keypad - * @num_rows - number of row of keypad - * @debounce_ms - debounce period in milliseconds - * @scan_delay_ms - scan delay in milliseconds - * @row_hold_ns - row hold period in nanoseconds - * @wakeup - configure keypad as wakeup - * @rep - enable or disable key repeat bit - */ -struct pm8xxx_keypad_platform_data { - const struct matrix_keymap_data *keymap_data; - - const char *input_name; - const char *input_phys_device; - - unsigned int num_cols; - unsigned int num_rows; - unsigned int rows_gpio_start; - unsigned int cols_gpio_start; - - unsigned int debounce_ms; - unsigned int scan_delay_ms; - unsigned int row_hold_ns; - - bool wakeup; - bool rep; -}; - -#endif /*__PMIC8XXX_KEYPAD_H__ */ diff --git a/trunk/include/linux/input/pmic8xxx-pwrkey.h b/trunk/include/linux/input/pmic8xxx-pwrkey.h deleted file mode 100644 index 6d2974e57109..000000000000 --- a/trunk/include/linux/input/pmic8xxx-pwrkey.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __PMIC8XXX_PWRKEY_H__ -#define __PMIC8XXX_PWRKEY_H__ - -#define PM8XXX_PWRKEY_DEV_NAME "pm8xxx-pwrkey" - -/** - * struct pm8xxx_pwrkey_platform_data - platform data for pwrkey driver - * @pull up: power on register control for pull up/down configuration - * @kpd_trigger_delay_us: time delay for power key state change interrupt - * trigger. - * @wakeup: configure power key as wakeup source - */ -struct pm8xxx_pwrkey_platform_data { - bool pull_up; - u32 kpd_trigger_delay_us; - u32 wakeup; -}; - -#endif /* __PMIC8XXX_PWRKEY_H__ */ diff --git a/trunk/include/linux/ipmi_smi.h b/trunk/include/linux/ipmi_smi.h index 204f9cd26c16..906590aa6907 100644 --- a/trunk/include/linux/ipmi_smi.h +++ b/trunk/include/linux/ipmi_smi.h @@ -236,7 +236,7 @@ static inline void ipmi_free_smi_msg(struct ipmi_smi_msg *msg) directory for this interface. Note that the entry will automatically be dstroyed when the interface is destroyed. */ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, - const struct file_operations *proc_ops, + read_proc_t *read_proc, void *data); #endif /* __LINUX_IPMI_SMI_H */ diff --git a/trunk/include/linux/jbd2.h b/trunk/include/linux/jbd2.h index 4ecb7b16b278..a32dcaec04e1 100644 --- a/trunk/include/linux/jbd2.h +++ b/trunk/include/linux/jbd2.h @@ -529,10 +529,9 @@ struct transaction_s enum { T_RUNNING, T_LOCKED, + T_RUNDOWN, T_FLUSH, T_COMMIT, - T_COMMIT_DFLUSH, - T_COMMIT_JFLUSH, T_FINISHED } t_state; @@ -659,9 +658,7 @@ struct transaction_s * waiting for it to finish. */ unsigned int t_synchronous_commit:1; - - /* Disk flush needs to be sent to fs partition [no locking] */ - int t_need_data_flush; + unsigned int t_flushed_data_blocks:1; /* * For use by the filesystem to store fs-specific data @@ -1231,7 +1228,6 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *tid); int jbd2_journal_force_commit_nested(journal_t *journal); int jbd2_log_wait_commit(journal_t *journal, tid_t tid); int jbd2_log_do_checkpoint(journal_t *journal); -int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid); void __jbd2_log_wait_for_space(journal_t *journal); extern void __jbd2_journal_drop_transaction(journal_t *, transaction_t *); diff --git a/trunk/include/linux/memcontrol.h b/trunk/include/linux/memcontrol.h index 9724a38ee69d..5e9840f50980 100644 --- a/trunk/include/linux/memcontrol.h +++ b/trunk/include/linux/memcontrol.h @@ -20,8 +20,6 @@ #ifndef _LINUX_MEMCONTROL_H #define _LINUX_MEMCONTROL_H #include -#include - struct mem_cgroup; struct page_cgroup; struct page; @@ -108,10 +106,9 @@ extern void mem_cgroup_end_migration(struct mem_cgroup *mem, */ int mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg); int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg); -int mem_cgroup_select_victim_node(struct mem_cgroup *memcg); -unsigned long mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, - struct zone *zone, - enum lru_list lru); +unsigned long mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg, + struct zone *zone, + enum lru_list lru); struct zone_reclaim_stat *mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg, struct zone *zone); struct zone_reclaim_stat* @@ -147,11 +144,9 @@ static inline void mem_cgroup_dec_page_stat(struct page *page, } unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, - gfp_t gfp_mask, - unsigned long *total_scanned); + gfp_t gfp_mask); u64 mem_cgroup_get_limit(struct mem_cgroup *mem); -void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx); #ifdef CONFIG_TRANSPARENT_HUGEPAGE void mem_cgroup_split_huge_fixup(struct page *head, struct page *tail); #endif @@ -307,8 +302,8 @@ mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg) } static inline unsigned long -mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, struct zone *zone, - enum lru_list lru) +mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg, struct zone *zone, + enum lru_list lru) { return 0; } @@ -343,8 +338,7 @@ static inline void mem_cgroup_dec_page_stat(struct page *page, static inline unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, - gfp_t gfp_mask, - unsigned long *total_scanned) + gfp_t gfp_mask) { return 0; } @@ -360,10 +354,6 @@ static inline void mem_cgroup_split_huge_fixup(struct page *head, { } -static inline -void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx) -{ -} #endif /* CONFIG_CGROUP_MEM_CONT */ #if !defined(CONFIG_CGROUP_MEM_RES_CTLR) || !defined(CONFIG_DEBUG_VM) diff --git a/trunk/include/linux/mfd/88pm860x.h b/trunk/include/linux/mfd/88pm860x.h index 63b4fb8e3b6f..8fba7972ff5f 100644 --- a/trunk/include/linux/mfd/88pm860x.h +++ b/trunk/include/linux/mfd/88pm860x.h @@ -330,11 +330,6 @@ struct pm860x_led_pdata { unsigned long flags; }; -struct pm860x_rtc_pdata { - int (*sync)(unsigned int ticks); - int vrtc; -}; - struct pm860x_touch_pdata { int gpadc_prebias; int slot_cycle; @@ -354,7 +349,6 @@ struct pm860x_power_pdata { struct pm860x_platform_data { struct pm860x_backlight_pdata *backlight; struct pm860x_led_pdata *led; - struct pm860x_rtc_pdata *rtc; struct pm860x_touch_pdata *touch; struct pm860x_power_pdata *power; struct regulator_init_data *regulator; diff --git a/trunk/include/linux/mfd/abx500.h b/trunk/include/linux/mfd/abx500.h index 896b5e47f16e..7d9b6ae1c203 100644 --- a/trunk/include/linux/mfd/abx500.h +++ b/trunk/include/linux/mfd/abx500.h @@ -34,13 +34,6 @@ #define AB5500_2_0 0x21 #define AB5500_2_1 0x22 -/* AB8500 CIDs*/ -#define AB8500_CUTEARLY 0x00 -#define AB8500_CUT1P0 0x10 -#define AB8500_CUT1P1 0x11 -#define AB8500_CUT2P0 0x20 -#define AB8500_CUT3P0 0x30 - /* * AB3100, EVENTA1, A2 and A3 event register flags * these are catenated into a single 32-bit flag in the code @@ -193,7 +186,6 @@ struct abx500_init_settings { struct ab3550_platform_data { struct {unsigned int base; unsigned int count; } irq; void *dev_data[AB3550_NUM_DEVICES]; - size_t dev_data_sz[AB3550_NUM_DEVICES]; struct abx500_init_settings *init_settings; unsigned int init_settings_sz; }; diff --git a/trunk/include/linux/mfd/asic3.h b/trunk/include/linux/mfd/asic3.h index ed793b77a1c5..de3c4ad19afb 100644 --- a/trunk/include/linux/mfd/asic3.h +++ b/trunk/include/linux/mfd/asic3.h @@ -16,13 +16,6 @@ #include -struct led_classdev; -struct asic3_led { - const char *name; - const char *default_trigger; - struct led_classdev *cdev; -}; - struct asic3_platform_data { u16 *gpio_config; unsigned int gpio_config_num; @@ -30,8 +23,6 @@ struct asic3_platform_data { unsigned int irq_base; unsigned int gpio_base; - - struct asic3_led *leds; }; #define ASIC3_NUM_GPIO_BANKS 4 @@ -120,9 +111,9 @@ struct asic3_platform_data { #define ASIC3_GPIOA11_PWM0 ASIC3_CONFIG_GPIO(11, 1, 1, 0) #define ASIC3_GPIOA12_PWM1 ASIC3_CONFIG_GPIO(12, 1, 1, 0) #define ASIC3_GPIOA15_CONTROL_CX ASIC3_CONFIG_GPIO(15, 1, 1, 0) -#define ASIC3_GPIOC0_LED0 ASIC3_CONFIG_GPIO(32, 1, 0, 0) -#define ASIC3_GPIOC1_LED1 ASIC3_CONFIG_GPIO(33, 1, 0, 0) -#define ASIC3_GPIOC2_LED2 ASIC3_CONFIG_GPIO(34, 1, 0, 0) +#define ASIC3_GPIOC0_LED0 ASIC3_CONFIG_GPIO(32, 1, 1, 0) +#define ASIC3_GPIOC1_LED1 ASIC3_CONFIG_GPIO(33, 1, 1, 0) +#define ASIC3_GPIOC2_LED2 ASIC3_CONFIG_GPIO(34, 1, 1, 0) #define ASIC3_GPIOC3_SPI_RXD ASIC3_CONFIG_GPIO(35, 1, 0, 0) #define ASIC3_GPIOC4_CF_nCD ASIC3_CONFIG_GPIO(36, 1, 0, 0) #define ASIC3_GPIOC4_SPI_TXD ASIC3_CONFIG_GPIO(36, 1, 1, 0) @@ -161,7 +152,6 @@ struct asic3_platform_data { #define PWM_TIMEBASE_VALUE(x) ((x)&0xf) /* Low 4 bits sets time base */ #define PWM_TIMEBASE_ENABLE (1 << 4) /* Enable clock */ -#define ASIC3_NUM_LEDS 3 #define ASIC3_LED_0_Base 0x0700 #define ASIC3_LED_1_Base 0x0800 #define ASIC3_LED_2_Base 0x0900 @@ -297,17 +287,10 @@ struct asic3_platform_data { * *****************************************************************************/ #define ASIC3_SD_CONFIG_BASE 0x0400 /* Assumes 32 bit addressing */ -#define ASIC3_SD_CONFIG_SIZE 0x0200 /* Assumes 32 bit addressing */ #define ASIC3_SD_CTRL_BASE 0x1000 #define ASIC3_SDIO_CTRL_BASE 0x1200 #define ASIC3_MAP_SIZE_32BIT 0x2000 #define ASIC3_MAP_SIZE_16BIT 0x1000 -/* Functions needed by leds-asic3 */ - -struct asic3; -extern void asic3_write_register(struct asic3 *asic, unsigned int reg, u32 val); -extern u32 asic3_read_register(struct asic3 *asic, unsigned int reg); - #endif /* __ASIC3_H__ */ diff --git a/trunk/include/linux/mfd/core.h b/trunk/include/linux/mfd/core.h index 4e76163dd862..aef23309a742 100644 --- a/trunk/include/linux/mfd/core.h +++ b/trunk/include/linux/mfd/core.h @@ -33,9 +33,8 @@ struct mfd_cell { int (*suspend)(struct platform_device *dev); int (*resume)(struct platform_device *dev); - /* platform data passed to the sub devices drivers */ - void *platform_data; - size_t pdata_size; + /* mfd_data can be used to pass data to client drivers */ + void *mfd_data; /* * These resources can be specified relative to the parent device. @@ -90,6 +89,24 @@ static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev) return pdev->mfd_cell; } +/* + * Given a platform device that's been created by mfd_add_devices(), fetch + * the .mfd_data entry from the mfd_cell that created it. + * Otherwise just return the platform_data pointer. + * This maintains compatibility with platform drivers whose devices aren't + * created by the mfd layer, and expect platform_data to contain what would've + * otherwise been in mfd_data. + */ +static inline void *mfd_get_data(struct platform_device *pdev) +{ + const struct mfd_cell *cell = mfd_get_cell(pdev); + + if (cell) + return cell->mfd_data; + else + return pdev->dev.platform_data; +} + extern int mfd_add_devices(struct device *parent, int id, struct mfd_cell *cells, int n_devs, struct resource *mem_base, diff --git a/trunk/include/linux/mfd/max8997-private.h b/trunk/include/linux/mfd/max8997-private.h index 5ff2400ad46c..69d1010e2e51 100644 --- a/trunk/include/linux/mfd/max8997-private.h +++ b/trunk/include/linux/mfd/max8997-private.h @@ -311,6 +311,10 @@ enum max8997_irq { MAX8997_IRQ_NR, }; +#define MAX8997_REG_BUCK1DVS(x) (MAX8997_REG_BUCK1DVS1 + (x) - 1) +#define MAX8997_REG_BUCK2DVS(x) (MAX8997_REG_BUCK2DVS1 + (x) - 1) +#define MAX8997_REG_BUCK5DVS(x) (MAX8997_REG_BUCK5DVS1 + (x) - 1) + #define MAX8997_NUM_GPIO 12 struct max8997_dev { struct device *dev; diff --git a/trunk/include/linux/mfd/pm8xxx/core.h b/trunk/include/linux/mfd/pm8xxx/core.h deleted file mode 100644 index bd2f4f64e931..000000000000 --- a/trunk/include/linux/mfd/pm8xxx/core.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -/* - * Qualcomm PMIC 8xxx driver header file - * - */ - -#ifndef __MFD_PM8XXX_CORE_H -#define __MFD_PM8XXX_CORE_H - -#include - -struct pm8xxx_drvdata { - int (*pmic_readb) (const struct device *dev, u16 addr, u8 *val); - int (*pmic_writeb) (const struct device *dev, u16 addr, u8 val); - int (*pmic_read_buf) (const struct device *dev, u16 addr, u8 *buf, - int n); - int (*pmic_write_buf) (const struct device *dev, u16 addr, u8 *buf, - int n); - int (*pmic_read_irq_stat) (const struct device *dev, int irq); - void *pm_chip_data; -}; - -static inline int pm8xxx_readb(const struct device *dev, u16 addr, u8 *val) -{ - struct pm8xxx_drvdata *dd = dev_get_drvdata(dev); - - if (!dd) - return -EINVAL; - return dd->pmic_readb(dev, addr, val); -} - -static inline int pm8xxx_writeb(const struct device *dev, u16 addr, u8 val) -{ - struct pm8xxx_drvdata *dd = dev_get_drvdata(dev); - - if (!dd) - return -EINVAL; - return dd->pmic_writeb(dev, addr, val); -} - -static inline int pm8xxx_read_buf(const struct device *dev, u16 addr, u8 *buf, - int n) -{ - struct pm8xxx_drvdata *dd = dev_get_drvdata(dev); - - if (!dd) - return -EINVAL; - return dd->pmic_read_buf(dev, addr, buf, n); -} - -static inline int pm8xxx_write_buf(const struct device *dev, u16 addr, u8 *buf, - int n) -{ - struct pm8xxx_drvdata *dd = dev_get_drvdata(dev); - - if (!dd) - return -EINVAL; - return dd->pmic_write_buf(dev, addr, buf, n); -} - -static inline int pm8xxx_read_irq_stat(const struct device *dev, int irq) -{ - struct pm8xxx_drvdata *dd = dev_get_drvdata(dev); - - if (!dd) - return -EINVAL; - return dd->pmic_read_irq_stat(dev, irq); -} - -#endif diff --git a/trunk/include/linux/mfd/pm8xxx/irq.h b/trunk/include/linux/mfd/pm8xxx/irq.h deleted file mode 100644 index 4b21769f4483..000000000000 --- a/trunk/include/linux/mfd/pm8xxx/irq.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -/* - * Qualcomm PMIC irq 8xxx driver header file - * - */ - -#ifndef __MFD_PM8XXX_IRQ_H -#define __MFD_PM8XXX_IRQ_H - -#include -#include - -struct pm8xxx_irq_core_data { - u32 rev; - int nirqs; -}; - -struct pm8xxx_irq_platform_data { - int irq_base; - struct pm8xxx_irq_core_data irq_cdata; - int devirq; - int irq_trigger_flag; -}; - -struct pm_irq_chip; - -#ifdef CONFIG_MFD_PM8XXX_IRQ -int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq); -struct pm_irq_chip * __devinit pm8xxx_irq_init(struct device *dev, - const struct pm8xxx_irq_platform_data *pdata); -int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip); -#else -static inline int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq) -{ - return -ENXIO; -} -static inline struct pm_irq_chip * __devinit pm8xxx_irq_init( - const struct device *dev, - const struct pm8xxx_irq_platform_data *pdata) -{ - return ERR_PTR(-ENXIO); -} -static inline int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip) -{ - return -ENXIO; -} -#endif /* CONFIG_MFD_PM8XXX_IRQ */ -#endif /* __MFD_PM8XXX_IRQ_H */ diff --git a/trunk/include/linux/mfd/pm8xxx/pm8921.h b/trunk/include/linux/mfd/pm8xxx/pm8921.h deleted file mode 100644 index d5517fd32d1b..000000000000 --- a/trunk/include/linux/mfd/pm8xxx/pm8921.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -/* - * Qualcomm PMIC 8921 driver header file - * - */ - -#ifndef __MFD_PM8921_H -#define __MFD_PM8921_H - -#include -#include - -#define PM8921_NR_IRQS 256 - -struct pm8921_platform_data { - int irq_base; - struct pm8xxx_irq_platform_data *irq_pdata; -}; - -#endif diff --git a/trunk/include/linux/mfd/tps65910.h b/trunk/include/linux/mfd/tps65910.h deleted file mode 100644 index 8bb85b930c07..000000000000 --- a/trunk/include/linux/mfd/tps65910.h +++ /dev/null @@ -1,800 +0,0 @@ -/* - * tps65910.h -- TI TPS6591x - * - * Copyright 2010-2011 Texas Instruments Inc. - * - * Author: Graeme Gregory - * Author: Jorge Eduardo Candelaria - * Author: Arnaud Deconinck - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#ifndef __LINUX_MFD_TPS65910_H -#define __LINUX_MFD_TPS65910_H - -/* TPS chip id list */ -#define TPS65910 0 -#define TPS65911 1 - -/* TPS regulator type list */ -#define REGULATOR_LDO 0 -#define REGULATOR_DCDC 1 - -/* - * List of registers for component TPS65910 - * - */ - -#define TPS65910_SECONDS 0x0 -#define TPS65910_MINUTES 0x1 -#define TPS65910_HOURS 0x2 -#define TPS65910_DAYS 0x3 -#define TPS65910_MONTHS 0x4 -#define TPS65910_YEARS 0x5 -#define TPS65910_WEEKS 0x6 -#define TPS65910_ALARM_SECONDS 0x8 -#define TPS65910_ALARM_MINUTES 0x9 -#define TPS65910_ALARM_HOURS 0xA -#define TPS65910_ALARM_DAYS 0xB -#define TPS65910_ALARM_MONTHS 0xC -#define TPS65910_ALARM_YEARS 0xD -#define TPS65910_RTC_CTRL 0x10 -#define TPS65910_RTC_STATUS 0x11 -#define TPS65910_RTC_INTERRUPTS 0x12 -#define TPS65910_RTC_COMP_LSB 0x13 -#define TPS65910_RTC_COMP_MSB 0x14 -#define TPS65910_RTC_RES_PROG 0x15 -#define TPS65910_RTC_RESET_STATUS 0x16 -#define TPS65910_BCK1 0x17 -#define TPS65910_BCK2 0x18 -#define TPS65910_BCK3 0x19 -#define TPS65910_BCK4 0x1A -#define TPS65910_BCK5 0x1B -#define TPS65910_PUADEN 0x1C -#define TPS65910_REF 0x1D -#define TPS65910_VRTC 0x1E -#define TPS65910_VIO 0x20 -#define TPS65910_VDD1 0x21 -#define TPS65910_VDD1_OP 0x22 -#define TPS65910_VDD1_SR 0x23 -#define TPS65910_VDD2 0x24 -#define TPS65910_VDD2_OP 0x25 -#define TPS65910_VDD2_SR 0x26 -#define TPS65910_VDD3 0x27 -#define TPS65910_VDIG1 0x30 -#define TPS65910_VDIG2 0x31 -#define TPS65910_VAUX1 0x32 -#define TPS65910_VAUX2 0x33 -#define TPS65910_VAUX33 0x34 -#define TPS65910_VMMC 0x35 -#define TPS65910_VPLL 0x36 -#define TPS65910_VDAC 0x37 -#define TPS65910_THERM 0x38 -#define TPS65910_BBCH 0x39 -#define TPS65910_DCDCCTRL 0x3E -#define TPS65910_DEVCTRL 0x3F -#define TPS65910_DEVCTRL2 0x40 -#define TPS65910_SLEEP_KEEP_LDO_ON 0x41 -#define TPS65910_SLEEP_KEEP_RES_ON 0x42 -#define TPS65910_SLEEP_SET_LDO_OFF 0x43 -#define TPS65910_SLEEP_SET_RES_OFF 0x44 -#define TPS65910_EN1_LDO_ASS 0x45 -#define TPS65910_EN1_SMPS_ASS 0x46 -#define TPS65910_EN2_LDO_ASS 0x47 -#define TPS65910_EN2_SMPS_ASS 0x48 -#define TPS65910_EN3_LDO_ASS 0x49 -#define TPS65910_SPARE 0x4A -#define TPS65910_INT_STS 0x50 -#define TPS65910_INT_MSK 0x51 -#define TPS65910_INT_STS2 0x52 -#define TPS65910_INT_MSK2 0x53 -#define TPS65910_INT_STS3 0x54 -#define TPS65910_INT_MSK3 0x55 -#define TPS65910_GPIO0 0x60 -#define TPS65910_GPIO1 0x61 -#define TPS65910_GPIO2 0x62 -#define TPS65910_GPIO3 0x63 -#define TPS65910_GPIO4 0x64 -#define TPS65910_GPIO5 0x65 -#define TPS65910_GPIO6 0x66 -#define TPS65910_GPIO7 0x67 -#define TPS65910_GPIO8 0x68 -#define TPS65910_JTAGVERNUM 0x80 -#define TPS65910_MAX_REGISTER 0x80 - -/* - * List of registers specific to TPS65911 - */ -#define TPS65911_VDDCTRL 0x27 -#define TPS65911_VDDCTRL_OP 0x28 -#define TPS65911_VDDCTRL_SR 0x29 -#define TPS65911_LDO1 0x30 -#define TPS65911_LDO2 0x31 -#define TPS65911_LDO5 0x32 -#define TPS65911_LDO8 0x33 -#define TPS65911_LDO7 0x34 -#define TPS65911_LDO6 0x35 -#define TPS65911_LDO4 0x36 -#define TPS65911_LDO3 0x37 -#define TPS65911_VMBCH 0x6A -#define TPS65911_VMBCH2 0x6B - -/* - * List of register bitfields for component TPS65910 - * - */ - - -/*Register BCK1 (0x80) register.RegisterDescription */ -#define BCK1_BCKUP_MASK 0xFF -#define BCK1_BCKUP_SHIFT 0 - - -/*Register BCK2 (0x80) register.RegisterDescription */ -#define BCK2_BCKUP_MASK 0xFF -#define BCK2_BCKUP_SHIFT 0 - - -/*Register BCK3 (0x80) register.RegisterDescription */ -#define BCK3_BCKUP_MASK 0xFF -#define BCK3_BCKUP_SHIFT 0 - - -/*Register BCK4 (0x80) register.RegisterDescription */ -#define BCK4_BCKUP_MASK 0xFF -#define BCK4_BCKUP_SHIFT 0 - - -/*Register BCK5 (0x80) register.RegisterDescription */ -#define BCK5_BCKUP_MASK 0xFF -#define BCK5_BCKUP_SHIFT 0 - - -/*Register PUADEN (0x80) register.RegisterDescription */ -#define PUADEN_EN3P_MASK 0x80 -#define PUADEN_EN3P_SHIFT 7 -#define PUADEN_I2CCTLP_MASK 0x40 -#define PUADEN_I2CCTLP_SHIFT 6 -#define PUADEN_I2CSRP_MASK 0x20 -#define PUADEN_I2CSRP_SHIFT 5 -#define PUADEN_PWRONP_MASK 0x10 -#define PUADEN_PWRONP_SHIFT 4 -#define PUADEN_SLEEPP_MASK 0x08 -#define PUADEN_SLEEPP_SHIFT 3 -#define PUADEN_PWRHOLDP_MASK 0x04 -#define PUADEN_PWRHOLDP_SHIFT 2 -#define PUADEN_BOOT1P_MASK 0x02 -#define PUADEN_BOOT1P_SHIFT 1 -#define PUADEN_BOOT0P_MASK 0x01 -#define PUADEN_BOOT0P_SHIFT 0 - - -/*Register REF (0x80) register.RegisterDescription */ -#define REF_VMBCH_SEL_MASK 0x0C -#define REF_VMBCH_SEL_SHIFT 2 -#define REF_ST_MASK 0x03 -#define REF_ST_SHIFT 0 - - -/*Register VRTC (0x80) register.RegisterDescription */ -#define VRTC_VRTC_OFFMASK_MASK 0x08 -#define VRTC_VRTC_OFFMASK_SHIFT 3 -#define VRTC_ST_MASK 0x03 -#define VRTC_ST_SHIFT 0 - - -/*Register VIO (0x80) register.RegisterDescription */ -#define VIO_ILMAX_MASK 0xC0 -#define VIO_ILMAX_SHIFT 6 -#define VIO_SEL_MASK 0x0C -#define VIO_SEL_SHIFT 2 -#define VIO_ST_MASK 0x03 -#define VIO_ST_SHIFT 0 - - -/*Register VDD1 (0x80) register.RegisterDescription */ -#define VDD1_VGAIN_SEL_MASK 0xC0 -#define VDD1_VGAIN_SEL_SHIFT 6 -#define VDD1_ILMAX_MASK 0x20 -#define VDD1_ILMAX_SHIFT 5 -#define VDD1_TSTEP_MASK 0x1C -#define VDD1_TSTEP_SHIFT 2 -#define VDD1_ST_MASK 0x03 -#define VDD1_ST_SHIFT 0 - - -/*Register VDD1_OP (0x80) register.RegisterDescription */ -#define VDD1_OP_CMD_MASK 0x80 -#define VDD1_OP_CMD_SHIFT 7 -#define VDD1_OP_SEL_MASK 0x7F -#define VDD1_OP_SEL_SHIFT 0 - - -/*Register VDD1_SR (0x80) register.RegisterDescription */ -#define VDD1_SR_SEL_MASK 0x7F -#define VDD1_SR_SEL_SHIFT 0 - - -/*Register VDD2 (0x80) register.RegisterDescription */ -#define VDD2_VGAIN_SEL_MASK 0xC0 -#define VDD2_VGAIN_SEL_SHIFT 6 -#define VDD2_ILMAX_MASK 0x20 -#define VDD2_ILMAX_SHIFT 5 -#define VDD2_TSTEP_MASK 0x1C -#define VDD2_TSTEP_SHIFT 2 -#define VDD2_ST_MASK 0x03 -#define VDD2_ST_SHIFT 0 - - -/*Register VDD2_OP (0x80) register.RegisterDescription */ -#define VDD2_OP_CMD_MASK 0x80 -#define VDD2_OP_CMD_SHIFT 7 -#define VDD2_OP_SEL_MASK 0x7F -#define VDD2_OP_SEL_SHIFT 0 - -/*Register VDD2_SR (0x80) register.RegisterDescription */ -#define VDD2_SR_SEL_MASK 0x7F -#define VDD2_SR_SEL_SHIFT 0 - - -/*Registers VDD1, VDD2 voltage values definitions */ -#define VDD1_2_NUM_VOLTS 73 -#define VDD1_2_MIN_VOLT 6000 -#define VDD1_2_OFFSET 125 - - -/*Register VDD3 (0x80) register.RegisterDescription */ -#define VDD3_CKINEN_MASK 0x04 -#define VDD3_CKINEN_SHIFT 2 -#define VDD3_ST_MASK 0x03 -#define VDD3_ST_SHIFT 0 -#define VDDCTRL_MIN_VOLT 6000 -#define VDDCTRL_OFFSET 125 - -/*Registers VDIG (0x80) to VDAC register.RegisterDescription */ -#define LDO_SEL_MASK 0x0C -#define LDO_SEL_SHIFT 2 -#define LDO_ST_MASK 0x03 -#define LDO_ST_SHIFT 0 -#define LDO_ST_ON_BIT 0x01 -#define LDO_ST_MODE_BIT 0x02 - - -/* Registers LDO1 to LDO8 in tps65910 */ -#define LDO1_SEL_MASK 0xFC -#define LDO3_SEL_MASK 0x7C -#define LDO_MIN_VOLT 1000 -#define LDO_MAX_VOLT 3300; - - -/*Register VDIG1 (0x80) register.RegisterDescription */ -#define VDIG1_SEL_MASK 0x0C -#define VDIG1_SEL_SHIFT 2 -#define VDIG1_ST_MASK 0x03 -#define VDIG1_ST_SHIFT 0 - - -/*Register VDIG2 (0x80) register.RegisterDescription */ -#define VDIG2_SEL_MASK 0x0C -#define VDIG2_SEL_SHIFT 2 -#define VDIG2_ST_MASK 0x03 -#define VDIG2_ST_SHIFT 0 - - -/*Register VAUX1 (0x80) register.RegisterDescription */ -#define VAUX1_SEL_MASK 0x0C -#define VAUX1_SEL_SHIFT 2 -#define VAUX1_ST_MASK 0x03 -#define VAUX1_ST_SHIFT 0 - - -/*Register VAUX2 (0x80) register.RegisterDescription */ -#define VAUX2_SEL_MASK 0x0C -#define VAUX2_SEL_SHIFT 2 -#define VAUX2_ST_MASK 0x03 -#define VAUX2_ST_SHIFT 0 - - -/*Register VAUX33 (0x80) register.RegisterDescription */ -#define VAUX33_SEL_MASK 0x0C -#define VAUX33_SEL_SHIFT 2 -#define VAUX33_ST_MASK 0x03 -#define VAUX33_ST_SHIFT 0 - - -/*Register VMMC (0x80) register.RegisterDescription */ -#define VMMC_SEL_MASK 0x0C -#define VMMC_SEL_SHIFT 2 -#define VMMC_ST_MASK 0x03 -#define VMMC_ST_SHIFT 0 - - -/*Register VPLL (0x80) register.RegisterDescription */ -#define VPLL_SEL_MASK 0x0C -#define VPLL_SEL_SHIFT 2 -#define VPLL_ST_MASK 0x03 -#define VPLL_ST_SHIFT 0 - - -/*Register VDAC (0x80) register.RegisterDescription */ -#define VDAC_SEL_MASK 0x0C -#define VDAC_SEL_SHIFT 2 -#define VDAC_ST_MASK 0x03 -#define VDAC_ST_SHIFT 0 - - -/*Register THERM (0x80) register.RegisterDescription */ -#define THERM_THERM_HD_MASK 0x20 -#define THERM_THERM_HD_SHIFT 5 -#define THERM_THERM_TS_MASK 0x10 -#define THERM_THERM_TS_SHIFT 4 -#define THERM_THERM_HDSEL_MASK 0x0C -#define THERM_THERM_HDSEL_SHIFT 2 -#define THERM_RSVD1_MASK 0x02 -#define THERM_RSVD1_SHIFT 1 -#define THERM_THERM_STATE_MASK 0x01 -#define THERM_THERM_STATE_SHIFT 0 - - -/*Register BBCH (0x80) register.RegisterDescription */ -#define BBCH_BBSEL_MASK 0x06 -#define BBCH_BBSEL_SHIFT 1 -#define BBCH_BBCHEN_MASK 0x01 -#define BBCH_BBCHEN_SHIFT 0 - - -/*Register DCDCCTRL (0x80) register.RegisterDescription */ -#define DCDCCTRL_VDD2_PSKIP_MASK 0x20 -#define DCDCCTRL_VDD2_PSKIP_SHIFT 5 -#define DCDCCTRL_VDD1_PSKIP_MASK 0x10 -#define DCDCCTRL_VDD1_PSKIP_SHIFT 4 -#define DCDCCTRL_VIO_PSKIP_MASK 0x08 -#define DCDCCTRL_VIO_PSKIP_SHIFT 3 -#define DCDCCTRL_DCDCCKEXT_MASK 0x04 -#define DCDCCTRL_DCDCCKEXT_SHIFT 2 -#define DCDCCTRL_DCDCCKSYNC_MASK 0x03 -#define DCDCCTRL_DCDCCKSYNC_SHIFT 0 - - -/*Register DEVCTRL (0x80) register.RegisterDescription */ -#define DEVCTRL_RTC_PWDN_MASK 0x40 -#define DEVCTRL_RTC_PWDN_SHIFT 6 -#define DEVCTRL_CK32K_CTRL_MASK 0x20 -#define DEVCTRL_CK32K_CTRL_SHIFT 5 -#define DEVCTRL_SR_CTL_I2C_SEL_MASK 0x10 -#define DEVCTRL_SR_CTL_I2C_SEL_SHIFT 4 -#define DEVCTRL_DEV_OFF_RST_MASK 0x08 -#define DEVCTRL_DEV_OFF_RST_SHIFT 3 -#define DEVCTRL_DEV_ON_MASK 0x04 -#define DEVCTRL_DEV_ON_SHIFT 2 -#define DEVCTRL_DEV_SLP_MASK 0x02 -#define DEVCTRL_DEV_SLP_SHIFT 1 -#define DEVCTRL_DEV_OFF_MASK 0x01 -#define DEVCTRL_DEV_OFF_SHIFT 0 - - -/*Register DEVCTRL2 (0x80) register.RegisterDescription */ -#define DEVCTRL2_TSLOT_LENGTH_MASK 0x30 -#define DEVCTRL2_TSLOT_LENGTH_SHIFT 4 -#define DEVCTRL2_SLEEPSIG_POL_MASK 0x08 -#define DEVCTRL2_SLEEPSIG_POL_SHIFT 3 -#define DEVCTRL2_PWON_LP_OFF_MASK 0x04 -#define DEVCTRL2_PWON_LP_OFF_SHIFT 2 -#define DEVCTRL2_PWON_LP_RST_MASK 0x02 -#define DEVCTRL2_PWON_LP_RST_SHIFT 1 -#define DEVCTRL2_IT_POL_MASK 0x01 -#define DEVCTRL2_IT_POL_SHIFT 0 - - -/*Register SLEEP_KEEP_LDO_ON (0x80) register.RegisterDescription */ -#define SLEEP_KEEP_LDO_ON_VDAC_KEEPON_MASK 0x80 -#define SLEEP_KEEP_LDO_ON_VDAC_KEEPON_SHIFT 7 -#define SLEEP_KEEP_LDO_ON_VPLL_KEEPON_MASK 0x40 -#define SLEEP_KEEP_LDO_ON_VPLL_KEEPON_SHIFT 6 -#define SLEEP_KEEP_LDO_ON_VAUX33_KEEPON_MASK 0x20 -#define SLEEP_KEEP_LDO_ON_VAUX33_KEEPON_SHIFT 5 -#define SLEEP_KEEP_LDO_ON_VAUX2_KEEPON_MASK 0x10 -#define SLEEP_KEEP_LDO_ON_VAUX2_KEEPON_SHIFT 4 -#define SLEEP_KEEP_LDO_ON_VAUX1_KEEPON_MASK 0x08 -#define SLEEP_KEEP_LDO_ON_VAUX1_KEEPON_SHIFT 3 -#define SLEEP_KEEP_LDO_ON_VDIG2_KEEPON_MASK 0x04 -#define SLEEP_KEEP_LDO_ON_VDIG2_KEEPON_SHIFT 2 -#define SLEEP_KEEP_LDO_ON_VDIG1_KEEPON_MASK 0x02 -#define SLEEP_KEEP_LDO_ON_VDIG1_KEEPON_SHIFT 1 -#define SLEEP_KEEP_LDO_ON_VMMC_KEEPON_MASK 0x01 -#define SLEEP_KEEP_LDO_ON_VMMC_KEEPON_SHIFT 0 - - -/*Register SLEEP_KEEP_RES_ON (0x80) register.RegisterDescription */ -#define SLEEP_KEEP_RES_ON_THERM_KEEPON_MASK 0x80 -#define SLEEP_KEEP_RES_ON_THERM_KEEPON_SHIFT 7 -#define SLEEP_KEEP_RES_ON_CLKOUT32K_KEEPON_MASK 0x40 -#define SLEEP_KEEP_RES_ON_CLKOUT32K_KEEPON_SHIFT 6 -#define SLEEP_KEEP_RES_ON_VRTC_KEEPON_MASK 0x20 -#define SLEEP_KEEP_RES_ON_VRTC_KEEPON_SHIFT 5 -#define SLEEP_KEEP_RES_ON_I2CHS_KEEPON_MASK 0x10 -#define SLEEP_KEEP_RES_ON_I2CHS_KEEPON_SHIFT 4 -#define SLEEP_KEEP_RES_ON_VDD3_KEEPON_MASK 0x08 -#define SLEEP_KEEP_RES_ON_VDD3_KEEPON_SHIFT 3 -#define SLEEP_KEEP_RES_ON_VDD2_KEEPON_MASK 0x04 -#define SLEEP_KEEP_RES_ON_VDD2_KEEPON_SHIFT 2 -#define SLEEP_KEEP_RES_ON_VDD1_KEEPON_MASK 0x02 -#define SLEEP_KEEP_RES_ON_VDD1_KEEPON_SHIFT 1 -#define SLEEP_KEEP_RES_ON_VIO_KEEPON_MASK 0x01 -#define SLEEP_KEEP_RES_ON_VIO_KEEPON_SHIFT 0 - - -/*Register SLEEP_SET_LDO_OFF (0x80) register.RegisterDescription */ -#define SLEEP_SET_LDO_OFF_VDAC_SETOFF_MASK 0x80 -#define SLEEP_SET_LDO_OFF_VDAC_SETOFF_SHIFT 7 -#define SLEEP_SET_LDO_OFF_VPLL_SETOFF_MASK 0x40 -#define SLEEP_SET_LDO_OFF_VPLL_SETOFF_SHIFT 6 -#define SLEEP_SET_LDO_OFF_VAUX33_SETOFF_MASK 0x20 -#define SLEEP_SET_LDO_OFF_VAUX33_SETOFF_SHIFT 5 -#define SLEEP_SET_LDO_OFF_VAUX2_SETOFF_MASK 0x10 -#define SLEEP_SET_LDO_OFF_VAUX2_SETOFF_SHIFT 4 -#define SLEEP_SET_LDO_OFF_VAUX1_SETOFF_MASK 0x08 -#define SLEEP_SET_LDO_OFF_VAUX1_SETOFF_SHIFT 3 -#define SLEEP_SET_LDO_OFF_VDIG2_SETOFF_MASK 0x04 -#define SLEEP_SET_LDO_OFF_VDIG2_SETOFF_SHIFT 2 -#define SLEEP_SET_LDO_OFF_VDIG1_SETOFF_MASK 0x02 -#define SLEEP_SET_LDO_OFF_VDIG1_SETOFF_SHIFT 1 -#define SLEEP_SET_LDO_OFF_VMMC_SETOFF_MASK 0x01 -#define SLEEP_SET_LDO_OFF_VMMC_SETOFF_SHIFT 0 - - -/*Register SLEEP_SET_RES_OFF (0x80) register.RegisterDescription */ -#define SLEEP_SET_RES_OFF_DEFAULT_VOLT_MASK 0x80 -#define SLEEP_SET_RES_OFF_DEFAULT_VOLT_SHIFT 7 -#define SLEEP_SET_RES_OFF_RSVD_MASK 0x60 -#define SLEEP_SET_RES_OFF_RSVD_SHIFT 5 -#define SLEEP_SET_RES_OFF_SPARE_SETOFF_MASK 0x10 -#define SLEEP_SET_RES_OFF_SPARE_SETOFF_SHIFT 4 -#define SLEEP_SET_RES_OFF_VDD3_SETOFF_MASK 0x08 -#define SLEEP_SET_RES_OFF_VDD3_SETOFF_SHIFT 3 -#define SLEEP_SET_RES_OFF_VDD2_SETOFF_MASK 0x04 -#define SLEEP_SET_RES_OFF_VDD2_SETOFF_SHIFT 2 -#define SLEEP_SET_RES_OFF_VDD1_SETOFF_MASK 0x02 -#define SLEEP_SET_RES_OFF_VDD1_SETOFF_SHIFT 1 -#define SLEEP_SET_RES_OFF_VIO_SETOFF_MASK 0x01 -#define SLEEP_SET_RES_OFF_VIO_SETOFF_SHIFT 0 - - -/*Register EN1_LDO_ASS (0x80) register.RegisterDescription */ -#define EN1_LDO_ASS_VDAC_EN1_MASK 0x80 -#define EN1_LDO_ASS_VDAC_EN1_SHIFT 7 -#define EN1_LDO_ASS_VPLL_EN1_MASK 0x40 -#define EN1_LDO_ASS_VPLL_EN1_SHIFT 6 -#define EN1_LDO_ASS_VAUX33_EN1_MASK 0x20 -#define EN1_LDO_ASS_VAUX33_EN1_SHIFT 5 -#define EN1_LDO_ASS_VAUX2_EN1_MASK 0x10 -#define EN1_LDO_ASS_VAUX2_EN1_SHIFT 4 -#define EN1_LDO_ASS_VAUX1_EN1_MASK 0x08 -#define EN1_LDO_ASS_VAUX1_EN1_SHIFT 3 -#define EN1_LDO_ASS_VDIG2_EN1_MASK 0x04 -#define EN1_LDO_ASS_VDIG2_EN1_SHIFT 2 -#define EN1_LDO_ASS_VDIG1_EN1_MASK 0x02 -#define EN1_LDO_ASS_VDIG1_EN1_SHIFT 1 -#define EN1_LDO_ASS_VMMC_EN1_MASK 0x01 -#define EN1_LDO_ASS_VMMC_EN1_SHIFT 0 - - -/*Register EN1_SMPS_ASS (0x80) register.RegisterDescription */ -#define EN1_SMPS_ASS_RSVD_MASK 0xE0 -#define EN1_SMPS_ASS_RSVD_SHIFT 5 -#define EN1_SMPS_ASS_SPARE_EN1_MASK 0x10 -#define EN1_SMPS_ASS_SPARE_EN1_SHIFT 4 -#define EN1_SMPS_ASS_VDD3_EN1_MASK 0x08 -#define EN1_SMPS_ASS_VDD3_EN1_SHIFT 3 -#define EN1_SMPS_ASS_VDD2_EN1_MASK 0x04 -#define EN1_SMPS_ASS_VDD2_EN1_SHIFT 2 -#define EN1_SMPS_ASS_VDD1_EN1_MASK 0x02 -#define EN1_SMPS_ASS_VDD1_EN1_SHIFT 1 -#define EN1_SMPS_ASS_VIO_EN1_MASK 0x01 -#define EN1_SMPS_ASS_VIO_EN1_SHIFT 0 - - -/*Register EN2_LDO_ASS (0x80) register.RegisterDescription */ -#define EN2_LDO_ASS_VDAC_EN2_MASK 0x80 -#define EN2_LDO_ASS_VDAC_EN2_SHIFT 7 -#define EN2_LDO_ASS_VPLL_EN2_MASK 0x40 -#define EN2_LDO_ASS_VPLL_EN2_SHIFT 6 -#define EN2_LDO_ASS_VAUX33_EN2_MASK 0x20 -#define EN2_LDO_ASS_VAUX33_EN2_SHIFT 5 -#define EN2_LDO_ASS_VAUX2_EN2_MASK 0x10 -#define EN2_LDO_ASS_VAUX2_EN2_SHIFT 4 -#define EN2_LDO_ASS_VAUX1_EN2_MASK 0x08 -#define EN2_LDO_ASS_VAUX1_EN2_SHIFT 3 -#define EN2_LDO_ASS_VDIG2_EN2_MASK 0x04 -#define EN2_LDO_ASS_VDIG2_EN2_SHIFT 2 -#define EN2_LDO_ASS_VDIG1_EN2_MASK 0x02 -#define EN2_LDO_ASS_VDIG1_EN2_SHIFT 1 -#define EN2_LDO_ASS_VMMC_EN2_MASK 0x01 -#define EN2_LDO_ASS_VMMC_EN2_SHIFT 0 - - -/*Register EN2_SMPS_ASS (0x80) register.RegisterDescription */ -#define EN2_SMPS_ASS_RSVD_MASK 0xE0 -#define EN2_SMPS_ASS_RSVD_SHIFT 5 -#define EN2_SMPS_ASS_SPARE_EN2_MASK 0x10 -#define EN2_SMPS_ASS_SPARE_EN2_SHIFT 4 -#define EN2_SMPS_ASS_VDD3_EN2_MASK 0x08 -#define EN2_SMPS_ASS_VDD3_EN2_SHIFT 3 -#define EN2_SMPS_ASS_VDD2_EN2_MASK 0x04 -#define EN2_SMPS_ASS_VDD2_EN2_SHIFT 2 -#define EN2_SMPS_ASS_VDD1_EN2_MASK 0x02 -#define EN2_SMPS_ASS_VDD1_EN2_SHIFT 1 -#define EN2_SMPS_ASS_VIO_EN2_MASK 0x01 -#define EN2_SMPS_ASS_VIO_EN2_SHIFT 0 - - -/*Register EN3_LDO_ASS (0x80) register.RegisterDescription */ -#define EN3_LDO_ASS_VDAC_EN3_MASK 0x80 -#define EN3_LDO_ASS_VDAC_EN3_SHIFT 7 -#define EN3_LDO_ASS_VPLL_EN3_MASK 0x40 -#define EN3_LDO_ASS_VPLL_EN3_SHIFT 6 -#define EN3_LDO_ASS_VAUX33_EN3_MASK 0x20 -#define EN3_LDO_ASS_VAUX33_EN3_SHIFT 5 -#define EN3_LDO_ASS_VAUX2_EN3_MASK 0x10 -#define EN3_LDO_ASS_VAUX2_EN3_SHIFT 4 -#define EN3_LDO_ASS_VAUX1_EN3_MASK 0x08 -#define EN3_LDO_ASS_VAUX1_EN3_SHIFT 3 -#define EN3_LDO_ASS_VDIG2_EN3_MASK 0x04 -#define EN3_LDO_ASS_VDIG2_EN3_SHIFT 2 -#define EN3_LDO_ASS_VDIG1_EN3_MASK 0x02 -#define EN3_LDO_ASS_VDIG1_EN3_SHIFT 1 -#define EN3_LDO_ASS_VMMC_EN3_MASK 0x01 -#define EN3_LDO_ASS_VMMC_EN3_SHIFT 0 - - -/*Register SPARE (0x80) register.RegisterDescription */ -#define SPARE_SPARE_MASK 0xFF -#define SPARE_SPARE_SHIFT 0 - - -/*Register INT_STS (0x80) register.RegisterDescription */ -#define INT_STS_RTC_PERIOD_IT_MASK 0x80 -#define INT_STS_RTC_PERIOD_IT_SHIFT 7 -#define INT_STS_RTC_ALARM_IT_MASK 0x40 -#define INT_STS_RTC_ALARM_IT_SHIFT 6 -#define INT_STS_HOTDIE_IT_MASK 0x20 -#define INT_STS_HOTDIE_IT_SHIFT 5 -#define INT_STS_PWRHOLD_IT_MASK 0x10 -#define INT_STS_PWRHOLD_IT_SHIFT 4 -#define INT_STS_PWRON_LP_IT_MASK 0x08 -#define INT_STS_PWRON_LP_IT_SHIFT 3 -#define INT_STS_PWRON_IT_MASK 0x04 -#define INT_STS_PWRON_IT_SHIFT 2 -#define INT_STS_VMBHI_IT_MASK 0x02 -#define INT_STS_VMBHI_IT_SHIFT 1 -#define INT_STS_VMBDCH_IT_MASK 0x01 -#define INT_STS_VMBDCH_IT_SHIFT 0 - - -/*Register INT_MSK (0x80) register.RegisterDescription */ -#define INT_MSK_RTC_PERIOD_IT_MSK_MASK 0x80 -#define INT_MSK_RTC_PERIOD_IT_MSK_SHIFT 7 -#define INT_MSK_RTC_ALARM_IT_MSK_MASK 0x40 -#define INT_MSK_RTC_ALARM_IT_MSK_SHIFT 6 -#define INT_MSK_HOTDIE_IT_MSK_MASK 0x20 -#define INT_MSK_HOTDIE_IT_MSK_SHIFT 5 -#define INT_MSK_PWRHOLD_IT_MSK_MASK 0x10 -#define INT_MSK_PWRHOLD_IT_MSK_SHIFT 4 -#define INT_MSK_PWRON_LP_IT_MSK_MASK 0x08 -#define INT_MSK_PWRON_LP_IT_MSK_SHIFT 3 -#define INT_MSK_PWRON_IT_MSK_MASK 0x04 -#define INT_MSK_PWRON_IT_MSK_SHIFT 2 -#define INT_MSK_VMBHI_IT_MSK_MASK 0x02 -#define INT_MSK_VMBHI_IT_MSK_SHIFT 1 -#define INT_MSK_VMBDCH_IT_MSK_MASK 0x01 -#define INT_MSK_VMBDCH_IT_MSK_SHIFT 0 - - -/*Register INT_STS2 (0x80) register.RegisterDescription */ -#define INT_STS2_GPIO3_F_IT_MASK 0x80 -#define INT_STS2_GPIO3_F_IT_SHIFT 7 -#define INT_STS2_GPIO3_R_IT_MASK 0x40 -#define INT_STS2_GPIO3_R_IT_SHIFT 6 -#define INT_STS2_GPIO2_F_IT_MASK 0x20 -#define INT_STS2_GPIO2_F_IT_SHIFT 5 -#define INT_STS2_GPIO2_R_IT_MASK 0x10 -#define INT_STS2_GPIO2_R_IT_SHIFT 4 -#define INT_STS2_GPIO1_F_IT_MASK 0x08 -#define INT_STS2_GPIO1_F_IT_SHIFT 3 -#define INT_STS2_GPIO1_R_IT_MASK 0x04 -#define INT_STS2_GPIO1_R_IT_SHIFT 2 -#define INT_STS2_GPIO0_F_IT_MASK 0x02 -#define INT_STS2_GPIO0_F_IT_SHIFT 1 -#define INT_STS2_GPIO0_R_IT_MASK 0x01 -#define INT_STS2_GPIO0_R_IT_SHIFT 0 - - -/*Register INT_MSK2 (0x80) register.RegisterDescription */ -#define INT_MSK2_GPIO3_F_IT_MSK_MASK 0x80 -#define INT_MSK2_GPIO3_F_IT_MSK_SHIFT 7 -#define INT_MSK2_GPIO3_R_IT_MSK_MASK 0x40 -#define INT_MSK2_GPIO3_R_IT_MSK_SHIFT 6 -#define INT_MSK2_GPIO2_F_IT_MSK_MASK 0x20 -#define INT_MSK2_GPIO2_F_IT_MSK_SHIFT 5 -#define INT_MSK2_GPIO2_R_IT_MSK_MASK 0x10 -#define INT_MSK2_GPIO2_R_IT_MSK_SHIFT 4 -#define INT_MSK2_GPIO1_F_IT_MSK_MASK 0x08 -#define INT_MSK2_GPIO1_F_IT_MSK_SHIFT 3 -#define INT_MSK2_GPIO1_R_IT_MSK_MASK 0x04 -#define INT_MSK2_GPIO1_R_IT_MSK_SHIFT 2 -#define INT_MSK2_GPIO0_F_IT_MSK_MASK 0x02 -#define INT_MSK2_GPIO0_F_IT_MSK_SHIFT 1 -#define INT_MSK2_GPIO0_R_IT_MSK_MASK 0x01 -#define INT_MSK2_GPIO0_R_IT_MSK_SHIFT 0 - - -/*Register INT_STS3 (0x80) register.RegisterDescription */ -#define INT_STS3_GPIO5_F_IT_MASK 0x08 -#define INT_STS3_GPIO5_F_IT_SHIFT 3 -#define INT_STS3_GPIO5_R_IT_MASK 0x04 -#define INT_STS3_GPIO5_R_IT_SHIFT 2 -#define INT_STS3_GPIO4_F_IT_MASK 0x02 -#define INT_STS3_GPIO4_F_IT_SHIFT 1 -#define INT_STS3_GPIO4_R_IT_MASK 0x01 -#define INT_STS3_GPIO4_R_IT_SHIFT 0 - - -/*Register INT_MSK3 (0x80) register.RegisterDescription */ -#define INT_MSK3_GPIO5_F_IT_MSK_MASK 0x08 -#define INT_MSK3_GPIO5_F_IT_MSK_SHIFT 3 -#define INT_MSK3_GPIO5_R_IT_MSK_MASK 0x04 -#define INT_MSK3_GPIO5_R_IT_MSK_SHIFT 2 -#define INT_MSK3_GPIO4_F_IT_MSK_MASK 0x02 -#define INT_MSK3_GPIO4_F_IT_MSK_SHIFT 1 -#define INT_MSK3_GPIO4_R_IT_MSK_MASK 0x01 -#define INT_MSK3_GPIO4_R_IT_MSK_SHIFT 0 - - -/*Register GPIO (0x80) register.RegisterDescription */ -#define GPIO_DEB_MASK 0x10 -#define GPIO_DEB_SHIFT 4 -#define GPIO_PUEN_MASK 0x08 -#define GPIO_PUEN_SHIFT 3 -#define GPIO_CFG_MASK 0x04 -#define GPIO_CFG_SHIFT 2 -#define GPIO_STS_MASK 0x02 -#define GPIO_STS_SHIFT 1 -#define GPIO_SET_MASK 0x01 -#define GPIO_SET_SHIFT 0 - - -/*Register JTAGVERNUM (0x80) register.RegisterDescription */ -#define JTAGVERNUM_VERNUM_MASK 0x0F -#define JTAGVERNUM_VERNUM_SHIFT 0 - - -/* Register VDDCTRL (0x27) bit definitions */ -#define VDDCTRL_ST_MASK 0x03 -#define VDDCTRL_ST_SHIFT 0 - - -/*Register VDDCTRL_OP (0x28) bit definitios */ -#define VDDCTRL_OP_CMD_MASK 0x80 -#define VDDCTRL_OP_CMD_SHIFT 7 -#define VDDCTRL_OP_SEL_MASK 0x7F -#define VDDCTRL_OP_SEL_SHIFT 0 - - -/*Register VDDCTRL_SR (0x29) bit definitions */ -#define VDDCTRL_SR_SEL_MASK 0x7F -#define VDDCTRL_SR_SEL_SHIFT 0 - - -/* IRQ Definitions */ -#define TPS65910_IRQ_VBAT_VMBDCH 0 -#define TPS65910_IRQ_VBAT_VMHI 1 -#define TPS65910_IRQ_PWRON 2 -#define TPS65910_IRQ_PWRON_LP 3 -#define TPS65910_IRQ_PWRHOLD 4 -#define TPS65910_IRQ_HOTDIE 5 -#define TPS65910_IRQ_RTC_ALARM 6 -#define TPS65910_IRQ_RTC_PERIOD 7 -#define TPS65910_IRQ_GPIO_R 8 -#define TPS65910_IRQ_GPIO_F 9 -#define TPS65910_NUM_IRQ 10 - -#define TPS65911_IRQ_VBAT_VMBDCH 0 -#define TPS65911_IRQ_VBAT_VMBDCH2L 1 -#define TPS65911_IRQ_VBAT_VMBDCH2H 2 -#define TPS65911_IRQ_VBAT_VMHI 3 -#define TPS65911_IRQ_PWRON 4 -#define TPS65911_IRQ_PWRON_LP 5 -#define TPS65911_IRQ_PWRHOLD_F 6 -#define TPS65911_IRQ_PWRHOLD_R 7 -#define TPS65911_IRQ_HOTDIE 8 -#define TPS65911_IRQ_RTC_ALARM 9 -#define TPS65911_IRQ_RTC_PERIOD 10 -#define TPS65911_IRQ_GPIO0_R 11 -#define TPS65911_IRQ_GPIO0_F 12 -#define TPS65911_IRQ_GPIO1_R 13 -#define TPS65911_IRQ_GPIO1_F 14 -#define TPS65911_IRQ_GPIO2_R 15 -#define TPS65911_IRQ_GPIO2_F 16 -#define TPS65911_IRQ_GPIO3_R 17 -#define TPS65911_IRQ_GPIO3_F 18 -#define TPS65911_IRQ_GPIO4_R 19 -#define TPS65911_IRQ_GPIO4_F 20 -#define TPS65911_IRQ_GPIO5_R 21 -#define TPS65911_IRQ_GPIO5_F 22 -#define TPS65911_IRQ_WTCHDG 23 -#define TPS65911_IRQ_PWRDN 24 - -#define TPS65911_NUM_IRQ 25 - - -/* GPIO Register Definitions */ -#define TPS65910_GPIO_DEB BIT(2) -#define TPS65910_GPIO_PUEN BIT(3) -#define TPS65910_GPIO_CFG BIT(2) -#define TPS65910_GPIO_STS BIT(1) -#define TPS65910_GPIO_SET BIT(0) - -/** - * struct tps65910_board - * Board platform data may be used to initialize regulators. - */ - -struct tps65910_board { - int gpio_base; - int irq; - int irq_base; - int vmbch_threshold; - int vmbch2_threshold; - struct regulator_init_data *tps65910_pmic_init_data; -}; - -/** - * struct tps65910 - tps65910 sub-driver chip access routines - */ - -struct tps65910 { - struct device *dev; - struct i2c_client *i2c_client; - struct mutex io_mutex; - unsigned int id; - int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest); - int (*write)(struct tps65910 *tps65910, u8 reg, int size, void *src); - - /* Client devices */ - struct tps65910_pmic *pmic; - struct tps65910_rtc *rtc; - struct tps65910_power *power; - - /* GPIO Handling */ - struct gpio_chip gpio; - - /* IRQ Handling */ - struct mutex irq_lock; - int chip_irq; - int irq_base; - int irq_num; - u32 irq_mask; -}; - -struct tps65910_platform_data { - int irq; - int irq_base; -}; - -int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask); -int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask); -void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base); -int tps65910_irq_init(struct tps65910 *tps65910, int irq, - struct tps65910_platform_data *pdata); - -static inline int tps65910_chip_id(struct tps65910 *tps65910) -{ - return tps65910->id; -} - -#endif /* __LINUX_MFD_TPS65910_H */ diff --git a/trunk/include/linux/mfd/twl4030-codec.h b/trunk/include/linux/mfd/twl4030-codec.h index 5cc16bbd1da1..2ec317c68e59 100644 --- a/trunk/include/linux/mfd/twl4030-codec.h +++ b/trunk/include/linux/mfd/twl4030-codec.h @@ -1,7 +1,7 @@ /* * MFD driver for twl4030 codec submodule * - * Author: Peter Ujfalusi + * Author: Peter Ujfalusi * * Copyright: (C) 2009 Nokia Corporation * diff --git a/trunk/include/linux/mfd/wm831x/core.h b/trunk/include/linux/mfd/wm831x/core.h index 0d515ee1c247..903280d21866 100644 --- a/trunk/include/linux/mfd/wm831x/core.h +++ b/trunk/include/linux/mfd/wm831x/core.h @@ -301,4 +301,30 @@ int wm831x_device_suspend(struct wm831x *wm831x); int wm831x_irq_init(struct wm831x *wm831x, int irq); void wm831x_irq_exit(struct wm831x *wm831x); +static inline int __must_check wm831x_request_irq(struct wm831x *wm831x, + unsigned int irq, + irq_handler_t handler, + unsigned long flags, + const char *name, + void *dev) +{ + return request_threaded_irq(irq, NULL, handler, flags, name, dev); +} + +static inline void wm831x_free_irq(struct wm831x *wm831x, + unsigned int irq, void *dev) +{ + free_irq(irq, dev); +} + +static inline void wm831x_disable_irq(struct wm831x *wm831x, int irq) +{ + disable_irq(irq); +} + +static inline void wm831x_enable_irq(struct wm831x *wm831x, int irq) +{ + enable_irq(irq); +} + #endif diff --git a/trunk/include/linux/mfd/wm831x/pdata.h b/trunk/include/linux/mfd/wm831x/pdata.h index ff42d700293f..632d1567a1b6 100644 --- a/trunk/include/linux/mfd/wm831x/pdata.h +++ b/trunk/include/linux/mfd/wm831x/pdata.h @@ -105,9 +105,6 @@ struct wm831x_watchdog_pdata { #define WM831X_MAX_LDO 11 #define WM831X_MAX_ISINK 2 -#define WM831X_GPIO_CONFIGURE 0x10000 -#define WM831X_GPIO_NUM 16 - struct wm831x_pdata { /** Used to distinguish multiple WM831x chips */ int wm831x_num; @@ -122,7 +119,6 @@ struct wm831x_pdata { int irq_base; int gpio_base; - int gpio_defaults[WM831X_GPIO_NUM]; struct wm831x_backlight_pdata *backlight; struct wm831x_backup_pdata *backup; struct wm831x_battery_pdata *battery; diff --git a/trunk/include/linux/mm.h b/trunk/include/linux/mm.h index 9670f71d7be9..8eb969ebf904 100644 --- a/trunk/include/linux/mm.h +++ b/trunk/include/linux/mm.h @@ -165,12 +165,12 @@ extern pgprot_t protection_map[16]; */ static inline int is_linear_pfn_mapping(struct vm_area_struct *vma) { - return !!(vma->vm_flags & VM_PFN_AT_MMAP); + return (vma->vm_flags & VM_PFN_AT_MMAP); } static inline int is_pfn_mapping(struct vm_area_struct *vma) { - return !!(vma->vm_flags & VM_PFNMAP); + return (vma->vm_flags & VM_PFNMAP); } /* @@ -1408,11 +1408,17 @@ extern void exit_mmap(struct mm_struct *); extern int mm_take_all_locks(struct mm_struct *mm); extern void mm_drop_all_locks(struct mm_struct *mm); +#ifdef CONFIG_PROC_FS /* From fs/proc/base.c. callers must _not_ hold the mm's exe_file_lock */ extern void added_exe_file_vma(struct mm_struct *mm); extern void removed_exe_file_vma(struct mm_struct *mm); -extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file); -extern struct file *get_mm_exe_file(struct mm_struct *mm); +#else +static inline void added_exe_file_vma(struct mm_struct *mm) +{} + +static inline void removed_exe_file_vma(struct mm_struct *mm) +{} +#endif /* CONFIG_PROC_FS */ extern int may_expand_vm(struct mm_struct *mm, unsigned long npages); extern int install_special_mapping(struct mm_struct *mm, @@ -1426,7 +1432,7 @@ extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, unsigned long flag, unsigned long pgoff); extern unsigned long mmap_region(struct file *file, unsigned long addr, unsigned long len, unsigned long flags, - vm_flags_t vm_flags, unsigned long pgoff); + unsigned int vm_flags, unsigned long pgoff); static inline unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, diff --git a/trunk/include/linux/mm_types.h b/trunk/include/linux/mm_types.h index 2a78aae78c69..071d459e866b 100644 --- a/trunk/include/linux/mm_types.h +++ b/trunk/include/linux/mm_types.h @@ -102,8 +102,6 @@ struct page { #endif }; -typedef unsigned long __nocast vm_flags_t; - /* * A region containing a mapping of a non-memory backed file under NOMMU * conditions. These are held in a global tree and are pinned by the VMAs that @@ -111,7 +109,7 @@ typedef unsigned long __nocast vm_flags_t; */ struct vm_region { struct rb_node vm_rb; /* link in global region tree */ - vm_flags_t vm_flags; /* VMA vm_flags */ + unsigned long vm_flags; /* VMA vm_flags */ unsigned long vm_start; /* start address of region */ unsigned long vm_end; /* region initialised to here */ unsigned long vm_top; /* region allocated to here */ @@ -302,9 +300,11 @@ struct mm_struct { struct task_struct __rcu *owner; #endif +#ifdef CONFIG_PROC_FS /* store ref to file /proc//exe symlink points to */ struct file *exe_file; unsigned long num_exe_file_vmas; +#endif #ifdef CONFIG_MMU_NOTIFIER struct mmu_notifier_mm *mmu_notifier_mm; #endif diff --git a/trunk/include/linux/mmzone.h b/trunk/include/linux/mmzone.h index 29312bdf119f..217bcf6bca77 100644 --- a/trunk/include/linux/mmzone.h +++ b/trunk/include/linux/mmzone.h @@ -273,6 +273,11 @@ struct zone_reclaim_stat { */ unsigned long recent_rotated[2]; unsigned long recent_scanned[2]; + + /* + * accumulated for batching + */ + unsigned long nr_saved_scan[NR_LRU_LISTS]; }; struct zone { diff --git a/trunk/include/linux/netlink.h b/trunk/include/linux/netlink.h index a9dd89552f9c..4c4ac3f3ce5a 100644 --- a/trunk/include/linux/netlink.h +++ b/trunk/include/linux/netlink.h @@ -24,7 +24,6 @@ /* leave room for NETLINK_DM (DM Events) */ #define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ #define NETLINK_ECRYPTFS 19 -#define NETLINK_RDMA 20 #define MAX_LINKS 32 diff --git a/trunk/include/linux/nsproxy.h b/trunk/include/linux/nsproxy.h index 50d20aba57d3..7b370c7cfeff 100644 --- a/trunk/include/linux/nsproxy.h +++ b/trunk/include/linux/nsproxy.h @@ -81,4 +81,13 @@ static inline void get_nsproxy(struct nsproxy *ns) atomic_inc(&ns->count); } +#ifdef CONFIG_CGROUP_NS +int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid); +#else +static inline int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid) +{ + return 0; +} +#endif + #endif diff --git a/trunk/include/linux/pid.h b/trunk/include/linux/pid.h index b152d44fb181..cdced84261d7 100644 --- a/trunk/include/linux/pid.h +++ b/trunk/include/linux/pid.h @@ -105,7 +105,7 @@ extern struct pid_namespace init_pid_ns; * or rcu_read_lock() held. * * find_pid_ns() finds the pid in the namespace specified - * find_vpid() finds the pid by its virtual id, i.e. in the current namespace + * find_vpid() finr the pid by its virtual id, i.e. in the current namespace * * see also find_task_by_vpid() set in include/linux/sched.h */ diff --git a/trunk/include/linux/power/isp1704_charger.h b/trunk/include/linux/power/isp1704_charger.h deleted file mode 100644 index 68096a6aa2d7..000000000000 --- a/trunk/include/linux/power/isp1704_charger.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * ISP1704 USB Charger Detection driver - * - * Copyright (C) 2011 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#ifndef __ISP1704_CHARGER_H -#define __ISP1704_CHARGER_H - -struct isp1704_charger_data { - void (*set_power)(bool on); -}; - -#endif diff --git a/trunk/include/linux/power/max8903_charger.h b/trunk/include/linux/power/max8903_charger.h deleted file mode 100644 index 24f51db8a83f..000000000000 --- a/trunk/include/linux/power/max8903_charger.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * max8903_charger.h - Maxim 8903 USB/Adapter Charger Driver - * - * Copyright (C) 2011 Samsung Electronics - * MyungJoo Ham - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __MAX8903_CHARGER_H__ -#define __MAX8903_CHARGER_H__ - -struct max8903_pdata { - /* - * GPIOs - * cen, chg, flt, and usus are optional. - * dok, dcm, and uok are not optional depending on the status of - * dc_valid and usb_valid. - */ - int cen; /* Charger Enable input */ - int dok; /* DC(Adapter) Power OK output */ - int uok; /* USB Power OK output */ - int chg; /* Charger status output */ - int flt; /* Fault output */ - int dcm; /* Current-Limit Mode input (1: DC, 2: USB) */ - int usus; /* USB Suspend Input (1: suspended) */ - - /* - * DC(Adapter/TA) is wired - * When dc_valid is true, - * dok and dcm should be valid. - * - * At least one of dc_valid or usb_valid should be true. - */ - bool dc_valid; - /* - * USB is wired - * When usb_valid is true, - * uok should be valid. - */ - bool usb_valid; -}; - -#endif /* __MAX8903_CHARGER_H__ */ diff --git a/trunk/include/linux/proc_fs.h b/trunk/include/linux/proc_fs.h index e7576cf9e32d..648c9c58add7 100644 --- a/trunk/include/linux/proc_fs.h +++ b/trunk/include/linux/proc_fs.h @@ -173,6 +173,12 @@ extern void proc_net_remove(struct net *net, const char *name); extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name, struct proc_dir_entry *parent); +/* While the {get|set|dup}_mm_exe_file functions are for mm_structs, they are + * only needed to implement /proc/|self/exe so we define them here. */ +extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file); +extern struct file *get_mm_exe_file(struct mm_struct *mm); +extern void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm); + extern struct file *proc_ns_fget(int fd); #else @@ -224,6 +230,19 @@ static inline void pid_ns_release_proc(struct pid_namespace *ns) { } +static inline void set_mm_exe_file(struct mm_struct *mm, + struct file *new_exe_file) +{} + +static inline struct file *get_mm_exe_file(struct mm_struct *mm) +{ + return NULL; +} + +static inline void dup_mm_exe_file(struct mm_struct *oldmm, + struct mm_struct *newmm) +{} + static inline struct file *proc_ns_fget(int fd) { return ERR_PTR(-EINVAL); diff --git a/trunk/include/linux/regulator/machine.h b/trunk/include/linux/regulator/machine.h index ce3127a75c88..c4c4fc45f856 100644 --- a/trunk/include/linux/regulator/machine.h +++ b/trunk/include/linux/regulator/machine.h @@ -68,8 +68,6 @@ struct regulator_state { * * @min_uV: Smallest voltage consumers may set. * @max_uV: Largest voltage consumers may set. - * @uV_offset: Offset applied to voltages from consumer to compensate for - * voltage drops. * * @min_uA: Smallest consumers consumers may set. * @max_uA: Largest current consumers may set. @@ -101,8 +99,6 @@ struct regulation_constraints { int min_uV; int max_uV; - int uV_offset; - /* current output range (inclusive) - for current control */ int min_uA; int max_uA; @@ -164,6 +160,8 @@ struct regulator_consumer_supply { * @supply_regulator: Parent regulator. Specified using the regulator name * as it appears in the name field in sysfs, which can * be explicitly set using the constraints field 'name'. + * @supply_regulator_dev: Parent regulator (if any) - DEPRECATED in favour + * of supply_regulator. * * @constraints: Constraints. These must be specified for the regulator to * be usable. @@ -175,6 +173,7 @@ struct regulator_consumer_supply { */ struct regulator_init_data { const char *supply_regulator; /* or NULL for system supply */ + struct device *supply_regulator_dev; /* or NULL for system supply */ struct regulation_constraints constraints; diff --git a/trunk/include/linux/rtc.h b/trunk/include/linux/rtc.h index b27ebea25660..877ece45426f 100644 --- a/trunk/include/linux/rtc.h +++ b/trunk/include/linux/rtc.h @@ -92,10 +92,10 @@ struct rtc_pll_info { #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ /* interrupt flags */ -#define RTC_IRQF 0x80 /* Any of the following is active */ -#define RTC_PF 0x40 /* Periodic interrupt */ -#define RTC_AF 0x20 /* Alarm interrupt */ -#define RTC_UF 0x10 /* Update interrupt for 1Hz RTC */ +#define RTC_IRQF 0x80 /* any of the following is active */ +#define RTC_PF 0x40 +#define RTC_AF 0x20 +#define RTC_UF 0x10 #ifdef __KERNEL__ diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index dc8871295a5a..f18300eddfcb 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -513,7 +513,6 @@ struct thread_group_cputimer { spinlock_t lock; }; -#include struct autogroup; /* @@ -633,16 +632,6 @@ struct signal_struct { unsigned audit_tty; struct tty_audit_buf *tty_audit_buf; #endif -#ifdef CONFIG_CGROUPS - /* - * The threadgroup_fork_lock prevents threads from forking with - * CLONE_THREAD while held for writing. Use this for fork-sensitive - * threadgroup-wide operations. It's taken for reading in fork.c in - * copy_process(). - * Currently only needed write-side by cgroups. - */ - struct rw_semaphore threadgroup_fork_lock; -#endif int oom_adj; /* OOM kill score adjustment (bit shift) */ int oom_score_adj; /* OOM kill score adjustment */ @@ -2334,31 +2323,6 @@ static inline void unlock_task_sighand(struct task_struct *tsk, spin_unlock_irqrestore(&tsk->sighand->siglock, *flags); } -/* See the declaration of threadgroup_fork_lock in signal_struct. */ -#ifdef CONFIG_CGROUPS -static inline void threadgroup_fork_read_lock(struct task_struct *tsk) -{ - down_read(&tsk->signal->threadgroup_fork_lock); -} -static inline void threadgroup_fork_read_unlock(struct task_struct *tsk) -{ - up_read(&tsk->signal->threadgroup_fork_lock); -} -static inline void threadgroup_fork_write_lock(struct task_struct *tsk) -{ - down_write(&tsk->signal->threadgroup_fork_lock); -} -static inline void threadgroup_fork_write_unlock(struct task_struct *tsk) -{ - up_write(&tsk->signal->threadgroup_fork_lock); -} -#else -static inline void threadgroup_fork_read_lock(struct task_struct *tsk) {} -static inline void threadgroup_fork_read_unlock(struct task_struct *tsk) {} -static inline void threadgroup_fork_write_lock(struct task_struct *tsk) {} -static inline void threadgroup_fork_write_unlock(struct task_struct *tsk) {} -#endif - #ifndef __HAVE_THREAD_FUNCTIONS #define task_thread_info(task) ((struct thread_info *)(task)->stack) diff --git a/trunk/include/linux/seqlock.h b/trunk/include/linux/seqlock.h index e9811892844f..06d69648fc86 100644 --- a/trunk/include/linux/seqlock.h +++ b/trunk/include/linux/seqlock.h @@ -41,6 +41,9 @@ typedef struct { #define __SEQLOCK_UNLOCKED(lockname) \ { 0, __SPIN_LOCK_UNLOCKED(lockname) } +#define SEQLOCK_UNLOCKED \ + __SEQLOCK_UNLOCKED(old_style_seqlock_init) + #define seqlock_init(x) \ do { \ (x)->sequence = 0; \ diff --git a/trunk/include/linux/smp.h b/trunk/include/linux/smp.h index 7ad824d510a2..74243c86ba39 100644 --- a/trunk/include/linux/smp.h +++ b/trunk/include/linux/smp.h @@ -98,6 +98,16 @@ void ipi_call_unlock_irq(void); */ int on_each_cpu(smp_call_func_t func, void *info, int wait); +#define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */ +#define MSG_ALL 0x8001 + +#define MSG_INVALIDATE_TLB 0x0001 /* Remote processor TLB invalidate */ +#define MSG_STOP_CPU 0x0002 /* Sent to shut down slave CPU's + * when rebooting + */ +#define MSG_RESCHEDULE 0x0003 /* Reschedule request from master CPU*/ +#define MSG_CALL_FUNCTION 0x0004 /* Call function on all other CPUs */ + /* * Mark the boot cpu "online" so that it can call console drivers in * printk() and can access its per-cpu storage. diff --git a/trunk/include/linux/spi/spi.h b/trunk/include/linux/spi/spi.h index bb4f5fbbbd8e..b4d7710bc38d 100644 --- a/trunk/include/linux/spi/spi.h +++ b/trunk/include/linux/spi/spi.h @@ -581,7 +581,7 @@ extern int spi_bus_unlock(struct spi_master *master); * Callable only from contexts that can sleep. */ static inline int -spi_write(struct spi_device *spi, const void *buf, size_t len) +spi_write(struct spi_device *spi, const u8 *buf, size_t len) { struct spi_transfer t = { .tx_buf = buf, @@ -605,7 +605,7 @@ spi_write(struct spi_device *spi, const void *buf, size_t len) * Callable only from contexts that can sleep. */ static inline int -spi_read(struct spi_device *spi, void *buf, size_t len) +spi_read(struct spi_device *spi, u8 *buf, size_t len) { struct spi_transfer t = { .rx_buf = buf, @@ -620,8 +620,8 @@ spi_read(struct spi_device *spi, void *buf, size_t len) /* this copies txbuf and rxbuf data; for small transfers only! */ extern int spi_write_then_read(struct spi_device *spi, - const void *txbuf, unsigned n_tx, - void *rxbuf, unsigned n_rx); + const u8 *txbuf, unsigned n_tx, + u8 *rxbuf, unsigned n_rx); /** * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read diff --git a/trunk/include/linux/swap.h b/trunk/include/linux/swap.h index 384eb5fe530b..a5c6da5d8df8 100644 --- a/trunk/include/linux/swap.h +++ b/trunk/include/linux/swap.h @@ -257,8 +257,7 @@ extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem, extern unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, gfp_t gfp_mask, bool noswap, unsigned int swappiness, - struct zone *zone, - unsigned long *nr_scanned); + struct zone *zone); extern int __isolate_lru_page(struct page *page, int mode, int file); extern unsigned long shrink_all_memory(unsigned long nr_pages); extern int vm_swappiness; diff --git a/trunk/include/linux/vm_event_item.h b/trunk/include/linux/vm_event_item.h deleted file mode 100644 index 03b90cdc1921..000000000000 --- a/trunk/include/linux/vm_event_item.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef VM_EVENT_ITEM_H_INCLUDED -#define VM_EVENT_ITEM_H_INCLUDED - -#ifdef CONFIG_ZONE_DMA -#define DMA_ZONE(xx) xx##_DMA, -#else -#define DMA_ZONE(xx) -#endif - -#ifdef CONFIG_ZONE_DMA32 -#define DMA32_ZONE(xx) xx##_DMA32, -#else -#define DMA32_ZONE(xx) -#endif - -#ifdef CONFIG_HIGHMEM -#define HIGHMEM_ZONE(xx) , xx##_HIGH -#else -#define HIGHMEM_ZONE(xx) -#endif - -#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx) , xx##_MOVABLE - -enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, - FOR_ALL_ZONES(PGALLOC), - PGFREE, PGACTIVATE, PGDEACTIVATE, - PGFAULT, PGMAJFAULT, - FOR_ALL_ZONES(PGREFILL), - FOR_ALL_ZONES(PGSTEAL), - FOR_ALL_ZONES(PGSCAN_KSWAPD), - FOR_ALL_ZONES(PGSCAN_DIRECT), -#ifdef CONFIG_NUMA - PGSCAN_ZONE_RECLAIM_FAILED, -#endif - PGINODESTEAL, SLABS_SCANNED, KSWAPD_STEAL, KSWAPD_INODESTEAL, - KSWAPD_LOW_WMARK_HIT_QUICKLY, KSWAPD_HIGH_WMARK_HIT_QUICKLY, - KSWAPD_SKIP_CONGESTION_WAIT, - PAGEOUTRUN, ALLOCSTALL, PGROTATED, -#ifdef CONFIG_COMPACTION - COMPACTBLOCKS, COMPACTPAGES, COMPACTPAGEFAILED, - COMPACTSTALL, COMPACTFAIL, COMPACTSUCCESS, -#endif -#ifdef CONFIG_HUGETLB_PAGE - HTLB_BUDDY_PGALLOC, HTLB_BUDDY_PGALLOC_FAIL, -#endif - UNEVICTABLE_PGCULLED, /* culled to noreclaim list */ - UNEVICTABLE_PGSCANNED, /* scanned for reclaimability */ - UNEVICTABLE_PGRESCUED, /* rescued from noreclaim list */ - UNEVICTABLE_PGMLOCKED, - UNEVICTABLE_PGMUNLOCKED, - UNEVICTABLE_PGCLEARED, /* on COW, page truncate */ - UNEVICTABLE_PGSTRANDED, /* unable to isolate on unlock */ - UNEVICTABLE_MLOCKFREED, -#ifdef CONFIG_TRANSPARENT_HUGEPAGE - THP_FAULT_ALLOC, - THP_FAULT_FALLBACK, - THP_COLLAPSE_ALLOC, - THP_COLLAPSE_ALLOC_FAILED, - THP_SPLIT, -#endif - NR_VM_EVENT_ITEMS -}; - -#endif /* VM_EVENT_ITEM_H_INCLUDED */ diff --git a/trunk/include/linux/vmstat.h b/trunk/include/linux/vmstat.h index bcd942fa611c..51359837511a 100644 --- a/trunk/include/linux/vmstat.h +++ b/trunk/include/linux/vmstat.h @@ -5,9 +5,69 @@ #include #include #include -#include #include +#ifdef CONFIG_ZONE_DMA +#define DMA_ZONE(xx) xx##_DMA, +#else +#define DMA_ZONE(xx) +#endif + +#ifdef CONFIG_ZONE_DMA32 +#define DMA32_ZONE(xx) xx##_DMA32, +#else +#define DMA32_ZONE(xx) +#endif + +#ifdef CONFIG_HIGHMEM +#define HIGHMEM_ZONE(xx) , xx##_HIGH +#else +#define HIGHMEM_ZONE(xx) +#endif + + +#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx) , xx##_MOVABLE + +enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, + FOR_ALL_ZONES(PGALLOC), + PGFREE, PGACTIVATE, PGDEACTIVATE, + PGFAULT, PGMAJFAULT, + FOR_ALL_ZONES(PGREFILL), + FOR_ALL_ZONES(PGSTEAL), + FOR_ALL_ZONES(PGSCAN_KSWAPD), + FOR_ALL_ZONES(PGSCAN_DIRECT), +#ifdef CONFIG_NUMA + PGSCAN_ZONE_RECLAIM_FAILED, +#endif + PGINODESTEAL, SLABS_SCANNED, KSWAPD_STEAL, KSWAPD_INODESTEAL, + KSWAPD_LOW_WMARK_HIT_QUICKLY, KSWAPD_HIGH_WMARK_HIT_QUICKLY, + KSWAPD_SKIP_CONGESTION_WAIT, + PAGEOUTRUN, ALLOCSTALL, PGROTATED, +#ifdef CONFIG_COMPACTION + COMPACTBLOCKS, COMPACTPAGES, COMPACTPAGEFAILED, + COMPACTSTALL, COMPACTFAIL, COMPACTSUCCESS, +#endif +#ifdef CONFIG_HUGETLB_PAGE + HTLB_BUDDY_PGALLOC, HTLB_BUDDY_PGALLOC_FAIL, +#endif + UNEVICTABLE_PGCULLED, /* culled to noreclaim list */ + UNEVICTABLE_PGSCANNED, /* scanned for reclaimability */ + UNEVICTABLE_PGRESCUED, /* rescued from noreclaim list */ + UNEVICTABLE_PGMLOCKED, + UNEVICTABLE_PGMUNLOCKED, + UNEVICTABLE_PGCLEARED, /* on COW, page truncate */ + UNEVICTABLE_PGSTRANDED, /* unable to isolate on unlock */ + UNEVICTABLE_MLOCKFREED, +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + THP_FAULT_ALLOC, + THP_FAULT_FALLBACK, + THP_COLLAPSE_ALLOC, + THP_COLLAPSE_ALLOC_FAILED, + THP_SPLIT, +#endif + NR_VM_EVENT_ITEMS +}; + extern int sysctl_stat_interval; #ifdef CONFIG_VM_EVENT_COUNTERS diff --git a/trunk/include/media/m5mols.h b/trunk/include/media/m5mols.h deleted file mode 100644 index 2d7e7ca2313d..000000000000 --- a/trunk/include/media/m5mols.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Driver header for M-5MOLS 8M Pixel camera sensor with ISP - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com - * - * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef MEDIA_M5MOLS_H -#define MEDIA_M5MOLS_H - -/** - * struct m5mols_platform_data - platform data for M-5MOLS driver - * @irq: GPIO getting the irq pin of M-5MOLS - * @gpio_reset: GPIO driving the reset pin of M-5MOLS - * @reset_polarity: active state for gpio_rst pin, 0 or 1 - * @set_power: an additional callback to the board setup code - * to be called after enabling and before disabling - * the sensor's supply regulators - */ -struct m5mols_platform_data { - int irq; - int gpio_reset; - u8 reset_polarity; - int (*set_power)(struct device *dev, int on); -}; - -#endif /* MEDIA_M5MOLS_H */ diff --git a/trunk/include/media/videobuf-dvb.h b/trunk/include/media/videobuf-dvb.h index bf365721d6b0..07cf4b9d0a65 100644 --- a/trunk/include/media/videobuf-dvb.h +++ b/trunk/include/media/videobuf-dvb.h @@ -4,9 +4,6 @@ #include #include -#ifndef _VIDEOBUF_DVB_H_ -#define _VIDEOBUF_DVB_H_ - struct videobuf_dvb { /* filling that the job of the driver */ char *name; @@ -57,7 +54,6 @@ void videobuf_dvb_dealloc_frontends(struct videobuf_dvb_frontends *f); struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_frontends *f, int id); int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p); -#endif /* _VIDEOBUF_DVB_H_ */ /* * Local variables: diff --git a/trunk/include/rdma/Kbuild b/trunk/include/rdma/Kbuild index ea56f76c0c22..e7c043216558 100644 --- a/trunk/include/rdma/Kbuild +++ b/trunk/include/rdma/Kbuild @@ -1,6 +1 @@ -header-y += ib_user_cm.h header-y += ib_user_mad.h -header-y += ib_user_sa.h -header-y += ib_user_verbs.h -header-y += rdma_netlink.h -header-y += rdma_user_cm.h diff --git a/trunk/include/rdma/ib_user_cm.h b/trunk/include/rdma/ib_user_cm.h index f79014aa28f9..bd3d380781e0 100644 --- a/trunk/include/rdma/ib_user_cm.h +++ b/trunk/include/rdma/ib_user_cm.h @@ -34,7 +34,6 @@ #ifndef IB_USER_CM_H #define IB_USER_CM_H -#include #include #define IB_USER_CM_ABI_VERSION 5 diff --git a/trunk/include/rdma/rdma_cm.h b/trunk/include/rdma/rdma_cm.h index 26977c149c41..169f7a53fb0c 100644 --- a/trunk/include/rdma/rdma_cm.h +++ b/trunk/include/rdma/rdma_cm.h @@ -111,20 +111,6 @@ struct rdma_cm_event { } param; }; -enum rdma_cm_state { - RDMA_CM_IDLE, - RDMA_CM_ADDR_QUERY, - RDMA_CM_ADDR_RESOLVED, - RDMA_CM_ROUTE_QUERY, - RDMA_CM_ROUTE_RESOLVED, - RDMA_CM_CONNECT, - RDMA_CM_DISCONNECT, - RDMA_CM_ADDR_BOUND, - RDMA_CM_LISTEN, - RDMA_CM_DEVICE_REMOVAL, - RDMA_CM_DESTROYING -}; - struct rdma_cm_id; /** @@ -144,7 +130,6 @@ struct rdma_cm_id { rdma_cm_event_handler event_handler; struct rdma_route route; enum rdma_port_space ps; - enum ib_qp_type qp_type; u8 port_num; }; @@ -155,11 +140,9 @@ struct rdma_cm_id { * returned rdma_id. * @context: User specified context associated with the id. * @ps: RDMA port space. - * @qp_type: type of queue pair associated with the id. */ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler, - void *context, enum rdma_port_space ps, - enum ib_qp_type qp_type); + void *context, enum rdma_port_space ps); /** * rdma_destroy_id - Destroys an RDMA identifier. diff --git a/trunk/include/rdma/rdma_netlink.h b/trunk/include/rdma/rdma_netlink.h deleted file mode 100644 index 3c5363ab867b..000000000000 --- a/trunk/include/rdma/rdma_netlink.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef _RDMA_NETLINK_H -#define _RDMA_NETLINK_H - -#include - -enum { - RDMA_NL_RDMA_CM = 1 -}; - -#define RDMA_NL_GET_CLIENT(type) ((type & (((1 << 6) - 1) << 10)) >> 10) -#define RDMA_NL_GET_OP(type) (type & ((1 << 10) - 1)) -#define RDMA_NL_GET_TYPE(client, op) ((client << 10) + op) - -enum { - RDMA_NL_RDMA_CM_ID_STATS = 0, - RDMA_NL_RDMA_CM_NUM_OPS -}; - -enum { - RDMA_NL_RDMA_CM_ATTR_SRC_ADDR = 1, - RDMA_NL_RDMA_CM_ATTR_DST_ADDR, - RDMA_NL_RDMA_CM_NUM_ATTR, -}; - -struct rdma_cm_id_stats { - __u32 qp_num; - __u32 bound_dev_if; - __u32 port_space; - __s32 pid; - __u8 cm_state; - __u8 node_type; - __u8 port_num; - __u8 qp_type; -}; - -#ifdef __KERNEL__ - -#include - -struct ibnl_client_cbs { - int (*dump)(struct sk_buff *skb, struct netlink_callback *nlcb); -}; - -int ibnl_init(void); -void ibnl_cleanup(void); - -/** - * Add a a client to the list of IB netlink exporters. - * @index: Index of the added client - * @nops: Number of supported ops by the added client. - * @cb_table: A table for op->callback - * - * Returns 0 on success or a negative error code. - */ -int ibnl_add_client(int index, int nops, - const struct ibnl_client_cbs cb_table[]); - -/** - * Remove a client from IB netlink. - * @index: Index of the removed IB client. - * - * Returns 0 on success or a negative error code. - */ -int ibnl_remove_client(int index); - -/** - * Put a new message in a supplied skb. - * @skb: The netlink skb. - * @nlh: Pointer to put the header of the new netlink message. - * @seq: The message sequence number. - * @len: The requested message length to allocate. - * @client: Calling IB netlink client. - * @op: message content op. - * Returns the allocated buffer on success and NULL on failure. - */ -void *ibnl_put_msg(struct sk_buff *skb, struct nlmsghdr **nlh, int seq, - int len, int client, int op); -/** - * Put a new attribute in a supplied skb. - * @skb: The netlink skb. - * @nlh: Header of the netlink message to append the attribute to. - * @len: The length of the attribute data. - * @data: The attribute data to put. - * @type: The attribute type. - * Returns the 0 and a negative error code on failure. - */ -int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh, - int len, void *data, int type); - -#endif /* __KERNEL__ */ - -#endif /* _RDMA_NETLINK_H */ diff --git a/trunk/include/trace/events/gpio.h b/trunk/include/trace/events/gpio.h deleted file mode 100644 index 927a8ad9e51b..000000000000 --- a/trunk/include/trace/events/gpio.h +++ /dev/null @@ -1,56 +0,0 @@ -#undef TRACE_SYSTEM -#define TRACE_SYSTEM gpio - -#if !defined(_TRACE_GPIO_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_GPIO_H - -#include - -TRACE_EVENT(gpio_direction, - - TP_PROTO(unsigned gpio, int in, int err), - - TP_ARGS(gpio, in, err), - - TP_STRUCT__entry( - __field(unsigned, gpio) - __field(int, in) - __field(int, err) - ), - - TP_fast_assign( - __entry->gpio = gpio; - __entry->in = in; - __entry->err = err; - ), - - TP_printk("%u %3s (%d)", __entry->gpio, - __entry->in ? "in" : "out", __entry->err) -); - -TRACE_EVENT(gpio_value, - - TP_PROTO(unsigned gpio, int get, int value), - - TP_ARGS(gpio, get, value), - - TP_STRUCT__entry( - __field(unsigned, gpio) - __field(int, get) - __field(int, value) - ), - - TP_fast_assign( - __entry->gpio = gpio; - __entry->get = get; - __entry->value = value; - ), - - TP_printk("%u %3s %d", __entry->gpio, - __entry->get ? "get" : "set", __entry->value) -); - -#endif /* if !defined(_TRACE_GPIO_H) || defined(TRACE_HEADER_MULTI_READ) */ - -/* This part must be outside protection */ -#include diff --git a/trunk/include/xen/interface/xen.h b/trunk/include/xen/interface/xen.h index 70213b4515eb..b33257bc7e83 100644 --- a/trunk/include/xen/interface/xen.h +++ b/trunk/include/xen/interface/xen.h @@ -58,7 +58,6 @@ #define __HYPERVISOR_event_channel_op 32 #define __HYPERVISOR_physdev_op 33 #define __HYPERVISOR_hvm_op 34 -#define __HYPERVISOR_tmem_op 38 /* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48 @@ -462,27 +461,6 @@ typedef uint8_t xen_domain_handle_t[16]; #define __mk_unsigned_long(x) x ## UL #define mk_unsigned_long(x) __mk_unsigned_long(x) -#define TMEM_SPEC_VERSION 1 - -struct tmem_op { - uint32_t cmd; - int32_t pool_id; - union { - struct { /* for cmd == TMEM_NEW_POOL */ - uint64_t uuid[2]; - uint32_t flags; - } new; - struct { - uint64_t oid[3]; - uint32_t index; - uint32_t tmem_offset; - uint32_t pfn_offset; - uint32_t len; - GUEST_HANDLE(void) gmfn; /* guest machine page frame */ - } gen; - } u; -}; - #else /* __ASSEMBLY__ */ /* In assembly code we cannot use C numeric constant suffixes. */ diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index ebafac4231ee..332aac649966 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -589,6 +589,14 @@ config CGROUP_DEBUG Say N if unsure. +config CGROUP_NS + bool "Namespace cgroup subsystem" + help + Provides a simple namespace cgroup subsystem to + provide hierarchical naming of sets of namespaces, + for instance virtual servers and checkpoint/restart + jobs. + config CGROUP_FREEZER bool "Freezer cgroup subsystem" help diff --git a/trunk/ipc/shm.c b/trunk/ipc/shm.c index ab3385a21b27..729acb7e3148 100644 --- a/trunk/ipc/shm.c +++ b/trunk/ipc/shm.c @@ -347,7 +347,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) struct file * file; char name[13]; int id; - vm_flags_t acctflag = 0; + int acctflag = 0; if (size < SHMMIN || size > ns->shm_ctlmax) return -EINVAL; diff --git a/trunk/kernel/Makefile b/trunk/kernel/Makefile index 2d64cfcc8b42..e9cf19155b46 100644 --- a/trunk/kernel/Makefile +++ b/trunk/kernel/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_CGROUPS) += cgroup.o obj-$(CONFIG_CGROUP_FREEZER) += cgroup_freezer.o obj-$(CONFIG_CPUSETS) += cpuset.o +obj-$(CONFIG_CGROUP_NS) += ns_cgroup.o obj-$(CONFIG_UTS_NS) += utsname.o obj-$(CONFIG_USER_NS) += user_namespace.o obj-$(CONFIG_PID_NS) += pid_namespace.o diff --git a/trunk/kernel/cgroup.c b/trunk/kernel/cgroup.c index 2731d115d725..909a35510af5 100644 --- a/trunk/kernel/cgroup.c +++ b/trunk/kernel/cgroup.c @@ -57,7 +57,6 @@ #include /* TODO: replace with more sophisticated array */ #include #include -#include /* used in cgroup_attach_proc */ #include @@ -1736,76 +1735,6 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen) } EXPORT_SYMBOL_GPL(cgroup_path); -/* - * cgroup_task_migrate - move a task from one cgroup to another. - * - * 'guarantee' is set if the caller promises that a new css_set for the task - * will already exist. If not set, this function might sleep, and can fail with - * -ENOMEM. Otherwise, it can only fail with -ESRCH. - */ -static int cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp, - struct task_struct *tsk, bool guarantee) -{ - struct css_set *oldcg; - struct css_set *newcg; - - /* - * get old css_set. we need to take task_lock and refcount it, because - * an exiting task can change its css_set to init_css_set and drop its - * old one without taking cgroup_mutex. - */ - task_lock(tsk); - oldcg = tsk->cgroups; - get_css_set(oldcg); - task_unlock(tsk); - - /* locate or allocate a new css_set for this task. */ - if (guarantee) { - /* we know the css_set we want already exists. */ - struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT]; - read_lock(&css_set_lock); - newcg = find_existing_css_set(oldcg, cgrp, template); - BUG_ON(!newcg); - get_css_set(newcg); - read_unlock(&css_set_lock); - } else { - might_sleep(); - /* find_css_set will give us newcg already referenced. */ - newcg = find_css_set(oldcg, cgrp); - if (!newcg) { - put_css_set(oldcg); - return -ENOMEM; - } - } - put_css_set(oldcg); - - /* if PF_EXITING is set, the tsk->cgroups pointer is no longer safe. */ - task_lock(tsk); - if (tsk->flags & PF_EXITING) { - task_unlock(tsk); - put_css_set(newcg); - return -ESRCH; - } - rcu_assign_pointer(tsk->cgroups, newcg); - task_unlock(tsk); - - /* Update the css_set linked lists if we're using them */ - write_lock(&css_set_lock); - if (!list_empty(&tsk->cg_list)) - list_move(&tsk->cg_list, &newcg->tasks); - write_unlock(&css_set_lock); - - /* - * We just gained a reference on oldcg by taking it from the task. As - * trading it for newcg is protected by cgroup_mutex, we're safe to drop - * it here; it will be freed under RCU. - */ - put_css_set(oldcg); - - set_bit(CGRP_RELEASABLE, &oldcgrp->flags); - return 0; -} - /** * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp' * @cgrp: the cgroup the task is attaching to @@ -1816,9 +1745,11 @@ static int cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp, */ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) { - int retval; + int retval = 0; struct cgroup_subsys *ss, *failed_ss = NULL; struct cgroup *oldcgrp; + struct css_set *cg; + struct css_set *newcg; struct cgroupfs_root *root = cgrp->root; /* Nothing to do if the task is already in that cgroup */ @@ -1828,7 +1759,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) for_each_subsys(root, ss) { if (ss->can_attach) { - retval = ss->can_attach(ss, cgrp, tsk); + retval = ss->can_attach(ss, cgrp, tsk, false); if (retval) { /* * Remember on which subsystem the can_attach() @@ -1840,29 +1771,46 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) goto out; } } - if (ss->can_attach_task) { - retval = ss->can_attach_task(cgrp, tsk); - if (retval) { - failed_ss = ss; - goto out; - } - } } - retval = cgroup_task_migrate(cgrp, oldcgrp, tsk, false); - if (retval) + task_lock(tsk); + cg = tsk->cgroups; + get_css_set(cg); + task_unlock(tsk); + /* + * Locate or allocate a new css_set for this task, + * based on its final set of cgroups + */ + newcg = find_css_set(cg, cgrp); + put_css_set(cg); + if (!newcg) { + retval = -ENOMEM; + goto out; + } + + task_lock(tsk); + if (tsk->flags & PF_EXITING) { + task_unlock(tsk); + put_css_set(newcg); + retval = -ESRCH; goto out; + } + rcu_assign_pointer(tsk->cgroups, newcg); + task_unlock(tsk); + + /* Update the css_set linked lists if we're using them */ + write_lock(&css_set_lock); + if (!list_empty(&tsk->cg_list)) + list_move(&tsk->cg_list, &newcg->tasks); + write_unlock(&css_set_lock); for_each_subsys(root, ss) { - if (ss->pre_attach) - ss->pre_attach(cgrp); - if (ss->attach_task) - ss->attach_task(cgrp, tsk); if (ss->attach) - ss->attach(ss, cgrp, oldcgrp, tsk); + ss->attach(ss, cgrp, oldcgrp, tsk, false); } - + set_bit(CGRP_RELEASABLE, &oldcgrp->flags); synchronize_rcu(); + put_css_set(cg); /* * wake up rmdir() waiter. the rmdir should fail since the cgroup @@ -1881,7 +1829,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) */ break; if (ss->cancel_attach) - ss->cancel_attach(ss, cgrp, tsk); + ss->cancel_attach(ss, cgrp, tsk, false); } } return retval; @@ -1912,370 +1860,49 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk) EXPORT_SYMBOL_GPL(cgroup_attach_task_all); /* - * cgroup_attach_proc works in two stages, the first of which prefetches all - * new css_sets needed (to make sure we have enough memory before committing - * to the move) and stores them in a list of entries of the following type. - * TODO: possible optimization: use css_set->rcu_head for chaining instead - */ -struct cg_list_entry { - struct css_set *cg; - struct list_head links; -}; - -static bool css_set_check_fetched(struct cgroup *cgrp, - struct task_struct *tsk, struct css_set *cg, - struct list_head *newcg_list) -{ - struct css_set *newcg; - struct cg_list_entry *cg_entry; - struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT]; - - read_lock(&css_set_lock); - newcg = find_existing_css_set(cg, cgrp, template); - if (newcg) - get_css_set(newcg); - read_unlock(&css_set_lock); - - /* doesn't exist at all? */ - if (!newcg) - return false; - /* see if it's already in the list */ - list_for_each_entry(cg_entry, newcg_list, links) { - if (cg_entry->cg == newcg) { - put_css_set(newcg); - return true; - } - } - - /* not found */ - put_css_set(newcg); - return false; -} - -/* - * Find the new css_set and store it in the list in preparation for moving the - * given task to the given cgroup. Returns 0 or -ENOMEM. - */ -static int css_set_prefetch(struct cgroup *cgrp, struct css_set *cg, - struct list_head *newcg_list) -{ - struct css_set *newcg; - struct cg_list_entry *cg_entry; - - /* ensure a new css_set will exist for this thread */ - newcg = find_css_set(cg, cgrp); - if (!newcg) - return -ENOMEM; - /* add it to the list */ - cg_entry = kmalloc(sizeof(struct cg_list_entry), GFP_KERNEL); - if (!cg_entry) { - put_css_set(newcg); - return -ENOMEM; - } - cg_entry->cg = newcg; - list_add(&cg_entry->links, newcg_list); - return 0; -} - -/** - * cgroup_attach_proc - attach all threads in a threadgroup to a cgroup - * @cgrp: the cgroup to attach to - * @leader: the threadgroup leader task_struct of the group to be attached - * - * Call holding cgroup_mutex and the threadgroup_fork_lock of the leader. Will - * take task_lock of each thread in leader's threadgroup individually in turn. - */ -int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader) -{ - int retval, i, group_size; - struct cgroup_subsys *ss, *failed_ss = NULL; - bool cancel_failed_ss = false; - /* guaranteed to be initialized later, but the compiler needs this */ - struct cgroup *oldcgrp = NULL; - struct css_set *oldcg; - struct cgroupfs_root *root = cgrp->root; - /* threadgroup list cursor and array */ - struct task_struct *tsk; - struct flex_array *group; - /* - * we need to make sure we have css_sets for all the tasks we're - * going to move -before- we actually start moving them, so that in - * case we get an ENOMEM we can bail out before making any changes. - */ - struct list_head newcg_list; - struct cg_list_entry *cg_entry, *temp_nobe; - - /* - * step 0: in order to do expensive, possibly blocking operations for - * every thread, we cannot iterate the thread group list, since it needs - * rcu or tasklist locked. instead, build an array of all threads in the - * group - threadgroup_fork_lock prevents new threads from appearing, - * and if threads exit, this will just be an over-estimate. - */ - group_size = get_nr_threads(leader); - /* flex_array supports very large thread-groups better than kmalloc. */ - group = flex_array_alloc(sizeof(struct task_struct *), group_size, - GFP_KERNEL); - if (!group) - return -ENOMEM; - /* pre-allocate to guarantee space while iterating in rcu read-side. */ - retval = flex_array_prealloc(group, 0, group_size - 1, GFP_KERNEL); - if (retval) - goto out_free_group_list; - - /* prevent changes to the threadgroup list while we take a snapshot. */ - rcu_read_lock(); - if (!thread_group_leader(leader)) { - /* - * a race with de_thread from another thread's exec() may strip - * us of our leadership, making while_each_thread unsafe to use - * on this task. if this happens, there is no choice but to - * throw this task away and try again (from cgroup_procs_write); - * this is "double-double-toil-and-trouble-check locking". - */ - rcu_read_unlock(); - retval = -EAGAIN; - goto out_free_group_list; - } - /* take a reference on each task in the group to go in the array. */ - tsk = leader; - i = 0; - do { - /* as per above, nr_threads may decrease, but not increase. */ - BUG_ON(i >= group_size); - get_task_struct(tsk); - /* - * saying GFP_ATOMIC has no effect here because we did prealloc - * earlier, but it's good form to communicate our expectations. - */ - retval = flex_array_put_ptr(group, i, tsk, GFP_ATOMIC); - BUG_ON(retval != 0); - i++; - } while_each_thread(leader, tsk); - /* remember the number of threads in the array for later. */ - group_size = i; - rcu_read_unlock(); - - /* - * step 1: check that we can legitimately attach to the cgroup. - */ - for_each_subsys(root, ss) { - if (ss->can_attach) { - retval = ss->can_attach(ss, cgrp, leader); - if (retval) { - failed_ss = ss; - goto out_cancel_attach; - } - } - /* a callback to be run on every thread in the threadgroup. */ - if (ss->can_attach_task) { - /* run on each task in the threadgroup. */ - for (i = 0; i < group_size; i++) { - tsk = flex_array_get_ptr(group, i); - retval = ss->can_attach_task(cgrp, tsk); - if (retval) { - failed_ss = ss; - cancel_failed_ss = true; - goto out_cancel_attach; - } - } - } - } - - /* - * step 2: make sure css_sets exist for all threads to be migrated. - * we use find_css_set, which allocates a new one if necessary. - */ - INIT_LIST_HEAD(&newcg_list); - for (i = 0; i < group_size; i++) { - tsk = flex_array_get_ptr(group, i); - /* nothing to do if this task is already in the cgroup */ - oldcgrp = task_cgroup_from_root(tsk, root); - if (cgrp == oldcgrp) - continue; - /* get old css_set pointer */ - task_lock(tsk); - if (tsk->flags & PF_EXITING) { - /* ignore this task if it's going away */ - task_unlock(tsk); - continue; - } - oldcg = tsk->cgroups; - get_css_set(oldcg); - task_unlock(tsk); - /* see if the new one for us is already in the list? */ - if (css_set_check_fetched(cgrp, tsk, oldcg, &newcg_list)) { - /* was already there, nothing to do. */ - put_css_set(oldcg); - } else { - /* we don't already have it. get new one. */ - retval = css_set_prefetch(cgrp, oldcg, &newcg_list); - put_css_set(oldcg); - if (retval) - goto out_list_teardown; - } - } - - /* - * step 3: now that we're guaranteed success wrt the css_sets, proceed - * to move all tasks to the new cgroup, calling ss->attach_task for each - * one along the way. there are no failure cases after here, so this is - * the commit point. - */ - for_each_subsys(root, ss) { - if (ss->pre_attach) - ss->pre_attach(cgrp); - } - for (i = 0; i < group_size; i++) { - tsk = flex_array_get_ptr(group, i); - /* leave current thread as it is if it's already there */ - oldcgrp = task_cgroup_from_root(tsk, root); - if (cgrp == oldcgrp) - continue; - /* attach each task to each subsystem */ - for_each_subsys(root, ss) { - if (ss->attach_task) - ss->attach_task(cgrp, tsk); - } - /* if the thread is PF_EXITING, it can just get skipped. */ - retval = cgroup_task_migrate(cgrp, oldcgrp, tsk, true); - BUG_ON(retval != 0 && retval != -ESRCH); - } - /* nothing is sensitive to fork() after this point. */ - - /* - * step 4: do expensive, non-thread-specific subsystem callbacks. - * TODO: if ever a subsystem needs to know the oldcgrp for each task - * being moved, this call will need to be reworked to communicate that. - */ - for_each_subsys(root, ss) { - if (ss->attach) - ss->attach(ss, cgrp, oldcgrp, leader); - } - - /* - * step 5: success! and cleanup - */ - synchronize_rcu(); - cgroup_wakeup_rmdir_waiter(cgrp); - retval = 0; -out_list_teardown: - /* clean up the list of prefetched css_sets. */ - list_for_each_entry_safe(cg_entry, temp_nobe, &newcg_list, links) { - list_del(&cg_entry->links); - put_css_set(cg_entry->cg); - kfree(cg_entry); - } -out_cancel_attach: - /* same deal as in cgroup_attach_task */ - if (retval) { - for_each_subsys(root, ss) { - if (ss == failed_ss) { - if (cancel_failed_ss && ss->cancel_attach) - ss->cancel_attach(ss, cgrp, leader); - break; - } - if (ss->cancel_attach) - ss->cancel_attach(ss, cgrp, leader); - } - } - /* clean up the array of referenced threads in the group. */ - for (i = 0; i < group_size; i++) { - tsk = flex_array_get_ptr(group, i); - put_task_struct(tsk); - } -out_free_group_list: - flex_array_free(group); - return retval; -} - -/* - * Find the task_struct of the task to attach by vpid and pass it along to the - * function to attach either it or all tasks in its threadgroup. Will take - * cgroup_mutex; may take task_lock of task. + * Attach task with pid 'pid' to cgroup 'cgrp'. Call with cgroup_mutex + * held. May take task_lock of task */ -static int attach_task_by_pid(struct cgroup *cgrp, u64 pid, bool threadgroup) +static int attach_task_by_pid(struct cgroup *cgrp, u64 pid) { struct task_struct *tsk; const struct cred *cred = current_cred(), *tcred; int ret; - if (!cgroup_lock_live_group(cgrp)) - return -ENODEV; - if (pid) { rcu_read_lock(); tsk = find_task_by_vpid(pid); - if (!tsk) { + if (!tsk || tsk->flags & PF_EXITING) { rcu_read_unlock(); - cgroup_unlock(); - return -ESRCH; - } - if (threadgroup) { - /* - * RCU protects this access, since tsk was found in the - * tid map. a race with de_thread may cause group_leader - * to stop being the leader, but cgroup_attach_proc will - * detect it later. - */ - tsk = tsk->group_leader; - } else if (tsk->flags & PF_EXITING) { - /* optimization for the single-task-only case */ - rcu_read_unlock(); - cgroup_unlock(); return -ESRCH; } - /* - * even if we're attaching all tasks in the thread group, we - * only need to check permissions on one of them. - */ tcred = __task_cred(tsk); if (cred->euid && cred->euid != tcred->uid && cred->euid != tcred->suid) { rcu_read_unlock(); - cgroup_unlock(); return -EACCES; } get_task_struct(tsk); rcu_read_unlock(); } else { - if (threadgroup) - tsk = current->group_leader; - else - tsk = current; + tsk = current; get_task_struct(tsk); } - if (threadgroup) { - threadgroup_fork_write_lock(tsk); - ret = cgroup_attach_proc(cgrp, tsk); - threadgroup_fork_write_unlock(tsk); - } else { - ret = cgroup_attach_task(cgrp, tsk); - } + ret = cgroup_attach_task(cgrp, tsk); put_task_struct(tsk); - cgroup_unlock(); return ret; } static int cgroup_tasks_write(struct cgroup *cgrp, struct cftype *cft, u64 pid) -{ - return attach_task_by_pid(cgrp, pid, false); -} - -static int cgroup_procs_write(struct cgroup *cgrp, struct cftype *cft, u64 tgid) { int ret; - do { - /* - * attach_proc fails with -EAGAIN if threadgroup leadership - * changes in the middle of the operation, in which case we need - * to find the task_struct for the new leader and start over. - */ - ret = attach_task_by_pid(cgrp, tgid, true); - } while (ret == -EAGAIN); + if (!cgroup_lock_live_group(cgrp)) + return -ENODEV; + ret = attach_task_by_pid(cgrp, pid); + cgroup_unlock(); return ret; } @@ -3632,9 +3259,9 @@ static struct cftype files[] = { { .name = CGROUP_FILE_GENERIC_PREFIX "procs", .open = cgroup_procs_open, - .write_u64 = cgroup_procs_write, + /* .write_u64 = cgroup_procs_write, TODO */ .release = cgroup_pidlist_release, - .mode = S_IRUGO | S_IWUSR, + .mode = S_IRUGO, }, { .name = "notify_on_release", @@ -4629,6 +4256,122 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks) put_css_set_taskexit(cg); } +/** + * cgroup_clone - clone the cgroup the given subsystem is attached to + * @tsk: the task to be moved + * @subsys: the given subsystem + * @nodename: the name for the new cgroup + * + * Duplicate the current cgroup in the hierarchy that the given + * subsystem is attached to, and move this task into the new + * child. + */ +int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys, + char *nodename) +{ + struct dentry *dentry; + int ret = 0; + struct cgroup *parent, *child; + struct inode *inode; + struct css_set *cg; + struct cgroupfs_root *root; + struct cgroup_subsys *ss; + + /* We shouldn't be called by an unregistered subsystem */ + BUG_ON(!subsys->active); + + /* First figure out what hierarchy and cgroup we're dealing + * with, and pin them so we can drop cgroup_mutex */ + mutex_lock(&cgroup_mutex); + again: + root = subsys->root; + if (root == &rootnode) { + mutex_unlock(&cgroup_mutex); + return 0; + } + + /* Pin the hierarchy */ + if (!atomic_inc_not_zero(&root->sb->s_active)) { + /* We race with the final deactivate_super() */ + mutex_unlock(&cgroup_mutex); + return 0; + } + + /* Keep the cgroup alive */ + task_lock(tsk); + parent = task_cgroup(tsk, subsys->subsys_id); + cg = tsk->cgroups; + get_css_set(cg); + task_unlock(tsk); + + mutex_unlock(&cgroup_mutex); + + /* Now do the VFS work to create a cgroup */ + inode = parent->dentry->d_inode; + + /* Hold the parent directory mutex across this operation to + * stop anyone else deleting the new cgroup */ + mutex_lock(&inode->i_mutex); + dentry = lookup_one_len(nodename, parent->dentry, strlen(nodename)); + if (IS_ERR(dentry)) { + printk(KERN_INFO + "cgroup: Couldn't allocate dentry for %s: %ld\n", nodename, + PTR_ERR(dentry)); + ret = PTR_ERR(dentry); + goto out_release; + } + + /* Create the cgroup directory, which also creates the cgroup */ + ret = vfs_mkdir(inode, dentry, 0755); + child = __d_cgrp(dentry); + dput(dentry); + if (ret) { + printk(KERN_INFO + "Failed to create cgroup %s: %d\n", nodename, + ret); + goto out_release; + } + + /* The cgroup now exists. Retake cgroup_mutex and check + * that we're still in the same state that we thought we + * were. */ + mutex_lock(&cgroup_mutex); + if ((root != subsys->root) || + (parent != task_cgroup(tsk, subsys->subsys_id))) { + /* Aargh, we raced ... */ + mutex_unlock(&inode->i_mutex); + put_css_set(cg); + + deactivate_super(root->sb); + /* The cgroup is still accessible in the VFS, but + * we're not going to try to rmdir() it at this + * point. */ + printk(KERN_INFO + "Race in cgroup_clone() - leaking cgroup %s\n", + nodename); + goto again; + } + + /* do any required auto-setup */ + for_each_subsys(root, ss) { + if (ss->post_clone) + ss->post_clone(ss, child); + } + + /* All seems fine. Finish by moving the task into the new cgroup */ + ret = cgroup_attach_task(child, tsk); + mutex_unlock(&cgroup_mutex); + + out_release: + mutex_unlock(&inode->i_mutex); + + mutex_lock(&cgroup_mutex); + put_css_set(cg); + mutex_unlock(&cgroup_mutex); + deactivate_super(root->sb); + return ret; +} + /** * cgroup_is_descendant - see if @cgrp is a descendant of @task's cgrp * @cgrp: the cgroup in question diff --git a/trunk/kernel/cgroup_freezer.c b/trunk/kernel/cgroup_freezer.c index e691818d7e45..e7bebb7c6c38 100644 --- a/trunk/kernel/cgroup_freezer.c +++ b/trunk/kernel/cgroup_freezer.c @@ -160,7 +160,7 @@ static void freezer_destroy(struct cgroup_subsys *ss, */ static int freezer_can_attach(struct cgroup_subsys *ss, struct cgroup *new_cgroup, - struct task_struct *task) + struct task_struct *task, bool threadgroup) { struct freezer *freezer; @@ -172,17 +172,26 @@ static int freezer_can_attach(struct cgroup_subsys *ss, if (freezer->state != CGROUP_THAWED) return -EBUSY; - return 0; -} - -static int freezer_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk) -{ rcu_read_lock(); - if (__cgroup_freezing_or_frozen(tsk)) { + if (__cgroup_freezing_or_frozen(task)) { rcu_read_unlock(); return -EBUSY; } rcu_read_unlock(); + + if (threadgroup) { + struct task_struct *c; + + rcu_read_lock(); + list_for_each_entry_rcu(c, &task->thread_group, thread_group) { + if (__cgroup_freezing_or_frozen(c)) { + rcu_read_unlock(); + return -EBUSY; + } + } + rcu_read_unlock(); + } + return 0; } @@ -381,9 +390,6 @@ struct cgroup_subsys freezer_subsys = { .populate = freezer_populate, .subsys_id = freezer_subsys_id, .can_attach = freezer_can_attach, - .can_attach_task = freezer_can_attach_task, - .pre_attach = NULL, - .attach_task = NULL, .attach = NULL, .fork = freezer_fork, .exit = NULL, diff --git a/trunk/kernel/cpuset.c b/trunk/kernel/cpuset.c index 1ceeb049c827..2bb8c2e98fff 100644 --- a/trunk/kernel/cpuset.c +++ b/trunk/kernel/cpuset.c @@ -1367,10 +1367,14 @@ static int fmeter_getrate(struct fmeter *fmp) return val; } +/* Protected by cgroup_lock */ +static cpumask_var_t cpus_attach; + /* Called by cgroups to determine if a cpuset is usable; cgroup_mutex held */ static int cpuset_can_attach(struct cgroup_subsys *ss, struct cgroup *cont, - struct task_struct *tsk) + struct task_struct *tsk, bool threadgroup) { + int ret; struct cpuset *cs = cgroup_cs(cont); if (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)) @@ -1387,42 +1391,29 @@ static int cpuset_can_attach(struct cgroup_subsys *ss, struct cgroup *cont, if (tsk->flags & PF_THREAD_BOUND) return -EINVAL; + ret = security_task_setscheduler(tsk); + if (ret) + return ret; + if (threadgroup) { + struct task_struct *c; + + rcu_read_lock(); + list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) { + ret = security_task_setscheduler(c); + if (ret) { + rcu_read_unlock(); + return ret; + } + } + rcu_read_unlock(); + } return 0; } -static int cpuset_can_attach_task(struct cgroup *cgrp, struct task_struct *task) -{ - return security_task_setscheduler(task); -} - -/* - * Protected by cgroup_lock. The nodemasks must be stored globally because - * dynamically allocating them is not allowed in pre_attach, and they must - * persist among pre_attach, attach_task, and attach. - */ -static cpumask_var_t cpus_attach; -static nodemask_t cpuset_attach_nodemask_from; -static nodemask_t cpuset_attach_nodemask_to; - -/* Set-up work for before attaching each task. */ -static void cpuset_pre_attach(struct cgroup *cont) -{ - struct cpuset *cs = cgroup_cs(cont); - - if (cs == &top_cpuset) - cpumask_copy(cpus_attach, cpu_possible_mask); - else - guarantee_online_cpus(cs, cpus_attach); - - guarantee_online_mems(cs, &cpuset_attach_nodemask_to); -} - -/* Per-thread attachment work. */ -static void cpuset_attach_task(struct cgroup *cont, struct task_struct *tsk) +static void cpuset_attach_task(struct task_struct *tsk, nodemask_t *to, + struct cpuset *cs) { int err; - struct cpuset *cs = cgroup_cs(cont); - /* * can_attach beforehand should guarantee that this doesn't fail. * TODO: have a better way to handle failure here @@ -1430,29 +1421,45 @@ static void cpuset_attach_task(struct cgroup *cont, struct task_struct *tsk) err = set_cpus_allowed_ptr(tsk, cpus_attach); WARN_ON_ONCE(err); - cpuset_change_task_nodemask(tsk, &cpuset_attach_nodemask_to); + cpuset_change_task_nodemask(tsk, to); cpuset_update_task_spread_flag(cs, tsk); + } static void cpuset_attach(struct cgroup_subsys *ss, struct cgroup *cont, - struct cgroup *oldcont, struct task_struct *tsk) + struct cgroup *oldcont, struct task_struct *tsk, + bool threadgroup) { struct mm_struct *mm; struct cpuset *cs = cgroup_cs(cont); struct cpuset *oldcs = cgroup_cs(oldcont); + static nodemask_t to; /* protected by cgroup_mutex */ - /* - * Change mm, possibly for multiple threads in a threadgroup. This is - * expensive and may sleep. - */ - cpuset_attach_nodemask_from = oldcs->mems_allowed; - cpuset_attach_nodemask_to = cs->mems_allowed; + if (cs == &top_cpuset) { + cpumask_copy(cpus_attach, cpu_possible_mask); + } else { + guarantee_online_cpus(cs, cpus_attach); + } + guarantee_online_mems(cs, &to); + + /* do per-task migration stuff possibly for each in the threadgroup */ + cpuset_attach_task(tsk, &to, cs); + if (threadgroup) { + struct task_struct *c; + rcu_read_lock(); + list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) { + cpuset_attach_task(c, &to, cs); + } + rcu_read_unlock(); + } + + /* change mm; only needs to be done once even if threadgroup */ + to = cs->mems_allowed; mm = get_task_mm(tsk); if (mm) { - mpol_rebind_mm(mm, &cpuset_attach_nodemask_to); + mpol_rebind_mm(mm, &to); if (is_memory_migrate(cs)) - cpuset_migrate_mm(mm, &cpuset_attach_nodemask_from, - &cpuset_attach_nodemask_to); + cpuset_migrate_mm(mm, &oldcs->mems_allowed, &to); mmput(mm); } } @@ -1802,9 +1809,10 @@ static int cpuset_populate(struct cgroup_subsys *ss, struct cgroup *cont) } /* - * post_clone() is called during cgroup_create() when the - * clone_children mount argument was specified. The cgroup - * can not yet have any tasks. + * post_clone() is called at the end of cgroup_clone(). + * 'cgroup' was just created automatically as a result of + * a cgroup_clone(), and the current task is about to + * be moved into 'cgroup'. * * Currently we refuse to set up the cgroup - thereby * refusing the task to be entered, and as a result refusing @@ -1903,9 +1911,6 @@ struct cgroup_subsys cpuset_subsys = { .create = cpuset_create, .destroy = cpuset_destroy, .can_attach = cpuset_can_attach, - .can_attach_task = cpuset_can_attach_task, - .pre_attach = cpuset_pre_attach, - .attach_task = cpuset_attach_task, .attach = cpuset_attach, .populate = cpuset_populate, .post_clone = cpuset_post_clone, diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index ca406d916713..8e7e135d0817 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -596,57 +597,6 @@ void mmput(struct mm_struct *mm) } EXPORT_SYMBOL_GPL(mmput); -/* - * We added or removed a vma mapping the executable. The vmas are only mapped - * during exec and are not mapped with the mmap system call. - * Callers must hold down_write() on the mm's mmap_sem for these - */ -void added_exe_file_vma(struct mm_struct *mm) -{ - mm->num_exe_file_vmas++; -} - -void removed_exe_file_vma(struct mm_struct *mm) -{ - mm->num_exe_file_vmas--; - if ((mm->num_exe_file_vmas == 0) && mm->exe_file){ - fput(mm->exe_file); - mm->exe_file = NULL; - } - -} - -void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) -{ - if (new_exe_file) - get_file(new_exe_file); - if (mm->exe_file) - fput(mm->exe_file); - mm->exe_file = new_exe_file; - mm->num_exe_file_vmas = 0; -} - -struct file *get_mm_exe_file(struct mm_struct *mm) -{ - struct file *exe_file; - - /* We need mmap_sem to protect against races with removal of - * VM_EXECUTABLE vmas */ - down_read(&mm->mmap_sem); - exe_file = mm->exe_file; - if (exe_file) - get_file(exe_file); - up_read(&mm->mmap_sem); - return exe_file; -} - -static void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm) -{ - /* It's safe to write the exe_file pointer without exe_file_lock because - * this is called during fork when the task is not yet in /proc */ - newmm->exe_file = get_mm_exe_file(oldmm); -} - /** * get_task_mm - acquire a reference to the task's mm * @@ -1007,10 +957,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) tty_audit_fork(sig); sched_autogroup_fork(sig); -#ifdef CONFIG_CGROUPS - init_rwsem(&sig->threadgroup_fork_lock); -#endif - sig->oom_adj = current->signal->oom_adj; sig->oom_score_adj = current->signal->oom_score_adj; sig->oom_score_adj_min = current->signal->oom_score_adj_min; @@ -1192,8 +1138,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, monotonic_to_bootbased(&p->real_start_time); p->io_context = NULL; p->audit_context = NULL; - if (clone_flags & CLONE_THREAD) - threadgroup_fork_read_lock(current); cgroup_fork(p); #ifdef CONFIG_NUMA p->mempolicy = mpol_dup(p->mempolicy); @@ -1279,6 +1223,12 @@ static struct task_struct *copy_process(unsigned long clone_flags, if (clone_flags & CLONE_THREAD) p->tgid = current->tgid; + if (current->nsproxy != p->nsproxy) { + retval = ns_cgroup_clone(p, pid); + if (retval) + goto bad_fork_free_pid; + } + p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; /* * Clear TID on mm_release()? @@ -1392,8 +1342,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, write_unlock_irq(&tasklist_lock); proc_fork_connector(p); cgroup_post_fork(p); - if (clone_flags & CLONE_THREAD) - threadgroup_fork_read_unlock(current); perf_event_fork(p); return p; @@ -1432,8 +1380,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, mpol_put(p->mempolicy); bad_fork_cleanup_cgroup: #endif - if (clone_flags & CLONE_THREAD) - threadgroup_fork_read_unlock(current); cgroup_exit(p, cgroup_callbacks_done); delayacct_tsk_free(p); module_put(task_thread_info(p)->exec_domain->module); diff --git a/trunk/kernel/irq/proc.c b/trunk/kernel/irq/proc.c index 4bd4faa6323a..64e3df6ab1ef 100644 --- a/trunk/kernel/irq/proc.c +++ b/trunk/kernel/irq/proc.c @@ -352,7 +352,6 @@ void unregister_irq_proc(unsigned int irq, struct irq_desc *desc) #ifdef CONFIG_SMP remove_proc_entry("smp_affinity", desc->dir); remove_proc_entry("affinity_hint", desc->dir); - remove_proc_entry("smp_affinity_list", desc->dir); remove_proc_entry("node", desc->dir); #endif remove_proc_entry("spurious", desc->dir); diff --git a/trunk/kernel/ns_cgroup.c b/trunk/kernel/ns_cgroup.c new file mode 100644 index 000000000000..2c98ad94ba0e --- /dev/null +++ b/trunk/kernel/ns_cgroup.c @@ -0,0 +1,118 @@ +/* + * ns_cgroup.c - namespace cgroup subsystem + * + * Copyright 2006, 2007 IBM Corp + */ + +#include +#include +#include +#include +#include +#include + +struct ns_cgroup { + struct cgroup_subsys_state css; +}; + +struct cgroup_subsys ns_subsys; + +static inline struct ns_cgroup *cgroup_to_ns( + struct cgroup *cgroup) +{ + return container_of(cgroup_subsys_state(cgroup, ns_subsys_id), + struct ns_cgroup, css); +} + +int ns_cgroup_clone(struct task_struct *task, struct pid *pid) +{ + char name[PROC_NUMBUF]; + + snprintf(name, PROC_NUMBUF, "%d", pid_vnr(pid)); + return cgroup_clone(task, &ns_subsys, name); +} + +/* + * Rules: + * 1. you can only enter a cgroup which is a descendant of your current + * cgroup + * 2. you can only place another process into a cgroup if + * a. you have CAP_SYS_ADMIN + * b. your cgroup is an ancestor of task's destination cgroup + * (hence either you are in the same cgroup as task, or in an + * ancestor cgroup thereof) + */ +static int ns_can_attach(struct cgroup_subsys *ss, struct cgroup *new_cgroup, + struct task_struct *task, bool threadgroup) +{ + if (current != task) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (!cgroup_is_descendant(new_cgroup, current)) + return -EPERM; + } + + if (!cgroup_is_descendant(new_cgroup, task)) + return -EPERM; + + if (threadgroup) { + struct task_struct *c; + rcu_read_lock(); + list_for_each_entry_rcu(c, &task->thread_group, thread_group) { + if (!cgroup_is_descendant(new_cgroup, c)) { + rcu_read_unlock(); + return -EPERM; + } + } + rcu_read_unlock(); + } + + return 0; +} + +/* + * Rules: you can only create a cgroup if + * 1. you are capable(CAP_SYS_ADMIN) + * 2. the target cgroup is a descendant of your own cgroup + */ +static struct cgroup_subsys_state *ns_create(struct cgroup_subsys *ss, + struct cgroup *cgroup) +{ + struct ns_cgroup *ns_cgroup; + + if (!capable(CAP_SYS_ADMIN)) + return ERR_PTR(-EPERM); + if (!cgroup_is_descendant(cgroup, current)) + return ERR_PTR(-EPERM); + if (test_bit(CGRP_CLONE_CHILDREN, &cgroup->flags)) { + printk("ns_cgroup can't be created with parent " + "'clone_children' set.\n"); + return ERR_PTR(-EINVAL); + } + + printk_once("ns_cgroup deprecated: consider using the " + "'clone_children' flag without the ns_cgroup.\n"); + + ns_cgroup = kzalloc(sizeof(*ns_cgroup), GFP_KERNEL); + if (!ns_cgroup) + return ERR_PTR(-ENOMEM); + return &ns_cgroup->css; +} + +static void ns_destroy(struct cgroup_subsys *ss, + struct cgroup *cgroup) +{ + struct ns_cgroup *ns_cgroup; + + ns_cgroup = cgroup_to_ns(cgroup); + kfree(ns_cgroup); +} + +struct cgroup_subsys ns_subsys = { + .name = "ns", + .can_attach = ns_can_attach, + .create = ns_create, + .destroy = ns_destroy, + .subsys_id = ns_subsys_id, +}; diff --git a/trunk/kernel/nsproxy.c b/trunk/kernel/nsproxy.c index d6a00f3de15d..5424e37673ed 100644 --- a/trunk/kernel/nsproxy.c +++ b/trunk/kernel/nsproxy.c @@ -201,6 +201,10 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags, goto out; } + err = ns_cgroup_clone(current, task_pid(current)); + if (err) + put_nsproxy(*new_nsp); + out: return err; } diff --git a/trunk/kernel/profile.c b/trunk/kernel/profile.c index 961b389fe52f..14c9f87b9fc9 100644 --- a/trunk/kernel/profile.c +++ b/trunk/kernel/profile.c @@ -303,12 +303,14 @@ static void profile_discard_flip_buffers(void) mutex_unlock(&profile_flip_mutex); } -static void do_profile_hits(int type, void *__pc, unsigned int nr_hits) +void profile_hits(int type, void *__pc, unsigned int nr_hits) { unsigned long primary, secondary, flags, pc = (unsigned long)__pc; int i, j, cpu; struct profile_hit *hits; + if (prof_on != type || !prof_buffer) + return; pc = min((pc - (unsigned long)_stext) >> prof_shift, prof_len - 1); i = primary = (pc & (NR_PROFILE_GRP - 1)) << PROFILE_GRPSHIFT; secondary = (~(pc << 1) & (NR_PROFILE_GRP - 1)) << PROFILE_GRPSHIFT; @@ -415,20 +417,16 @@ static int __cpuinit profile_cpu_callback(struct notifier_block *info, #define profile_discard_flip_buffers() do { } while (0) #define profile_cpu_callback NULL -static void do_profile_hits(int type, void *__pc, unsigned int nr_hits) +void profile_hits(int type, void *__pc, unsigned int nr_hits) { unsigned long pc; - pc = ((unsigned long)__pc - (unsigned long)_stext) >> prof_shift; - atomic_add(nr_hits, &prof_buffer[min(pc, prof_len - 1)]); -} -#endif /* !CONFIG_SMP */ -void profile_hits(int type, void *__pc, unsigned int nr_hits) -{ if (prof_on != type || !prof_buffer) return; - do_profile_hits(type, __pc, nr_hits); + pc = ((unsigned long)__pc - (unsigned long)_stext) >> prof_shift; + atomic_add(nr_hits, &prof_buffer[min(pc, prof_len - 1)]); } +#endif /* !CONFIG_SMP */ EXPORT_SYMBOL_GPL(profile_hits); void profile_tick(int type) diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 5e43e9dc65d1..2d12893b8b0f 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -8764,10 +8764,42 @@ cpu_cgroup_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk) return 0; } +static int +cpu_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp, + struct task_struct *tsk, bool threadgroup) +{ + int retval = cpu_cgroup_can_attach_task(cgrp, tsk); + if (retval) + return retval; + if (threadgroup) { + struct task_struct *c; + rcu_read_lock(); + list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) { + retval = cpu_cgroup_can_attach_task(cgrp, c); + if (retval) { + rcu_read_unlock(); + return retval; + } + } + rcu_read_unlock(); + } + return 0; +} + static void -cpu_cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) +cpu_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp, + struct cgroup *old_cont, struct task_struct *tsk, + bool threadgroup) { sched_move_task(tsk); + if (threadgroup) { + struct task_struct *c; + rcu_read_lock(); + list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) { + sched_move_task(c); + } + rcu_read_unlock(); + } } static void @@ -8855,8 +8887,8 @@ struct cgroup_subsys cpu_cgroup_subsys = { .name = "cpu", .create = cpu_cgroup_create, .destroy = cpu_cgroup_destroy, - .can_attach_task = cpu_cgroup_can_attach_task, - .attach_task = cpu_cgroup_attach_task, + .can_attach = cpu_cgroup_can_attach, + .attach = cpu_cgroup_attach, .exit = cpu_cgroup_exit, .populate = cpu_cgroup_populate, .subsys_id = cpu_cgroup_subsys_id, diff --git a/trunk/lib/Kconfig b/trunk/lib/Kconfig index 830181cc7a83..9c10e38fc609 100644 --- a/trunk/lib/Kconfig +++ b/trunk/lib/Kconfig @@ -19,6 +19,16 @@ config RATIONAL config GENERIC_FIND_FIRST_BIT bool +config GENERIC_FIND_NEXT_BIT + bool + +config GENERIC_FIND_BIT_LE + bool + +config GENERIC_FIND_LAST_BIT + bool + default y + config CRC_CCITT tristate "CRC-CCITT functions" help diff --git a/trunk/lib/Makefile b/trunk/lib/Makefile index 6b597fdb1898..4b49a249064b 100644 --- a/trunk/lib/Makefile +++ b/trunk/lib/Makefile @@ -12,7 +12,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o \ proportions.o prio_heap.o ratelimit.o show_mem.o \ - is_single_threaded.o plist.o decompress.o find_next_bit.o + is_single_threaded.o plist.o decompress.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o @@ -22,7 +22,7 @@ lib-y += kobject.o kref.o klist.o obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o \ - bsearch.o find_last_bit.o + bsearch.o obj-y += kstrtox.o obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o @@ -39,6 +39,10 @@ obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o +lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o +lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o +lib-$(CONFIG_GENERIC_FIND_BIT_LE) += find_next_bit.o +obj-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS)) obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o diff --git a/trunk/lib/find_last_bit.c b/trunk/lib/find_last_bit.c index d903959ad695..5d202e36bdd8 100644 --- a/trunk/lib/find_last_bit.c +++ b/trunk/lib/find_last_bit.c @@ -15,8 +15,6 @@ #include #include -#ifndef find_last_bit - unsigned long find_last_bit(const unsigned long *addr, unsigned long size) { unsigned long words; @@ -45,5 +43,3 @@ unsigned long find_last_bit(const unsigned long *addr, unsigned long size) return size; } EXPORT_SYMBOL(find_last_bit); - -#endif diff --git a/trunk/lib/find_next_bit.c b/trunk/lib/find_next_bit.c index 4bd75a73ba00..b0a8767282bf 100644 --- a/trunk/lib/find_next_bit.c +++ b/trunk/lib/find_next_bit.c @@ -16,7 +16,7 @@ #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) -#ifndef find_next_bit +#ifdef CONFIG_GENERIC_FIND_NEXT_BIT /* * Find the next set bit in a memory region. */ @@ -59,9 +59,7 @@ unsigned long find_next_bit(const unsigned long *addr, unsigned long size, return result + __ffs(tmp); } EXPORT_SYMBOL(find_next_bit); -#endif -#ifndef find_next_zero_bit /* * This implementation of find_{first,next}_zero_bit was stolen from * Linus' asm-alpha/bitops.h. @@ -105,9 +103,9 @@ unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, return result + ffz(tmp); } EXPORT_SYMBOL(find_next_zero_bit); -#endif +#endif /* CONFIG_GENERIC_FIND_NEXT_BIT */ -#ifndef find_first_bit +#ifdef CONFIG_GENERIC_FIND_FIRST_BIT /* * Find the first set bit in a memory region. */ @@ -133,9 +131,7 @@ unsigned long find_first_bit(const unsigned long *addr, unsigned long size) return result + __ffs(tmp); } EXPORT_SYMBOL(find_first_bit); -#endif -#ifndef find_first_zero_bit /* * Find the first cleared bit in a memory region. */ @@ -161,9 +157,10 @@ unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) return result + ffz(tmp); } EXPORT_SYMBOL(find_first_zero_bit); -#endif +#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ #ifdef __BIG_ENDIAN +#ifdef CONFIG_GENERIC_FIND_BIT_LE /* include/linux/byteorder does not support "unsigned long" type */ static inline unsigned long ext2_swabp(const unsigned long * x) @@ -189,7 +186,6 @@ static inline unsigned long ext2_swab(const unsigned long y) #endif } -#ifndef find_next_zero_bit_le unsigned long find_next_zero_bit_le(const void *addr, unsigned long size, unsigned long offset) { @@ -233,9 +229,7 @@ unsigned long find_next_zero_bit_le(const void *addr, unsigned return result + ffz(ext2_swab(tmp)); } EXPORT_SYMBOL(find_next_zero_bit_le); -#endif -#ifndef find_next_bit_le unsigned long find_next_bit_le(const void *addr, unsigned long size, unsigned long offset) { @@ -280,6 +274,6 @@ unsigned long find_next_bit_le(const void *addr, unsigned return result + __ffs(ext2_swab(tmp)); } EXPORT_SYMBOL(find_next_bit_le); -#endif +#endif /* CONFIG_GENERIC_FIND_BIT_LE */ #endif /* __BIG_ENDIAN */ diff --git a/trunk/lib/flex_array.c b/trunk/lib/flex_array.c index 9b8b89458c4c..cab7621f98aa 100644 --- a/trunk/lib/flex_array.c +++ b/trunk/lib/flex_array.c @@ -24,7 +24,6 @@ #include #include #include -#include struct flex_array_part { char elements[FLEX_ARRAY_PART_SIZE]; @@ -71,15 +70,15 @@ static inline int elements_fit_in_base(struct flex_array *fa) * Element size | Objects | Objects | * PAGE_SIZE=4k | 32-bit | 64-bit | * ---------------------------------| - * 1 bytes | 4177920 | 2088960 | - * 2 bytes | 2088960 | 1044480 | - * 3 bytes | 1392300 | 696150 | - * 4 bytes | 1044480 | 522240 | - * 32 bytes | 130560 | 65408 | - * 33 bytes | 126480 | 63240 | - * 2048 bytes | 2040 | 1020 | - * 2049 bytes | 1020 | 510 | - * void * | 1044480 | 261120 | + * 1 bytes | 4186112 | 2093056 | + * 2 bytes | 2093056 | 1046528 | + * 3 bytes | 1395030 | 697515 | + * 4 bytes | 1046528 | 523264 | + * 32 bytes | 130816 | 65408 | + * 33 bytes | 126728 | 63364 | + * 2048 bytes | 2044 | 1022 | + * 2049 bytes | 1022 | 511 | + * void * | 1046528 | 261632 | * * Since 64-bit pointers are twice the size, we lose half the * capacity in the base structure. Also note that no effort is made @@ -89,15 +88,11 @@ struct flex_array *flex_array_alloc(int element_size, unsigned int total, gfp_t flags) { struct flex_array *ret; - int elems_per_part = 0; - int reciprocal_elems = 0; int max_size = 0; - if (element_size) { - elems_per_part = FLEX_ARRAY_ELEMENTS_PER_PART(element_size); - reciprocal_elems = reciprocal_value(elems_per_part); - max_size = FLEX_ARRAY_NR_BASE_PTRS * elems_per_part; - } + if (element_size) + max_size = FLEX_ARRAY_NR_BASE_PTRS * + FLEX_ARRAY_ELEMENTS_PER_PART(element_size); /* max_size will end up 0 if element_size > PAGE_SIZE */ if (total > max_size) @@ -107,8 +102,6 @@ struct flex_array *flex_array_alloc(int element_size, unsigned int total, return NULL; ret->element_size = element_size; ret->total_nr_elements = total; - ret->elems_per_part = elems_per_part; - ret->reciprocal_elems = reciprocal_elems; if (elements_fit_in_base(ret) && !(flags & __GFP_ZERO)) memset(&ret->parts[0], FLEX_ARRAY_FREE, FLEX_ARRAY_BASE_BYTES_LEFT); @@ -119,7 +112,7 @@ EXPORT_SYMBOL(flex_array_alloc); static int fa_element_to_part_nr(struct flex_array *fa, unsigned int element_nr) { - return reciprocal_divide(element_nr, fa->reciprocal_elems); + return element_nr / FLEX_ARRAY_ELEMENTS_PER_PART(fa->element_size); } /** @@ -148,12 +141,12 @@ void flex_array_free(struct flex_array *fa) EXPORT_SYMBOL(flex_array_free); static unsigned int index_inside_part(struct flex_array *fa, - unsigned int element_nr, - unsigned int part_nr) + unsigned int element_nr) { unsigned int part_offset; - part_offset = element_nr - part_nr * fa->elems_per_part; + part_offset = element_nr % + FLEX_ARRAY_ELEMENTS_PER_PART(fa->element_size); return part_offset * fa->element_size; } @@ -193,7 +186,7 @@ __fa_get_part(struct flex_array *fa, int part_nr, gfp_t flags) int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, gfp_t flags) { - int part_nr = 0; + int part_nr; struct flex_array_part *part; void *dst; @@ -209,7 +202,7 @@ int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, if (!part) return -ENOMEM; } - dst = &part->elements[index_inside_part(fa, element_nr, part_nr)]; + dst = &part->elements[index_inside_part(fa, element_nr)]; memcpy(dst, src, fa->element_size); return 0; } @@ -224,7 +217,7 @@ EXPORT_SYMBOL(flex_array_put); */ int flex_array_clear(struct flex_array *fa, unsigned int element_nr) { - int part_nr = 0; + int part_nr; struct flex_array_part *part; void *dst; @@ -240,7 +233,7 @@ int flex_array_clear(struct flex_array *fa, unsigned int element_nr) if (!part) return -EINVAL; } - dst = &part->elements[index_inside_part(fa, element_nr, part_nr)]; + dst = &part->elements[index_inside_part(fa, element_nr)]; memset(dst, FLEX_ARRAY_FREE, fa->element_size); return 0; } @@ -309,7 +302,7 @@ EXPORT_SYMBOL(flex_array_prealloc); */ void *flex_array_get(struct flex_array *fa, unsigned int element_nr) { - int part_nr = 0; + int part_nr; struct flex_array_part *part; if (!fa->element_size) @@ -324,7 +317,7 @@ void *flex_array_get(struct flex_array *fa, unsigned int element_nr) if (!part) return NULL; } - return &part->elements[index_inside_part(fa, element_nr, part_nr)]; + return &part->elements[index_inside_part(fa, element_nr)]; } EXPORT_SYMBOL(flex_array_get); diff --git a/trunk/mm/Kconfig b/trunk/mm/Kconfig index 8ca47a5ee9c8..e9c0c61f2ddd 100644 --- a/trunk/mm/Kconfig +++ b/trunk/mm/Kconfig @@ -347,26 +347,3 @@ config NEED_PER_CPU_KM depends on !SMP bool default y - -config CLEANCACHE - bool "Enable cleancache driver to cache clean pages if tmem is present" - default n - help - Cleancache can be thought of as a page-granularity victim cache - for clean pages that the kernel's pageframe replacement algorithm - (PFRA) would like to keep around, but can't since there isn't enough - memory. So when the PFRA "evicts" a page, it first attempts to use - cleancacne code to put the data contained in that page into - "transcendent memory", memory that is not directly accessible or - addressable by the kernel and is of unknown and possibly - time-varying size. And when a cleancache-enabled - filesystem wishes to access a page in a file on disk, it first - checks cleancache to see if it already contains it; if it does, - the page is copied into the kernel and a disk access is avoided. - When a transcendent memory driver is available (such as zcache or - Xen transcendent memory), a significant I/O reduction - may be achieved. When none is available, all cleancache calls - are reduced to a single pointer-compare-against-NULL resulting - in a negligible performance hit. - - If unsure, say Y to enable cleancache diff --git a/trunk/mm/Makefile b/trunk/mm/Makefile index 836e4163c1bf..42a8326c3e3d 100644 --- a/trunk/mm/Makefile +++ b/trunk/mm/Makefile @@ -49,4 +49,3 @@ obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o -obj-$(CONFIG_CLEANCACHE) += cleancache.o diff --git a/trunk/mm/cleancache.c b/trunk/mm/cleancache.c deleted file mode 100644 index bcaae4c2a770..000000000000 --- a/trunk/mm/cleancache.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Cleancache frontend - * - * This code provides the generic "frontend" layer to call a matching - * "backend" driver implementation of cleancache. See - * Documentation/vm/cleancache.txt for more information. - * - * Copyright (C) 2009-2010 Oracle Corp. All rights reserved. - * Author: Dan Magenheimer - * - * This work is licensed under the terms of the GNU GPL, version 2. - */ - -#include -#include -#include -#include -#include - -/* - * This global enablement flag may be read thousands of times per second - * by cleancache_get/put/flush even on systems where cleancache_ops - * is not claimed (e.g. cleancache is config'ed on but remains - * disabled), so is preferred to the slower alternative: a function - * call that checks a non-global. - */ -int cleancache_enabled; -EXPORT_SYMBOL(cleancache_enabled); - -/* - * cleancache_ops is set by cleancache_ops_register to contain the pointers - * to the cleancache "backend" implementation functions. - */ -static struct cleancache_ops cleancache_ops; - -/* useful stats available in /sys/kernel/mm/cleancache */ -static unsigned long cleancache_succ_gets; -static unsigned long cleancache_failed_gets; -static unsigned long cleancache_puts; -static unsigned long cleancache_flushes; - -/* - * register operations for cleancache, returning previous thus allowing - * detection of multiple backends and possible nesting - */ -struct cleancache_ops cleancache_register_ops(struct cleancache_ops *ops) -{ - struct cleancache_ops old = cleancache_ops; - - cleancache_ops = *ops; - cleancache_enabled = 1; - return old; -} -EXPORT_SYMBOL(cleancache_register_ops); - -/* Called by a cleancache-enabled filesystem at time of mount */ -void __cleancache_init_fs(struct super_block *sb) -{ - sb->cleancache_poolid = (*cleancache_ops.init_fs)(PAGE_SIZE); -} -EXPORT_SYMBOL(__cleancache_init_fs); - -/* Called by a cleancache-enabled clustered filesystem at time of mount */ -void __cleancache_init_shared_fs(char *uuid, struct super_block *sb) -{ - sb->cleancache_poolid = - (*cleancache_ops.init_shared_fs)(uuid, PAGE_SIZE); -} -EXPORT_SYMBOL(__cleancache_init_shared_fs); - -/* - * If the filesystem uses exportable filehandles, use the filehandle as - * the key, else use the inode number. - */ -static int cleancache_get_key(struct inode *inode, - struct cleancache_filekey *key) -{ - int (*fhfn)(struct dentry *, __u32 *fh, int *, int); - int len = 0, maxlen = CLEANCACHE_KEY_MAX; - struct super_block *sb = inode->i_sb; - - key->u.ino = inode->i_ino; - if (sb->s_export_op != NULL) { - fhfn = sb->s_export_op->encode_fh; - if (fhfn) { - struct dentry d; - d.d_inode = inode; - len = (*fhfn)(&d, &key->u.fh[0], &maxlen, 0); - if (len <= 0 || len == 255) - return -1; - if (maxlen > CLEANCACHE_KEY_MAX) - return -1; - } - } - return 0; -} - -/* - * "Get" data from cleancache associated with the poolid/inode/index - * that were specified when the data was put to cleanache and, if - * successful, use it to fill the specified page with data and return 0. - * The pageframe is unchanged and returns -1 if the get fails. - * Page must be locked by caller. - */ -int __cleancache_get_page(struct page *page) -{ - int ret = -1; - int pool_id; - struct cleancache_filekey key = { .u.key = { 0 } }; - - VM_BUG_ON(!PageLocked(page)); - pool_id = page->mapping->host->i_sb->cleancache_poolid; - if (pool_id < 0) - goto out; - - if (cleancache_get_key(page->mapping->host, &key) < 0) - goto out; - - ret = (*cleancache_ops.get_page)(pool_id, key, page->index, page); - if (ret == 0) - cleancache_succ_gets++; - else - cleancache_failed_gets++; -out: - return ret; -} -EXPORT_SYMBOL(__cleancache_get_page); - -/* - * "Put" data from a page to cleancache and associate it with the - * (previously-obtained per-filesystem) poolid and the page's, - * inode and page index. Page must be locked. Note that a put_page - * always "succeeds", though a subsequent get_page may succeed or fail. - */ -void __cleancache_put_page(struct page *page) -{ - int pool_id; - struct cleancache_filekey key = { .u.key = { 0 } }; - - VM_BUG_ON(!PageLocked(page)); - pool_id = page->mapping->host->i_sb->cleancache_poolid; - if (pool_id >= 0 && - cleancache_get_key(page->mapping->host, &key) >= 0) { - (*cleancache_ops.put_page)(pool_id, key, page->index, page); - cleancache_puts++; - } -} -EXPORT_SYMBOL(__cleancache_put_page); - -/* - * Flush any data from cleancache associated with the poolid and the - * page's inode and page index so that a subsequent "get" will fail. - */ -void __cleancache_flush_page(struct address_space *mapping, struct page *page) -{ - /* careful... page->mapping is NULL sometimes when this is called */ - int pool_id = mapping->host->i_sb->cleancache_poolid; - struct cleancache_filekey key = { .u.key = { 0 } }; - - if (pool_id >= 0) { - VM_BUG_ON(!PageLocked(page)); - if (cleancache_get_key(mapping->host, &key) >= 0) { - (*cleancache_ops.flush_page)(pool_id, key, page->index); - cleancache_flushes++; - } - } -} -EXPORT_SYMBOL(__cleancache_flush_page); - -/* - * Flush all data from cleancache associated with the poolid and the - * mappings's inode so that all subsequent gets to this poolid/inode - * will fail. - */ -void __cleancache_flush_inode(struct address_space *mapping) -{ - int pool_id = mapping->host->i_sb->cleancache_poolid; - struct cleancache_filekey key = { .u.key = { 0 } }; - - if (pool_id >= 0 && cleancache_get_key(mapping->host, &key) >= 0) - (*cleancache_ops.flush_inode)(pool_id, key); -} -EXPORT_SYMBOL(__cleancache_flush_inode); - -/* - * Called by any cleancache-enabled filesystem at time of unmount; - * note that pool_id is surrendered and may be reutrned by a subsequent - * cleancache_init_fs or cleancache_init_shared_fs - */ -void __cleancache_flush_fs(struct super_block *sb) -{ - if (sb->cleancache_poolid >= 0) { - int old_poolid = sb->cleancache_poolid; - sb->cleancache_poolid = -1; - (*cleancache_ops.flush_fs)(old_poolid); - } -} -EXPORT_SYMBOL(__cleancache_flush_fs); - -#ifdef CONFIG_SYSFS - -/* see Documentation/ABI/xxx/sysfs-kernel-mm-cleancache */ - -#define CLEANCACHE_SYSFS_RO(_name) \ - static ssize_t cleancache_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ - { \ - return sprintf(buf, "%lu\n", cleancache_##_name); \ - } \ - static struct kobj_attribute cleancache_##_name##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = cleancache_##_name##_show, \ - } - -CLEANCACHE_SYSFS_RO(succ_gets); -CLEANCACHE_SYSFS_RO(failed_gets); -CLEANCACHE_SYSFS_RO(puts); -CLEANCACHE_SYSFS_RO(flushes); - -static struct attribute *cleancache_attrs[] = { - &cleancache_succ_gets_attr.attr, - &cleancache_failed_gets_attr.attr, - &cleancache_puts_attr.attr, - &cleancache_flushes_attr.attr, - NULL, -}; - -static struct attribute_group cleancache_attr_group = { - .attrs = cleancache_attrs, - .name = "cleancache", -}; - -#endif /* CONFIG_SYSFS */ - -static int __init init_cleancache(void) -{ -#ifdef CONFIG_SYSFS - int err; - - err = sysfs_create_group(mm_kobj, &cleancache_attr_group); -#endif /* CONFIG_SYSFS */ - return 0; -} -module_init(init_cleancache) diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index bcdc393b6580..68e782b3d3de 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -34,7 +34,6 @@ #include /* for BUG_ON(!in_atomic()) only */ #include #include /* for page_is_file_cache() */ -#include #include "internal.h" /* @@ -119,16 +118,6 @@ void __delete_from_page_cache(struct page *page) { struct address_space *mapping = page->mapping; - /* - * if we're uptodate, flush out into the cleancache, otherwise - * invalidate any existing cleancache entries. We can't leave - * stale data around in the cleancache once our page is gone - */ - if (PageUptodate(page) && PageMappedToDisk(page)) - cleancache_put_page(page); - else - cleancache_flush_page(mapping, page); - radix_tree_delete(&mapping->page_tree, page->index); page->mapping = NULL; mapping->nrpages--; @@ -1661,7 +1650,6 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) /* No page in the page cache at all */ do_sync_mmap_readahead(vma, ra, file, offset); count_vm_event(PGMAJFAULT); - mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT); ret = VM_FAULT_MAJOR; retry_find: page = find_get_page(mapping, offset); diff --git a/trunk/mm/fremap.c b/trunk/mm/fremap.c index b8e0e2d468af..7f4123056e06 100644 --- a/trunk/mm/fremap.c +++ b/trunk/mm/fremap.c @@ -224,7 +224,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, /* * drop PG_Mlocked flag for over-mapped range */ - vm_flags_t saved_flags = vma->vm_flags; + unsigned int saved_flags = vma->vm_flags; munlock_vma_pages_range(vma, start, start + size); vma->vm_flags = saved_flags; } diff --git a/trunk/mm/hugetlb.c b/trunk/mm/hugetlb.c index f33bb319b73f..5fd68b95c671 100644 --- a/trunk/mm/hugetlb.c +++ b/trunk/mm/hugetlb.c @@ -2833,7 +2833,7 @@ void hugetlb_change_protection(struct vm_area_struct *vma, int hugetlb_reserve_pages(struct inode *inode, long from, long to, struct vm_area_struct *vma, - vm_flags_t vm_flags) + int acctflag) { long ret, chg; struct hstate *h = hstate_inode(inode); @@ -2843,7 +2843,7 @@ int hugetlb_reserve_pages(struct inode *inode, * attempt will be made for VM_NORESERVE to allocate a page * and filesystem quota without using reserves */ - if (vm_flags & VM_NORESERVE) + if (acctflag & VM_NORESERVE) return 0; /* diff --git a/trunk/mm/memcontrol.c b/trunk/mm/memcontrol.c index bd9052a5d3ad..d5fd3dcd3f2e 100644 --- a/trunk/mm/memcontrol.c +++ b/trunk/mm/memcontrol.c @@ -94,8 +94,6 @@ enum mem_cgroup_events_index { MEM_CGROUP_EVENTS_PGPGIN, /* # of pages paged in */ MEM_CGROUP_EVENTS_PGPGOUT, /* # of pages paged out */ MEM_CGROUP_EVENTS_COUNT, /* # of pages paged in/out */ - MEM_CGROUP_EVENTS_PGFAULT, /* # of page-faults */ - MEM_CGROUP_EVENTS_PGMAJFAULT, /* # of major page-faults */ MEM_CGROUP_EVENTS_NSTATS, }; /* @@ -233,11 +231,6 @@ struct mem_cgroup { * reclaimed from. */ int last_scanned_child; - int last_scanned_node; -#if MAX_NUMNODES > 1 - nodemask_t scan_nodes; - unsigned long next_scan_node_update; -#endif /* * Should the accounting and control be hierarchical, per subtree? */ @@ -592,16 +585,6 @@ static void mem_cgroup_swap_statistics(struct mem_cgroup *mem, this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_SWAPOUT], val); } -void mem_cgroup_pgfault(struct mem_cgroup *mem, int val) -{ - this_cpu_add(mem->stat->events[MEM_CGROUP_EVENTS_PGFAULT], val); -} - -void mem_cgroup_pgmajfault(struct mem_cgroup *mem, int val) -{ - this_cpu_add(mem->stat->events[MEM_CGROUP_EVENTS_PGMAJFAULT], val); -} - static unsigned long mem_cgroup_read_events(struct mem_cgroup *mem, enum mem_cgroup_events_index idx) { @@ -641,27 +624,18 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *mem, preempt_enable(); } -static unsigned long -mem_cgroup_get_zonestat_node(struct mem_cgroup *mem, int nid, enum lru_list idx) -{ - struct mem_cgroup_per_zone *mz; - u64 total = 0; - int zid; - - for (zid = 0; zid < MAX_NR_ZONES; zid++) { - mz = mem_cgroup_zoneinfo(mem, nid, zid); - total += MEM_CGROUP_ZSTAT(mz, idx); - } - return total; -} static unsigned long mem_cgroup_get_local_zonestat(struct mem_cgroup *mem, enum lru_list idx) { - int nid; + int nid, zid; + struct mem_cgroup_per_zone *mz; u64 total = 0; for_each_online_node(nid) - total += mem_cgroup_get_zonestat_node(mem, nid, idx); + for (zid = 0; zid < MAX_NR_ZONES; zid++) { + mz = mem_cgroup_zoneinfo(mem, nid, zid); + total += MEM_CGROUP_ZSTAT(mz, idx); + } return total; } @@ -839,33 +813,6 @@ static inline bool mem_cgroup_is_root(struct mem_cgroup *mem) return (mem == root_mem_cgroup); } -void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx) -{ - struct mem_cgroup *mem; - - if (!mm) - return; - - rcu_read_lock(); - mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); - if (unlikely(!mem)) - goto out; - - switch (idx) { - case PGMAJFAULT: - mem_cgroup_pgmajfault(mem, 1); - break; - case PGFAULT: - mem_cgroup_pgfault(mem, 1); - break; - default: - BUG(); - } -out: - rcu_read_unlock(); -} -EXPORT_SYMBOL(mem_cgroup_count_vm_event); - /* * Following LRU functions are allowed to be used without PCG_LOCK. * Operations are called by routine of global LRU independently from memcg. @@ -1117,9 +1064,9 @@ int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg) return (active > inactive); } -unsigned long mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, - struct zone *zone, - enum lru_list lru) +unsigned long mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg, + struct zone *zone, + enum lru_list lru) { int nid = zone_to_nid(zone); int zid = zone_idx(zone); @@ -1128,93 +1075,6 @@ unsigned long mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, return MEM_CGROUP_ZSTAT(mz, lru); } -#ifdef CONFIG_NUMA -static unsigned long mem_cgroup_node_nr_file_lru_pages(struct mem_cgroup *memcg, - int nid) -{ - unsigned long ret; - - ret = mem_cgroup_get_zonestat_node(memcg, nid, LRU_INACTIVE_FILE) + - mem_cgroup_get_zonestat_node(memcg, nid, LRU_ACTIVE_FILE); - - return ret; -} - -static unsigned long mem_cgroup_nr_file_lru_pages(struct mem_cgroup *memcg) -{ - u64 total = 0; - int nid; - - for_each_node_state(nid, N_HIGH_MEMORY) - total += mem_cgroup_node_nr_file_lru_pages(memcg, nid); - - return total; -} - -static unsigned long mem_cgroup_node_nr_anon_lru_pages(struct mem_cgroup *memcg, - int nid) -{ - unsigned long ret; - - ret = mem_cgroup_get_zonestat_node(memcg, nid, LRU_INACTIVE_ANON) + - mem_cgroup_get_zonestat_node(memcg, nid, LRU_ACTIVE_ANON); - - return ret; -} - -static unsigned long mem_cgroup_nr_anon_lru_pages(struct mem_cgroup *memcg) -{ - u64 total = 0; - int nid; - - for_each_node_state(nid, N_HIGH_MEMORY) - total += mem_cgroup_node_nr_anon_lru_pages(memcg, nid); - - return total; -} - -static unsigned long -mem_cgroup_node_nr_unevictable_lru_pages(struct mem_cgroup *memcg, int nid) -{ - return mem_cgroup_get_zonestat_node(memcg, nid, LRU_UNEVICTABLE); -} - -static unsigned long -mem_cgroup_nr_unevictable_lru_pages(struct mem_cgroup *memcg) -{ - u64 total = 0; - int nid; - - for_each_node_state(nid, N_HIGH_MEMORY) - total += mem_cgroup_node_nr_unevictable_lru_pages(memcg, nid); - - return total; -} - -static unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg, - int nid) -{ - enum lru_list l; - u64 total = 0; - - for_each_lru(l) - total += mem_cgroup_get_zonestat_node(memcg, nid, l); - - return total; -} - -static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg) -{ - u64 total = 0; - int nid; - - for_each_node_state(nid, N_HIGH_MEMORY) - total += mem_cgroup_node_nr_lru_pages(memcg, nid); - - return total; -} -#endif /* CONFIG_NUMA */ - struct zone_reclaim_stat *mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg, struct zone *zone) { @@ -1558,81 +1418,6 @@ mem_cgroup_select_victim(struct mem_cgroup *root_mem) return ret; } -#if MAX_NUMNODES > 1 - -/* - * Always updating the nodemask is not very good - even if we have an empty - * list or the wrong list here, we can start from some node and traverse all - * nodes based on the zonelist. So update the list loosely once per 10 secs. - * - */ -static void mem_cgroup_may_update_nodemask(struct mem_cgroup *mem) -{ - int nid; - - if (time_after(mem->next_scan_node_update, jiffies)) - return; - - mem->next_scan_node_update = jiffies + 10*HZ; - /* make a nodemask where this memcg uses memory from */ - mem->scan_nodes = node_states[N_HIGH_MEMORY]; - - for_each_node_mask(nid, node_states[N_HIGH_MEMORY]) { - - if (mem_cgroup_get_zonestat_node(mem, nid, LRU_INACTIVE_FILE) || - mem_cgroup_get_zonestat_node(mem, nid, LRU_ACTIVE_FILE)) - continue; - - if (total_swap_pages && - (mem_cgroup_get_zonestat_node(mem, nid, LRU_INACTIVE_ANON) || - mem_cgroup_get_zonestat_node(mem, nid, LRU_ACTIVE_ANON))) - continue; - node_clear(nid, mem->scan_nodes); - } -} - -/* - * Selecting a node where we start reclaim from. Because what we need is just - * reducing usage counter, start from anywhere is O,K. Considering - * memory reclaim from current node, there are pros. and cons. - * - * Freeing memory from current node means freeing memory from a node which - * we'll use or we've used. So, it may make LRU bad. And if several threads - * hit limits, it will see a contention on a node. But freeing from remote - * node means more costs for memory reclaim because of memory latency. - * - * Now, we use round-robin. Better algorithm is welcomed. - */ -int mem_cgroup_select_victim_node(struct mem_cgroup *mem) -{ - int node; - - mem_cgroup_may_update_nodemask(mem); - node = mem->last_scanned_node; - - node = next_node(node, mem->scan_nodes); - if (node == MAX_NUMNODES) - node = first_node(mem->scan_nodes); - /* - * We call this when we hit limit, not when pages are added to LRU. - * No LRU may hold pages because all pages are UNEVICTABLE or - * memcg is too small and all pages are not on LRU. In that case, - * we use curret node. - */ - if (unlikely(node == MAX_NUMNODES)) - node = numa_node_id(); - - mem->last_scanned_node = node; - return node; -} - -#else -int mem_cgroup_select_victim_node(struct mem_cgroup *mem) -{ - return 0; -} -#endif - /* * Scan the hierarchy if needed to reclaim memory. We remember the last child * we reclaimed from, so that we don't end up penalizing one child extensively @@ -1648,8 +1433,7 @@ int mem_cgroup_select_victim_node(struct mem_cgroup *mem) static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, struct zone *zone, gfp_t gfp_mask, - unsigned long reclaim_options, - unsigned long *total_scanned) + unsigned long reclaim_options) { struct mem_cgroup *victim; int ret, total = 0; @@ -1658,7 +1442,6 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, bool shrink = reclaim_options & MEM_CGROUP_RECLAIM_SHRINK; bool check_soft = reclaim_options & MEM_CGROUP_RECLAIM_SOFT; unsigned long excess; - unsigned long nr_scanned; excess = res_counter_soft_limit_excess(&root_mem->res) >> PAGE_SHIFT; @@ -1701,12 +1484,10 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, continue; } /* we use swappiness of local cgroup */ - if (check_soft) { + if (check_soft) ret = mem_cgroup_shrink_node_zone(victim, gfp_mask, - noswap, get_swappiness(victim), zone, - &nr_scanned); - *total_scanned += nr_scanned; - } else + noswap, get_swappiness(victim), zone); + else ret = try_to_free_mem_cgroup_pages(victim, gfp_mask, noswap, get_swappiness(victim)); css_put(&victim->css); @@ -1722,7 +1503,7 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, if (!res_counter_soft_limit_excess(&root_mem->res)) return total; } else if (mem_cgroup_margin(root_mem)) - return total; + return 1 + total; } return total; } @@ -2147,7 +1928,7 @@ static int mem_cgroup_do_charge(struct mem_cgroup *mem, gfp_t gfp_mask, return CHARGE_WOULDBLOCK; ret = mem_cgroup_hierarchical_reclaim(mem_over_limit, NULL, - gfp_mask, flags, NULL); + gfp_mask, flags); if (mem_cgroup_margin(mem_over_limit) >= nr_pages) return CHARGE_RETRY; /* @@ -3430,8 +3211,7 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg, break; mem_cgroup_hierarchical_reclaim(memcg, NULL, GFP_KERNEL, - MEM_CGROUP_RECLAIM_SHRINK, - NULL); + MEM_CGROUP_RECLAIM_SHRINK); curusage = res_counter_read_u64(&memcg->res, RES_USAGE); /* Usage is reduced ? */ if (curusage >= oldusage) @@ -3491,8 +3271,7 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, mem_cgroup_hierarchical_reclaim(memcg, NULL, GFP_KERNEL, MEM_CGROUP_RECLAIM_NOSWAP | - MEM_CGROUP_RECLAIM_SHRINK, - NULL); + MEM_CGROUP_RECLAIM_SHRINK); curusage = res_counter_read_u64(&memcg->memsw, RES_USAGE); /* Usage is reduced ? */ if (curusage >= oldusage) @@ -3506,8 +3285,7 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, } unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, - gfp_t gfp_mask, - unsigned long *total_scanned) + gfp_t gfp_mask) { unsigned long nr_reclaimed = 0; struct mem_cgroup_per_zone *mz, *next_mz = NULL; @@ -3515,7 +3293,6 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, int loop = 0; struct mem_cgroup_tree_per_zone *mctz; unsigned long long excess; - unsigned long nr_scanned; if (order > 0) return 0; @@ -3534,13 +3311,10 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, if (!mz) break; - nr_scanned = 0; reclaimed = mem_cgroup_hierarchical_reclaim(mz->mem, zone, gfp_mask, - MEM_CGROUP_RECLAIM_SOFT, - &nr_scanned); + MEM_CGROUP_RECLAIM_SOFT); nr_reclaimed += reclaimed; - *total_scanned += nr_scanned; spin_lock(&mctz->lock); /* @@ -3563,9 +3337,10 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, */ next_mz = __mem_cgroup_largest_soft_limit_node(mctz); - if (next_mz == mz) + if (next_mz == mz) { css_put(&next_mz->mem->css); - else /* next_mz == NULL or other memcg */ + next_mz = NULL; + } else /* next_mz == NULL or other memcg */ break; } while (1); } @@ -3997,8 +3772,6 @@ enum { MCS_PGPGIN, MCS_PGPGOUT, MCS_SWAP, - MCS_PGFAULT, - MCS_PGMAJFAULT, MCS_INACTIVE_ANON, MCS_ACTIVE_ANON, MCS_INACTIVE_FILE, @@ -4021,8 +3794,6 @@ struct { {"pgpgin", "total_pgpgin"}, {"pgpgout", "total_pgpgout"}, {"swap", "total_swap"}, - {"pgfault", "total_pgfault"}, - {"pgmajfault", "total_pgmajfault"}, {"inactive_anon", "total_inactive_anon"}, {"active_anon", "total_active_anon"}, {"inactive_file", "total_inactive_file"}, @@ -4051,10 +3822,6 @@ mem_cgroup_get_local_stat(struct mem_cgroup *mem, struct mcs_total_stat *s) val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_SWAPOUT); s->stat[MCS_SWAP] += val * PAGE_SIZE; } - val = mem_cgroup_read_events(mem, MEM_CGROUP_EVENTS_PGFAULT); - s->stat[MCS_PGFAULT] += val; - val = mem_cgroup_read_events(mem, MEM_CGROUP_EVENTS_PGMAJFAULT); - s->stat[MCS_PGMAJFAULT] += val; /* per zone stat */ val = mem_cgroup_get_local_zonestat(mem, LRU_INACTIVE_ANON); @@ -4078,51 +3845,6 @@ mem_cgroup_get_total_stat(struct mem_cgroup *mem, struct mcs_total_stat *s) mem_cgroup_get_local_stat(iter, s); } -#ifdef CONFIG_NUMA -static int mem_control_numa_stat_show(struct seq_file *m, void *arg) -{ - int nid; - unsigned long total_nr, file_nr, anon_nr, unevictable_nr; - unsigned long node_nr; - struct cgroup *cont = m->private; - struct mem_cgroup *mem_cont = mem_cgroup_from_cont(cont); - - total_nr = mem_cgroup_nr_lru_pages(mem_cont); - seq_printf(m, "total=%lu", total_nr); - for_each_node_state(nid, N_HIGH_MEMORY) { - node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid); - seq_printf(m, " N%d=%lu", nid, node_nr); - } - seq_putc(m, '\n'); - - file_nr = mem_cgroup_nr_file_lru_pages(mem_cont); - seq_printf(m, "file=%lu", file_nr); - for_each_node_state(nid, N_HIGH_MEMORY) { - node_nr = mem_cgroup_node_nr_file_lru_pages(mem_cont, nid); - seq_printf(m, " N%d=%lu", nid, node_nr); - } - seq_putc(m, '\n'); - - anon_nr = mem_cgroup_nr_anon_lru_pages(mem_cont); - seq_printf(m, "anon=%lu", anon_nr); - for_each_node_state(nid, N_HIGH_MEMORY) { - node_nr = mem_cgroup_node_nr_anon_lru_pages(mem_cont, nid); - seq_printf(m, " N%d=%lu", nid, node_nr); - } - seq_putc(m, '\n'); - - unevictable_nr = mem_cgroup_nr_unevictable_lru_pages(mem_cont); - seq_printf(m, "unevictable=%lu", unevictable_nr); - for_each_node_state(nid, N_HIGH_MEMORY) { - node_nr = mem_cgroup_node_nr_unevictable_lru_pages(mem_cont, - nid); - seq_printf(m, " N%d=%lu", nid, node_nr); - } - seq_putc(m, '\n'); - return 0; -} -#endif /* CONFIG_NUMA */ - static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft, struct cgroup_map_cb *cb) { @@ -4133,7 +3855,6 @@ static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft, memset(&mystat, 0, sizeof(mystat)); mem_cgroup_get_local_stat(mem_cont, &mystat); - for (i = 0; i < NR_MCS_STAT; i++) { if (i == MCS_SWAP && !do_swap_account) continue; @@ -4557,22 +4278,6 @@ static int mem_cgroup_oom_control_write(struct cgroup *cgrp, return 0; } -#ifdef CONFIG_NUMA -static const struct file_operations mem_control_numa_stat_file_operations = { - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int mem_control_numa_stat_open(struct inode *unused, struct file *file) -{ - struct cgroup *cont = file->f_dentry->d_parent->d_fsdata; - - file->f_op = &mem_control_numa_stat_file_operations; - return single_open(file, mem_control_numa_stat_show, cont); -} -#endif /* CONFIG_NUMA */ - static struct cftype mem_cgroup_files[] = { { .name = "usage_in_bytes", @@ -4636,12 +4341,6 @@ static struct cftype mem_cgroup_files[] = { .unregister_event = mem_cgroup_oom_unregister_event, .private = MEMFILE_PRIVATE(_OOM_TYPE, OOM_CONTROL), }, -#ifdef CONFIG_NUMA - { - .name = "numa_stat", - .open = mem_control_numa_stat_open, - }, -#endif }; #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP @@ -4897,7 +4596,6 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) res_counter_init(&mem->memsw, NULL); } mem->last_scanned_child = 0; - mem->last_scanned_node = MAX_NUMNODES; INIT_LIST_HEAD(&mem->oom_notify); if (parent) @@ -5255,7 +4953,8 @@ static void mem_cgroup_clear_mc(void) static int mem_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgroup, - struct task_struct *p) + struct task_struct *p, + bool threadgroup) { int ret = 0; struct mem_cgroup *mem = mem_cgroup_from_cont(cgroup); @@ -5294,7 +4993,8 @@ static int mem_cgroup_can_attach(struct cgroup_subsys *ss, static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss, struct cgroup *cgroup, - struct task_struct *p) + struct task_struct *p, + bool threadgroup) { mem_cgroup_clear_mc(); } @@ -5412,7 +5112,8 @@ static void mem_cgroup_move_charge(struct mm_struct *mm) static void mem_cgroup_move_task(struct cgroup_subsys *ss, struct cgroup *cont, struct cgroup *old_cont, - struct task_struct *p) + struct task_struct *p, + bool threadgroup) { struct mm_struct *mm; @@ -5430,19 +5131,22 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss, #else /* !CONFIG_MMU */ static int mem_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgroup, - struct task_struct *p) + struct task_struct *p, + bool threadgroup) { return 0; } static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss, struct cgroup *cgroup, - struct task_struct *p) + struct task_struct *p, + bool threadgroup) { } static void mem_cgroup_move_task(struct cgroup_subsys *ss, struct cgroup *cont, struct cgroup *old_cont, - struct task_struct *p) + struct task_struct *p, + bool threadgroup) { } #endif diff --git a/trunk/mm/memory.c b/trunk/mm/memory.c index 6953d3926e01..b73f677f0bb1 100644 --- a/trunk/mm/memory.c +++ b/trunk/mm/memory.c @@ -730,7 +730,7 @@ static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr, add_taint(TAINT_BAD_PAGE); } -static inline int is_cow_mapping(vm_flags_t flags) +static inline int is_cow_mapping(unsigned int flags) { return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE; } @@ -2874,7 +2874,6 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, /* Had to read the page from swap area: Major fault */ ret = VM_FAULT_MAJOR; count_vm_event(PGMAJFAULT); - mem_cgroup_count_vm_event(mm, PGMAJFAULT); } else if (PageHWPoison(page)) { /* * hwpoisoned dirty swapcache pages are kept for killing @@ -3414,7 +3413,6 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, __set_current_state(TASK_RUNNING); count_vm_event(PGFAULT); - mem_cgroup_count_vm_event(mm, PGFAULT); /* do counter updates before entering really critical section. */ check_sync_rss_stat(current); diff --git a/trunk/mm/mlock.c b/trunk/mm/mlock.c index 048260c4e02e..516b2c2ddd5a 100644 --- a/trunk/mm/mlock.c +++ b/trunk/mm/mlock.c @@ -307,13 +307,13 @@ void munlock_vma_pages_range(struct vm_area_struct *vma, * For vmas that pass the filters, merge/split as appropriate. */ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev, - unsigned long start, unsigned long end, vm_flags_t newflags) + unsigned long start, unsigned long end, unsigned int newflags) { struct mm_struct *mm = vma->vm_mm; pgoff_t pgoff; int nr_pages; int ret = 0; - int lock = !!(newflags & VM_LOCKED); + int lock = newflags & VM_LOCKED; if (newflags == vma->vm_flags || (vma->vm_flags & VM_SPECIAL) || is_vm_hugetlb_page(vma) || vma == get_gate_vma(current->mm)) @@ -385,7 +385,7 @@ static int do_mlock(unsigned long start, size_t len, int on) prev = vma; for (nstart = start ; ; ) { - vm_flags_t newflags; + unsigned int newflags; /* Here we know that vma->vm_start <= nstart < vma->vm_end. */ @@ -524,7 +524,7 @@ static int do_mlockall(int flags) goto out; for (vma = current->mm->mmap; vma ; vma = prev->vm_next) { - vm_flags_t newflags; + unsigned int newflags; newflags = vma->vm_flags | VM_LOCKED; if (!(flags & MCL_CURRENT)) diff --git a/trunk/mm/mmap.c b/trunk/mm/mmap.c index bbdc9af5e117..ac2631b7477f 100644 --- a/trunk/mm/mmap.c +++ b/trunk/mm/mmap.c @@ -960,7 +960,7 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, { struct mm_struct * mm = current->mm; struct inode *inode; - vm_flags_t vm_flags; + unsigned int vm_flags; int error; unsigned long reqprot = prot; @@ -1165,7 +1165,7 @@ SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg) */ int vma_wants_writenotify(struct vm_area_struct *vma) { - vm_flags_t vm_flags = vma->vm_flags; + unsigned int vm_flags = vma->vm_flags; /* If it was private or non-writable, the write bit is already clear */ if ((vm_flags & (VM_WRITE|VM_SHARED)) != ((VM_WRITE|VM_SHARED))) @@ -1193,7 +1193,7 @@ int vma_wants_writenotify(struct vm_area_struct *vma) * We account for memory if it's a private writeable mapping, * not hugepages and VM_NORESERVE wasn't set. */ -static inline int accountable_mapping(struct file *file, vm_flags_t vm_flags) +static inline int accountable_mapping(struct file *file, unsigned int vm_flags) { /* * hugetlb has its own accounting separate from the core VM @@ -1207,7 +1207,7 @@ static inline int accountable_mapping(struct file *file, vm_flags_t vm_flags) unsigned long mmap_region(struct file *file, unsigned long addr, unsigned long len, unsigned long flags, - vm_flags_t vm_flags, unsigned long pgoff) + unsigned int vm_flags, unsigned long pgoff) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma, *prev; diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index a4e1db3f1981..2a00f17c3bf4 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -4323,8 +4323,10 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, zone->zone_pgdat = pgdat; zone_pcp_init(zone); - for_each_lru(l) + for_each_lru(l) { INIT_LIST_HEAD(&zone->lru[l].list); + zone->reclaim_stat.nr_saved_scan[l] = 0; + } zone->reclaim_stat.recent_rotated[0] = 0; zone->reclaim_stat.recent_rotated[1] = 0; zone->reclaim_stat.recent_scanned[0] = 0; diff --git a/trunk/mm/page_cgroup.c b/trunk/mm/page_cgroup.c index 74ccff61d1be..2daadc322ba6 100644 --- a/trunk/mm/page_cgroup.c +++ b/trunk/mm/page_cgroup.c @@ -130,7 +130,7 @@ struct page *lookup_cgroup_page(struct page_cgroup *pc) return page; } -static void *__meminit alloc_page_cgroup(size_t size, int nid) +static void *__init_refok alloc_page_cgroup(size_t size, int nid) { void *addr = NULL; @@ -162,7 +162,7 @@ static void free_page_cgroup(void *addr) } #endif -static int __meminit init_section_page_cgroup(unsigned long pfn) +static int __init_refok init_section_page_cgroup(unsigned long pfn) { struct page_cgroup *base, *pc; struct mem_section *section; @@ -475,7 +475,7 @@ int swap_cgroup_swapon(int type, unsigned long max_pages) if (!do_swap_account) return 0; - length = DIV_ROUND_UP(max_pages, SC_PER_PAGE); + length = ((max_pages/SC_PER_PAGE) + 1); array_size = length * sizeof(void *); array = vmalloc(array_size); @@ -492,8 +492,8 @@ int swap_cgroup_swapon(int type, unsigned long max_pages) /* memory shortage */ ctrl->map = NULL; ctrl->length = 0; - mutex_unlock(&swap_cgroup_mutex); vfree(array); + mutex_unlock(&swap_cgroup_mutex); goto nomem; } mutex_unlock(&swap_cgroup_mutex); @@ -508,8 +508,7 @@ int swap_cgroup_swapon(int type, unsigned long max_pages) void swap_cgroup_swapoff(int type) { - struct page **map; - unsigned long i, length; + int i; struct swap_cgroup_ctrl *ctrl; if (!do_swap_account) @@ -517,20 +516,17 @@ void swap_cgroup_swapoff(int type) mutex_lock(&swap_cgroup_mutex); ctrl = &swap_cgroup_ctrl[type]; - map = ctrl->map; - length = ctrl->length; - ctrl->map = NULL; - ctrl->length = 0; - mutex_unlock(&swap_cgroup_mutex); - - if (map) { - for (i = 0; i < length; i++) { - struct page *page = map[i]; + if (ctrl->map) { + for (i = 0; i < ctrl->length; i++) { + struct page *page = ctrl->map[i]; if (page) __free_page(page); } - vfree(map); + vfree(ctrl->map); + ctrl->map = NULL; + ctrl->length = 0; } + mutex_unlock(&swap_cgroup_mutex); } #endif diff --git a/trunk/mm/shmem.c b/trunk/mm/shmem.c index 1acfb2687bfa..69edb45a9f28 100644 --- a/trunk/mm/shmem.c +++ b/trunk/mm/shmem.c @@ -1305,10 +1305,12 @@ static int shmem_getpage(struct inode *inode, unsigned long idx, swappage = lookup_swap_cache(swap); if (!swappage) { shmem_swp_unmap(entry); - spin_unlock(&info->lock); /* here we actually do the io */ - if (type) + if (type && !(*type & VM_FAULT_MAJOR)) { + __count_vm_event(PGMAJFAULT); *type |= VM_FAULT_MAJOR; + } + spin_unlock(&info->lock); swappage = shmem_swapin(swap, gfp, info, idx); if (!swappage) { spin_lock(&info->lock); @@ -1547,10 +1549,7 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret); if (error) return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS); - if (ret & VM_FAULT_MAJOR) { - count_vm_event(PGMAJFAULT); - mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT); - } + return ret | VM_FAULT_LOCKED; } diff --git a/trunk/mm/truncate.c b/trunk/mm/truncate.c index 3a29a6180212..a95667529135 100644 --- a/trunk/mm/truncate.c +++ b/trunk/mm/truncate.c @@ -19,7 +19,6 @@ #include #include /* grr. try_to_release_page, do_invalidatepage */ -#include #include "internal.h" @@ -52,7 +51,6 @@ void do_invalidatepage(struct page *page, unsigned long offset) static inline void truncate_partial_page(struct page *page, unsigned partial) { zero_user_segment(page, partial, PAGE_CACHE_SIZE); - cleancache_flush_page(page->mapping, page); if (page_has_private(page)) do_invalidatepage(page, partial); } @@ -216,7 +214,6 @@ void truncate_inode_pages_range(struct address_space *mapping, pgoff_t next; int i; - cleancache_flush_inode(mapping); if (mapping->nrpages == 0) return; @@ -294,7 +291,6 @@ void truncate_inode_pages_range(struct address_space *mapping, pagevec_release(&pvec); mem_cgroup_uncharge_end(); } - cleancache_flush_inode(mapping); } EXPORT_SYMBOL(truncate_inode_pages_range); @@ -444,7 +440,6 @@ int invalidate_inode_pages2_range(struct address_space *mapping, int did_range_unmap = 0; int wrapped = 0; - cleancache_flush_inode(mapping); pagevec_init(&pvec, 0); next = start; while (next <= end && !wrapped && @@ -503,7 +498,6 @@ int invalidate_inode_pages2_range(struct address_space *mapping, mem_cgroup_uncharge_end(); cond_resched(); } - cleancache_flush_inode(mapping); return ret; } EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range); diff --git a/trunk/mm/vmalloc.c b/trunk/mm/vmalloc.c index 1d34d75366a7..b5ccf3158d82 100644 --- a/trunk/mm/vmalloc.c +++ b/trunk/mm/vmalloc.c @@ -2153,6 +2153,10 @@ struct vm_struct *alloc_vm_area(size_t size) return NULL; } + /* Make sure the pagetables are constructed in process kernel + mappings */ + vmalloc_sync_all(); + return area; } EXPORT_SYMBOL_GPL(alloc_vm_area); diff --git a/trunk/mm/vmscan.c b/trunk/mm/vmscan.c index faa0a088f9cc..7e0116150dc7 100644 --- a/trunk/mm/vmscan.c +++ b/trunk/mm/vmscan.c @@ -173,7 +173,7 @@ static unsigned long zone_nr_lru_pages(struct zone *zone, struct scan_control *sc, enum lru_list lru) { if (!scanning_global_lru(sc)) - return mem_cgroup_zone_nr_lru_pages(sc->mem_cgroup, zone, lru); + return mem_cgroup_zone_nr_pages(sc->mem_cgroup, zone, lru); return zone_page_state(zone, NR_LRU_BASE + lru); } @@ -1717,6 +1717,26 @@ static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan, return shrink_inactive_list(nr_to_scan, zone, sc, priority, file); } +/* + * Smallish @nr_to_scan's are deposited in @nr_saved_scan, + * until we collected @swap_cluster_max pages to scan. + */ +static unsigned long nr_scan_try_batch(unsigned long nr_to_scan, + unsigned long *nr_saved_scan) +{ + unsigned long nr; + + *nr_saved_scan += nr_to_scan; + nr = *nr_saved_scan; + + if (nr >= SWAP_CLUSTER_MAX) + *nr_saved_scan = 0; + else + nr = 0; + + return nr; +} + /* * Determine how aggressively the anon and file LRU lists should be * scanned. The relative value of each set of LRU lists is determined @@ -1735,22 +1755,6 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc, u64 fraction[2], denominator; enum lru_list l; int noswap = 0; - int force_scan = 0; - - - anon = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) + - zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON); - file = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_FILE) + - zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE); - - if (((anon + file) >> priority) < SWAP_CLUSTER_MAX) { - /* kswapd does zone balancing and need to scan this zone */ - if (scanning_global_lru(sc) && current_is_kswapd()) - force_scan = 1; - /* memcg may have small limit and need to avoid priority drop */ - if (!scanning_global_lru(sc)) - force_scan = 1; - } /* If we have no swap space, do not bother scanning anon pages. */ if (!sc->may_swap || (nr_swap_pages <= 0)) { @@ -1761,6 +1765,11 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc, goto out; } + anon = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) + + zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON); + file = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_FILE) + + zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE); + if (scanning_global_lru(sc)) { free = zone_page_state(zone, NR_FREE_PAGES); /* If we have very few page cache pages, @@ -1827,23 +1836,8 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc, scan >>= priority; scan = div64_u64(scan * fraction[file], denominator); } - - /* - * If zone is small or memcg is small, nr[l] can be 0. - * This results no-scan on this priority and priority drop down. - * For global direct reclaim, it can visit next zone and tend - * not to have problems. For global kswapd, it's for zone - * balancing and it need to scan a small amounts. When using - * memcg, priority drop can cause big latency. So, it's better - * to scan small amount. See may_noscan above. - */ - if (!scan && force_scan) { - if (file) - scan = SWAP_CLUSTER_MAX; - else if (!noswap) - scan = SWAP_CLUSTER_MAX; - } - nr[l] = scan; + nr[l] = nr_scan_try_batch(scan, + &reclaim_stat->nr_saved_scan[l]); } } @@ -1983,14 +1977,11 @@ static void shrink_zone(int priority, struct zone *zone, * If a zone is deemed to be full of pinned pages then just give it a light * scan then give up on it. */ -static unsigned long shrink_zones(int priority, struct zonelist *zonelist, +static void shrink_zones(int priority, struct zonelist *zonelist, struct scan_control *sc) { struct zoneref *z; struct zone *zone; - unsigned long nr_soft_reclaimed; - unsigned long nr_soft_scanned; - unsigned long total_scanned = 0; for_each_zone_zonelist_nodemask(zone, z, zonelist, gfp_zone(sc->gfp_mask), sc->nodemask) { @@ -2007,17 +1998,8 @@ static unsigned long shrink_zones(int priority, struct zonelist *zonelist, continue; /* Let kswapd poll it */ } - nr_soft_scanned = 0; - nr_soft_reclaimed = mem_cgroup_soft_limit_reclaim(zone, - sc->order, sc->gfp_mask, - &nr_soft_scanned); - sc->nr_reclaimed += nr_soft_reclaimed; - total_scanned += nr_soft_scanned; - shrink_zone(priority, zone, sc); } - - return total_scanned; } static bool zone_reclaimable(struct zone *zone) @@ -2082,7 +2064,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, sc->nr_scanned = 0; if (!priority) disable_swap_token(); - total_scanned += shrink_zones(priority, zonelist, sc); + shrink_zones(priority, zonelist, sc); /* * Don't shrink slabs when reclaiming memory from * over limit cgroups @@ -2189,11 +2171,9 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order, unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, gfp_t gfp_mask, bool noswap, unsigned int swappiness, - struct zone *zone, - unsigned long *nr_scanned) + struct zone *zone) { struct scan_control sc = { - .nr_scanned = 0, .nr_to_reclaim = SWAP_CLUSTER_MAX, .may_writepage = !laptop_mode, .may_unmap = 1, @@ -2202,7 +2182,6 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, .order = 0, .mem_cgroup = mem, }; - sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) | (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK); @@ -2221,7 +2200,6 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, trace_mm_vmscan_memcg_softlimit_reclaim_end(sc.nr_reclaimed); - *nr_scanned = sc.nr_scanned; return sc.nr_reclaimed; } @@ -2232,7 +2210,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, { struct zonelist *zonelist; unsigned long nr_reclaimed; - int nid; struct scan_control sc = { .may_writepage = !laptop_mode, .may_unmap = 1, @@ -2249,14 +2226,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, .gfp_mask = sc.gfp_mask, }; - /* - * Unlike direct reclaim via alloc_pages(), memcg's reclaim doesn't - * take care of from where we get pages. So the node where we start the - * scan does not need to be the current node. - */ - nid = mem_cgroup_select_victim_node(mem_cont); - - zonelist = NODE_DATA(nid)->node_zonelists; + zonelist = NODE_DATA(numa_node_id())->node_zonelists; trace_mm_vmscan_memcg_reclaim_begin(0, sc.may_writepage, @@ -2377,8 +2347,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, int end_zone = 0; /* Inclusive. 0 = ZONE_DMA */ unsigned long total_scanned; struct reclaim_state *reclaim_state = current->reclaim_state; - unsigned long nr_soft_reclaimed; - unsigned long nr_soft_scanned; struct scan_control sc = { .gfp_mask = GFP_KERNEL, .may_unmap = 1, @@ -2471,15 +2439,11 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, sc.nr_scanned = 0; - nr_soft_scanned = 0; /* * Call soft limit reclaim before calling shrink_zone. + * For now we ignore the return value */ - nr_soft_reclaimed = mem_cgroup_soft_limit_reclaim(zone, - order, sc.gfp_mask, - &nr_soft_scanned); - sc.nr_reclaimed += nr_soft_reclaimed; - total_scanned += nr_soft_scanned; + mem_cgroup_soft_limit_reclaim(zone, order, sc.gfp_mask); /* * We put equal pressure on every zone, unless diff --git a/trunk/net/9p/trans_rdma.c b/trunk/net/9p/trans_rdma.c index 159c50f1c6bf..844a7a5607e3 100644 --- a/trunk/net/9p/trans_rdma.c +++ b/trunk/net/9p/trans_rdma.c @@ -589,8 +589,7 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args) return -ENOMEM; /* Create the RDMA CM ID */ - rdma->cm_id = rdma_create_id(p9_cm_event_handler, client, RDMA_PS_TCP, - IB_QPT_RC); + rdma->cm_id = rdma_create_id(p9_cm_event_handler, client, RDMA_PS_TCP); if (IS_ERR(rdma->cm_id)) goto error; diff --git a/trunk/net/atm/lec.c b/trunk/net/atm/lec.c index ba48daa68c1f..25073b6ef474 100644 --- a/trunk/net/atm/lec.c +++ b/trunk/net/atm/lec.c @@ -1171,7 +1171,7 @@ static int __init lane_module_init(void) #endif register_atm_ioctl(&lane_ioctl_ops); - pr_info("lec.c: initialized\n"); + pr_info("lec.c: " __DATE__ " " __TIME__ " initialized\n"); return 0; } diff --git a/trunk/net/atm/mpc.c b/trunk/net/atm/mpc.c index 3ccca42e6f90..644cdf071642 100644 --- a/trunk/net/atm/mpc.c +++ b/trunk/net/atm/mpc.c @@ -1482,7 +1482,7 @@ static __init int atm_mpoa_init(void) if (mpc_proc_init() != 0) pr_info("failed to initialize /proc/mpoa\n"); - pr_info("mpc.c: initialized\n"); + pr_info("mpc.c: " __DATE__ " " __TIME__ " initialized\n"); return 0; } diff --git a/trunk/net/ipv4/inet_connection_sock.c b/trunk/net/ipv4/inet_connection_sock.c index c14d88ad348d..61fac4cabc78 100644 --- a/trunk/net/ipv4/inet_connection_sock.c +++ b/trunk/net/ipv4/inet_connection_sock.c @@ -33,7 +33,7 @@ EXPORT_SYMBOL(inet_csk_timer_bug_msg); * This struct holds the first and last local port number. */ struct local_ports sysctl_local_ports __read_mostly = { - .lock = __SEQLOCK_UNLOCKED(sysctl_local_ports.lock), + .lock = SEQLOCK_UNLOCKED, .range = { 32768, 61000 }, }; diff --git a/trunk/net/rds/ib.c b/trunk/net/rds/ib.c index 3b83086bcc30..cce19f95c624 100644 --- a/trunk/net/rds/ib.c +++ b/trunk/net/rds/ib.c @@ -325,7 +325,7 @@ static int rds_ib_laddr_check(__be32 addr) /* Create a CMA ID and try to bind it. This catches both * IB and iWARP capable NICs. */ - cm_id = rdma_create_id(NULL, NULL, RDMA_PS_TCP, IB_QPT_RC); + cm_id = rdma_create_id(NULL, NULL, RDMA_PS_TCP); if (IS_ERR(cm_id)) return PTR_ERR(cm_id); diff --git a/trunk/net/rds/ib_cm.c b/trunk/net/rds/ib_cm.c index fd453dd5124b..ee369d201a65 100644 --- a/trunk/net/rds/ib_cm.c +++ b/trunk/net/rds/ib_cm.c @@ -587,7 +587,7 @@ int rds_ib_conn_connect(struct rds_connection *conn) /* XXX I wonder what affect the port space has */ /* delegate cm event handler to rdma_transport */ ic->i_cm_id = rdma_create_id(rds_rdma_cm_event_handler, conn, - RDMA_PS_TCP, IB_QPT_RC); + RDMA_PS_TCP); if (IS_ERR(ic->i_cm_id)) { ret = PTR_ERR(ic->i_cm_id); ic->i_cm_id = NULL; diff --git a/trunk/net/rds/iw.c b/trunk/net/rds/iw.c index f7474844f096..5a9676fe594f 100644 --- a/trunk/net/rds/iw.c +++ b/trunk/net/rds/iw.c @@ -226,7 +226,7 @@ static int rds_iw_laddr_check(__be32 addr) /* Create a CMA ID and try to bind it. This catches both * IB and iWARP capable NICs. */ - cm_id = rdma_create_id(NULL, NULL, RDMA_PS_TCP, IB_QPT_RC); + cm_id = rdma_create_id(NULL, NULL, RDMA_PS_TCP); if (IS_ERR(cm_id)) return PTR_ERR(cm_id); diff --git a/trunk/net/rds/iw_cm.c b/trunk/net/rds/iw_cm.c index c12db66f24c7..3a60a15d1b4a 100644 --- a/trunk/net/rds/iw_cm.c +++ b/trunk/net/rds/iw_cm.c @@ -522,7 +522,7 @@ int rds_iw_conn_connect(struct rds_connection *conn) /* XXX I wonder what affect the port space has */ /* delegate cm event handler to rdma_transport */ ic->i_cm_id = rdma_create_id(rds_rdma_cm_event_handler, conn, - RDMA_PS_TCP, IB_QPT_RC); + RDMA_PS_TCP); if (IS_ERR(ic->i_cm_id)) { ret = PTR_ERR(ic->i_cm_id); ic->i_cm_id = NULL; diff --git a/trunk/net/rds/rdma_transport.c b/trunk/net/rds/rdma_transport.c index f8760e1b6688..4195a0539829 100644 --- a/trunk/net/rds/rdma_transport.c +++ b/trunk/net/rds/rdma_transport.c @@ -158,8 +158,7 @@ static int rds_rdma_listen_init(void) struct rdma_cm_id *cm_id; int ret; - cm_id = rdma_create_id(rds_rdma_cm_event_handler, NULL, RDMA_PS_TCP, - IB_QPT_RC); + cm_id = rdma_create_id(rds_rdma_cm_event_handler, NULL, RDMA_PS_TCP); if (IS_ERR(cm_id)) { ret = PTR_ERR(cm_id); printk(KERN_ERR "RDS/RDMA: failed to setup listener, " diff --git a/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c b/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c index c3c232a88d94..6c014dd3a20b 100644 --- a/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -695,8 +695,7 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, return ERR_PTR(-ENOMEM); xprt = &cma_xprt->sc_xprt; - listen_id = rdma_create_id(rdma_listen_handler, cma_xprt, RDMA_PS_TCP, - IB_QPT_RC); + listen_id = rdma_create_id(rdma_listen_handler, cma_xprt, RDMA_PS_TCP); if (IS_ERR(listen_id)) { ret = PTR_ERR(listen_id); dprintk("svcrdma: rdma_create_id failed = %d\n", ret); diff --git a/trunk/net/sunrpc/xprtrdma/verbs.c b/trunk/net/sunrpc/xprtrdma/verbs.c index 80f8da344df5..d4297dc43dc4 100644 --- a/trunk/net/sunrpc/xprtrdma/verbs.c +++ b/trunk/net/sunrpc/xprtrdma/verbs.c @@ -387,7 +387,7 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt, init_completion(&ia->ri_done); - id = rdma_create_id(rpcrdma_conn_upcall, xprt, RDMA_PS_TCP, IB_QPT_RC); + id = rdma_create_id(rpcrdma_conn_upcall, xprt, RDMA_PS_TCP); if (IS_ERR(id)) { rc = PTR_ERR(id); dprintk("RPC: %s: rdma_create_id() failed %i\n", diff --git a/trunk/security/device_cgroup.c b/trunk/security/device_cgroup.c index cd1f779fa51d..8d9c48f13774 100644 --- a/trunk/security/device_cgroup.c +++ b/trunk/security/device_cgroup.c @@ -62,7 +62,8 @@ static inline struct dev_cgroup *task_devcgroup(struct task_struct *task) struct cgroup_subsys devices_subsys; static int devcgroup_can_attach(struct cgroup_subsys *ss, - struct cgroup *new_cgroup, struct task_struct *task) + struct cgroup *new_cgroup, struct task_struct *task, + bool threadgroup) { if (current != task && !capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/trunk/security/keys/process_keys.c b/trunk/security/keys/process_keys.c index a3063eb3dc23..6c0480db8885 100644 --- a/trunk/security/keys/process_keys.c +++ b/trunk/security/keys/process_keys.c @@ -847,7 +847,6 @@ void key_replace_session_keyring(void) new-> sgid = old-> sgid; new->fsgid = old->fsgid; new->user = get_uid(old->user); - new->user_ns = new->user->user_ns; new->group_info = get_group_info(old->group_info); new->securebits = old->securebits; diff --git a/trunk/security/selinux/avc.c b/trunk/security/selinux/avc.c index d515b2128a4e..fcb89cb0f223 100644 --- a/trunk/security/selinux/avc.c +++ b/trunk/security/selinux/avc.c @@ -752,9 +752,10 @@ int avc_ss_reset(u32 seqno) int avc_has_perm_noaudit(u32 ssid, u32 tsid, u16 tclass, u32 requested, unsigned flags, - struct av_decision *avd) + struct av_decision *in_avd) { struct avc_node *node; + struct av_decision avd_entry, *avd; int rc = 0; u32 denied; @@ -765,11 +766,18 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, node = avc_lookup(ssid, tsid, tclass); if (unlikely(!node)) { rcu_read_unlock(); + + if (in_avd) + avd = in_avd; + else + avd = &avd_entry; + security_compute_av(ssid, tsid, tclass, avd); rcu_read_lock(); node = avc_insert(ssid, tsid, tclass, avd); } else { - memcpy(avd, &node->ae.avd, sizeof(*avd)); + if (in_avd) + memcpy(in_avd, &node->ae.avd, sizeof(*in_avd)); avd = &node->ae.avd; } diff --git a/trunk/security/selinux/ss/services.c b/trunk/security/selinux/ss/services.c index 973e00e34fa9..c3e4b52699f4 100644 --- a/trunk/security/selinux/ss/services.c +++ b/trunk/security/selinux/ss/services.c @@ -2217,11 +2217,10 @@ int security_get_user_sids(u32 fromsid, goto out; } for (i = 0, j = 0; i < mynel; i++) { - struct av_decision dummy_avd; rc = avc_has_perm_noaudit(fromsid, mysids[i], SECCLASS_PROCESS, /* kernel value */ PROCESS__TRANSITION, AVC_STRICT, - &dummy_avd); + NULL); if (!rc) mysids2[j++] = mysids[i]; cond_resched(); diff --git a/trunk/sound/core/control.c b/trunk/sound/core/control.c index f8c5be464510..5d98194bcad5 100644 --- a/trunk/sound/core/control.c +++ b/trunk/sound/core/control.c @@ -704,12 +704,13 @@ static int snd_ctl_elem_list(struct snd_card *card, struct snd_ctl_elem_list list; struct snd_kcontrol *kctl; struct snd_ctl_elem_id *dst, *id; - unsigned int offset, space, jidx; + unsigned int offset, space, first, jidx; if (copy_from_user(&list, _list, sizeof(list))) return -EFAULT; offset = list.offset; space = list.space; + first = 0; /* try limit maximum space */ if (space > 16384) return -ENOMEM; diff --git a/trunk/sound/core/init.c b/trunk/sound/core/init.c index 2c041bb36ab3..30ecad41403c 100644 --- a/trunk/sound/core/init.c +++ b/trunk/sound/core/init.c @@ -342,6 +342,7 @@ static const struct file_operations snd_shutdown_f_ops = int snd_card_disconnect(struct snd_card *card) { struct snd_monitor_file *mfile; + struct file *file; int err; if (!card) @@ -365,6 +366,8 @@ int snd_card_disconnect(struct snd_card *card) spin_lock(&card->files_lock); list_for_each_entry(mfile, &card->files_list, list) { + file = mfile->file; + /* it's critical part, use endless loop */ /* we have no room to fail */ mfile->disconnected_f_op = mfile->file->f_op; diff --git a/trunk/sound/core/oss/linear.c b/trunk/sound/core/oss/linear.c index 2045697f449d..13b3f6f49fae 100644 --- a/trunk/sound/core/oss/linear.c +++ b/trunk/sound/core/oss/linear.c @@ -90,8 +90,11 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin, struct snd_pcm_plugin_channel *dst_channels, snd_pcm_uframes_t frames) { + struct linear_priv *data; + if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) return -ENXIO; + data = (struct linear_priv *)plugin->extra_data; if (frames == 0) return 0; #ifdef CONFIG_SND_DEBUG diff --git a/trunk/sound/core/pcm_lib.c b/trunk/sound/core/pcm_lib.c index f1341308beda..abfeff1611ce 100644 --- a/trunk/sound/core/pcm_lib.c +++ b/trunk/sound/core/pcm_lib.c @@ -1756,18 +1756,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream, wait_queue_t wait; int err = 0; snd_pcm_uframes_t avail = 0; - long wait_time, tout; - - if (runtime->no_period_wakeup) - wait_time = MAX_SCHEDULE_TIMEOUT; - else { - wait_time = 10; - if (runtime->rate) { - long t = runtime->period_size * 2 / runtime->rate; - wait_time = max(t, wait_time); - } - wait_time = msecs_to_jiffies(wait_time * 1000); - } + long tout; + init_waitqueue_entry(&wait, current); add_wait_queue(&runtime->tsleep, &wait); for (;;) { @@ -1775,8 +1765,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream, err = -ERESTARTSYS; break; } + set_current_state(TASK_INTERRUPTIBLE); snd_pcm_stream_unlock_irq(substream); - tout = schedule_timeout_interruptible(wait_time); + tout = schedule_timeout(msecs_to_jiffies(10000)); snd_pcm_stream_lock_irq(substream); switch (runtime->status->state) { case SNDRV_PCM_STATE_SUSPENDED: diff --git a/trunk/sound/core/pcm_native.c b/trunk/sound/core/pcm_native.c index 1c6be91dfb98..1a07750f3836 100644 --- a/trunk/sound/core/pcm_native.c +++ b/trunk/sound/core/pcm_native.c @@ -1481,20 +1481,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, break; /* all drained */ init_waitqueue_entry(&wait, current); add_wait_queue(&to_check->sleep, &wait); + set_current_state(TASK_INTERRUPTIBLE); snd_pcm_stream_unlock_irq(substream); up_read(&snd_pcm_link_rwsem); snd_power_unlock(card); - if (runtime->no_period_wakeup) - tout = MAX_SCHEDULE_TIMEOUT; - else { - tout = 10; - if (runtime->rate) { - long t = runtime->period_size * 2 / runtime->rate; - tout = max(t, tout); - } - tout = msecs_to_jiffies(tout * 1000); - } - tout = schedule_timeout_interruptible(tout); + tout = schedule_timeout(10 * HZ); snd_power_lock(card); down_read(&snd_pcm_link_rwsem); snd_pcm_stream_lock_irq(substream); @@ -1527,11 +1518,13 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, static int snd_pcm_drop(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; + struct snd_card *card; int result = 0; if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; + card = substream->pcm->card; if (runtime->status->state == SNDRV_PCM_STATE_OPEN || runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED || @@ -2063,6 +2056,7 @@ static int snd_pcm_open_file(struct file *file, { struct snd_pcm_file *pcm_file; struct snd_pcm_substream *substream; + struct snd_pcm_str *str; int err; if (rpcm_file) @@ -2079,6 +2073,7 @@ static int snd_pcm_open_file(struct file *file, } pcm_file->substream = substream; if (substream->ref_count == 1) { + str = substream->pstr; substream->file = pcm_file; substream->pcm_release = pcm_release_private; } @@ -3020,9 +3015,11 @@ static const struct vm_operations_struct snd_pcm_vm_ops_status = static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area) { + struct snd_pcm_runtime *runtime; long size; if (!(area->vm_flags & VM_READ)) return -EINVAL; + runtime = substream->runtime; size = area->vm_end - area->vm_start; if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))) return -EINVAL; @@ -3057,9 +3054,11 @@ static const struct vm_operations_struct snd_pcm_vm_ops_control = static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area) { + struct snd_pcm_runtime *runtime; long size; if (!(area->vm_flags & VM_READ)) return -EINVAL; + runtime = substream->runtime; size = area->vm_end - area->vm_start; if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))) return -EINVAL; diff --git a/trunk/sound/core/seq/seq_queue.c b/trunk/sound/core/seq/seq_queue.c index f9077361c119..e7a8e9e4edb2 100644 --- a/trunk/sound/core/seq/seq_queue.c +++ b/trunk/sound/core/seq/seq_queue.c @@ -467,11 +467,13 @@ int snd_seq_queue_timer_open(int queueid) int snd_seq_queue_timer_close(int queueid) { struct snd_seq_queue *queue; + struct snd_seq_timer *tmr; int result = 0; queue = queueptr(queueid); if (queue == NULL) return -EINVAL; + tmr = queue->timer; snd_seq_timer_close(queue); queuefree(queue); return result; diff --git a/trunk/sound/pci/hda/hda_codec.c b/trunk/sound/pci/hda/hda_codec.c index 45b4a8d70e08..8edd998509f7 100644 --- a/trunk/sound/pci/hda/hda_codec.c +++ b/trunk/sound/pci/hda/hda_codec.c @@ -4719,7 +4719,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, cfg->dig_out_pins[0], cfg->dig_out_pins[1]); snd_printd(" inputs:"); for (i = 0; i < cfg->num_inputs; i++) { - snd_printd(" %s=0x%x", + snd_printdd(" %s=0x%x", hda_get_autocfg_input_label(codec, cfg, i), cfg->inputs[i].pin); } diff --git a/trunk/sound/pci/hda/hda_eld.c b/trunk/sound/pci/hda/hda_eld.c index b05f7be9dc1b..74b0560289c0 100644 --- a/trunk/sound/pci/hda/hda_eld.c +++ b/trunk/sound/pci/hda/hda_eld.c @@ -312,6 +312,23 @@ static int hdmi_update_eld(struct hdmi_eld *e, return -EINVAL; } +static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid) +{ + int eldv; + int present; + + present = snd_hda_pin_sense(codec, nid); + eldv = (present & AC_PINSENSE_ELDV); + present = (present & AC_PINSENSE_PRESENCE); + +#ifdef CONFIG_SND_DEBUG_VERBOSE + printk(KERN_INFO "HDMI: sink_present = %d, eld_valid = %d\n", + !!present, !!eldv); +#endif + + return eldv && present; +} + int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) { return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, @@ -326,7 +343,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, int size; unsigned char *buf; - if (!eld->eld_valid) + if (!hdmi_eld_valid(codec, nid)) return -ENOENT; size = snd_hdmi_get_eld_size(codec, nid); @@ -460,8 +477,6 @@ static void hdmi_print_eld_info(struct snd_info_entry *entry, snd_iprintf(buffer, "monitor_present\t\t%d\n", e->monitor_present); snd_iprintf(buffer, "eld_valid\t\t%d\n", e->eld_valid); - if (!e->eld_valid) - return; snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name); snd_iprintf(buffer, "connection_type\t\t%s\n", eld_connection_type_names[e->conn_type]); diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index 348705666f99..43a036716d25 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -391,7 +391,6 @@ struct azx { /* chip type specific */ int driver_type; - unsigned int driver_caps; int playback_streams; int playback_index_offset; int capture_streams; @@ -465,34 +464,6 @@ enum { AZX_NUM_DRIVERS, /* keep this as last entry */ }; -/* driver quirks (capabilities) */ -/* bits 0-7 are used for indicating driver type */ -#define AZX_DCAPS_NO_TCSEL (1 << 8) /* No Intel TCSEL bit */ -#define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */ -#define AZX_DCAPS_ATI_SNOOP (1 << 10) /* ATI snoop enable */ -#define AZX_DCAPS_NVIDIA_SNOOP (1 << 11) /* Nvidia snoop enable */ -#define AZX_DCAPS_SCH_SNOOP (1 << 12) /* SCH/PCH snoop enable */ -#define AZX_DCAPS_RIRB_DELAY (1 << 13) /* Long delay in read loop */ -#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14) /* Put a delay before read */ -#define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ -#define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ -#define AZX_DCAPS_POSFIX_VIA (1 << 17) /* Use VIACOMBO as default */ -#define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */ -#define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ - -/* quirks for ATI SB / AMD Hudson */ -#define AZX_DCAPS_PRESET_ATI_SB \ - (AZX_DCAPS_ATI_SNOOP | AZX_DCAPS_NO_TCSEL | \ - AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB) - -/* quirks for ATI/AMD HDMI */ -#define AZX_DCAPS_PRESET_ATI_HDMI \ - (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB) - -/* quirks for Nvidia */ -#define AZX_DCAPS_PRESET_NVIDIA \ - (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI) - static char *driver_short_names[] __devinitdata = { [AZX_DRIVER_ICH] = "HDA Intel", [AZX_DRIVER_PCH] = "HDA Intel PCH", @@ -595,7 +566,7 @@ static void azx_init_cmd_io(struct azx *chip) /* reset the rirb hw write pointer */ azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); /* set N=1, get RIRB response interrupt for new entry */ - if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) + if (chip->driver_type == AZX_DRIVER_CTX) azx_writew(chip, RINTCNT, 0xc0); else azx_writew(chip, RINTCNT, 1); @@ -1085,24 +1056,19 @@ static void azx_init_pci(struct azx *chip) * codecs. * The PCI register TCSEL is defined in the Intel manuals. */ - if (chip->driver_caps & AZX_DCAPS_NO_TCSEL) { - snd_printdd(SFX "Clearing TCSEL\n"); + if (chip->driver_type != AZX_DRIVER_ATI && + chip->driver_type != AZX_DRIVER_ATIHDMI) update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); - } - /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio, - * we need to enable snoop. - */ - if (chip->driver_caps & AZX_DCAPS_ATI_SNOOP) { - snd_printdd(SFX "Enabling ATI snoop\n"); + switch (chip->driver_type) { + case AZX_DRIVER_ATI: + /* For ATI SB450 azalia HD audio, we need to enable snoop */ update_pci_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP); - } - - /* For NVIDIA HDA, enable snoop */ - if (chip->driver_caps & AZX_DCAPS_NVIDIA_SNOOP) { - snd_printdd(SFX "Enabling Nvidia snoop\n"); + break; + case AZX_DRIVER_NVIDIA: + /* For NVIDIA HDA, enable snoop */ update_pci_byte(chip->pci, NVIDIA_HDA_TRANSREG_ADDR, 0x0f, NVIDIA_HDA_ENABLE_COHBITS); @@ -1112,10 +1078,9 @@ static void azx_init_pci(struct azx *chip) update_pci_byte(chip->pci, NVIDIA_HDA_OSTRM_COH, 0x01, NVIDIA_HDA_ENABLE_COHBIT); - } - - /* Enable SCH/PCH snoop if needed */ - if (chip->driver_caps & AZX_DCAPS_SCH_SNOOP) { + break; + case AZX_DRIVER_SCH: + case AZX_DRIVER_PCH: pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) { pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, @@ -1126,6 +1091,14 @@ static void azx_init_pci(struct azx *chip) (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) ? "Failed" : "OK"); } + break; + default: + /* AMD Hudson needs the similar snoop, as it seems... */ + if (chip->pci->vendor == PCI_VENDOR_ID_AMD) + update_pci_byte(chip->pci, + ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, + 0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP); + break; } } @@ -1179,7 +1152,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) status = azx_readb(chip, RIRBSTS); if (status & RIRB_INT_MASK) { if (status & RIRB_INT_RESPONSE) { - if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY) + if (chip->driver_type == AZX_DRIVER_CTX) udelay(80); azx_update_rirb(chip); } @@ -1448,10 +1421,8 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) if (err < 0) return err; - if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) { - snd_printd(SFX "Enable delay in RIRB handling\n"); + if (chip->driver_type == AZX_DRIVER_NVIDIA) chip->bus->needs_damn_long_delay = 1; - } codecs = 0; max_slots = azx_max_codecs[chip->driver_type]; @@ -1486,8 +1457,9 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) * sequence like the pin-detection. It seems that forcing the synced * access works around the stall. Grrr... */ - if (chip->driver_caps & AZX_DCAPS_SYNC_WRITE) { - snd_printd(SFX "Enable sync_write for stable communication\n"); + if (chip->pci->vendor == PCI_VENDOR_ID_AMD || + chip->pci->vendor == PCI_VENDOR_ID_ATI) { + snd_printk(KERN_INFO SFX "Enable sync_write for AMD chipset\n"); chip->bus->sync_write = 1; chip->bus->allow_bus_reset = 1; } @@ -1748,7 +1720,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) stream_tag = azx_dev->stream_tag; /* CA-IBG chips need the playback stream starting from 1 */ - if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) && + if (chip->driver_type == AZX_DRIVER_CTX && stream_tag > chip->capture_streams) stream_tag -= chip->capture_streams; return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, @@ -2393,14 +2365,20 @@ static int __devinit check_position_fix(struct azx *chip, int fix) } /* Check VIA/ATI HD Audio Controller exist */ - if (chip->driver_caps & AZX_DCAPS_POSFIX_VIA) { - snd_printd(SFX "Using VIACOMBO position fix\n"); + switch (chip->driver_type) { + case AZX_DRIVER_VIA: + /* Use link position directly, avoid any transfer problem. */ return POS_FIX_VIACOMBO; - } - if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) { - snd_printd(SFX "Using LPIB position fix\n"); + case AZX_DRIVER_ATI: + /* ATI chipsets don't work well with position-buffer */ return POS_FIX_LPIB; + case AZX_DRIVER_GENERIC: + /* AMD chipsets also don't work with position-buffer */ + if (chip->pci->vendor == PCI_VENDOR_ID_AMD) + return POS_FIX_LPIB; + break; } + return POS_FIX_AUTO; } @@ -2482,8 +2460,8 @@ static void __devinit check_msi(struct azx *chip) } /* NVidia chipsets seem to cause troubles with MSI */ - if (chip->driver_caps & AZX_DCAPS_NO_MSI) { - printk(KERN_INFO "hda_intel: Disabling MSI\n"); + if (chip->driver_type == AZX_DRIVER_NVIDIA) { + printk(KERN_INFO "hda_intel: Disable MSI for Nvidia chipset\n"); chip->msi = 0; } } @@ -2493,7 +2471,7 @@ static void __devinit check_msi(struct azx *chip) * constructor */ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, - int dev, unsigned int driver_caps, + int dev, int driver_type, struct azx **rchip) { struct azx *chip; @@ -2521,8 +2499,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->card = card; chip->pci = pci; chip->irq = -1; - chip->driver_caps = driver_caps; - chip->driver_type = driver_caps & 0xff; + chip->driver_type = driver_type; check_msi(chip); chip->dev_index = dev; INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); @@ -2586,7 +2563,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap); /* disable SB600 64bit support for safety */ - if (chip->pci->vendor == PCI_VENDOR_ID_ATI) { + if ((chip->driver_type == AZX_DRIVER_ATI) || + (chip->driver_type == AZX_DRIVER_ATIHDMI)) { struct pci_dev *p_smbus; p_smbus = pci_get_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, @@ -2596,13 +2574,19 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, gcap &= ~ICH6_GCAP_64OK; pci_dev_put(p_smbus); } + } else { + /* FIXME: not sure whether this is really needed, but + * Hudson isn't stable enough for allowing everything... + * let's check later again. + */ + if (chip->pci->vendor == PCI_VENDOR_ID_AMD) + gcap &= ~ICH6_GCAP_64OK; } - /* disable 64bit DMA address on some devices */ - if (chip->driver_caps & AZX_DCAPS_NO_64BIT) { - snd_printd(SFX "Disabling 64bit DMA\n"); + /* disable 64bit DMA address for Teradici */ + /* it does not work with device 6549:1200 subsys e4a2:040b */ + if (chip->driver_type == AZX_DRIVER_TERA) gcap &= ~ICH6_GCAP_64OK; - } /* allow 64bit DMA address if supported by H/W */ if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) @@ -2804,62 +2788,38 @@ static void __devexit azx_remove(struct pci_dev *pci) /* PCI IDs */ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* CPT */ - { PCI_DEVICE(0x8086, 0x1c20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP }, + { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, /* PBG */ - { PCI_DEVICE(0x8086, 0x1d20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP }, + { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH }, /* Panther Point */ - { PCI_DEVICE(0x8086, 0x1e20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP }, + { PCI_DEVICE(0x8086, 0x1e20), .driver_data = AZX_DRIVER_PCH }, /* SCH */ - { PCI_DEVICE(0x8086, 0x811b), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP }, + { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, /* Generic Intel */ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID), .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, .driver_data = AZX_DRIVER_ICH }, - /* ATI SB 450/600/700/800/900 */ - { PCI_DEVICE(0x1002, 0x437b), - .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB }, - { PCI_DEVICE(0x1002, 0x4383), - .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB }, - /* AMD Hudson */ - { PCI_DEVICE(0x1022, 0x780d), - .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, + /* ATI SB 450/600 */ + { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI }, + { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI }, /* ATI HDMI */ - { PCI_DEVICE(0x1002, 0x793b), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0x7919), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0x960f), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0x970f), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa00), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa08), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa10), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa18), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa20), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa28), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa30), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa38), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa40), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa48), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, + { PCI_DEVICE(0x1002, 0x793b), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0x7919), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0x960f), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0x970f), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0xaa00), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0xaa08), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0xaa10), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0xaa18), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0xaa20), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0xaa28), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0xaa30), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0xaa38), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0xaa40), .driver_data = AZX_DRIVER_ATIHDMI }, + { PCI_DEVICE(0x1002, 0xaa48), .driver_data = AZX_DRIVER_ATIHDMI }, /* VIA VT8251/VT8237A */ - { PCI_DEVICE(0x1106, 0x3288), - .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, + { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA }, /* SIS966 */ { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS }, /* ULI M5461 */ @@ -2868,10 +2828,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, - .driver_data = AZX_DRIVER_NVIDIA | AZX_DCAPS_PRESET_NVIDIA }, + .driver_data = AZX_DRIVER_NVIDIA }, /* Teradici */ - { PCI_DEVICE(0x6549, 0x1200), - .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, + { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, /* Creative X-Fi (CA0110-IBG) */ #if !defined(CONFIG_SND_CTXFI) && !defined(CONFIG_SND_CTXFI_MODULE) /* the following entry conflicts with snd-ctxfi driver, @@ -2881,13 +2840,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID), .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, - .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | - AZX_DCAPS_RIRB_PRE_DELAY }, + .driver_data = AZX_DRIVER_CTX }, #else /* this entry seems still valid -- i.e. without emu20kx chip */ - { PCI_DEVICE(0x1102, 0x0009), - .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | - AZX_DCAPS_RIRB_PRE_DELAY }, + { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX }, #endif /* Vortex86MX */ { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, @@ -2897,11 +2853,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, - .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI }, + .driver_data = AZX_DRIVER_GENERIC }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_ANY_ID), .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, - .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI }, + .driver_data = AZX_DRIVER_GENERIC }, { 0, } }; MODULE_DEVICE_TABLE(pci, azx_ids); diff --git a/trunk/sound/pci/hda/patch_analog.c b/trunk/sound/pci/hda/patch_analog.c index 696ac2590307..f1b3875c57df 100644 --- a/trunk/sound/pci/hda/patch_analog.c +++ b/trunk/sound/pci/hda/patch_analog.c @@ -3159,7 +3159,6 @@ static const struct snd_pci_quirk ad1988_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG), SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG), SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG), - SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG), SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG), {} }; diff --git a/trunk/sound/pci/hda/patch_conexant.c b/trunk/sound/pci/hda/patch_conexant.c index 3e6b9a8539c2..4f37477d3c71 100644 --- a/trunk/sound/pci/hda/patch_conexant.c +++ b/trunk/sound/pci/hda/patch_conexant.c @@ -3098,9 +3098,7 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD), - SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), - SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */ {} }; @@ -3435,9 +3433,7 @@ static void cx_auto_parse_output(struct hda_codec *codec) break; } } - if (spec->auto_mute && - cfg->line_out_pins[0] && - cfg->line_out_type != AUTO_PIN_SPEAKER_OUT && + if (spec->auto_mute && cfg->line_out_pins[0] && cfg->line_out_pins[0] != cfg->hp_pins[0] && cfg->line_out_pins[0] != cfg->speaker_pins[0]) { for (i = 0; i < cfg->line_outs; i++) { @@ -3485,32 +3481,25 @@ static void cx_auto_update_speakers(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - int on = 1; + int on; - /* turn on HP EAPD when HP jacks are present */ - if (spec->auto_mute) - on = spec->hp_present; + if (!spec->auto_mute) + on = 0; + else + on = spec->hp_present | spec->line_present; cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on); - /* mute speakers in auto-mode if HP or LO jacks are plugged */ - if (spec->auto_mute) - on = !(spec->hp_present || - (spec->detect_line && spec->line_present)); - do_automute(codec, cfg->speaker_outs, cfg->speaker_pins, on); + do_automute(codec, cfg->speaker_outs, cfg->speaker_pins, !on); /* toggle line-out mutes if needed, too */ /* if LO is a copy of either HP or Speaker, don't need to handle it */ if (cfg->line_out_pins[0] == cfg->hp_pins[0] || cfg->line_out_pins[0] == cfg->speaker_pins[0]) return; - if (spec->auto_mute) { - /* mute LO in auto-mode when HP jack is present */ - if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT || - spec->automute_lines) - on = !spec->hp_present; - else - on = 1; - } - do_automute(codec, cfg->line_outs, cfg->line_out_pins, on); + if (!spec->automute_lines || !spec->auto_mute) + on = 0; + else + on = spec->hp_present; + do_automute(codec, cfg->line_outs, cfg->line_out_pins, !on); } static void cx_auto_hp_automute(struct hda_codec *codec) @@ -3707,14 +3696,13 @@ static int cx_auto_mux_enum_update(struct hda_codec *codec, { struct conexant_spec *spec = codec->spec; hda_nid_t adc; - int changed = 1; if (!imux->num_items) return 0; if (idx >= imux->num_items) idx = imux->num_items - 1; if (spec->cur_mux[0] == idx) - changed = 0; + return 0; adc = spec->imux_info[idx].adc; select_input_connection(codec, spec->imux_info[idx].adc, spec->imux_info[idx].pin); @@ -3727,7 +3715,7 @@ static int cx_auto_mux_enum_update(struct hda_codec *codec, spec->cur_adc_format); } spec->cur_mux[0] = idx; - return changed; + return 1; } static int cx_auto_mux_enum_put(struct snd_kcontrol *kcontrol, @@ -3801,7 +3789,7 @@ static void cx_auto_check_auto_mic(struct hda_codec *codec) int pset[INPUT_PIN_ATTR_NORMAL + 1]; int i; - for (i = 0; i < ARRAY_SIZE(pset); i++) + for (i = 0; i < INPUT_PIN_ATTR_NORMAL; i++) pset[i] = -1; for (i = 0; i < spec->private_imux.num_items; i++) { hda_nid_t pin = spec->imux_info[i].pin; diff --git a/trunk/sound/pci/hda/patch_hdmi.c b/trunk/sound/pci/hda/patch_hdmi.c index bd0ae697f9c4..322901873222 100644 --- a/trunk/sound/pci/hda/patch_hdmi.c +++ b/trunk/sound/pci/hda/patch_hdmi.c @@ -48,8 +48,8 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); * * The HDA correspondence of pipes/ports are converter/pin nodes. */ -#define MAX_HDMI_CVTS 4 -#define MAX_HDMI_PINS 4 +#define MAX_HDMI_CVTS 3 +#define MAX_HDMI_PINS 3 struct hdmi_spec { int num_cvts; @@ -78,6 +78,10 @@ struct hdmi_spec { */ struct hda_multi_out multiout; const struct hda_pcm_stream *pcm_playback; + + /* misc flags */ + /* PD bit indicates only the update, not the current state */ + unsigned int old_pin_detect:1; }; @@ -296,6 +300,13 @@ static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) return -EINVAL; } +static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_eld *eld) +{ + if (!snd_hdmi_get_eld(eld, codec, pin_nid)) + snd_hdmi_show_eld(eld); +} + #ifdef BE_PARANOID static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, int *packet_index, int *byte_index) @@ -683,20 +694,35 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) { struct hdmi_spec *spec = codec->spec; - int pin_nid = res >> AC_UNSOL_RES_TAG_SHIFT; - int pd = !!(res & AC_UNSOL_RES_PD); + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int pind = !!(res & AC_UNSOL_RES_PD); int eldv = !!(res & AC_UNSOL_RES_ELDV); int index; printk(KERN_INFO "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - pin_nid, pd, eldv); + tag, pind, eldv); - index = hda_node_index(spec->pin, pin_nid); + index = hda_node_index(spec->pin, tag); if (index < 0) return; - hdmi_present_sense(codec, pin_nid, &spec->sink_eld[index]); + if (spec->old_pin_detect) { + if (pind) + hdmi_present_sense(codec, tag, &spec->sink_eld[index]); + pind = spec->sink_eld[index].monitor_present; + } + + spec->sink_eld[index].monitor_present = pind; + spec->sink_eld[index].eld_valid = eldv; + + if (pind && eldv) { + hdmi_get_show_eld(codec, spec->pin[index], + &spec->sink_eld[index]); + /* TODO: do real things about ELD */ + } + + snd_hda_input_jack_report(codec, tag); } static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) @@ -877,33 +903,13 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, struct hdmi_eld *eld) { - /* - * Always execute a GetPinSense verb here, even when called from - * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited - * response's PD bit is not the real PD value, but indicates that - * the real PD value changed. An older version of the HD-audio - * specification worked this way. Hence, we just ignore the data in - * the unsolicited response to avoid custom WARs. - */ int present = snd_hda_pin_sense(codec, pin_nid); - memset(eld, 0, sizeof(*eld)); - eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); - if (eld->monitor_present) - eld->eld_valid = !!(present & AC_PINSENSE_ELDV); - else - eld->eld_valid = 0; + eld->eld_valid = !!(present & AC_PINSENSE_ELDV); - printk(KERN_INFO - "HDMI status: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - pin_nid, eld->monitor_present, eld->eld_valid); - - if (eld->eld_valid) - if (!snd_hdmi_get_eld(eld, codec, pin_nid)) - snd_hdmi_show_eld(eld); - - snd_hda_input_jack_report(codec, pin_nid); + if (present & AC_PINSENSE_ELDV) + hdmi_get_show_eld(codec, pin_nid, eld); } static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) @@ -921,6 +927,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) SND_JACK_VIDEOOUT, NULL); if (err < 0) return err; + snd_hda_input_jack_report(codec, pin_nid); hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); @@ -1027,7 +1034,6 @@ static char *generic_hdmi_pcm_names[MAX_HDMI_CVTS] = { "HDMI 0", "HDMI 1", "HDMI 2", - "HDMI 3", }; /* @@ -1484,6 +1490,18 @@ static const struct hda_codec_ops nvhdmi_patch_ops_2ch = { .free = generic_hdmi_free, }; +static int patch_nvhdmi_8ch_89(struct hda_codec *codec) +{ + struct hdmi_spec *spec; + int err = patch_generic_hdmi(codec); + + if (err < 0) + return err; + spec = codec->spec; + spec->old_pin_detect = 1; + return 0; +} + static int patch_nvhdmi_2ch(struct hda_codec *codec) { struct hdmi_spec *spec; @@ -1497,6 +1515,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) spec->multiout.num_dacs = 0; /* no analog */ spec->multiout.max_channels = 2; spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; + spec->old_pin_detect = 1; spec->num_cvts = 1; spec->cvt[0] = nvhdmi_master_con_nid_7x; spec->pcm_playback = &nvhdmi_pcm_playback_2ch; @@ -1639,28 +1658,28 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, -{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_generic_hdmi }, +{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, /* 17 is known to be absent */ -{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, +{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, +{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, diff --git a/trunk/sound/soc/atmel/sam9g20_wm8731.c b/trunk/sound/soc/atmel/sam9g20_wm8731.c index 95572d290c27..28afbbf69ce0 100644 --- a/trunk/sound/soc/atmel/sam9g20_wm8731.c +++ b/trunk/sound/soc/atmel/sam9g20_wm8731.c @@ -146,7 +146,7 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) "at91sam9g20ek_wm8731 " ": at91sam9g20ek_wm8731_init() called\n"); - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_MCLK, + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, MCLK_RATE, SND_SOC_CLOCK_IN); if (ret < 0) { printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); diff --git a/trunk/sound/soc/codecs/cq93vc.c b/trunk/sound/soc/codecs/cq93vc.c index 46dbfd067f79..b8066ef10bb0 100644 --- a/trunk/sound/soc/codecs/cq93vc.c +++ b/trunk/sound/soc/codecs/cq93vc.c @@ -153,7 +153,8 @@ static int cq93vc_resume(struct snd_soc_codec *codec) static int cq93vc_probe(struct snd_soc_codec *codec) { - struct davinci_vc *davinci_vc = codec->dev->platform_data; + struct davinci_vc *davinci_vc = + mfd_get_data(to_platform_device(codec->dev)); davinci_vc->cq93vc.codec = codec; codec->control_data = davinci_vc; diff --git a/trunk/sound/soc/codecs/twl4030.c b/trunk/sound/soc/codecs/twl4030.c index bec788b12613..575238d68e5e 100644 --- a/trunk/sound/soc/codecs/twl4030.c +++ b/trunk/sound/soc/codecs/twl4030.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -732,7 +733,8 @@ static int aif_event(struct snd_soc_dapm_widget *w, static void headset_ramp(struct snd_soc_codec *codec, int ramp) { - struct twl4030_codec_audio_data *pdata = codec->dev->platform_data; + struct twl4030_codec_audio_data *pdata = + mfd_get_data(to_platform_device(codec->dev)); unsigned char hs_gain, hs_pop; struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); /* Base values for ramp delay calculation: 2^19 - 2^26 */ @@ -2297,7 +2299,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { static int __devinit twl4030_codec_probe(struct platform_device *pdev) { - struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; + struct twl4030_codec_audio_data *pdata = mfd_get_data(pdev); if (!pdata) { dev_err(&pdev->dev, "platform_data is missing\n"); diff --git a/trunk/sound/soc/codecs/wl1273.c b/trunk/sound/soc/codecs/wl1273.c index 5836201834d9..c8a874d0d4ca 100644 --- a/trunk/sound/soc/codecs/wl1273.c +++ b/trunk/sound/soc/codecs/wl1273.c @@ -441,7 +441,8 @@ EXPORT_SYMBOL_GPL(wl1273_get_format); static int wl1273_probe(struct snd_soc_codec *codec) { - struct wl1273_core **core = codec->dev->platform_data; + struct wl1273_core **core = + mfd_get_data(to_platform_device(codec->dev)); struct wl1273_priv *wl1273; int r; diff --git a/trunk/sound/soc/codecs/wm1250-ev1.c b/trunk/sound/soc/codecs/wm1250-ev1.c index bcc208967917..14d0716bf009 100644 --- a/trunk/sound/soc/codecs/wm1250-ev1.c +++ b/trunk/sound/soc/codecs/wm1250-ev1.c @@ -22,7 +22,7 @@ SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC("DAC", "wm1250-ev1 Playback", SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_INPUT("WM1250 Input"), -SND_SOC_DAPM_OUTPUT("WM1250 Output"), +SND_SOC_DAPM_INPUT("WM1250 Output"), }; static const struct snd_soc_dapm_route wm1250_ev1_dapm_routes[] = { diff --git a/trunk/sound/soc/codecs/wm8400.c b/trunk/sound/soc/codecs/wm8400.c index fbee556cbf35..736b785e3756 100644 --- a/trunk/sound/soc/codecs/wm8400.c +++ b/trunk/sound/soc/codecs/wm8400.c @@ -1378,7 +1378,7 @@ static void wm8400_probe_deferred(struct work_struct *work) static int wm8400_codec_probe(struct snd_soc_codec *codec) { - struct wm8400 *wm8400 = dev_get_platdata(codec->dev); + struct wm8400 *wm8400 = mfd_get_data(to_platform_device(codec->dev)); struct wm8400_priv *priv; int ret; u16 reg; diff --git a/trunk/sound/soc/codecs/wm8731.c b/trunk/sound/soc/codecs/wm8731.c index 2dc964b55e4f..6dec7cee2cb4 100644 --- a/trunk/sound/soc/codecs/wm8731.c +++ b/trunk/sound/soc/codecs/wm8731.c @@ -198,7 +198,7 @@ static int wm8731_check_osc(struct snd_soc_dapm_widget *source, { struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec); - return wm8731->sysclk_type == WM8731_SYSCLK_XTAL; + return wm8731->sysclk_type == WM8731_SYSCLK_MCLK; } static const struct snd_soc_dapm_route wm8731_intercon[] = { diff --git a/trunk/sound/soc/codecs/wm8915.c b/trunk/sound/soc/codecs/wm8915.c index a0b1a7278284..ccc9bd832794 100644 --- a/trunk/sound/soc/codecs/wm8915.c +++ b/trunk/sound/soc/codecs/wm8915.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/sound/soc/davinci/davinci-vcif.c b/trunk/sound/soc/davinci/davinci-vcif.c index 9259f1f34899..13e05a302a92 100644 --- a/trunk/sound/soc/davinci/davinci-vcif.c +++ b/trunk/sound/soc/davinci/davinci-vcif.c @@ -205,7 +205,7 @@ static struct snd_soc_dai_driver davinci_vcif_dai = { static int davinci_vcif_probe(struct platform_device *pdev) { - struct davinci_vc *davinci_vc = pdev->dev.platform_data; + struct davinci_vc *davinci_vc = mfd_get_data(pdev); struct davinci_vcif_dev *davinci_vcif_dev; int ret; diff --git a/trunk/sound/soc/omap/Kconfig b/trunk/sound/soc/omap/Kconfig index 99054cf1f68f..b5922984eac6 100644 --- a/trunk/sound/soc/omap/Kconfig +++ b/trunk/sound/soc/omap/Kconfig @@ -65,6 +65,14 @@ config SND_OMAP_SOC_OVERO Say Y if you want to add support for SoC audio on the Gumstix Overo or CompuLab CM-T35 +config SND_OMAP_SOC_OMAP2EVM + tristate "SoC Audio support for OMAP2EVM board" + depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP2EVM + select SND_OMAP_SOC_MCBSP + select SND_SOC_TWL4030 + help + Say Y if you want to add support for SoC audio on the omap2evm board. + config SND_OMAP_SOC_OMAP3EVM tristate "SoC Audio support for OMAP3EVM board" depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3EVM diff --git a/trunk/sound/soc/omap/Makefile b/trunk/sound/soc/omap/Makefile index 6c2c87eed5bb..ba9fc650db28 100644 --- a/trunk/sound/soc/omap/Makefile +++ b/trunk/sound/soc/omap/Makefile @@ -13,6 +13,7 @@ snd-soc-rx51-objs := rx51.o snd-soc-ams-delta-objs := ams-delta.o snd-soc-osk5912-objs := osk5912.o snd-soc-overo-objs := overo.o +snd-soc-omap2evm-objs := omap2evm.o snd-soc-omap3evm-objs := omap3evm.o snd-soc-am3517evm-objs := am3517evm.o snd-soc-sdp3430-objs := sdp3430.o diff --git a/trunk/sound/soc/omap/omap2evm.c b/trunk/sound/soc/omap/omap2evm.c new file mode 100644 index 000000000000..29b60d6796e7 --- /dev/null +++ b/trunk/sound/soc/omap/omap2evm.c @@ -0,0 +1,139 @@ +/* + * omap2evm.c -- SoC audio machine driver for omap2evm board + * + * Author: Arun KS + * + * Based on sound/soc/omap/overo.c by Steve Sakoman + * + * 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 in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "omap-mcbsp.h" +#include "omap-pcm.h" + +static int omap2evm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret; + + /* Set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) { + printk(KERN_ERR "can't set codec DAI configuration\n"); + return ret; + } + + /* Set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) { + printk(KERN_ERR "can't set cpu DAI configuration\n"); + return ret; + } + + /* Set the codec system clock for DAC and ADC */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, + SND_SOC_CLOCK_IN); + if (ret < 0) { + printk(KERN_ERR "can't set codec system clock\n"); + return ret; + } + + return 0; +} + +static struct snd_soc_ops omap2evm_ops = { + .hw_params = omap2evm_hw_params, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link omap2evm_dai = { + .name = "TWL4030", + .stream_name = "TWL4030", + .cpu_dai_name = "omap-mcbsp-dai.1", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", + .ops = &omap2evm_ops, +}; + +/* Audio machine driver */ +static struct snd_soc_card snd_soc_omap2evm = { + .name = "omap2evm", + .dai_link = &omap2evm_dai, + .num_links = 1, +}; + +static struct platform_device *omap2evm_snd_device; + +static int __init omap2evm_soc_init(void) +{ + int ret; + + if (!machine_is_omap2evm()) + return -ENODEV; + printk(KERN_INFO "omap2evm SoC init\n"); + + omap2evm_snd_device = platform_device_alloc("soc-audio", -1); + if (!omap2evm_snd_device) { + printk(KERN_ERR "Platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(omap2evm_snd_device, &snd_soc_omap2evm); + + ret = platform_device_add(omap2evm_snd_device); + if (ret) + goto err1; + + return 0; + +err1: + printk(KERN_ERR "Unable to add platform device\n"); + platform_device_put(omap2evm_snd_device); + + return ret; +} +module_init(omap2evm_soc_init); + +static void __exit omap2evm_soc_exit(void) +{ + platform_device_unregister(omap2evm_snd_device); +} +module_exit(omap2evm_soc_exit); + +MODULE_AUTHOR("Arun KS "); +MODULE_DESCRIPTION("ALSA SoC omap2evm"); +MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/pxa/raumfeld.c b/trunk/sound/soc/pxa/raumfeld.c index 1a591f1ebfbd..2afabaf59491 100644 --- a/trunk/sound/soc/pxa/raumfeld.c +++ b/trunk/sound/soc/pxa/raumfeld.c @@ -151,13 +151,13 @@ static struct snd_soc_ops raumfeld_cs4270_ops = { .hw_params = raumfeld_cs4270_hw_params, }; -static int raumfeld_analog_suspend(struct snd_soc_card *card) +static int raumfeld_line_suspend(struct snd_soc_card *card) { raumfeld_enable_audio(false); return 0; } -static int raumfeld_analog_resume(struct snd_soc_card *card) +static int raumfeld_line_resume(struct snd_soc_card *card) { raumfeld_enable_audio(true); return 0; @@ -225,53 +225,32 @@ static struct snd_soc_ops raumfeld_ak4104_ops = { .hw_params = raumfeld_ak4104_hw_params, }; -#define DAI_LINK_CS4270 \ -{ \ - .name = "CS4270", \ - .stream_name = "CS4270", \ - .cpu_dai_name = "pxa-ssp-dai.0", \ - .platform_name = "pxa-pcm-audio", \ - .codec_dai_name = "cs4270-hifi", \ - .codec_name = "cs4270-codec.0-0048", \ - .ops = &raumfeld_cs4270_ops, \ -} - -#define DAI_LINK_AK4104 \ -{ \ - .name = "ak4104", \ - .stream_name = "Playback", \ - .cpu_dai_name = "pxa-ssp-dai.1", \ - .codec_dai_name = "ak4104-hifi", \ - .platform_name = "pxa-pcm-audio", \ - .ops = &raumfeld_ak4104_ops, \ - .codec_name = "spi0.0", \ -} - -static struct snd_soc_dai_link snd_soc_raumfeld_connector_dai[] = +static struct snd_soc_dai_link raumfeld_dai[] = { { - DAI_LINK_CS4270, - DAI_LINK_AK4104, -}; - -static struct snd_soc_dai_link snd_soc_raumfeld_speaker_dai[] = + .name = "ak4104", + .stream_name = "Playback", + .cpu_dai_name = "pxa-ssp-dai.1", + .codec_dai_name = "ak4104-hifi", + .platform_name = "pxa-pcm-audio", + .ops = &raumfeld_ak4104_ops, + .codec_name = "ak4104-codec.0", +}, { - DAI_LINK_CS4270, -}; - -static struct snd_soc_card snd_soc_raumfeld_connector = { - .name = "Raumfeld Connector", - .dai_link = snd_soc_raumfeld_connector_dai, - .num_links = ARRAY_SIZE(snd_soc_raumfeld_connector_dai), - .suspend_post = raumfeld_analog_suspend, - .resume_pre = raumfeld_analog_resume, -}; - -static struct snd_soc_card snd_soc_raumfeld_speaker = { - .name = "Raumfeld Speaker", - .dai_link = snd_soc_raumfeld_speaker_dai, - .num_links = ARRAY_SIZE(snd_soc_raumfeld_speaker_dai), - .suspend_post = raumfeld_analog_suspend, - .resume_pre = raumfeld_analog_resume, + .name = "CS4270", + .stream_name = "CS4270", + .cpu_dai_name = "pxa-ssp-dai.0", + .platform_name = "pxa-pcm-audio", + .codec_dai_name = "cs4270-hifi", + .codec_name = "cs4270-codec.0-0048", + .ops = &raumfeld_cs4270_ops, +},}; + +static struct snd_soc_card snd_soc_raumfeld = { + .name = "Raumfeld", + .dai_link = raumfeld_dai, + .suspend_post = raumfeld_line_suspend, + .resume_pre = raumfeld_line_resume, + .num_links = ARRAY_SIZE(raumfeld_dai), }; static struct platform_device *raumfeld_audio_device; @@ -292,25 +271,22 @@ static int __init raumfeld_audio_init(void) set_max9485_clk(MAX9485_MCLK_FREQ_122880); - /* Register analog device */ + /* Register LINE and SPDIF */ raumfeld_audio_device = platform_device_alloc("soc-audio", 0); if (!raumfeld_audio_device) return -ENOMEM; - if (machine_is_raumfeld_speaker()) - platform_set_drvdata(raumfeld_audio_device, - &snd_soc_raumfeld_speaker); - - if (machine_is_raumfeld_connector()) - platform_set_drvdata(raumfeld_audio_device, - &snd_soc_raumfeld_connector); - + platform_set_drvdata(raumfeld_audio_device, + &snd_soc_raumfeld); ret = platform_device_add(raumfeld_audio_device); - if (ret < 0) + + /* no S/PDIF on Speakers */ + if (machine_is_raumfeld_speaker()) return ret; raumfeld_enable_audio(true); - return 0; + + return ret; } static void __exit raumfeld_audio_exit(void) diff --git a/trunk/sound/soc/soc-core.c b/trunk/sound/soc/soc-core.c index d75043ed7fc0..bb7cd5812945 100644 --- a/trunk/sound/soc/soc-core.c +++ b/trunk/sound/soc/soc-core.c @@ -1306,6 +1306,10 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) /* no, then find CPU DAI from registered DAIs*/ list_for_each_entry(cpu_dai, &dai_list, list) { if (!strcmp(cpu_dai->name, dai_link->cpu_dai_name)) { + + if (!try_module_get(cpu_dai->dev->driver->owner)) + return -ENODEV; + rtd->cpu_dai = cpu_dai; goto find_codec; } @@ -1618,15 +1622,11 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) /* probe the cpu_dai */ if (!cpu_dai->probed) { - if (!try_module_get(cpu_dai->dev->driver->owner)) - return -ENODEV; - if (cpu_dai->driver->probe) { ret = cpu_dai->driver->probe(cpu_dai); if (ret < 0) { printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n", cpu_dai->name); - module_put(cpu_dai->dev->driver->owner); return ret; } } diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index 999bb08cdfb1..456617e63789 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -1110,7 +1110,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) trace_snd_soc_dapm_start(card); list_for_each_entry(d, &card->dapm_list, list) - if (d->n_widgets || d->codec == NULL) + if (d->n_widgets) d->dev_power = 0; /* Check which widgets we need to power and store them in diff --git a/trunk/sound/usb/card.c b/trunk/sound/usb/card.c index 220c6167dd86..a90662af2d6b 100644 --- a/trunk/sound/usb/card.c +++ b/trunk/sound/usb/card.c @@ -48,7 +48,6 @@ #include #include -#include #include #include #include @@ -493,14 +492,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev, } } - /* - * For devices with more than one control interface, we assume the - * first contains the audio controls. We might need a more specific - * check here in the future. - */ - if (!chip->ctrl_intf) - chip->ctrl_intf = alts; - chip->txfr_quirk = 0; err = 1; /* continue */ if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { @@ -509,6 +500,14 @@ static void *snd_usb_audio_probe(struct usb_device *dev, goto __error; } + /* + * For devices with more than one control interface, we assume the + * first contains the audio controls. We might need a more specific + * check here in the future. + */ + if (!chip->ctrl_intf) + chip->ctrl_intf = alts; + if (err > 0) { /* create normal USB audio interfaces */ if (snd_usb_create_streams(chip, ifnum) < 0 || diff --git a/trunk/sound/usb/mixer.c b/trunk/sound/usb/mixer.c index c22fa76e363a..eab06edcc9b7 100644 --- a/trunk/sound/usb/mixer.c +++ b/trunk/sound/usb/mixer.c @@ -86,6 +86,16 @@ struct mixer_build { const struct usbmix_selector_map *selector_map; }; +enum { + USB_MIXER_BOOLEAN, + USB_MIXER_INV_BOOLEAN, + USB_MIXER_S8, + USB_MIXER_U8, + USB_MIXER_S16, + USB_MIXER_U16, +}; + + /*E-mu 0202/0404/0204 eXtension Unit(XU) control*/ enum { USB_XU_CLOCK_RATE = 0xe301, @@ -525,21 +535,20 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou * if failed, give up and free the control instance. */ -int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, - struct snd_kcontrol *kctl) +static int add_control_to_empty(struct mixer_build *state, struct snd_kcontrol *kctl) { struct usb_mixer_elem_info *cval = kctl->private_data; int err; - while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) + while (snd_ctl_find_id(state->chip->card, &kctl->id)) kctl->id.index++; - if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) { + if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) { snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); return err; } cval->elem_id = &kctl->id; - cval->next_id_elem = mixer->id_elems[cval->id]; - mixer->id_elems[cval->id] = cval; + cval->next_id_elem = state->mixer->id_elems[cval->id]; + state->mixer->id_elems[cval->id] = cval; return 0; } @@ -975,9 +984,6 @@ static struct snd_kcontrol_new usb_feature_unit_ctl_ro = { .put = NULL, }; -/* This symbol is exported in order to allow the mixer quirks to - * hook up to the standard feature unit control mechanism */ -struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl; /* * build a feature control @@ -1170,7 +1176,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); - snd_usb_mixer_add_control(state->mixer, kctl); + add_control_to_empty(state, kctl); } @@ -1334,7 +1340,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); - snd_usb_mixer_add_control(state->mixer, kctl); + add_control_to_empty(state, kctl); } @@ -1635,7 +1641,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); - if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) + if ((err = add_control_to_empty(state, kctl)) < 0) return err; } return 0; @@ -1852,7 +1858,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", cval->id, kctl->id.name, desc->bNrInPins); - if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) + if ((err = add_control_to_empty(state, kctl)) < 0) return err; return 0; diff --git a/trunk/sound/usb/mixer.h b/trunk/sound/usb/mixer.h index ae1a14dcfe82..b4a2c8165e4b 100644 --- a/trunk/sound/usb/mixer.h +++ b/trunk/sound/usb/mixer.h @@ -24,16 +24,7 @@ struct usb_mixer_interface { u8 xonar_u1_status; }; -#define MAX_CHANNELS 16 /* max logical channels */ - -enum { - USB_MIXER_BOOLEAN, - USB_MIXER_INV_BOOLEAN, - USB_MIXER_S8, - USB_MIXER_U8, - USB_MIXER_S16, - USB_MIXER_U16, -}; +#define MAX_CHANNELS 10 /* max logical channels */ struct usb_mixer_elem_info { struct usb_mixer_interface *mixer; @@ -64,7 +55,4 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer); int snd_usb_mixer_activate(struct usb_mixer_interface *mixer); -int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, - struct snd_kcontrol *kctl); - #endif /* __USBMIXER_H */ diff --git a/trunk/sound/usb/mixer_quirks.c b/trunk/sound/usb/mixer_quirks.c index 3d0f4873112b..9146cffa6ede 100644 --- a/trunk/sound/usb/mixer_quirks.c +++ b/trunk/sound/usb/mixer_quirks.c @@ -40,8 +40,6 @@ #include "mixer_quirks.h" #include "helper.h" -extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; - /* * Sound Blaster remote control configuration * @@ -494,69 +492,6 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, return err; } -/* M-Audio FastTrack Ultra quirks */ - -/* private_free callback */ -static void usb_mixer_elem_free(struct snd_kcontrol *kctl) -{ - kfree(kctl->private_data); - kctl->private_data = NULL; -} - -static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer, - int in, int out, const char *name) -{ - struct usb_mixer_elem_info *cval; - struct snd_kcontrol *kctl; - - cval = kzalloc(sizeof(*cval), GFP_KERNEL); - if (!cval) - return -ENOMEM; - - cval->id = 5; - cval->mixer = mixer; - cval->val_type = USB_MIXER_S16; - cval->channels = 1; - cval->control = out + 1; - cval->cmask = 1 << in; - - kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval); - if (!kctl) { - kfree(cval); - return -ENOMEM; - } - - snprintf(kctl->id.name, sizeof(kctl->id.name), name); - kctl->private_free = usb_mixer_elem_free; - return snd_usb_mixer_add_control(mixer, kctl); -} - -static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) -{ - char name[64]; - int in, out, err; - - for (out = 0; out < 8; out++) { - for (in = 0; in < 8; in++) { - snprintf(name, sizeof(name), - "AIn%d - Out%d Capture Volume", in + 1, out + 1); - err = snd_maudio_ftu_create_ctl(mixer, in, out, name); - if (err < 0) - return err; - } - - for (in = 8; in < 16; in++) { - snprintf(name, sizeof(name), - "DIn%d - Out%d Playback Volume", in - 7, out + 1); - err = snd_maudio_ftu_create_ctl(mixer, in, out, name); - if (err < 0) - return err; - } - } - - return 0; -} - void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, unsigned char samplerate_id) { @@ -598,11 +533,6 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) snd_audigy2nx_proc_read); break; - case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ - case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ - err = snd_maudio_ftu_create_mixer(mixer); - break; - case USB_ID(0x0b05, 0x1739): case USB_ID(0x0b05, 0x1743): err = snd_xonar_u1_controls_create(mixer); diff --git a/trunk/sound/usb/quirks-table.h b/trunk/sound/usb/quirks-table.h index 0b2ae8e1c02d..78792a8900c3 100644 --- a/trunk/sound/usb/quirks-table.h +++ b/trunk/sound/usb/quirks-table.h @@ -1988,7 +1988,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .data = & (const struct snd_usb_audio_quirk[]) { { .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, + .type = QUIRK_IGNORE_INTERFACE }, { .ifnum = 1, @@ -2055,7 +2055,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .data = & (const struct snd_usb_audio_quirk[]) { { .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, + .type = QUIRK_IGNORE_INTERFACE }, { .ifnum = 1, diff --git a/trunk/sound/usb/quirks.c b/trunk/sound/usb/quirks.c index 2e969cbb393b..bd13d7257240 100644 --- a/trunk/sound/usb/quirks.c +++ b/trunk/sound/usb/quirks.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -263,20 +262,6 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, return 0; } -/* - * Create a standard mixer for the specified interface. - */ -static int create_standard_mixer_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - if (quirk->ifnum < 0) - return 0; - - return snd_usb_create_mixer(chip, quirk->ifnum, 0); -} - /* * audio-interface quirks * @@ -309,8 +294,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, - [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk, - [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk, + [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk }; if (quirk->type < QUIRK_TYPE_COUNT) { diff --git a/trunk/sound/usb/usbaudio.h b/trunk/sound/usb/usbaudio.h index 1e79986b5777..32f2a97f2f14 100644 --- a/trunk/sound/usb/usbaudio.h +++ b/trunk/sound/usb/usbaudio.h @@ -84,7 +84,6 @@ enum quirk_type { QUIRK_AUDIO_FIXED_ENDPOINT, QUIRK_AUDIO_EDIROL_UAXX, QUIRK_AUDIO_ALIGN_TRANSFER, - QUIRK_AUDIO_STANDARD_MIXER, QUIRK_TYPE_COUNT };